diff --git a/src/main/java/io/inisos/bank4j/impl/JAXBCreditTransfer.java b/src/main/java/io/inisos/bank4j/impl/JAXBCreditTransfer.java index 45e105d..eabb534 100644 --- a/src/main/java/io/inisos/bank4j/impl/JAXBCreditTransfer.java +++ b/src/main/java/io/inisos/bank4j/impl/JAXBCreditTransfer.java @@ -116,7 +116,7 @@ private CustomerCreditTransferInitiationV03 build() { paymentInstructionInformationSCT3.setCtrlSum(this.getTotalAmount()); paymentInstructionInformationSCT3.setDbtr(partyIdentification(this.debtor)); paymentInstructionInformationSCT3.setDbtrAcct(cashAccount(this.debtorAccount)); - branchAndFinancialInstitutionIdentification(this.debtorAccount).ifPresent(paymentInstructionInformationSCT3::setDbtrAgt); + paymentInstructionInformationSCT3.setDbtrAgt(mandatoryBranchAndFinancialInstitutionIdentification(this.debtorAccount)); if(this.serviceLevelCode != null) { ServiceLevel8Choice serviceLevel = new ServiceLevel8Choice(); @@ -179,28 +179,28 @@ private CreditTransferTransactionInformation10 transaction(Transaction transacti transaction.getChargeBearerCode().ifPresent(creditTransferTransactionInformation::setChrgBr); - branchAndFinancialInstitutionIdentification(transaction.getAccount()).ifPresent(creditTransferTransactionInformation::setCdtrAgt); + optionalBranchAndFinancialInstitutionIdentificationOpt(transaction.getAccount()).ifPresent(creditTransferTransactionInformation::setCdtrAgt); Iterator intermediaryAgentsIterator = transaction.getIntermediaryAgents().iterator(); if (intermediaryAgentsIterator.hasNext()) { BankAccount first = intermediaryAgentsIterator.next(); creditTransferTransactionInformation.setIntrmyAgt1Acct(cashAccount(first)); - branchAndFinancialInstitutionIdentification(first).ifPresent(creditTransferTransactionInformation::setIntrmyAgt1); + optionalBranchAndFinancialInstitutionIdentificationOpt(first).ifPresent(creditTransferTransactionInformation::setIntrmyAgt1); } if (intermediaryAgentsIterator.hasNext()) { BankAccount second = intermediaryAgentsIterator.next(); creditTransferTransactionInformation.setIntrmyAgt2Acct(cashAccount(second)); - branchAndFinancialInstitutionIdentification(second).ifPresent(creditTransferTransactionInformation::setIntrmyAgt2); + optionalBranchAndFinancialInstitutionIdentificationOpt(second).ifPresent(creditTransferTransactionInformation::setIntrmyAgt2); } if (intermediaryAgentsIterator.hasNext()) { BankAccount third = intermediaryAgentsIterator.next(); creditTransferTransactionInformation.setIntrmyAgt3Acct(cashAccount(third)); - branchAndFinancialInstitutionIdentification(third).ifPresent(creditTransferTransactionInformation::setIntrmyAgt3); + optionalBranchAndFinancialInstitutionIdentificationOpt(third).ifPresent(creditTransferTransactionInformation::setIntrmyAgt3); } return creditTransferTransactionInformation; } - private Optional branchAndFinancialInstitutionIdentification(BankAccount bankAccount) { + private Optional optionalBranchAndFinancialInstitutionIdentificationOpt(BankAccount bankAccount) { return bankAccount.getBic().map(bic -> { BicUtil.validate(bic); FinancialInstitutionIdentification7 financialInstitutionIdentification = new FinancialInstitutionIdentification7(); @@ -211,6 +211,17 @@ private Optional branchAndFinancia }); } + private BranchAndFinancialInstitutionIdentification4 mandatoryBranchAndFinancialInstitutionIdentification(BankAccount bankAccount) { + BranchAndFinancialInstitutionIdentification4 branchAndFinancialInstitutionIdentification = new BranchAndFinancialInstitutionIdentification4(); + FinancialInstitutionIdentification7 financialInstitutionIdentification = new FinancialInstitutionIdentification7(); + bankAccount.getBic().ifPresent(bic -> { + BicUtil.validate(bic); + financialInstitutionIdentification.setBIC(bic); + }); + branchAndFinancialInstitutionIdentification.setFinInstnId(financialInstitutionIdentification); + return branchAndFinancialInstitutionIdentification; + } + private PartyIdentification32 partyIdentification(Party party) { PartyIdentification32 partyIdentification = new PartyIdentification32(); if (party != null) { diff --git a/src/test/java/io/inisos/bank4j/CreditTransferTest.java b/src/test/java/io/inisos/bank4j/CreditTransferTest.java index 0b0f680..21d8a38 100644 --- a/src/test/java/io/inisos/bank4j/CreditTransferTest.java +++ b/src/test/java/io/inisos/bank4j/CreditTransferTest.java @@ -1,10 +1,10 @@ package io.inisos.bank4j; +import iso.std.iso._20022.tech.xsd.pain_001_001.ChargeBearerType1Code; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; -import iso.std.iso._20022.tech.xsd.pain_001_001.ChargeBearerType1Code; - +import java.io.StringReader; import java.time.LocalDate; import java.time.LocalDateTime; import java.util.ArrayList; @@ -71,10 +71,12 @@ void test_with_all_fields() { .chargeBearerCode(ChargeBearerType1Code.DEBT) .build(); - System.out.println(creditTransfer.marshal()); + String xml = creditTransfer.marshal(); Assertions.assertEquals("MYID2021-01-01T00:00:0094611.06Banque de FranceMYIDTRFfalse94611.06SEPA2021-01-02Banque de FranceFR7630001007941234567890185Compte de la Banque de FranceBDFEFRPPXXXDEBTID1ENDTOEND1112.34CREDPSSTFRPPDebtor 1ADDRDeptSubDept115 rue de Sèvres75006ParisIDFFRFR7610011000201234567890188Debtor Account 1My unstructured remittance informationID2ENDTOEND2212.34CREDPSSTFRPPDebtor 2ADDRDeptSubDept115 rue de Sèvres75006ParisIDFFRFR7610011000201234567890188Debtor Account 2My unstructured remittance informationID3ENDTOEND3312.34CREDPSSTFRPPDebtor 3ADDRDeptSubDept115 rue de Sèvres75006ParisIDFFRFR7610011000201234567890188Debtor Account 3My unstructured remittance informationID4ENDTOEND4412.34CREDPSSTFRPPDebtor 4ADDRDeptSubDept115 rue de Sèvres75006ParisIDFFRFR7610011000201234567890188Debtor Account 4My unstructured remittance informationID5ENDTOEND5512.34CREDPSSTFRPPDebtor 5ADDRDeptSubDept115 rue de Sèvres75006ParisIDFFRFR7610011000201234567890188Debtor Account 5My unstructured remittance informationID6ENDTOEND6612.34CREDPSSTFRPPDebtor 6ADDRDeptSubDept115 rue de Sèvres75006ParisIDFFRFR7610011000201234567890188Debtor Account 6My unstructured remittance informationID7ENDTOEND7712.34CREDPSSTFRPPDebtor 7ADDRDeptSubDept115 rue de Sèvres75006ParisIDFFRFR7610011000201234567890188Debtor Account 7My unstructured remittance informationID8ENDTOEND8812.34CREDPSSTFRPPDebtor 8ADDRDeptSubDept115 rue de Sèvres75006ParisIDFFRFR7610011000201234567890188Debtor Account 8My unstructured remittance informationID9ENDTOEND9912.34CREDPSSTFRPPDebtor 9ADDRDeptSubDept115 rue de Sèvres75006ParisIDFFRFR7610011000201234567890188Debtor Account 9My unstructured remittance information", - creditTransfer.marshal()); + xml); + + assertValid(xml); } @Test @@ -116,10 +118,12 @@ void test_with_account_other_id() { .requestedExecutionDate(nextDay) .build(); - System.out.println(jaxbCreditTransfer.marshal(false)); + String xml = jaxbCreditTransfer.marshal(); Assertions.assertEquals("MYID2021-01-01T00:00:00112.34Banque de FranceMYIDTRFfalse112.34SEPA2021-01-02Banque de FranceFR7630001007941234567890185Compte de la Banque de FranceBDFEFRPPXXXSLEVID1ENDTOEND112.34PSSTFRPPDebtor1234567890Debtor Account", - jaxbCreditTransfer.marshal()); + xml); + + assertValid(xml); } @Test @@ -167,8 +171,12 @@ void test_with_unstructured_address() { .requestedExecutionDate(nextDay) .build(); + String xml = creditTransfer.marshal(); + Assertions.assertEquals("MYID2021-01-01T00:00:0094611.06Banque de FranceMYIDTRFfalse94611.06SEPA2021-01-02Banque de FranceFR7630001007941234567890185BDFEFRPPXXXSLEVID1ENDTOEND1112.34PSSTFRPPBeneficiary 1FR115 rue de Sèvres75006 ParisFR7610011000201234567890188ID2ENDTOEND2212.34PSSTFRPPBeneficiary 2FR115 rue de Sèvres75006 ParisFR7610011000201234567890188ID3ENDTOEND3312.34PSSTFRPPBeneficiary 3FR115 rue de Sèvres75006 ParisFR7610011000201234567890188ID4ENDTOEND4412.34PSSTFRPPBeneficiary 4FR115 rue de Sèvres75006 ParisFR7610011000201234567890188ID5ENDTOEND5512.34PSSTFRPPBeneficiary 5FR115 rue de Sèvres75006 ParisFR7610011000201234567890188ID6ENDTOEND6612.34PSSTFRPPBeneficiary 6FR115 rue de Sèvres75006 ParisFR7610011000201234567890188ID7ENDTOEND7712.34PSSTFRPPBeneficiary 7FR115 rue de Sèvres75006 ParisFR7610011000201234567890188ID8ENDTOEND8812.34PSSTFRPPBeneficiary 8FR115 rue de Sèvres75006 ParisFR7610011000201234567890188ID9ENDTOEND9912.34PSSTFRPPBeneficiary 9FR115 rue de Sèvres75006 ParisFR7610011000201234567890188", - creditTransfer.marshal()); + xml); + + assertValid(xml); } @Test @@ -207,7 +215,15 @@ void test_without_optional_fields() { .requestedExecutionDate(nextDay) .build(); - Assertions.assertEquals("202101011200002021-01-01T00:00:0094611.06Banque de France20210101120000TRFfalse94611.06SEPA2021-01-02Banque de FranceFR7630001007941234567890185SLEVENDTOEND1112.34Beneficiary 1FR7610011000201234567890188ENDTOEND2212.34Beneficiary 2FR7610011000201234567890188ENDTOEND3312.34Beneficiary 3FR7610011000201234567890188ENDTOEND4412.34Beneficiary 4FR7610011000201234567890188ENDTOEND5512.34Beneficiary 5FR7610011000201234567890188ENDTOEND6612.34Beneficiary 6FR7610011000201234567890188ENDTOEND7712.34Beneficiary 7FR7610011000201234567890188ENDTOEND8812.34Beneficiary 8FR7610011000201234567890188ENDTOEND9912.34Beneficiary 9FR7610011000201234567890188", - creditTransfer.marshal()); + String xml = creditTransfer.marshal(); + + Assertions.assertEquals("202101011200002021-01-01T00:00:0094611.06Banque de France20210101120000TRFfalse94611.06SEPA2021-01-02Banque de FranceFR7630001007941234567890185SLEVENDTOEND1112.34Beneficiary 1FR7610011000201234567890188ENDTOEND2212.34Beneficiary 2FR7610011000201234567890188ENDTOEND3312.34Beneficiary 3FR7610011000201234567890188ENDTOEND4412.34Beneficiary 4FR7610011000201234567890188ENDTOEND5512.34Beneficiary 5FR7610011000201234567890188ENDTOEND6612.34Beneficiary 6FR7610011000201234567890188ENDTOEND7712.34Beneficiary 7FR7610011000201234567890188ENDTOEND8812.34Beneficiary 8FR7610011000201234567890188ENDTOEND9912.34Beneficiary 9FR7610011000201234567890188", + xml); + + assertValid(xml); + } + + private void assertValid(String xml) { + Assertions.assertDoesNotThrow(() -> SchemaValidator.validateCreditTransfer(new StringReader(xml))); } } diff --git a/src/test/java/io/inisos/bank4j/SchemaValidator.java b/src/test/java/io/inisos/bank4j/SchemaValidator.java new file mode 100644 index 0000000..a1a814c --- /dev/null +++ b/src/test/java/io/inisos/bank4j/SchemaValidator.java @@ -0,0 +1,36 @@ +package io.inisos.bank4j; + +import iso.std.iso._20022.tech.xsd.pain_001_001.ObjectFactory; +import org.xml.sax.SAXException; + +import javax.xml.XMLConstants; +import javax.xml.bind.JAXBContext; +import javax.xml.bind.JAXBException; +import javax.xml.bind.Unmarshaller; +import javax.xml.transform.Source; +import javax.xml.transform.stream.StreamSource; +import javax.xml.validation.Schema; +import javax.xml.validation.SchemaFactory; +import java.io.IOException; +import java.io.InputStream; +import java.io.Reader; + +public class SchemaValidator { + + public static void validateCreditTransfer(Reader reader) throws IOException, JAXBException, SAXException { + try (InputStream resourceAsStream = SchemaValidator.class.getClassLoader().getResourceAsStream("pain.001.001.03.xsd")) { + + JAXBContext jaxbContext = JAXBContext.newInstance(ObjectFactory.class); + + Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller(); + + Source xsdFile = new StreamSource(resourceAsStream); + + SchemaFactory sf = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); + Schema schema = sf.newSchema(xsdFile); + jaxbUnmarshaller.setSchema(schema); + + jaxbUnmarshaller.unmarshal(reader); + } + } +}