From 135374f7c8ebbc0f32af72c83047efa7b98d093e Mon Sep 17 00:00:00 2001 From: Philip Helger Date: Fri, 21 Feb 2025 23:41:40 +0100 Subject: [PATCH] Added conversion of UBL Credit Note --- .../ubl2cii/AbstractToCII16BConverter.java | 276 +++++++++-- .../UBL21CreditNoteToCII16BConverter.java | 315 ++++++++++++ .../UBL21InvoiceToCII16BConverter.java | 455 +++++------------- .../ubl2cii/UBLCIIConversionHelper.java | 26 +- .../helger/en16931/ubl2cii/MockSettings.java | 13 + ...llUBLFilesAreEN16931CompliantFuncTest.java | 32 +- .../UBL21CreditNoteToCII16BConverterTest.java | 115 +++++ .../UBL21InvoiceToCII16BConverterTest.java | 50 +- 8 files changed, 870 insertions(+), 412 deletions(-) create mode 100644 en16931-ubl2cii/src/main/java/com/helger/en16931/ubl2cii/UBL21CreditNoteToCII16BConverter.java create mode 100644 en16931-ubl2cii/src/test/java/com/helger/en16931/ubl2cii/UBL21CreditNoteToCII16BConverterTest.java diff --git a/en16931-ubl2cii/src/main/java/com/helger/en16931/ubl2cii/AbstractToCII16BConverter.java b/en16931-ubl2cii/src/main/java/com/helger/en16931/ubl2cii/AbstractToCII16BConverter.java index 1f1914b..b6a72b2 100644 --- a/en16931-ubl2cii/src/main/java/com/helger/en16931/ubl2cii/AbstractToCII16BConverter.java +++ b/en16931-ubl2cii/src/main/java/com/helger/en16931/ubl2cii/AbstractToCII16BConverter.java @@ -30,16 +30,38 @@ import com.helger.commons.string.StringHelper; import oasis.names.specification.ubl.schema.xsd.commonaggregatecomponents_21.AddressType; +import oasis.names.specification.ubl.schema.xsd.commonaggregatecomponents_21.AllowanceChargeType; +import oasis.names.specification.ubl.schema.xsd.commonaggregatecomponents_21.AttachmentType; +import oasis.names.specification.ubl.schema.xsd.commonaggregatecomponents_21.DeliveryType; +import oasis.names.specification.ubl.schema.xsd.commonaggregatecomponents_21.DocumentReferenceType; +import oasis.names.specification.ubl.schema.xsd.commonaggregatecomponents_21.LocationType; +import oasis.names.specification.ubl.schema.xsd.commonaggregatecomponents_21.MonetaryTotalType; import oasis.names.specification.ubl.schema.xsd.commonaggregatecomponents_21.PartyLegalEntityType; import oasis.names.specification.ubl.schema.xsd.commonaggregatecomponents_21.PartyTaxSchemeType; import oasis.names.specification.ubl.schema.xsd.commonaggregatecomponents_21.PartyType; +import oasis.names.specification.ubl.schema.xsd.commonaggregatecomponents_21.PaymentMeansType; +import oasis.names.specification.ubl.schema.xsd.commonaggregatecomponents_21.PaymentTermsType; +import oasis.names.specification.ubl.schema.xsd.commonaggregatecomponents_21.TaxCategoryType; +import oasis.names.specification.ubl.schema.xsd.commonaggregatecomponents_21.TaxSchemeType; +import oasis.names.specification.ubl.schema.xsd.commonaggregatecomponents_21.TaxSubtotalType; +import oasis.names.specification.ubl.schema.xsd.commonaggregatecomponents_21.TaxTotalType; +import un.unece.uncefact.data.standard.qualifieddatatype._100.FormattedDateTimeType; +import un.unece.uncefact.data.standard.reusableaggregatebusinessinformationentity._100.HeaderTradeDeliveryType; import un.unece.uncefact.data.standard.reusableaggregatebusinessinformationentity._100.LegalOrganizationType; +import un.unece.uncefact.data.standard.reusableaggregatebusinessinformationentity._100.ReferencedDocumentType; +import un.unece.uncefact.data.standard.reusableaggregatebusinessinformationentity._100.SupplyChainEventType; import un.unece.uncefact.data.standard.reusableaggregatebusinessinformationentity._100.TaxRegistrationType; import un.unece.uncefact.data.standard.reusableaggregatebusinessinformationentity._100.TradeAddressType; +import un.unece.uncefact.data.standard.reusableaggregatebusinessinformationentity._100.TradeAllowanceChargeType; import un.unece.uncefact.data.standard.reusableaggregatebusinessinformationentity._100.TradePartyType; +import un.unece.uncefact.data.standard.reusableaggregatebusinessinformationentity._100.TradePaymentTermsType; +import un.unece.uncefact.data.standard.reusableaggregatebusinessinformationentity._100.TradeSettlementHeaderMonetarySummationType; +import un.unece.uncefact.data.standard.reusableaggregatebusinessinformationentity._100.TradeTaxType; import un.unece.uncefact.data.standard.reusableaggregatebusinessinformationentity._100.UniversalCommunicationType; import un.unece.uncefact.data.standard.unqualifieddatatype._100.AmountType; +import un.unece.uncefact.data.standard.unqualifieddatatype._100.BinaryObjectType; import un.unece.uncefact.data.standard.unqualifieddatatype._100.IDType; +import un.unece.uncefact.data.standard.unqualifieddatatype._100.IndicatorType; import un.unece.uncefact.data.standard.unqualifieddatatype._100.TextType; public abstract class AbstractToCII16BConverter @@ -129,14 +151,14 @@ protected static TextType convertText (@Nullable final String sValue) } @Nullable - protected static IDType convertID (@Nullable final com.helger.xsds.ccts.cct.schemamodule.IdentifierType aID) + protected static IDType convertID (@Nullable final com.helger.xsds.ccts.cct.schemamodule.IdentifierType aUBLID) { - if (aID == null) + if (aUBLID == null) return null; final IDType ret = new IDType (); - ifNotNull (ret::setSchemeID, aID.getSchemeID ()); - ifNotNull (ret::setValue, aID.getValue ()); + ifNotNull (ret::setSchemeID, aUBLID.getSchemeID ()); + ifNotNull (ret::setValue, aUBLID.getValue ()); return ret; } @@ -161,91 +183,89 @@ protected static AmountType convertAmount (@Nullable final com.helger.xsds.ccts. } @Nullable - protected static un.unece.uncefact.data.standard.reusableaggregatebusinessinformationentity._100.NoteType convertNote (@Nullable final oasis.names.specification.ubl.schema.xsd.commonbasiccomponents_21.NoteType aNote) + protected static un.unece.uncefact.data.standard.reusableaggregatebusinessinformationentity._100.NoteType convertNote (@Nullable final oasis.names.specification.ubl.schema.xsd.commonbasiccomponents_21.NoteType aUBLNote) { - if (aNote == null || aNote.getValue () == null) + if (aUBLNote == null || aUBLNote.getValue () == null) return null; final un.unece.uncefact.data.standard.reusableaggregatebusinessinformationentity._100.NoteType ret = new un.unece.uncefact.data.standard.reusableaggregatebusinessinformationentity._100.NoteType (); final TextType aTT = new TextType (); - aTT.setValue (aNote.getValue ()); + aTT.setValue (aUBLNote.getValue ()); ret.addContent (aTT); return ret; } @Nullable - protected static TradeAddressType convertAddress (@Nullable final AddressType aAddress) + protected static TradeAddressType convertAddress (@Nullable final AddressType aUBLAddress) { - if (aAddress == null) + if (aUBLAddress == null) return null; final TradeAddressType ret = new TradeAddressType (); - - ifNotEmpty (ret::setLineOne, aAddress.getStreetNameValue ()); - ifNotEmpty (ret::setLineTwo, aAddress.getAdditionalStreetNameValue ()); - if (aAddress.hasAddressLineEntries ()) - ifNotEmpty (ret::setLineThree, aAddress.getAddressLineAtIndex (0).getLineValue ()); - ifNotEmpty (ret::setCityName, aAddress.getCityNameValue ()); - ifNotEmpty (ret::setPostcodeCode, aAddress.getPostalZoneValue ()); - if (aAddress.getCountrySubentity () != null) - ret.addCountrySubDivisionName (convertText (aAddress.getCountrySubentity ().getValue ())); - if (aAddress.getCountry () != null) - ifNotEmpty (ret::setCountryID, aAddress.getCountry ().getIdentificationCodeValue ()); - + ifNotEmpty (ret::setLineOne, aUBLAddress.getStreetNameValue ()); + ifNotEmpty (ret::setLineTwo, aUBLAddress.getAdditionalStreetNameValue ()); + if (aUBLAddress.hasAddressLineEntries ()) + ifNotEmpty (ret::setLineThree, aUBLAddress.getAddressLineAtIndex (0).getLineValue ()); + ifNotEmpty (ret::setCityName, aUBLAddress.getCityNameValue ()); + ifNotEmpty (ret::setPostcodeCode, aUBLAddress.getPostalZoneValue ()); + if (aUBLAddress.getCountrySubentity () != null) + ret.addCountrySubDivisionName (convertText (aUBLAddress.getCountrySubentity ().getValue ())); + if (aUBLAddress.getCountry () != null) + ifNotEmpty (ret::setCountryID, aUBLAddress.getCountry ().getIdentificationCodeValue ()); return ret; } @Nullable - protected static TradePartyType convertParty (@Nullable final PartyType aParty) + protected static TradePartyType convertParty (@Nullable final PartyType aUBLParty) { - if (aParty == null) + if (aUBLParty == null) return null; final TradePartyType aTPT = new TradePartyType (); - for (final var aPartyID : aParty.getPartyIdentification ()) - ifNotNull (aTPT::addID, convertID (aPartyID.getID ())); + for (final var aUBLPartyID : aUBLParty.getPartyIdentification ()) + ifNotNull (aTPT::addID, convertID (aUBLPartyID.getID ())); - if (aParty.hasPartyNameEntries ()) - ifNotEmpty (aTPT::setName, aParty.getPartyNameAtIndex (0).getNameValue ()); + if (aUBLParty.hasPartyNameEntries ()) + ifNotEmpty (aTPT::setName, aUBLParty.getPartyNameAtIndex (0).getNameValue ()); - if (aParty.hasPartyLegalEntityEntries ()) + if (aUBLParty.hasPartyLegalEntityEntries ()) { - final PartyLegalEntityType aLE = aParty.getPartyLegalEntity ().get (0); + final PartyLegalEntityType aUBLLegalEntity = aUBLParty.getPartyLegalEntity ().get (0); final LegalOrganizationType aLOT = new LegalOrganizationType (); - ifNotEmpty (aLOT::setTradingBusinessName, aLE.getRegistrationNameValue ()); - ifNotNull (aLOT::setID, convertID (aLE.getCompanyID ())); - ifNotNull (aLOT::setPostalTradeAddress, convertAddress (aLE.getRegistrationAddress ())); + ifNotEmpty (aLOT::setTradingBusinessName, aUBLLegalEntity.getRegistrationNameValue ()); + ifNotNull (aLOT::setID, convertID (aUBLLegalEntity.getCompanyID ())); + ifNotNull (aLOT::setPostalTradeAddress, convertAddress (aUBLLegalEntity.getRegistrationAddress ())); if (StringHelper.hasNoText (aTPT.getNameValue ())) { // Fill mandatory field - ifNotEmpty (aTPT::setName, aLE.getRegistrationNameValue ()); + ifNotEmpty (aTPT::setName, aUBLLegalEntity.getRegistrationNameValue ()); } aTPT.setSpecifiedLegalOrganization (aLOT); } - ifNotNull (aTPT::setPostalTradeAddress, convertAddress (aParty.getPostalAddress ())); + ifNotNull (aTPT::setPostalTradeAddress, convertAddress (aUBLParty.getPostalAddress ())); - if (aParty.getEndpointID () != null) + if (aUBLParty.getEndpointID () != null) { final UniversalCommunicationType aUCT = new UniversalCommunicationType (); - ifNotNull (aUCT::setURIID, convertID (aParty.getEndpointID ())); + ifNotNull (aUCT::setURIID, convertID (aUBLParty.getEndpointID ())); aTPT.addURIUniversalCommunication (aUCT); } - if (aParty.hasPartyTaxSchemeEntries ()) + if (aUBLParty.hasPartyTaxSchemeEntries ()) { - final PartyTaxSchemeType aPTS = aParty.getPartyTaxSchemeAtIndex (0); - if (aPTS.getCompanyIDValue () != null) + final PartyTaxSchemeType aUBLPartyTaxScheme = aUBLParty.getPartyTaxSchemeAtIndex (0); + if (aUBLPartyTaxScheme.getCompanyIDValue () != null) { final TaxRegistrationType aTaxReg = new TaxRegistrationType (); - final IDType aID = convertID (aPTS.getCompanyID ()); - if (aPTS.getTaxScheme () != null) + final IDType aID = convertID (aUBLPartyTaxScheme.getCompanyID ()); + if (aUBLPartyTaxScheme.getTaxScheme () != null) { // MUST use "VA" scheme - ifNotEmpty (aID::setSchemeID, _getAsVAIfNecessary (aPTS.getTaxScheme ().getIDValue ())); + ifNotEmpty (aID::setSchemeID, _getAsVAIfNecessary (aUBLPartyTaxScheme.getTaxScheme ().getIDValue ())); } aTaxReg.setID (aID); aTPT.addSpecifiedTaxRegistration (aTaxReg); @@ -253,4 +273,176 @@ protected static TradePartyType convertParty (@Nullable final PartyType aParty) } return aTPT; } + + @Nonnull + protected static ReferencedDocumentType convertAdditionalReferencedDocument (@Nonnull final DocumentReferenceType aUBLDocRef) + { + final ReferencedDocumentType aURDT = new ReferencedDocumentType (); + + ifNotEmpty (aURDT::setIssuerAssignedID, aUBLDocRef.getIDValue ()); + + // Add DocumentTypeCode where possible + if (isValidDocumentReferenceTypeCode (aUBLDocRef.getDocumentTypeCodeValue ())) + aURDT.setTypeCode (aUBLDocRef.getDocumentTypeCodeValue ()); + else + aURDT.setTypeCode ("916"); + + if (aUBLDocRef.getIssueDate () != null) + { + final FormattedDateTimeType aFIDT = new FormattedDateTimeType (); + aFIDT.setDateTimeString (createFormattedDateValue (aUBLDocRef.getIssueDateValueLocal ())); + aURDT.setFormattedIssueDateTime (aFIDT); + } + + for (final var aUBLDocDesc : aUBLDocRef.getDocumentDescription ()) + { + final TextType aText = new TextType (); + ifNotEmpty (aText::setValue, aUBLDocDesc.getValue ()); + ifNotEmpty (aText::setLanguageID, aUBLDocDesc.getLanguageID ()); + ifNotEmpty (aText::setLanguageLocaleID, aUBLDocDesc.getLanguageLocaleID ()); + aURDT.addName (aText); + } + + final AttachmentType aUBLAttachment = aUBLDocRef.getAttachment (); + if (aUBLAttachment != null) + { + // External Reference and Embedded Document Binary Object should be + // mutually exclusive + if (aUBLAttachment.getExternalReference () != null && aUBLAttachment.getExternalReference ().getURI () != null) + { + ifNotEmpty (aURDT::setURIID, aUBLAttachment.getExternalReference ().getURI ().getValue ()); + } + + if (aUBLAttachment.getEmbeddedDocumentBinaryObject () != null) + { + final BinaryObjectType aBOT = new BinaryObjectType (); + ifNotEmpty (aBOT::setMimeCode, aUBLAttachment.getEmbeddedDocumentBinaryObject ().getMimeCode ()); + ifNotNull (aBOT::setValue, aUBLAttachment.getEmbeddedDocumentBinaryObject ().getValue ()); + aURDT.addAttachmentBinaryObject (aBOT); + } + } + return aURDT; + } + + @Nullable + protected static HeaderTradeDeliveryType createApplicableHeaderTradeDelivery (@Nullable final DeliveryType aUBLDelivery) + { + // Object is mandatory + final HeaderTradeDeliveryType ret = new HeaderTradeDeliveryType (); + + if (aUBLDelivery != null) + { + final LocationType aUBLLocation = aUBLDelivery.getDeliveryLocation (); + if (aUBLLocation != null) + { + final TradePartyType aTPTHT = new TradePartyType (); + ifNotNull (aTPTHT::addID, convertID (aUBLLocation.getID ())); + ifNotNull (aTPTHT::setPostalTradeAddress, convertAddress (aUBLLocation.getAddress ())); + ret.setShipToTradeParty (aTPTHT); + } + + if (aUBLDelivery.getActualDeliveryDate () != null) + { + final SupplyChainEventType aSCET = new SupplyChainEventType (); + aSCET.setOccurrenceDateTime (convertDate (aUBLDelivery.getActualDeliveryDate ().getValueLocal ())); + ret.setActualDeliverySupplyChainEvent (aSCET); + } + } + return ret; + } + + @Nonnull + protected static TradeTaxType convertApplicableTradeTax (@Nonnull final TaxSubtotalType aUBLTaxSubtotal) + { + final TaxCategoryType aUBLTaxCategory = aUBLTaxSubtotal.getTaxCategory (); + final TaxSchemeType aUBLTaxScheme = aUBLTaxCategory.getTaxScheme (); + + final TradeTaxType ret = new TradeTaxType (); + if (aUBLTaxScheme != null) + ifNotEmpty (ret::setTypeCode, aUBLTaxScheme.getIDValue ()); + ifNotEmpty (ret::setCategoryCode, aUBLTaxCategory.getIDValue ()); + ifNotNull (ret::addCalculatedAmount, convertAmount (aUBLTaxSubtotal.getTaxAmount ())); + ifNotEmpty (ret::setCategoryCode, aUBLTaxCategory.getIDValue ()); + ifNotNull (ret::addBasisAmount, convertAmount (aUBLTaxSubtotal.getTaxableAmount ())); + ifNotNull (ret::setRateApplicablePercent, aUBLTaxCategory.getPercentValue ()); + if (aUBLTaxCategory.hasTaxExemptionReasonEntries ()) + ifNotEmpty (ret::setExemptionReason, aUBLTaxCategory.getTaxExemptionReasonAtIndex (0).getValue ()); + ifNotEmpty (ret::setExemptionReasonCode, aUBLTaxCategory.getTaxExemptionReasonCodeValue ()); + return ret; + } + + @Nonnull + protected static TradeAllowanceChargeType convertSpecifiedTradeAllowanceCharge (@Nonnull final AllowanceChargeType aUBLAllowanceCharge) + { + final TradeAllowanceChargeType ret = new TradeAllowanceChargeType (); + + final IndicatorType aITDC = new IndicatorType (); + aITDC.setIndicator (Boolean.valueOf (aUBLAllowanceCharge.getChargeIndicator ().isValue ())); + ret.setChargeIndicator (aITDC); + + ret.addActualAmount (convertAmount (aUBLAllowanceCharge.getAmount ())); + ifNotEmpty (ret::setReasonCode, aUBLAllowanceCharge.getAllowanceChargeReasonCodeValue ()); + if (aUBLAllowanceCharge.hasAllowanceChargeReasonEntries ()) + ret.setReason (aUBLAllowanceCharge.getAllowanceChargeReason ().get (0).getValue ()); + ifNotNull (ret::setCalculationPercent, aUBLAllowanceCharge.getMultiplierFactorNumericValue ()); + ifNotNull (ret::setBasisAmount, aUBLAllowanceCharge.getBaseAmountValue ()); + + if (aUBLAllowanceCharge.hasTaxCategoryEntries ()) + { + final TaxCategoryType aUBLTaxCategory = aUBLAllowanceCharge.getTaxCategoryAtIndex (0); + final TaxSchemeType aUBLTaxSchene = aUBLTaxCategory.getTaxScheme (); + + final TradeTaxType aTradeTax = new TradeTaxType (); + if (aUBLTaxSchene != null) + ifNotEmpty (aTradeTax::setTypeCode, aUBLTaxSchene.getIDValue ()); + ifNotEmpty (aTradeTax::setCategoryCode, aUBLTaxCategory.getIDValue ()); + ifNotNull (aTradeTax::setRateApplicablePercent, aUBLTaxCategory.getPercentValue ()); + ret.addCategoryTradeTax (aTradeTax); + } + + return ret; + } + + @Nonnull + protected static TradePaymentTermsType convertSpecifiedTradePaymentTerms (@Nonnull final PaymentTermsType aUBLPaymenTerms, + @Nullable final PaymentMeansType aUBLPaymentMeans) + { + final TradePaymentTermsType ret = new TradePaymentTermsType (); + for (final var aNote : aUBLPaymenTerms.getNote ()) + ret.addDescription (convertText (aNote.getValue ())); + + if (aUBLPaymentMeans != null && aUBLPaymentMeans.getPaymentDueDate () != null) + ret.setDueDateDateTime (convertDate (aUBLPaymentMeans.getPaymentDueDate ().getValueLocal ())); + return ret; + } + + @Nonnull + protected static TradeSettlementHeaderMonetarySummationType createSpecifiedTradeSettlementHeaderMonetarySummation (@Nullable final MonetaryTotalType aUBLMonetaryTotal, + @Nullable final TaxTotalType aUBLTaxTotal) + { + final TradeSettlementHeaderMonetarySummationType ret = new TradeSettlementHeaderMonetarySummationType (); + if (aUBLMonetaryTotal != null) + { + ifNotNull (ret::addLineTotalAmount, convertAmount (aUBLMonetaryTotal.getLineExtensionAmount ())); + ifNotNull (ret::addChargeTotalAmount, convertAmount (aUBLMonetaryTotal.getChargeTotalAmount ())); + ifNotNull (ret::addAllowanceTotalAmount, convertAmount (aUBLMonetaryTotal.getAllowanceTotalAmount ())); + ifNotNull (ret::addTaxBasisTotalAmount, convertAmount (aUBLMonetaryTotal.getTaxExclusiveAmount ())); + } + + if (aUBLTaxTotal != null) + { + // Currency ID is required here + ifNotNull (ret::addTaxTotalAmount, convertAmount (aUBLTaxTotal.getTaxAmount (), true)); + } + + if (aUBLMonetaryTotal != null) + { + ifNotNull (ret::addRoundingAmount, convertAmount (aUBLMonetaryTotal.getPayableRoundingAmount ())); + ifNotNull (ret::addGrandTotalAmount, convertAmount (aUBLMonetaryTotal.getTaxInclusiveAmount ())); + ifNotNull (ret::addTotalPrepaidAmount, convertAmount (aUBLMonetaryTotal.getPrepaidAmount ())); + ifNotNull (ret::addDuePayableAmount, convertAmount (aUBLMonetaryTotal.getPayableAmount ())); + } + + return ret; + } } diff --git a/en16931-ubl2cii/src/main/java/com/helger/en16931/ubl2cii/UBL21CreditNoteToCII16BConverter.java b/en16931-ubl2cii/src/main/java/com/helger/en16931/ubl2cii/UBL21CreditNoteToCII16BConverter.java new file mode 100644 index 0000000..ee33f35 --- /dev/null +++ b/en16931-ubl2cii/src/main/java/com/helger/en16931/ubl2cii/UBL21CreditNoteToCII16BConverter.java @@ -0,0 +1,315 @@ +/* + * Copyright (C) 2024-2025 Philip Helger + * http://www.helger.com + * philip[at]helger[dot]com + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.helger.en16931.ubl2cii; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +import com.helger.commons.ValueEnforcer; +import com.helger.commons.error.list.ErrorList; + +import oasis.names.specification.ubl.schema.xsd.commonaggregatecomponents_21.AllowanceChargeType; +import oasis.names.specification.ubl.schema.xsd.commonaggregatecomponents_21.CommodityClassificationType; +import oasis.names.specification.ubl.schema.xsd.commonaggregatecomponents_21.CreditNoteLineType; +import oasis.names.specification.ubl.schema.xsd.commonaggregatecomponents_21.CustomerPartyType; +import oasis.names.specification.ubl.schema.xsd.commonaggregatecomponents_21.ItemPropertyType; +import oasis.names.specification.ubl.schema.xsd.commonaggregatecomponents_21.ItemType; +import oasis.names.specification.ubl.schema.xsd.commonaggregatecomponents_21.PaymentMeansType; +import oasis.names.specification.ubl.schema.xsd.commonaggregatecomponents_21.PaymentTermsType; +import oasis.names.specification.ubl.schema.xsd.commonaggregatecomponents_21.PeriodType; +import oasis.names.specification.ubl.schema.xsd.commonaggregatecomponents_21.SupplierPartyType; +import oasis.names.specification.ubl.schema.xsd.commonaggregatecomponents_21.TaxCategoryType; +import oasis.names.specification.ubl.schema.xsd.commonaggregatecomponents_21.TaxSchemeType; +import oasis.names.specification.ubl.schema.xsd.commonaggregatecomponents_21.TaxSubtotalType; +import oasis.names.specification.ubl.schema.xsd.commonaggregatecomponents_21.TaxTotalType; +import oasis.names.specification.ubl.schema.xsd.creditnote_21.CreditNoteType; +import un.unece.uncefact.data.standard.crossindustryinvoice._100.CrossIndustryInvoiceType; +import un.unece.uncefact.data.standard.reusableaggregatebusinessinformationentity._100.*; +import un.unece.uncefact.data.standard.unqualifieddatatype._100.CodeType; +import un.unece.uncefact.data.standard.unqualifieddatatype._100.QuantityType; + +/** + * UBL 2.1 Credit Note to CII D16B converter. + * + * @author Philip Helger + */ +public final class UBL21CreditNoteToCII16BConverter extends AbstractToCII16BConverter +{ + private UBL21CreditNoteToCII16BConverter () + {} + + @Nonnull + private static SupplyChainTradeLineItemType _convertCreditNoteLine (@Nonnull final CreditNoteLineType aUBLLine) + { + final SupplyChainTradeLineItemType ret = new SupplyChainTradeLineItemType (); + final DocumentLineDocumentType aDLDT = new DocumentLineDocumentType (); + + aDLDT.setLineID (aUBLLine.getIDValue ()); + + for (final var aUBLNote : aUBLLine.getNote ()) + aDLDT.addIncludedNote (convertNote (aUBLNote)); + + ret.setAssociatedDocumentLineDocument (aDLDT); + + // SpecifiedTradeProduct + final TradeProductType aTPT = new TradeProductType (); + final ItemType aUBLItem = aUBLLine.getItem (); + if (aUBLItem.getStandardItemIdentification () != null) + aTPT.setGlobalID (convertID (aUBLItem.getStandardItemIdentification ().getID ())); + + if (aUBLItem.getSellersItemIdentification () != null) + aTPT.setSellerAssignedID (aUBLItem.getSellersItemIdentification ().getIDValue ()); + + aTPT.addName (convertText (aUBLItem.getNameValue ())); + + if (aUBLItem.hasDescriptionEntries ()) + aTPT.setDescription (aUBLItem.getDescriptionAtIndex (0).getValue ()); + + // ApplicableProductCharacteristic + for (final ItemPropertyType aUBLAddItemProp : aUBLLine.getItem ().getAdditionalItemProperty ()) + { + final ProductCharacteristicType aPCT = new ProductCharacteristicType (); + ifNotNull (aPCT::addDescription, convertText (aUBLAddItemProp.getNameValue ())); + ifNotNull (aPCT::addValue, convertText (aUBLAddItemProp.getValueValue ())); + aTPT.addApplicableProductCharacteristic (aPCT); + } + + // DesignatedProductClassification + for (final CommodityClassificationType aUBLCC : aUBLLine.getItem ().getCommodityClassification ()) + { + final ProductClassificationType aPCT = new ProductClassificationType (); + final CodeType aCT = new CodeType (); + ifNotEmpty (aCT::setListID, aUBLCC.getItemClassificationCode ().getListID ()); + ifNotEmpty (aCT::setValue, aUBLCC.getItemClassificationCode ().getValue ()); + aPCT.setClassCode (aCT); + aTPT.addDesignatedProductClassification (aPCT); + } + ret.setSpecifiedTradeProduct (aTPT); + + // BuyerOrderReferencedDocument + final ReferencedDocumentType aRDT = new ReferencedDocumentType (); + if (aUBLLine.hasOrderLineReferenceEntries ()) + { + aRDT.setLineID (aUBLLine.getOrderLineReferenceAtIndex (0).getLineIDValue ()); + } + + // NetPriceProductTradePrice + final TradePriceType aLTPT = new TradePriceType (); + if (aUBLLine.getPrice () != null && aUBLLine.getPrice ().getPriceAmount () != null) + { + aLTPT.addChargeAmount (convertAmount (aUBLLine.getPrice ().getPriceAmount ())); + } + + // SpecifiedLineTradeAgreement + final LineTradeAgreementType aLTAT = new LineTradeAgreementType (); + aLTAT.setBuyerOrderReferencedDocument (aRDT); + aLTAT.setNetPriceProductTradePrice (aLTPT); + ret.setSpecifiedLineTradeAgreement (aLTAT); + + // SpecifiedLineTradeDelivery + final LineTradeDeliveryType aLTDT = new LineTradeDeliveryType (); + final QuantityType aQuantity = new QuantityType (); + aQuantity.setUnitCode (aUBLLine.getCreditedQuantity ().getUnitCode ()); + aQuantity.setValue (aUBLLine.getCreditedQuantity ().getValue ()); + aLTDT.setBilledQuantity (aQuantity); + ret.setSpecifiedLineTradeDelivery (aLTDT); + + // SpecifiedLineTradeSettlement + final LineTradeSettlementType aSLTS = new LineTradeSettlementType (); + for (final TaxCategoryType aUBLTaxCategory : aUBLLine.getItem ().getClassifiedTaxCategory ()) + { + final TaxSchemeType aUBLTaxScheme = aUBLTaxCategory.getTaxScheme (); + + final TradeTaxType aTradeTax = new TradeTaxType (); + if (aUBLTaxScheme != null) + ifNotEmpty (aTradeTax::setTypeCode, aUBLTaxCategory.getTaxScheme ().getIDValue ()); + ifNotEmpty (aTradeTax::setCategoryCode, aUBLTaxCategory.getIDValue ()); + ifNotNull (aTradeTax::setRateApplicablePercent, aUBLTaxCategory.getPercentValue ()); + aSLTS.addApplicableTradeTax (aTradeTax); + } + + final TradeSettlementLineMonetarySummationType aTSLMST = new TradeSettlementLineMonetarySummationType (); + ifNotNull (aTSLMST::addLineTotalAmount, convertAmount (aUBLLine.getLineExtensionAmount ())); + + if (aUBLLine.getAccountingCostValue () != null) + { + final TradeAccountingAccountType aTAATL = new TradeAccountingAccountType (); + aTAATL.setID (aUBLLine.getAccountingCostValue ()); + aSLTS.addReceivableSpecifiedTradeAccountingAccount (aTAATL); + } + + aSLTS.setSpecifiedTradeSettlementLineMonetarySummation (aTSLMST); + ret.setSpecifiedLineTradeSettlement (aSLTS); + + return ret; + } + + @Nonnull + private static HeaderTradeSettlementType _createApplicableHeaderTradeSettlement (@Nonnull final CreditNoteType aUBLCreditNote) + { + final HeaderTradeSettlementType ret = new HeaderTradeSettlementType (); + + final PaymentMeansType aUBLPaymentMeans = aUBLCreditNote.hasPaymentMeansEntries () ? aUBLCreditNote.getPaymentMeansAtIndex (0) + : null; + + if (aUBLPaymentMeans != null && aUBLPaymentMeans.hasPaymentIDEntries ()) + ret.addPaymentReference (convertText (aUBLPaymentMeans.getPaymentIDAtIndex (0).getValue ())); + + ifNotEmpty (ret::setInvoiceCurrencyCode, aUBLCreditNote.getDocumentCurrencyCodeValue ()); + ifNotNull (ret::setPayeeTradeParty, convertParty (aUBLCreditNote.getPayeeParty ())); + + if (aUBLPaymentMeans != null) + { + final TradeSettlementPaymentMeansType aTSPMT = new TradeSettlementPaymentMeansType (); + ifNotEmpty (aTSPMT::setTypeCode, aUBLPaymentMeans.getPaymentMeansCodeValue ()); + + final CreditorFinancialAccountType aCFAT = new CreditorFinancialAccountType (); + if (aUBLPaymentMeans.getPayeeFinancialAccount () != null) + ifNotEmpty (aCFAT::setIBANID, aUBLPaymentMeans.getPayeeFinancialAccount ().getIDValue ()); + aTSPMT.setPayeePartyCreditorFinancialAccount (aCFAT); + ret.addSpecifiedTradeSettlementPaymentMeans (aTSPMT); + } + + for (final TaxTotalType aUBLTaxTotal : aUBLCreditNote.getTaxTotal ()) + for (final TaxSubtotalType aUBLTaxSubtotal : aUBLTaxTotal.getTaxSubtotal ()) + ret.addApplicableTradeTax (convertApplicableTradeTax (aUBLTaxSubtotal)); + + if (aUBLCreditNote.hasInvoicePeriodEntries ()) + { + final PeriodType aUBLPeriod = aUBLCreditNote.getInvoicePeriodAtIndex (0); + + final SpecifiedPeriodType aSPT = new SpecifiedPeriodType (); + if (aUBLPeriod.getStartDate () != null) + aSPT.setStartDateTime (convertDate (aUBLPeriod.getStartDate ().getValueLocal ())); + if (aUBLPeriod.getEndDate () != null) + aSPT.setEndDateTime (convertDate (aUBLPeriod.getEndDate ().getValueLocal ())); + ret.setBillingSpecifiedPeriod (aSPT); + } + + for (final AllowanceChargeType aUBLAllowanceCharge : aUBLCreditNote.getAllowanceCharge ()) + ret.addSpecifiedTradeAllowanceCharge (convertSpecifiedTradeAllowanceCharge (aUBLAllowanceCharge)); + + for (final PaymentTermsType aUBLPaymentTerms : aUBLCreditNote.getPaymentTerms ()) + ret.addSpecifiedTradePaymentTerms (convertSpecifiedTradePaymentTerms (aUBLPaymentTerms, aUBLPaymentMeans)); + + final TaxTotalType aUBLTaxTotal = aUBLCreditNote.hasTaxTotalEntries () ? aUBLCreditNote.getTaxTotalAtIndex (0) : null; + ret.setSpecifiedTradeSettlementHeaderMonetarySummation (createSpecifiedTradeSettlementHeaderMonetarySummation (aUBLCreditNote.getLegalMonetaryTotal (), + aUBLTaxTotal)); + + if (aUBLCreditNote.getAccountingCost () != null) + { + final TradeAccountingAccountType aTAAT = new TradeAccountingAccountType (); + aTAAT.setID (aUBLCreditNote.getAccountingCost ().getValue ()); + ret.addReceivableSpecifiedTradeAccountingAccount (aTAAT); + } + + return ret; + } + + @Nullable + public static CrossIndustryInvoiceType convertToCrossIndustryInvoice (@Nonnull final CreditNoteType aUBLCreditNote, + @Nonnull final ErrorList aErrorList) + { + ValueEnforcer.notNull (aUBLCreditNote, "UBLInvoice"); + ValueEnforcer.notNull (aErrorList, "ErrorList"); + + final CrossIndustryInvoiceType aCIIInvoice = new CrossIndustryInvoiceType (); + + { + final ExchangedDocumentContextType aEDCT = new ExchangedDocumentContextType (); + if (aUBLCreditNote.getCustomizationID () != null) + { + final DocumentContextParameterType aDCP = new DocumentContextParameterType (); + aDCP.setID (aUBLCreditNote.getCustomizationIDValue ()); + aEDCT.addGuidelineSpecifiedDocumentContextParameter (aDCP); + } + aCIIInvoice.setExchangedDocumentContext (aEDCT); + } + + { + final ExchangedDocumentType aEDT = new ExchangedDocumentType (); + ifNotEmpty (aEDT::setID, aUBLCreditNote.getIDValue ()); + ifNotEmpty (aEDT::setTypeCode, aUBLCreditNote.getCreditNoteTypeCodeValue ()); + + // IssueDate + if (aUBLCreditNote.getIssueDate () != null) + aEDT.setIssueDateTime (convertDate (aUBLCreditNote.getIssueDate ().getValueLocal ())); + + // Add add IncludedNote + for (final var aNote : aUBLCreditNote.getNote ()) + aEDT.addIncludedNote (convertNote (aNote)); + + aCIIInvoice.setExchangedDocument (aEDT); + } + + { + final SupplyChainTradeTransactionType aSCTT = new SupplyChainTradeTransactionType (); + + // IncludedSupplyChainTradeLineItem + for (final var aLine : aUBLCreditNote.getCreditNoteLine ()) + aSCTT.addIncludedSupplyChainTradeLineItem (_convertCreditNoteLine (aLine)); + + // ApplicableHeaderTradeAgreement + { + final HeaderTradeAgreementType aHTAT = new HeaderTradeAgreementType (); + + // SellerTradeParty + final SupplierPartyType aSupplierParty = aUBLCreditNote.getAccountingSupplierParty (); + if (aSupplierParty != null) + aHTAT.setSellerTradeParty (convertParty (aSupplierParty.getParty ())); + + // BuyerTradeParty + final CustomerPartyType aCustomerParty = aUBLCreditNote.getAccountingCustomerParty (); + if (aCustomerParty != null) + aHTAT.setBuyerTradeParty (convertParty (aCustomerParty.getParty ())); + + // BuyerOrderReferencedDocument + if (aUBLCreditNote.getOrderReference () != null && aUBLCreditNote.getOrderReference ().getID () != null) + { + final ReferencedDocumentType aRDT = new ReferencedDocumentType (); + aRDT.setIssuerAssignedID (aUBLCreditNote.getOrderReference ().getIDValue ()); + aHTAT.setBuyerOrderReferencedDocument (aRDT); + } + + // ContractReferencedDocument + if (aUBLCreditNote.hasContractDocumentReferenceEntries ()) + { + final ReferencedDocumentType aCRDT = new ReferencedDocumentType (); + aCRDT.setIssuerAssignedID (aUBLCreditNote.getContractDocumentReferenceAtIndex (0).getIDValue ()); + aHTAT.setContractReferencedDocument (aCRDT); + } + + // AdditionalReferencedDocument + for (final var aUBLDocDesc : aUBLCreditNote.getAdditionalDocumentReference ()) + aHTAT.addAdditionalReferencedDocument (convertAdditionalReferencedDocument (aUBLDocDesc)); + aSCTT.setApplicableHeaderTradeAgreement (aHTAT); + } + + // ApplicableHeaderTradeDelivery + aSCTT.setApplicableHeaderTradeDelivery (createApplicableHeaderTradeDelivery (aUBLCreditNote.hasDeliveryEntries () ? aUBLCreditNote.getDeliveryAtIndex (0) + : null)); + + // ApplicableHeaderTradeSettlement + aSCTT.setApplicableHeaderTradeSettlement (_createApplicableHeaderTradeSettlement (aUBLCreditNote)); + + aCIIInvoice.setSupplyChainTradeTransaction (aSCTT); + } + + return aCIIInvoice; + } +} diff --git a/en16931-ubl2cii/src/main/java/com/helger/en16931/ubl2cii/UBL21InvoiceToCII16BConverter.java b/en16931-ubl2cii/src/main/java/com/helger/en16931/ubl2cii/UBL21InvoiceToCII16BConverter.java index 02b845e..00bcb27 100644 --- a/en16931-ubl2cii/src/main/java/com/helger/en16931/ubl2cii/UBL21InvoiceToCII16BConverter.java +++ b/en16931-ubl2cii/src/main/java/com/helger/en16931/ubl2cii/UBL21InvoiceToCII16BConverter.java @@ -17,9 +17,6 @@ */ package com.helger.en16931.ubl2cii; -import java.util.ArrayList; -import java.util.List; - import javax.annotation.Nonnull; import javax.annotation.Nullable; @@ -27,16 +24,11 @@ import com.helger.commons.error.list.ErrorList; import oasis.names.specification.ubl.schema.xsd.commonaggregatecomponents_21.AllowanceChargeType; -import oasis.names.specification.ubl.schema.xsd.commonaggregatecomponents_21.AttachmentType; import oasis.names.specification.ubl.schema.xsd.commonaggregatecomponents_21.CommodityClassificationType; import oasis.names.specification.ubl.schema.xsd.commonaggregatecomponents_21.CustomerPartyType; -import oasis.names.specification.ubl.schema.xsd.commonaggregatecomponents_21.DeliveryType; -import oasis.names.specification.ubl.schema.xsd.commonaggregatecomponents_21.DocumentReferenceType; import oasis.names.specification.ubl.schema.xsd.commonaggregatecomponents_21.InvoiceLineType; import oasis.names.specification.ubl.schema.xsd.commonaggregatecomponents_21.ItemPropertyType; import oasis.names.specification.ubl.schema.xsd.commonaggregatecomponents_21.ItemType; -import oasis.names.specification.ubl.schema.xsd.commonaggregatecomponents_21.LocationType; -import oasis.names.specification.ubl.schema.xsd.commonaggregatecomponents_21.MonetaryTotalType; import oasis.names.specification.ubl.schema.xsd.commonaggregatecomponents_21.PaymentMeansType; import oasis.names.specification.ubl.schema.xsd.commonaggregatecomponents_21.PaymentTermsType; import oasis.names.specification.ubl.schema.xsd.commonaggregatecomponents_21.PeriodType; @@ -47,13 +39,9 @@ import oasis.names.specification.ubl.schema.xsd.commonaggregatecomponents_21.TaxTotalType; import oasis.names.specification.ubl.schema.xsd.invoice_21.InvoiceType; import un.unece.uncefact.data.standard.crossindustryinvoice._100.CrossIndustryInvoiceType; -import un.unece.uncefact.data.standard.qualifieddatatype._100.FormattedDateTimeType; import un.unece.uncefact.data.standard.reusableaggregatebusinessinformationentity._100.*; -import un.unece.uncefact.data.standard.unqualifieddatatype._100.BinaryObjectType; import un.unece.uncefact.data.standard.unqualifieddatatype._100.CodeType; -import un.unece.uncefact.data.standard.unqualifieddatatype._100.IndicatorType; import un.unece.uncefact.data.standard.unqualifieddatatype._100.QuantityType; -import un.unece.uncefact.data.standard.unqualifieddatatype._100.TextType; /** * UBL 2.1 to CII D16B converter. @@ -67,334 +55,109 @@ private UBL21InvoiceToCII16BConverter () {} @Nonnull - private static List _convertInvoiceLines (@Nonnull final List aLstIL) + private static SupplyChainTradeLineItemType _convertInvoiceLine (@Nonnull final InvoiceLineType aUBLLine) { - final List ret = new ArrayList <> (); - for (final InvoiceLineType aILT : aLstIL) - { - final SupplyChainTradeLineItemType aISCTLI = new SupplyChainTradeLineItemType (); - final DocumentLineDocumentType aDLDT = new DocumentLineDocumentType (); - - aDLDT.setLineID (aILT.getIDValue ()); - - for (final var aNote : aILT.getNote ()) - aDLDT.addIncludedNote (convertNote (aNote)); + final SupplyChainTradeLineItemType ret = new SupplyChainTradeLineItemType (); + final DocumentLineDocumentType aDLDT = new DocumentLineDocumentType (); - aISCTLI.setAssociatedDocumentLineDocument (aDLDT); + aDLDT.setLineID (aUBLLine.getIDValue ()); - // SpecifiedTradeProduct - final TradeProductType aTPT = new TradeProductType (); - final ItemType aIT = aILT.getItem (); - if (aIT.getStandardItemIdentification () != null) - { - aTPT.setGlobalID (convertID (aIT.getStandardItemIdentification ().getID ())); - } + for (final var aUBLNote : aUBLLine.getNote ()) + aDLDT.addIncludedNote (convertNote (aUBLNote)); - if (aIT.getSellersItemIdentification () != null) - aTPT.setSellerAssignedID (aIT.getSellersItemIdentification ().getIDValue ()); + ret.setAssociatedDocumentLineDocument (aDLDT); - aTPT.addName (convertText (aIT.getNameValue ())); + // SpecifiedTradeProduct + final TradeProductType aTPT = new TradeProductType (); + final ItemType aUBLItem = aUBLLine.getItem (); + if (aUBLItem.getStandardItemIdentification () != null) + aTPT.setGlobalID (convertID (aUBLItem.getStandardItemIdentification ().getID ())); - if (aIT.hasDescriptionEntries ()) - { - aTPT.setDescription (aIT.getDescriptionAtIndex (0).getValue ()); - } + if (aUBLItem.getSellersItemIdentification () != null) + aTPT.setSellerAssignedID (aUBLItem.getSellersItemIdentification ().getIDValue ()); - // ApplicableProductCharacteristic - for (final ItemPropertyType aIPT : aILT.getItem ().getAdditionalItemProperty ()) - { - final ProductCharacteristicType aPCT = new ProductCharacteristicType (); - aPCT.addDescription (convertText (aIPT.getNameValue ())); - aPCT.addValue (convertText (aIPT.getValueValue ())); - aTPT.addApplicableProductCharacteristic (aPCT); - } - - // DesignatedProductClassification - for (final CommodityClassificationType aCCT : aILT.getItem ().getCommodityClassification ()) - { - final ProductClassificationType aPCT = new ProductClassificationType (); - final CodeType aCT = new CodeType (); - aCT.setListID (aCCT.getItemClassificationCode ().getListID ()); - aCT.setValue (aCCT.getItemClassificationCode ().getValue ()); - aPCT.setClassCode (aCT); - aTPT.addDesignatedProductClassification (aPCT); - } - aISCTLI.setSpecifiedTradeProduct (aTPT); - - // SpecifiedLineTradeAgreement - final LineTradeAgreementType aLTAT = new LineTradeAgreementType (); - // BuyerOrderReferencedDocument - final ReferencedDocumentType aRDT = new ReferencedDocumentType (); - if (aILT.hasOrderLineReferenceEntries ()) - { - aRDT.setLineID (aILT.getOrderLineReference ().get (0).getLineIDValue ()); - } - - // NetPriceProductTradePrice - final TradePriceType aLTPT = new TradePriceType (); - if (aILT.getPrice () != null && aILT.getPrice ().getPriceAmount () != null) - { - aLTPT.addChargeAmount (convertAmount (aILT.getPrice ().getPriceAmount ())); - } - - aLTAT.setBuyerOrderReferencedDocument (aRDT); - aLTAT.setNetPriceProductTradePrice (aLTPT); - aISCTLI.setSpecifiedLineTradeAgreement (aLTAT); - - // SpecifiedLineTradeDelivery - final LineTradeDeliveryType aLTDT = new LineTradeDeliveryType (); - final QuantityType aQT = new QuantityType (); - aQT.setUnitCode (aILT.getInvoicedQuantity ().getUnitCode ()); - aQT.setValue (aILT.getInvoicedQuantity ().getValue ()); - aLTDT.setBilledQuantity (aQT); - aISCTLI.setSpecifiedLineTradeDelivery (aLTDT); - - // SpecifiedLineTradeSettlement - final LineTradeSettlementType aLTST = new LineTradeSettlementType (); - { - for (final TaxCategoryType aTaxCategory : aILT.getItem ().getClassifiedTaxCategory ()) - { - final TaxSchemeType aTaxScheme = aTaxCategory.getTaxScheme (); - - final TradeTaxType aTradeTax = new TradeTaxType (); - if (aTaxScheme != null) - ifNotEmpty (aTradeTax::setTypeCode, aTaxCategory.getTaxScheme ().getIDValue ()); - ifNotEmpty (aTradeTax::setCategoryCode, aTaxCategory.getIDValue ()); - ifNotNull (aTradeTax::setRateApplicablePercent, aTaxCategory.getPercentValue ()); - aLTST.addApplicableTradeTax (aTradeTax); - } - } - final TradeSettlementLineMonetarySummationType aTSLMST = new TradeSettlementLineMonetarySummationType (); - if (aILT.getLineExtensionAmount () != null) - aTSLMST.addLineTotalAmount (convertAmount (aILT.getLineExtensionAmount ())); - - if (aILT.getAccountingCostValue () != null) - { - final TradeAccountingAccountType aTAATL = new TradeAccountingAccountType (); - aTAATL.setID (aILT.getAccountingCostValue ()); - aLTST.addReceivableSpecifiedTradeAccountingAccount (aTAATL); - } + aTPT.addName (convertText (aUBLItem.getNameValue ())); - aLTST.setSpecifiedTradeSettlementLineMonetarySummation (aTSLMST); - aISCTLI.setSpecifiedLineTradeSettlement (aLTST); + if (aUBLItem.hasDescriptionEntries ()) + aTPT.setDescription (aUBLItem.getDescriptionAtIndex (0).getValue ()); - ret.add (aISCTLI); - } - return ret; - } - - @Nonnull - private static List _convertAdditionalReferencedDocument (@Nonnull final InvoiceType aUBLInvoice) - { - final List ret = new ArrayList <> (); - for (final DocumentReferenceType aDocDesc : aUBLInvoice.getAdditionalDocumentReference ()) + // ApplicableProductCharacteristic + for (final ItemPropertyType aUBLAddItemProp : aUBLLine.getItem ().getAdditionalItemProperty ()) { - final ReferencedDocumentType aURDT = new ReferencedDocumentType (); - - if (aDocDesc.getID () != null) - aURDT.setIssuerAssignedID (aDocDesc.getIDValue ()); - - // Add DocumentTypeCode where possible - if (aDocDesc.getDocumentTypeCode () != null && isValidDocumentReferenceTypeCode (aDocDesc.getDocumentTypeCodeValue ())) - aURDT.setTypeCode (aDocDesc.getDocumentTypeCodeValue ()); - else - aURDT.setTypeCode ("916"); - - if (aDocDesc.getIssueDate () != null) - { - final FormattedDateTimeType aFIDT = new FormattedDateTimeType (); - aFIDT.setDateTimeString (createFormattedDateValue (aDocDesc.getIssueDateValueLocal ())); - aURDT.setFormattedIssueDateTime (aFIDT); - } - - for (final var aDesc : aDocDesc.getDocumentDescription ()) - { - final TextType aText = new TextType (); - aText.setValue (aDesc.getValue ()); - aText.setLanguageID (aDesc.getLanguageID ()); - aText.setLanguageLocaleID (aDesc.getLanguageLocaleID ()); - aURDT.addName (aText); - } - - final AttachmentType aAttachment = aDocDesc.getAttachment (); - if (aAttachment != null) - { - // External Reference and Embedded Document Binary Object should be - // mutually exclusive - if (aAttachment.getExternalReference () != null && aAttachment.getExternalReference ().getURI () != null) - { - aURDT.setURIID (aAttachment.getExternalReference ().getURI ().getValue ()); - } - - if (aAttachment.getEmbeddedDocumentBinaryObject () != null) - { - final BinaryObjectType aBOT = new BinaryObjectType (); - aBOT.setMimeCode (aAttachment.getEmbeddedDocumentBinaryObject ().getMimeCode ()); - aBOT.setValue (aAttachment.getEmbeddedDocumentBinaryObject ().getValue ()); - aURDT.addAttachmentBinaryObject (aBOT); - } - } - ret.add (aURDT); + final ProductCharacteristicType aPCT = new ProductCharacteristicType (); + ifNotNull (aPCT::addDescription, convertText (aUBLAddItemProp.getNameValue ())); + ifNotNull (aPCT::addValue, convertText (aUBLAddItemProp.getValueValue ())); + aTPT.addApplicableProductCharacteristic (aPCT); } - return ret; - } - @Nullable - private static HeaderTradeDeliveryType _createApplicableHeaderTradeDelivery (@Nullable final DeliveryType aDelivery) - { - // Object is mandatory - final HeaderTradeDeliveryType ret = new HeaderTradeDeliveryType (); - - if (aDelivery != null) + // DesignatedProductClassification + for (final CommodityClassificationType aUBLCC : aUBLLine.getItem ().getCommodityClassification ()) { - final LocationType aDL = aDelivery.getDeliveryLocation (); - if (aDL != null) - { - final TradePartyType aTPTHT = new TradePartyType (); - ifNotNull (aTPTHT::addID, convertID (aDL.getID ())); - - aTPTHT.setPostalTradeAddress (convertAddress (aDL.getAddress ())); - ret.setShipToTradeParty (aTPTHT); - } - - if (aDelivery.getActualDeliveryDate () != null) - { - final SupplyChainEventType aSCET = new SupplyChainEventType (); - aSCET.setOccurrenceDateTime (convertDate (aDelivery.getActualDeliveryDate ().getValueLocal ())); - ret.setActualDeliverySupplyChainEvent (aSCET); - } + final ProductClassificationType aPCT = new ProductClassificationType (); + final CodeType aCT = new CodeType (); + ifNotEmpty (aCT::setListID, aUBLCC.getItemClassificationCode ().getListID ()); + ifNotEmpty (aCT::setValue, aUBLCC.getItemClassificationCode ().getValue ()); + aPCT.setClassCode (aCT); + aTPT.addDesignatedProductClassification (aPCT); } - return ret; - } - - @Nonnull - private static List _convertApplicableTradeTax (@Nonnull final InvoiceType aUBLInvoice) - { - final List ret = new ArrayList <> (); - for (final TaxTotalType aTaxTotal : aUBLInvoice.getTaxTotal ()) - for (final TaxSubtotalType aTaxSubtotal : aTaxTotal.getTaxSubtotal ()) - { - final TaxCategoryType aTaxCategory = aTaxSubtotal.getTaxCategory (); - final TaxSchemeType aTaxScheme = aTaxCategory.getTaxScheme (); - - final TradeTaxType aTradeTax = new TradeTaxType (); - - if (aTaxScheme != null) - ifNotEmpty (aTradeTax::setTypeCode, aTaxScheme.getIDValue ()); - ifNotEmpty (aTradeTax::setCategoryCode, aTaxCategory.getIDValue ()); - - ifNotNull (aTradeTax::addCalculatedAmount, convertAmount (aTaxSubtotal.getTaxAmount ())); - - if (aTaxSubtotal.getTaxCategory () != null) - ifNotEmpty (aTradeTax::setCategoryCode, aTaxSubtotal.getTaxCategory ().getIDValue ()); + ret.setSpecifiedTradeProduct (aTPT); - ifNotNull (aTradeTax::addBasisAmount, convertAmount (aTaxSubtotal.getTaxableAmount ())); - ifNotNull (aTradeTax::setRateApplicablePercent, aTaxCategory.getPercentValue ()); - - if (aTaxCategory.hasTaxExemptionReasonEntries ()) - ifNotEmpty (aTradeTax::setExemptionReason, aTaxCategory.getTaxExemptionReasonAtIndex (0).getValue ()); - - ifNotEmpty (aTradeTax::setExemptionReasonCode, aTaxCategory.getTaxExemptionReasonCodeValue ()); - ret.add (aTradeTax); - } - return ret; - } - - @Nonnull - private static List _convertSpecifiedTradeAllowanceCharge (@Nonnull final InvoiceType aUBLInvoice) - { - final List ret = new ArrayList <> (); - for (final AllowanceChargeType aItem : aUBLInvoice.getAllowanceCharge ()) + // BuyerOrderReferencedDocument + final ReferencedDocumentType aRDT = new ReferencedDocumentType (); + if (aUBLLine.hasOrderLineReferenceEntries ()) { - final TradeAllowanceChargeType aTDCT = new TradeAllowanceChargeType (); - - final IndicatorType aITDC = new IndicatorType (); - aITDC.setIndicator (Boolean.valueOf (aItem.getChargeIndicator ().isValue ())); - aTDCT.setChargeIndicator (aITDC); - - aTDCT.addActualAmount (convertAmount (aItem.getAmount ())); - - if (aItem.getAllowanceChargeReasonCode () != null) - aTDCT.setReasonCode (aItem.getAllowanceChargeReasonCodeValue ()); - - if (aItem.hasAllowanceChargeReasonEntries ()) - aTDCT.setReason (aItem.getAllowanceChargeReason ().get (0).getValue ()); - - if (aItem.getMultiplierFactorNumeric () != null) - aTDCT.setCalculationPercent (aItem.getMultiplierFactorNumericValue ()); - - if (aItem.getBaseAmount () != null) - aTDCT.setBasisAmount (aItem.getBaseAmountValue ()); - - if (aItem.hasTaxCategoryEntries ()) - { - final TaxCategoryType aTaxCategory = aItem.getTaxCategoryAtIndex (0); - final TaxSchemeType aTaxSchene = aTaxCategory.getTaxScheme (); - - final TradeTaxType aTradeTax = new TradeTaxType (); - if (aTaxSchene != null) - ifNotEmpty (aTradeTax::setTypeCode, aTaxSchene.getIDValue ()); - ifNotEmpty (aTradeTax::setCategoryCode, aTaxCategory.getIDValue ()); - ifNotNull (aTradeTax::setRateApplicablePercent, aTaxCategory.getPercentValue ()); - - aTDCT.addCategoryTradeTax (aTradeTax); - } - - ret.add (aTDCT); + aRDT.setLineID (aUBLLine.getOrderLineReferenceAtIndex (0).getLineIDValue ()); } - return ret; - } - @Nonnull - private static List _convertSpecifiedTradePaymentTerms (@Nonnull final InvoiceType aUBLInvoice) - { - final List ret = new ArrayList <> (); - for (final PaymentTermsType aPTT : aUBLInvoice.getPaymentTerms ()) + // NetPriceProductTradePrice + final TradePriceType aLTPT = new TradePriceType (); + if (aUBLLine.getPrice () != null && aUBLLine.getPrice ().getPriceAmount () != null) { - final TradePaymentTermsType aTPTT = new TradePaymentTermsType (); - - for (final var aNote : aPTT.getNote ()) - aTPTT.addDescription (convertText (aNote.getValue ())); - - if (aUBLInvoice.hasPaymentMeansEntries ()) - { - final PaymentMeansType aPM = aUBLInvoice.getPaymentMeans ().get (0); - if (aPM.getPaymentDueDate () != null) - aTPTT.setDueDateDateTime (convertDate (aPM.getPaymentDueDate ().getValueLocal ())); - } - ret.add (aTPTT); + aLTPT.addChargeAmount (convertAmount (aUBLLine.getPrice ().getPriceAmount ())); } - return ret; - } - @Nonnull - private static TradeSettlementHeaderMonetarySummationType _createSpecifiedTradeSettlementHeaderMonetarySummation (@Nonnull final InvoiceType aUBLInvoice) - { - final TradeSettlementHeaderMonetarySummationType aTSHMST = new TradeSettlementHeaderMonetarySummationType (); - final MonetaryTotalType aUBLLMT = aUBLInvoice.getLegalMonetaryTotal (); - if (aUBLLMT != null) + // SpecifiedLineTradeAgreement + final LineTradeAgreementType aLTAT = new LineTradeAgreementType (); + aLTAT.setBuyerOrderReferencedDocument (aRDT); + aLTAT.setNetPriceProductTradePrice (aLTPT); + ret.setSpecifiedLineTradeAgreement (aLTAT); + + // SpecifiedLineTradeDelivery + final LineTradeDeliveryType aLTDT = new LineTradeDeliveryType (); + final QuantityType aQuantity = new QuantityType (); + aQuantity.setUnitCode (aUBLLine.getInvoicedQuantity ().getUnitCode ()); + aQuantity.setValue (aUBLLine.getInvoicedQuantity ().getValue ()); + aLTDT.setBilledQuantity (aQuantity); + ret.setSpecifiedLineTradeDelivery (aLTDT); + + // SpecifiedLineTradeSettlement + final LineTradeSettlementType aSLTS = new LineTradeSettlementType (); + for (final TaxCategoryType aUBLTaxCategory : aUBLLine.getItem ().getClassifiedTaxCategory ()) { - ifNotNull (aTSHMST::addLineTotalAmount, convertAmount (aUBLLMT.getLineExtensionAmount ())); - ifNotNull (aTSHMST::addChargeTotalAmount, convertAmount (aUBLLMT.getChargeTotalAmount ())); - ifNotNull (aTSHMST::addAllowanceTotalAmount, convertAmount (aUBLLMT.getAllowanceTotalAmount ())); - ifNotNull (aTSHMST::addTaxBasisTotalAmount, convertAmount (aUBLLMT.getTaxExclusiveAmount ())); + final TaxSchemeType aUBLTaxScheme = aUBLTaxCategory.getTaxScheme (); + + final TradeTaxType aTradeTax = new TradeTaxType (); + if (aUBLTaxScheme != null) + ifNotEmpty (aTradeTax::setTypeCode, aUBLTaxCategory.getTaxScheme ().getIDValue ()); + ifNotEmpty (aTradeTax::setCategoryCode, aUBLTaxCategory.getIDValue ()); + ifNotNull (aTradeTax::setRateApplicablePercent, aUBLTaxCategory.getPercentValue ()); + aSLTS.addApplicableTradeTax (aTradeTax); } - if (aUBLInvoice.hasTaxTotalEntries ()) - { - // Currency ID is required here - ifNotNull (aTSHMST::addTaxTotalAmount, convertAmount (aUBLInvoice.getTaxTotalAtIndex (0).getTaxAmount (), true)); - } + final TradeSettlementLineMonetarySummationType aTSLMST = new TradeSettlementLineMonetarySummationType (); + ifNotNull (aTSLMST::addLineTotalAmount, convertAmount (aUBLLine.getLineExtensionAmount ())); - if (aUBLLMT != null) + if (aUBLLine.getAccountingCostValue () != null) { - ifNotNull (aTSHMST::addRoundingAmount, convertAmount (aUBLLMT.getPayableRoundingAmount ())); - ifNotNull (aTSHMST::addGrandTotalAmount, convertAmount (aUBLLMT.getTaxInclusiveAmount ())); - ifNotNull (aTSHMST::addTotalPrepaidAmount, convertAmount (aUBLLMT.getPrepaidAmount ())); - ifNotNull (aTSHMST::addDuePayableAmount, convertAmount (aUBLLMT.getPayableAmount ())); + final TradeAccountingAccountType aTAATL = new TradeAccountingAccountType (); + aTAATL.setID (aUBLLine.getAccountingCostValue ()); + aSLTS.addReceivableSpecifiedTradeAccountingAccount (aTAATL); } - return aTSHMST; + aSLTS.setSpecifiedTradeSettlementLineMonetarySummation (aTSLMST); + ret.setSpecifiedLineTradeSettlement (aSLTS); + + return ret; } @Nonnull @@ -402,48 +165,52 @@ private static HeaderTradeSettlementType _createApplicableHeaderTradeSettlement { final HeaderTradeSettlementType ret = new HeaderTradeSettlementType (); - final PaymentMeansType aPM = aUBLInvoice.hasPaymentMeansEntries () ? aUBLInvoice.getPaymentMeansAtIndex (0) : null; - - if (aPM != null && aPM.hasPaymentIDEntries ()) - ret.addPaymentReference (convertText (aPM.getPaymentIDAtIndex (0).getValue ())); + final PaymentMeansType aUBLPaymentMeans = aUBLInvoice.hasPaymentMeansEntries () ? aUBLInvoice.getPaymentMeansAtIndex (0) + : null; - ret.setInvoiceCurrencyCode (aUBLInvoice.getDocumentCurrencyCode ().getValue ()); + if (aUBLPaymentMeans != null && aUBLPaymentMeans.hasPaymentIDEntries ()) + ret.addPaymentReference (convertText (aUBLPaymentMeans.getPaymentIDAtIndex (0).getValue ())); - if (aUBLInvoice.getPayeeParty () != null) - ret.setPayeeTradeParty (convertParty (aUBLInvoice.getPayeeParty ())); + ifNotEmpty (ret::setInvoiceCurrencyCode, aUBLInvoice.getDocumentCurrencyCodeValue ()); + ifNotNull (ret::setPayeeTradeParty, convertParty (aUBLInvoice.getPayeeParty ())); - if (aPM != null) + if (aUBLPaymentMeans != null) { final TradeSettlementPaymentMeansType aTSPMT = new TradeSettlementPaymentMeansType (); - aTSPMT.setTypeCode (aPM.getPaymentMeansCodeValue ()); + ifNotEmpty (aTSPMT::setTypeCode, aUBLPaymentMeans.getPaymentMeansCodeValue ()); final CreditorFinancialAccountType aCFAT = new CreditorFinancialAccountType (); - if (aPM.getPayeeFinancialAccount () != null) - aCFAT.setIBANID (aPM.getPayeeFinancialAccount ().getIDValue ()); - + if (aUBLPaymentMeans.getPayeeFinancialAccount () != null) + ifNotEmpty (aCFAT::setIBANID, aUBLPaymentMeans.getPayeeFinancialAccount ().getIDValue ()); aTSPMT.setPayeePartyCreditorFinancialAccount (aCFAT); ret.addSpecifiedTradeSettlementPaymentMeans (aTSPMT); } - ret.setApplicableTradeTax (_convertApplicableTradeTax (aUBLInvoice)); + for (final TaxTotalType aUBLTaxTotal : aUBLInvoice.getTaxTotal ()) + for (final TaxSubtotalType aUBLTaxSubtotal : aUBLTaxTotal.getTaxSubtotal ()) + ret.addApplicableTradeTax (convertApplicableTradeTax (aUBLTaxSubtotal)); if (aUBLInvoice.hasInvoicePeriodEntries ()) { - final PeriodType aIP = aUBLInvoice.getInvoicePeriodAtIndex (0); + final PeriodType aUBLPeriod = aUBLInvoice.getInvoicePeriodAtIndex (0); final SpecifiedPeriodType aSPT = new SpecifiedPeriodType (); - if (aIP.getStartDate () != null) - aSPT.setStartDateTime (convertDate (aIP.getStartDate ().getValueLocal ())); - - if (aIP.getEndDate () != null) - aSPT.setEndDateTime (convertDate (aIP.getEndDate ().getValueLocal ())); - + if (aUBLPeriod.getStartDate () != null) + aSPT.setStartDateTime (convertDate (aUBLPeriod.getStartDate ().getValueLocal ())); + if (aUBLPeriod.getEndDate () != null) + aSPT.setEndDateTime (convertDate (aUBLPeriod.getEndDate ().getValueLocal ())); ret.setBillingSpecifiedPeriod (aSPT); } - ret.setSpecifiedTradeAllowanceCharge (_convertSpecifiedTradeAllowanceCharge (aUBLInvoice)); - ret.setSpecifiedTradePaymentTerms (_convertSpecifiedTradePaymentTerms (aUBLInvoice)); - ret.setSpecifiedTradeSettlementHeaderMonetarySummation (_createSpecifiedTradeSettlementHeaderMonetarySummation (aUBLInvoice)); + for (final AllowanceChargeType aUBLAllowanceCharge : aUBLInvoice.getAllowanceCharge ()) + ret.addSpecifiedTradeAllowanceCharge (convertSpecifiedTradeAllowanceCharge (aUBLAllowanceCharge)); + + for (final PaymentTermsType aUBLPaymentTerms : aUBLInvoice.getPaymentTerms ()) + ret.addSpecifiedTradePaymentTerms (convertSpecifiedTradePaymentTerms (aUBLPaymentTerms, aUBLPaymentMeans)); + + final TaxTotalType aUBLTaxTotal = aUBLInvoice.hasTaxTotalEntries () ? aUBLInvoice.getTaxTotalAtIndex (0) : null; + ret.setSpecifiedTradeSettlementHeaderMonetarySummation (createSpecifiedTradeSettlementHeaderMonetarySummation (aUBLInvoice.getLegalMonetaryTotal (), + aUBLTaxTotal)); if (aUBLInvoice.getAccountingCost () != null) { @@ -477,8 +244,8 @@ public static CrossIndustryInvoiceType convertToCrossIndustryInvoice (@Nonnull f { final ExchangedDocumentType aEDT = new ExchangedDocumentType (); - aEDT.setID (aUBLInvoice.getIDValue ()); - aEDT.setTypeCode (aUBLInvoice.getInvoiceTypeCodeValue ()); + ifNotEmpty (aEDT::setID, aUBLInvoice.getIDValue ()); + ifNotEmpty (aEDT::setTypeCode, aUBLInvoice.getInvoiceTypeCodeValue ()); // IssueDate if (aUBLInvoice.getIssueDate () != null) @@ -495,7 +262,8 @@ public static CrossIndustryInvoiceType convertToCrossIndustryInvoice (@Nonnull f final SupplyChainTradeTransactionType aSCTT = new SupplyChainTradeTransactionType (); // IncludedSupplyChainTradeLineItem - aSCTT.setIncludedSupplyChainTradeLineItem (_convertInvoiceLines (aUBLInvoice.getInvoiceLine ())); + for (final var aLine : aUBLInvoice.getInvoiceLine ()) + aSCTT.addIncludedSupplyChainTradeLineItem (_convertInvoiceLine (aLine)); // ApplicableHeaderTradeAgreement { @@ -515,7 +283,7 @@ public static CrossIndustryInvoiceType convertToCrossIndustryInvoice (@Nonnull f if (aUBLInvoice.getOrderReference () != null && aUBLInvoice.getOrderReference ().getID () != null) { final ReferencedDocumentType aRDT = new ReferencedDocumentType (); - aRDT.setIssuerAssignedID (aUBLInvoice.getOrderReference ().getID ().getValue ()); + aRDT.setIssuerAssignedID (aUBLInvoice.getOrderReference ().getIDValue ()); aHTAT.setBuyerOrderReferencedDocument (aRDT); } @@ -523,18 +291,19 @@ public static CrossIndustryInvoiceType convertToCrossIndustryInvoice (@Nonnull f if (aUBLInvoice.hasContractDocumentReferenceEntries ()) { final ReferencedDocumentType aCRDT = new ReferencedDocumentType (); - aCRDT.setIssuerAssignedID (aUBLInvoice.getContractDocumentReferenceAtIndex (0).getID ().getValue ()); + aCRDT.setIssuerAssignedID (aUBLInvoice.getContractDocumentReferenceAtIndex (0).getIDValue ()); aHTAT.setContractReferencedDocument (aCRDT); } // AdditionalReferencedDocument - aHTAT.setAdditionalReferencedDocument (_convertAdditionalReferencedDocument (aUBLInvoice)); + for (final var aUBLDocDesc : aUBLInvoice.getAdditionalDocumentReference ()) + aHTAT.addAdditionalReferencedDocument (convertAdditionalReferencedDocument (aUBLDocDesc)); aSCTT.setApplicableHeaderTradeAgreement (aHTAT); } // ApplicableHeaderTradeDelivery - aSCTT.setApplicableHeaderTradeDelivery (_createApplicableHeaderTradeDelivery (aUBLInvoice.hasDeliveryEntries () ? aUBLInvoice.getDeliveryAtIndex (0) - : null)); + aSCTT.setApplicableHeaderTradeDelivery (createApplicableHeaderTradeDelivery (aUBLInvoice.hasDeliveryEntries () ? aUBLInvoice.getDeliveryAtIndex (0) + : null)); // ApplicableHeaderTradeSettlement aSCTT.setApplicableHeaderTradeSettlement (_createApplicableHeaderTradeSettlement (aUBLInvoice)); diff --git a/en16931-ubl2cii/src/main/java/com/helger/en16931/ubl2cii/UBLCIIConversionHelper.java b/en16931-ubl2cii/src/main/java/com/helger/en16931/ubl2cii/UBLCIIConversionHelper.java index ddcb50d..78156a3 100644 --- a/en16931-ubl2cii/src/main/java/com/helger/en16931/ubl2cii/UBLCIIConversionHelper.java +++ b/en16931-ubl2cii/src/main/java/com/helger/en16931/ubl2cii/UBLCIIConversionHelper.java @@ -30,6 +30,7 @@ import com.helger.commons.state.ESuccess; import com.helger.ubl21.UBL21Marshaller; +import oasis.names.specification.ubl.schema.xsd.creditnote_21.CreditNoteType; import oasis.names.specification.ubl.schema.xsd.invoice_21.InvoiceType; import un.unece.uncefact.data.standard.crossindustryinvoice._100.CrossIndustryInvoiceType; @@ -54,7 +55,30 @@ public static ESuccess convertUBL21InvoicetoCIID16B (@Nonnull @WillNotClose fina return ESuccess.FAILURE; // Main conversion - final CrossIndustryInvoiceType aCrossIndustryInvoice = UBL21InvoiceToCII16BConverter.convertToCrossIndustryInvoice (aUBLInvoice, aErrorList); + final CrossIndustryInvoiceType aCrossIndustryInvoice = UBL21InvoiceToCII16BConverter.convertToCrossIndustryInvoice (aUBLInvoice, + aErrorList); + if (aCrossIndustryInvoice == null) + return ESuccess.FAILURE; + + // Write CII D16B XML + return new CIID16BCrossIndustryInvoiceTypeMarshaller ().setFormattedOutput (true) + .setCollectErrors (aErrorList) + .write (aCrossIndustryInvoice, aOS); + } + + @Nonnull + public static ESuccess convertUBL21CreditNotetoCIID16B (@Nonnull @WillNotClose final InputStream aIS, + @Nonnull @WillClose final OutputStream aOS, + @Nonnull final ErrorList aErrorList) + { + // Read UBL 2.1 + final CreditNoteType aUBLCreditNote = UBL21Marshaller.creditNote ().setCollectErrors (aErrorList).read (aIS); + if (aUBLCreditNote == null) + return ESuccess.FAILURE; + + // Main conversion + final CrossIndustryInvoiceType aCrossIndustryInvoice = UBL21CreditNoteToCII16BConverter.convertToCrossIndustryInvoice (aUBLCreditNote, + aErrorList); if (aCrossIndustryInvoice == null) return ESuccess.FAILURE; diff --git a/en16931-ubl2cii/src/test/java/com/helger/en16931/ubl2cii/MockSettings.java b/en16931-ubl2cii/src/test/java/com/helger/en16931/ubl2cii/MockSettings.java index 94f5ca8..2198adb 100644 --- a/en16931-ubl2cii/src/test/java/com/helger/en16931/ubl2cii/MockSettings.java +++ b/en16931-ubl2cii/src/test/java/com/helger/en16931/ubl2cii/MockSettings.java @@ -35,6 +35,7 @@ final class MockSettings { static final DVRCoordinate VID_CII_2017 = EN16931Validation.VID_CII_1313.getWithVersionLatestRelease (); static final DVRCoordinate VID_UBL_INV_2017 = EN16931Validation.VID_UBL_INVOICE_1313.getWithVersionLatestRelease (); + static final DVRCoordinate VID_UBL_CN_2017 = EN16931Validation.VID_UBL_CREDIT_NOTE_1313.getWithVersionLatestRelease (); static final ValidationExecutorSetRegistry VES_REGISTRY = new ValidationExecutorSetRegistry <> (); static @@ -53,4 +54,16 @@ public static ICommonsList getAllTestFilesUBL21Invoice () ret.add (f); return ret; } + + @Nonnull + @Nonempty + @ReturnsMutableCopy + public static ICommonsList getAllTestFilesUBL21CreditNote () + { + final ICommonsList ret = new CommonsArrayList <> (); + for (final File f : new FileSystemRecursiveIterator (new File ("src/test/resources/external/ubl21/cn"))) + if (f.isFile () && f.getName ().endsWith (".xml")) + ret.add (f); + return ret; + } } diff --git a/en16931-ubl2cii/src/test/java/com/helger/en16931/ubl2cii/TestIfAllUBLFilesAreEN16931CompliantFuncTest.java b/en16931-ubl2cii/src/test/java/com/helger/en16931/ubl2cii/TestIfAllUBLFilesAreEN16931CompliantFuncTest.java index 8ffc728..5ac7b30 100644 --- a/en16931-ubl2cii/src/test/java/com/helger/en16931/ubl2cii/TestIfAllUBLFilesAreEN16931CompliantFuncTest.java +++ b/en16931-ubl2cii/src/test/java/com/helger/en16931/ubl2cii/TestIfAllUBLFilesAreEN16931CompliantFuncTest.java @@ -46,7 +46,7 @@ public final class TestIfAllUBLFilesAreEN16931CompliantFuncTest @Test @Ignore ("This test only needs to run if new test files are added") - public void testConvertAndValidateAll () + public void testIfAllUBLInvoicesAreENCompliant () { for (final File aFile : MockSettings.getAllTestFilesUBL21Invoice ()) { @@ -62,7 +62,35 @@ public void testConvertAndValidateAll () { if (!aResult.getErrorList ().isEmpty ()) LOGGER.error (StringHelper.imploder () - .source (aResult.getErrorList (), x -> x.getErrorFieldName () + " - " + x.getErrorText (Locale.ROOT)) + .source (aResult.getErrorList (), + x -> x.getErrorFieldName () + " - " + x.getErrorText (Locale.ROOT)) + .separator ('\n') + .build ()); + assertTrue ("Errors: " + aResult.getErrorList ().toString (), aResult.getErrorList ().isEmpty ()); + } + } + } + + @Test + @Ignore ("This test only needs to run if new test files are added") + public void testIfAllUBLCreditNotesAreENCompliant () + { + for (final File aFile : MockSettings.getAllTestFilesUBL21CreditNote ()) + { + LOGGER.info ("Testing " + aFile.toString () + " UBL CreditNote"); + + // Validate against EN16931 validation rules + final ValidationResultList aResultList = ValidationExecutionManager.executeValidation (IValidityDeterminator.createDefault (), + MockSettings.VES_REGISTRY.getOfID (MockSettings.VID_UBL_CN_2017), + ValidationSourceXML.create (new FileSystemResource (aFile))); + + // Check that no errors (but maybe warnings) are contained + for (final ValidationResult aResult : aResultList) + { + if (!aResult.getErrorList ().isEmpty ()) + LOGGER.error (StringHelper.imploder () + .source (aResult.getErrorList (), + x -> x.getErrorFieldName () + " - " + x.getErrorText (Locale.ROOT)) .separator ('\n') .build ()); assertTrue ("Errors: " + aResult.getErrorList ().toString (), aResult.getErrorList ().isEmpty ()); diff --git a/en16931-ubl2cii/src/test/java/com/helger/en16931/ubl2cii/UBL21CreditNoteToCII16BConverterTest.java b/en16931-ubl2cii/src/test/java/com/helger/en16931/ubl2cii/UBL21CreditNoteToCII16BConverterTest.java new file mode 100644 index 0000000..a8be3ae --- /dev/null +++ b/en16931-ubl2cii/src/test/java/com/helger/en16931/ubl2cii/UBL21CreditNoteToCII16BConverterTest.java @@ -0,0 +1,115 @@ +/* + * Copyright (C) 2024-2025 Philip Helger + * http://www.helger.com + * philip[at]helger[dot]com + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.helger.en16931.ubl2cii; + +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.io.File; +import java.util.Locale; + +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.helger.cii.d16b.CIID16BCrossIndustryInvoiceTypeMarshaller; +import com.helger.commons.error.list.ErrorList; +import com.helger.commons.io.file.FilenameHelper; +import com.helger.commons.io.resource.FileSystemResource; +import com.helger.commons.state.ESuccess; +import com.helger.commons.string.StringHelper; +import com.helger.phive.api.execute.ValidationExecutionManager; +import com.helger.phive.api.result.ValidationResult; +import com.helger.phive.api.result.ValidationResultList; +import com.helger.phive.api.validity.IValidityDeterminator; +import com.helger.phive.xml.source.ValidationSourceXML; +import com.helger.ubl21.UBL21Marshaller; + +import oasis.names.specification.ubl.schema.xsd.creditnote_21.CreditNoteType; +import un.unece.uncefact.data.standard.crossindustryinvoice._100.CrossIndustryInvoiceType; + +/** + * Test class for class {@link UBL21CreditNoteToCII16BConverter}. + * + * @author Philip Helger + */ +public final class UBL21CreditNoteToCII16BConverterTest +{ + private static final Logger LOGGER = LoggerFactory.getLogger (UBL21CreditNoteToCII16BConverterTest.class); + + @Test + public void testConvertAndValidateAllInvoices () + { + for (final File aFile : MockSettings.getAllTestFilesUBL21CreditNote ()) + { + LOGGER.info ("Converting " + aFile.toString () + " to CII D16B"); + + // Read as UBL + final ErrorList aErrorList = new ErrorList (); + final CreditNoteType aUBLCreditNote = UBL21Marshaller.creditNote ().setCollectErrors (aErrorList).read (aFile); + assertTrue ("Errors: " + aErrorList.toString (), aErrorList.containsNoError ()); + assertNotNull (aUBLCreditNote); + + // Main conversion + final CrossIndustryInvoiceType aCrossIndustryInvoice = UBL21CreditNoteToCII16BConverter.convertToCrossIndustryInvoice (aUBLCreditNote, + aErrorList); + assertTrue ("Errors: " + aErrorList.toString (), aErrorList.containsNoError ()); + assertNotNull (aCrossIndustryInvoice); + + // Save converted file + final File aDestFile = new File ("generated/cii/cn-" + + FilenameHelper.getBaseName (aFile.getName ()) + + "-cii.xml"); + final ESuccess eSuccess = new CIID16BCrossIndustryInvoiceTypeMarshaller ().setFormattedOutput (true) + .setCollectErrors (aErrorList) + .write (aCrossIndustryInvoice, + aDestFile); + if (aErrorList.containsAtLeastOneError ()) + LOGGER.error (new CIID16BCrossIndustryInvoiceTypeMarshaller ().setFormattedOutput (true) + .setUseSchema (false) + .setCollectErrors (aErrorList) + .getAsString (aCrossIndustryInvoice)); + assertTrue ("Errors: " + aErrorList.toString (), aErrorList.containsNoError ()); + assertTrue (eSuccess.isSuccess ()); + + // Validate against EN16931 validation rules + final ValidationResultList aResultList = ValidationExecutionManager.executeValidation (IValidityDeterminator.createDefault (), + MockSettings.VES_REGISTRY.getOfID (MockSettings.VID_CII_2017), + ValidationSourceXML.create (new FileSystemResource (aDestFile))); + + // Check that no errors (but maybe warnings) are contained + for (final ValidationResult aResult : aResultList) + { + if (aResult.getErrorList ().isNotEmpty ()) + { + // Log Invoice + LOGGER.error (new CIID16BCrossIndustryInvoiceTypeMarshaller ().setFormattedOutput (true) + .getAsString (aCrossIndustryInvoice)); + + // Log errors + LOGGER.error (StringHelper.imploder () + .source (aResult.getErrorList (), + x -> x.getErrorFieldName () + " - " + x.getErrorText (Locale.ROOT)) + .separator ('\n') + .build ()); + } + assertTrue ("Errors: " + aResult.getErrorList ().toString (), aResult.getErrorList ().isEmpty ()); + } + } + } +} diff --git a/en16931-ubl2cii/src/test/java/com/helger/en16931/ubl2cii/UBL21InvoiceToCII16BConverterTest.java b/en16931-ubl2cii/src/test/java/com/helger/en16931/ubl2cii/UBL21InvoiceToCII16BConverterTest.java index 19d88ac..d5f5f31 100644 --- a/en16931-ubl2cii/src/test/java/com/helger/en16931/ubl2cii/UBL21InvoiceToCII16BConverterTest.java +++ b/en16931-ubl2cii/src/test/java/com/helger/en16931/ubl2cii/UBL21InvoiceToCII16BConverterTest.java @@ -53,7 +53,7 @@ public final class UBL21InvoiceToCII16BConverterTest private static final Logger LOGGER = LoggerFactory.getLogger (UBL21InvoiceToCII16BConverterTest.class); @Test - public void testConvertAndValidateAll () + public void testConvertAndValidateAllInvoices () { for (final File aFile : MockSettings.getAllTestFilesUBL21Invoice ()) { @@ -66,15 +66,19 @@ public void testConvertAndValidateAll () assertNotNull (aUBLInvoice); // Main conversion - final CrossIndustryInvoiceType aCrossIndustryInvoice = UBL21InvoiceToCII16BConverter.convertToCrossIndustryInvoice (aUBLInvoice, aErrorList); + final CrossIndustryInvoiceType aCrossIndustryInvoice = UBL21InvoiceToCII16BConverter.convertToCrossIndustryInvoice (aUBLInvoice, + aErrorList); assertTrue ("Errors: " + aErrorList.toString (), aErrorList.containsNoError ()); assertNotNull (aCrossIndustryInvoice); // Save converted file - final File aDestFile = new File ("generated/cii/" + FilenameHelper.getBaseName (aFile.getName ()) + "-cii.xml"); + final File aDestFile = new File ("generated/cii/inv-" + + FilenameHelper.getBaseName (aFile.getName ()) + + "-cii.xml"); final ESuccess eSuccess = new CIID16BCrossIndustryInvoiceTypeMarshaller ().setFormattedOutput (true) .setCollectErrors (aErrorList) - .write (aCrossIndustryInvoice, aDestFile); + .write (aCrossIndustryInvoice, + aDestFile); if (aErrorList.containsAtLeastOneError ()) LOGGER.error (new CIID16BCrossIndustryInvoiceTypeMarshaller ().setFormattedOutput (true) .setUseSchema (false) @@ -83,30 +87,28 @@ public void testConvertAndValidateAll () assertTrue ("Errors: " + aErrorList.toString (), aErrorList.containsNoError ()); assertTrue (eSuccess.isSuccess ()); - // TODO fix validation errors - if (true) - { - // Validate against EN16931 validation rules - final ValidationResultList aResultList = ValidationExecutionManager.executeValidation (IValidityDeterminator.createDefault (), - MockSettings.VES_REGISTRY.getOfID (MockSettings.VID_CII_2017), - ValidationSourceXML.create (new FileSystemResource (aDestFile))); + // Validate against EN16931 validation rules + final ValidationResultList aResultList = ValidationExecutionManager.executeValidation (IValidityDeterminator.createDefault (), + MockSettings.VES_REGISTRY.getOfID (MockSettings.VID_CII_2017), + ValidationSourceXML.create (new FileSystemResource (aDestFile))); - // Check that no errors (but maybe warnings) are contained - for (final ValidationResult aResult : aResultList) + // Check that no errors (but maybe warnings) are contained + for (final ValidationResult aResult : aResultList) + { + if (aResult.getErrorList ().isNotEmpty ()) { - if (aResult.getErrorList ().isNotEmpty ()) - { - // Log Invoice - LOGGER.error (new CIID16BCrossIndustryInvoiceTypeMarshaller ().setFormattedOutput (true).getAsString (aCrossIndustryInvoice)); + // Log Invoice + LOGGER.error (new CIID16BCrossIndustryInvoiceTypeMarshaller ().setFormattedOutput (true) + .getAsString (aCrossIndustryInvoice)); - // Log errors - LOGGER.error (StringHelper.imploder () - .source (aResult.getErrorList (), x -> x.getErrorFieldName () + " - " + x.getErrorText (Locale.ROOT)) - .separator ('\n') - .build ()); - } - assertTrue ("Errors: " + aResult.getErrorList ().toString (), aResult.getErrorList ().isEmpty ()); + // Log errors + LOGGER.error (StringHelper.imploder () + .source (aResult.getErrorList (), + x -> x.getErrorFieldName () + " - " + x.getErrorText (Locale.ROOT)) + .separator ('\n') + .build ()); } + assertTrue ("Errors: " + aResult.getErrorList ().toString (), aResult.getErrorList ().isEmpty ()); } } }