T get(String property) {
+ return (T) extensions.get(property);
+ }
+
+ public void set(String property, Object value) {
+ extensions.put(property, value);
+ }
+
+}
diff --git a/core/src/main/java/io/github/project/openubl/xbuilder/content/models/standard/general/DocumentoVentaDetalle.java b/core/src/main/java/io/github/project/openubl/xbuilder/content/models/standard/general/DocumentoVentaDetalle.java
index 944af794..c9128614 100644
--- a/core/src/main/java/io/github/project/openubl/xbuilder/content/models/standard/general/DocumentoVentaDetalle.java
+++ b/core/src/main/java/io/github/project/openubl/xbuilder/content/models/standard/general/DocumentoVentaDetalle.java
@@ -63,6 +63,9 @@ public class DocumentoVentaDetalle {
@Schema(description = "Catalogo 07")
private String igvTipo;
+ @Schema(minimum = "0")
+ private BigDecimal tasaIcb;
+
@Schema(minimum = "0")
private BigDecimal icb;
diff --git a/core/src/main/java/io/github/project/openubl/xbuilder/content/models/standard/general/Guia.java b/core/src/main/java/io/github/project/openubl/xbuilder/content/models/standard/general/Guia.java
index c2b8c754..eac4a02b 100644
--- a/core/src/main/java/io/github/project/openubl/xbuilder/content/models/standard/general/Guia.java
+++ b/core/src/main/java/io/github/project/openubl/xbuilder/content/models/standard/general/Guia.java
@@ -21,6 +21,7 @@
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
+import org.eclipse.persistence.oxm.annotations.XmlPath;
@Data
@Builder
@@ -28,6 +29,7 @@
@AllArgsConstructor
public class Guia {
+ @XmlPath("cbc:ID/text()")
@Schema(requiredMode = Schema.RequiredMode.REQUIRED)
private String serieNumero;
@@ -38,6 +40,7 @@ public class Guia {
*
* Valores válidos: "09", "31"
*/
+ @XmlPath("cbc:DocumentTypeCode/text()")
@Schema(description = "Catalogo 01", requiredMode = Schema.RequiredMode.REQUIRED)
private String tipoDocumento;
}
diff --git a/core/src/main/java/io/github/project/openubl/xbuilder/content/models/standard/general/Invoice.java b/core/src/main/java/io/github/project/openubl/xbuilder/content/models/standard/general/Invoice.java
index 50e67b9d..a2c82a66 100644
--- a/core/src/main/java/io/github/project/openubl/xbuilder/content/models/standard/general/Invoice.java
+++ b/core/src/main/java/io/github/project/openubl/xbuilder/content/models/standard/general/Invoice.java
@@ -67,9 +67,6 @@ public class Invoice extends SalesDocument {
@Singular
private List anticipos;
- @Singular
- private List otrosDocumentosTributariosRelacionados;
-
@Singular
private List descuentos;
}
diff --git a/core/src/main/java/io/github/project/openubl/xbuilder/content/unmarshall/LocalDateAdapter.java b/core/src/main/java/io/github/project/openubl/xbuilder/content/unmarshall/LocalDateAdapter.java
new file mode 100644
index 00000000..fb08a9e1
--- /dev/null
+++ b/core/src/main/java/io/github/project/openubl/xbuilder/content/unmarshall/LocalDateAdapter.java
@@ -0,0 +1,16 @@
+package io.github.project.openubl.xbuilder.content.unmarshall;
+
+import javax.xml.bind.annotation.adapters.XmlAdapter;
+import java.time.LocalDate;
+
+public class LocalDateAdapter extends XmlAdapter {
+ @Override
+ public LocalDate unmarshal(String v) throws Exception {
+ return LocalDate.parse(v);
+ }
+
+ @Override
+ public String marshal(LocalDate v) throws Exception {
+ return v.toString();
+ }
+}
diff --git a/core/src/main/java/io/github/project/openubl/xbuilder/content/unmarshall/LocalTimeAdapter.java b/core/src/main/java/io/github/project/openubl/xbuilder/content/unmarshall/LocalTimeAdapter.java
new file mode 100644
index 00000000..a02b4df2
--- /dev/null
+++ b/core/src/main/java/io/github/project/openubl/xbuilder/content/unmarshall/LocalTimeAdapter.java
@@ -0,0 +1,16 @@
+package io.github.project.openubl.xbuilder.content.unmarshall;
+
+import javax.xml.bind.annotation.adapters.XmlAdapter;
+import java.time.LocalTime;
+
+public class LocalTimeAdapter extends XmlAdapter {
+ @Override
+ public LocalTime unmarshal(String v) throws Exception {
+ return LocalTime.parse(v);
+ }
+
+ @Override
+ public String marshal(LocalTime v) throws Exception {
+ return v.toString();
+ }
+}
diff --git a/core/src/main/java/io/github/project/openubl/xbuilder/content/unmarshall/Unmarshall.java b/core/src/main/java/io/github/project/openubl/xbuilder/content/unmarshall/Unmarshall.java
new file mode 100644
index 00000000..6ec348f7
--- /dev/null
+++ b/core/src/main/java/io/github/project/openubl/xbuilder/content/unmarshall/Unmarshall.java
@@ -0,0 +1,606 @@
+package io.github.project.openubl.xbuilder.content.unmarshall;
+
+import io.github.project.openubl.xbuilder.content.catalogs.Catalog;
+import io.github.project.openubl.xbuilder.content.catalogs.Catalog12;
+import io.github.project.openubl.xbuilder.content.catalogs.Catalog12_Anticipo;
+import io.github.project.openubl.xbuilder.content.catalogs.Catalog5;
+import io.github.project.openubl.xbuilder.content.catalogs.Catalog53_Anticipo;
+import io.github.project.openubl.xbuilder.content.catalogs.Catalog53_DescuentoGlobal;
+import io.github.project.openubl.xbuilder.content.catalogs.CatalogContadoCredito;
+import io.github.project.openubl.xbuilder.content.models.common.Cliente;
+import io.github.project.openubl.xbuilder.content.models.common.Contacto;
+import io.github.project.openubl.xbuilder.content.models.common.Direccion;
+import io.github.project.openubl.xbuilder.content.models.common.Document;
+import io.github.project.openubl.xbuilder.content.models.common.Firmante;
+import io.github.project.openubl.xbuilder.content.models.common.Proveedor;
+import io.github.project.openubl.xbuilder.content.models.standard.general.Anticipo;
+import io.github.project.openubl.xbuilder.content.models.standard.general.CreditNote;
+import io.github.project.openubl.xbuilder.content.models.standard.general.CuotaDePago;
+import io.github.project.openubl.xbuilder.content.models.standard.general.DebitNote;
+import io.github.project.openubl.xbuilder.content.models.standard.general.Descuento;
+import io.github.project.openubl.xbuilder.content.models.standard.general.Detraccion;
+import io.github.project.openubl.xbuilder.content.models.standard.general.DocumentoRelacionado;
+import io.github.project.openubl.xbuilder.content.models.standard.general.DocumentoVentaDetalle;
+import io.github.project.openubl.xbuilder.content.models.standard.general.FormaDePago;
+import io.github.project.openubl.xbuilder.content.models.standard.general.Guia;
+import io.github.project.openubl.xbuilder.content.models.standard.general.Invoice;
+import io.github.project.openubl.xbuilder.content.models.standard.general.Note;
+import io.github.project.openubl.xbuilder.content.models.standard.general.Percepcion;
+import io.github.project.openubl.xbuilder.content.models.standard.general.SalesDocument;
+import io.github.project.openubl.xbuilder.content.models.standard.general.TotalImporteInvoice;
+import io.github.project.openubl.xbuilder.content.models.standard.general.TotalImporteNote;
+import io.github.project.openubl.xbuilder.content.models.standard.general.TotalImpuestos;
+import org.eclipse.persistence.jaxb.JAXBContextFactory;
+import org.eclipse.persistence.jaxb.JAXBContextProperties;
+import org.xml.sax.InputSource;
+
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBException;
+import javax.xml.bind.Unmarshaller;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.StringReader;
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.stream.Collectors;
+
+public class Unmarshall {
+
+ public static Invoice unmarshallInvoice(String xml) throws JAXBException, IOException {
+ try (
+ InputStream documentOXM = Thread.currentThread().getContextClassLoader().getResourceAsStream("jaxb/xml-bindings/invoice.xml");
+ StringReader reader = new StringReader(xml);
+ ) {
+ XMLSalesDocument xmlSalesDocument = unmarshall(documentOXM, new InputSource(reader));
+ Invoice.InvoiceBuilder, ?> builder = Invoice.builder();
+
+ enrichSalesDocument(xmlSalesDocument, builder);
+
+ // Fecha de vencimiento
+ builder.fechaVencimiento(xmlSalesDocument.getDueDate());
+
+ // Tipo de comprobante
+ builder.tipoComprobante(xmlSalesDocument.getInvoiceTypeCode());
+
+ // Observaciones
+ if (xmlSalesDocument.getNotes() != null) {
+ xmlSalesDocument.getNotes().stream()
+ .filter(e -> e.getLanguageLocaleId() == null)
+ .findFirst().ifPresent(n -> {
+ builder.observaciones(n.getValue());
+ });
+ }
+
+ // Tipo de operacion
+ builder.tipoOperacion(xmlSalesDocument.getInvoiceTypeCode_listID());
+
+ // Forma de pago
+ builder.formaDePago(mapFormaDePago(xmlSalesDocument.getPaymentTerms()));
+
+ // Total importe
+ builder.totalImporte(mapTotalImporteInvoice(xmlSalesDocument.getMonetaryTotal()));
+
+ // Direccion entrega
+ builder.direccionEntrega(mapDireccion(xmlSalesDocument.getDeliveryLocation()));
+
+ // Detraccion
+ builder.detraccion(mapDetraccion(xmlSalesDocument.getPaymentMeans(), xmlSalesDocument.getPaymentTerms()));
+
+ // Percepcion
+ builder.percepcion(mapPercepcion(xmlSalesDocument.getPaymentTerms(), xmlSalesDocument.getAllowanceCharges()));
+
+ // Anticipos
+ builder.anticipos(mapAnticipos(xmlSalesDocument.getAdditionalDocumentReferences(), xmlSalesDocument.getPrepaidPayments(), xmlSalesDocument.getAllowanceCharges()));
+
+ // Descuentos
+ builder.descuentos(mapDescuentos(xmlSalesDocument.getAllowanceCharges()));
+
+ return builder.build();
+ }
+ }
+
+ public static CreditNote unmarshallCreditNote(String xml) throws JAXBException, IOException {
+ try (
+ InputStream documentOXM = Thread.currentThread().getContextClassLoader().getResourceAsStream("jaxb/xml-bindings/credit-note.xml");
+ StringReader reader = new StringReader(xml);
+ ) {
+ XMLSalesDocument xmlSalesDocument = unmarshall(documentOXM, new InputSource(reader));
+ CreditNote.CreditNoteBuilder, ?> builder = CreditNote.builder();
+
+ enrichSalesDocument(xmlSalesDocument, builder);
+ enrichNote(xmlSalesDocument, builder);
+
+ return builder.build();
+ }
+ }
+
+ public static DebitNote unmarshallDebitNote(String xml) throws JAXBException, IOException {
+ try (
+ InputStream documentOXM = Thread.currentThread().getContextClassLoader().getResourceAsStream("jaxb/xml-bindings/debit-note.xml");
+ StringReader reader = new StringReader(xml);
+ ) {
+ XMLSalesDocument xmlSalesDocument = unmarshall(documentOXM, new InputSource(reader));
+ DebitNote.DebitNoteBuilder, ?> builder = DebitNote.builder();
+
+ enrichSalesDocument(xmlSalesDocument, builder);
+ enrichNote(xmlSalesDocument, builder);
+
+ return builder.build();
+ }
+ }
+
+ public static void enrichNote(XMLSalesDocument xmlSalesDocument, Note.NoteBuilder, ?> builder) {
+ enrichDocument(xmlSalesDocument, builder);
+
+ // ComprobanteAfectado
+ builder.comprobanteAfectadoSerieNumero(xmlSalesDocument.getDiscrepancyResponse_referenceId());
+ builder.comprobanteAfectadoTipo(xmlSalesDocument.getDiscrepancyResponse_responseCode());
+ builder.sustentoDescripcion(xmlSalesDocument.getDiscrepancyResponse_description());
+
+ // Total importe
+ builder.totalImporte(mapTotalImporteNote(xmlSalesDocument.getMonetaryTotal()));
+ }
+
+ public static T unmarshall(InputStream documentOXML, InputSource inputSource) throws JAXBException {
+ Map properties = new HashMap<>();
+ properties.put(JAXBContextProperties.OXM_METADATA_SOURCE, List.of(
+ Objects.requireNonNull(documentOXML)
+ ));
+
+ JAXBContext jaxbContext = JAXBContextFactory.createContext(Unmarshall.class.getPackageName(), null, properties);
+ Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
+ return (T) unmarshaller.unmarshal(inputSource);
+ }
+
+ public static void enrichSalesDocument(XMLSalesDocument xmlSalesDocument, SalesDocument.SalesDocumentBuilder, ?> builder) {
+ enrichDocument(xmlSalesDocument, builder);
+
+ // Leyendas
+ Optional