From 280cdd49ba0011c797a4c2d6e855eceb4e0391b3 Mon Sep 17 00:00:00 2001 From: javorosas Date: Tue, 7 Apr 2026 11:20:23 +0200 Subject: [PATCH 01/22] feat: complete java sdk v0 foundation and typed complement models --- .gitignore | 13 + README.md | 33 +- pom.xml | 9 +- .../com/facturapi/resources/BaseResource.java | 29 -- .../resources/CustomersResource.java | 49 --- .../facturapi/resources/InvoicesResource.java | 75 ---- .../resources/OrganizationsResource.java | 199 ----------- .../facturapi/resources/ProductsResource.java | 39 --- .../facturapi/resources/ReceiptsResource.java | 47 --- .../resources/RetentionsResource.java | 47 --- .../facturapi/resources/WebhooksResource.java | 97 ----- .../tools/CartaPorteCatalogsTool.java | 54 --- .../com/facturapi/tools/CatalogsTool.java | 21 -- .../tools/ComercioExteriorCatalogsTool.java | 17 - .../com/facturapi/tools/ToolsResource.java | 17 - .../{com => io}/facturapi/ApiVersion.java | 2 +- .../java/{com => io}/facturapi/Facturapi.java | 73 ++-- .../facturapi/FacturapiException.java | 2 +- .../constants/FacturapiConstants.java | 2 +- .../facturapi/enums/CancellationMotive.java | 2 +- .../facturapi/enums/InvoiceType.java | 2 +- .../facturapi/enums/PaymentForm.java | 2 +- .../facturapi/enums/TaxFactor.java | 2 +- .../{com => io}/facturapi/enums/TaxType.java | 2 +- .../facturapi/http/FacturapiConfig.java | 60 ++-- .../facturapi/http/FacturapiHttpClient.java | 104 ++++-- .../facturapi/http/MultipartBody.java | 2 +- .../facturapi/http/MultipartBodyBuilder.java | 2 +- .../java/io/facturapi/models/Address.java | 88 +++++ .../java/io/facturapi/models/ApiEvent.java | 25 ++ .../io/facturapi/models/ApiEventData.java | 14 + src/main/java/io/facturapi/models/ApiKey.java | 25 ++ .../models/CartaPorteAutotransporte.java | 31 ++ .../models/CartaPorteCantidadTransporta.java | 25 ++ .../models/CartaPorteCarroFerroviario.java | 31 ++ .../models/CartaPorteComplementData.java | 65 ++++ .../CartaPorteContenedorFerroviario.java | 21 ++ .../models/CartaPorteContenedorMaritimo.java | 39 +++ .../models/CartaPorteDerechosDePaso.java | 17 + .../models/CartaPorteDetalleMercancia.java | 29 ++ .../CartaPorteDocumentacionAduanera.java | 25 ++ .../facturapi/models/CartaPorteDomicilio.java | 49 +++ .../models/CartaPorteFiguraTransporte.java | 43 +++ .../models/CartaPorteGuiaIdentificacion.java | 21 ++ .../CartaPorteIdentificacionVehicular.java | 25 ++ .../facturapi/models/CartaPorteMercancia.java | 179 ++++++++++ .../models/CartaPorteMercancias.java | 55 +++ .../models/CartaPorteParteTransporte.java | 13 + .../facturapi/models/CartaPorteRemolque.java | 17 + .../models/CartaPorteRemolqueCcp.java | 17 + .../facturapi/models/CartaPorteSeguros.java | 37 ++ .../models/CartaPorteTransporteAereo.java | 57 +++ .../CartaPorteTransporteFerroviario.java | 35 ++ .../models/CartaPorteTransporteMaritimo.java | 103 ++++++ .../facturapi/models/CartaPorteUbicacion.java | 61 ++++ .../java/io/facturapi/models/CatalogItem.java | 39 +++ .../java/io/facturapi/models/Certificate.java | 25 ++ .../ComercioExteriorComplementData.java | 106 ++++++ ...ercioExteriorDescripcionesEspecificas.java | 25 ++ .../ComercioExteriorDestinatarioRef.java | 26 ++ .../models/ComercioExteriorDomicilio.java | 49 +++ .../models/ComercioExteriorEmisor.java | 17 + .../models/ComercioExteriorMercancia.java | 39 +++ .../models/ComercioExteriorMercancias.java | 15 + .../models/ComercioExteriorPartyRef.java | 20 ++ .../models/ComercioExteriorReceptorRef.java | 20 ++ .../io/facturapi/models/CompletionStep.java | 14 + .../java/io/facturapi/models/Customer.java | 66 ++++ .../io/facturapi/models/CustomerInfo.java | 27 ++ .../io/facturapi/models/Customization.java | 26 ++ .../facturapi/models/DomainAvailability.java | 16 + .../io/facturapi/models/GenericResponse.java | 16 + .../java/io/facturapi/models/GlobalInfo.java | 17 + .../java/io/facturapi/models/Invoice.java | 153 ++++++++ .../facturapi/models/InvoiceCancellation.java | 27 ++ .../facturapi/models/InvoiceComplement.java | 149 ++++++++ .../java/io/facturapi/models/InvoiceItem.java | 38 ++ .../io/facturapi/models/InvoiceItemPart.java | 30 ++ .../models/InvoiceItemThirdParty.java | 24 ++ src/main/java/io/facturapi/models/Legal.java | 40 +++ .../java/io/facturapi/models/LocalTax.java | 52 +++ .../io/facturapi/models/NominaAcciones.java | 17 + .../facturapi/models/NominaCompensacion.java | 20 ++ .../models/NominaComplementData.java | 50 +++ .../io/facturapi/models/NominaDeduccion.java | 22 ++ .../io/facturapi/models/NominaEmisor.java | 24 ++ .../facturapi/models/NominaEntidadSncf.java | 17 + .../io/facturapi/models/NominaHorasExtra.java | 24 ++ .../facturapi/models/NominaIncapacidad.java | 21 ++ .../io/facturapi/models/NominaJubilacion.java | 29 ++ .../io/facturapi/models/NominaOtroPago.java | 30 ++ .../io/facturapi/models/NominaPercepcion.java | 37 ++ .../facturapi/models/NominaPercepciones.java | 23 ++ .../io/facturapi/models/NominaReceptor.java | 85 +++++ .../io/facturapi/models/NominaSeparacion.java | 29 ++ .../models/NominaSubcontratacion.java | 17 + .../io/facturapi/models/Organization.java | 70 ++++ .../facturapi/models/OrganizationInvite.java | 42 +++ .../models/OrganizationTeamRole.java | 51 +++ .../models/OrganizationTeamRoleTemplate.java | 22 ++ .../models/OrganizationUserAccess.java | 42 +++ .../facturapi/models/PagoComplementData.java | 58 +++ .../java/io/facturapi/models/Payment.java | 27 ++ .../io/facturapi/models/PaymentRelated.java | 27 ++ .../models/PaymentRelatedDocument.java | 43 +++ .../models/PaymentRelatedDocumentTax.java | 23 ++ .../java/io/facturapi/models/PdfExtra.java | 40 +++ .../facturapi/models/PendingPlanUpdate.java | 16 + .../java/io/facturapi/models/Product.java | 59 ++++ .../java/io/facturapi/models/ProductInfo.java | 49 +++ .../java/io/facturapi/models/Receipt.java | 79 +++++ .../io/facturapi/models/ReceiptSettings.java | 24 ++ .../io/facturapi/models/RelatedDocument.java | 14 + .../java/io/facturapi/models/Retention.java | 87 +++++ .../io/facturapi/models/RetentionPeriod.java | 20 ++ .../models/RetentionRetainedTax.java | 28 ++ .../io/facturapi/models/RetentionTotals.java | 31 ++ .../io/facturapi/models/SearchResult.java | 60 ++++ .../facturapi/models/SelfInvoiceSettings.java | 27 ++ src/main/java/io/facturapi/models/Series.java | 22 ++ src/main/java/io/facturapi/models/Stamp.java | 31 ++ src/main/java/io/facturapi/models/Tax.java | 61 ++++ .../facturapi/models/TaxInfoValidation.java | 23 ++ .../models/TaxInfoValidationError.java | 14 + .../java/io/facturapi/models/Webhook.java | 40 +++ .../io/facturapi/models/XmlNamespace.java | 19 + .../io/facturapi/resources/BaseResource.java | 45 +++ .../resources/CustomersResource.java | 101 ++++++ .../facturapi/resources/InvoicesResource.java | 189 ++++++++++ .../resources/OrganizationsResource.java | 331 ++++++++++++++++++ .../facturapi/resources/ProductsResource.java | 74 ++++ .../facturapi/resources/ReceiptsResource.java | 110 ++++++ .../resources/RetentionsResource.java | 109 ++++++ .../facturapi/resources/WebhooksResource.java | 135 +++++++ .../tools/CartaPorteCatalogsTool.java | 126 +++++++ .../java/io/facturapi/tools/CatalogsTool.java | 42 +++ .../tools/ComercioExteriorCatalogsTool.java | 35 ++ .../io/facturapi/tools/ToolsResource.java | 29 ++ .../facturapi/FacturapiHttpClientTest.java | 91 ----- .../com/facturapi/FacturapiResourcesTest.java | 59 ---- .../io/facturapi/FacturapiHttpClientTest.java | 69 ++++ .../io/facturapi/FacturapiResourcesTest.java | 112 ++++++ .../java/io/facturapi/StubHttpClient.java | 191 ++++++++++ .../facturapi/WebhooksResourceTest.java | 14 +- 144 files changed, 5715 insertions(+), 967 deletions(-) create mode 100644 .gitignore delete mode 100644 src/main/java/com/facturapi/resources/BaseResource.java delete mode 100644 src/main/java/com/facturapi/resources/CustomersResource.java delete mode 100644 src/main/java/com/facturapi/resources/InvoicesResource.java delete mode 100644 src/main/java/com/facturapi/resources/OrganizationsResource.java delete mode 100644 src/main/java/com/facturapi/resources/ProductsResource.java delete mode 100644 src/main/java/com/facturapi/resources/ReceiptsResource.java delete mode 100644 src/main/java/com/facturapi/resources/RetentionsResource.java delete mode 100644 src/main/java/com/facturapi/resources/WebhooksResource.java delete mode 100644 src/main/java/com/facturapi/tools/CartaPorteCatalogsTool.java delete mode 100644 src/main/java/com/facturapi/tools/CatalogsTool.java delete mode 100644 src/main/java/com/facturapi/tools/ComercioExteriorCatalogsTool.java delete mode 100644 src/main/java/com/facturapi/tools/ToolsResource.java rename src/main/java/{com => io}/facturapi/ApiVersion.java (95%) rename src/main/java/{com => io}/facturapi/Facturapi.java (67%) rename src/main/java/{com => io}/facturapi/FacturapiException.java (96%) rename src/main/java/{com => io}/facturapi/constants/FacturapiConstants.java (87%) rename src/main/java/{com => io}/facturapi/enums/CancellationMotive.java (90%) rename src/main/java/{com => io}/facturapi/enums/InvoiceType.java (89%) rename src/main/java/{com => io}/facturapi/enums/PaymentForm.java (92%) rename src/main/java/{com => io}/facturapi/enums/TaxFactor.java (59%) rename src/main/java/{com => io}/facturapi/enums/TaxType.java (61%) rename src/main/java/{com => io}/facturapi/http/FacturapiConfig.java (62%) rename src/main/java/{com => io}/facturapi/http/FacturapiHttpClient.java (61%) rename src/main/java/{com => io}/facturapi/http/MultipartBody.java (94%) rename src/main/java/{com => io}/facturapi/http/MultipartBodyBuilder.java (98%) create mode 100644 src/main/java/io/facturapi/models/Address.java create mode 100644 src/main/java/io/facturapi/models/ApiEvent.java create mode 100644 src/main/java/io/facturapi/models/ApiEventData.java create mode 100644 src/main/java/io/facturapi/models/ApiKey.java create mode 100644 src/main/java/io/facturapi/models/CartaPorteAutotransporte.java create mode 100644 src/main/java/io/facturapi/models/CartaPorteCantidadTransporta.java create mode 100644 src/main/java/io/facturapi/models/CartaPorteCarroFerroviario.java create mode 100644 src/main/java/io/facturapi/models/CartaPorteComplementData.java create mode 100644 src/main/java/io/facturapi/models/CartaPorteContenedorFerroviario.java create mode 100644 src/main/java/io/facturapi/models/CartaPorteContenedorMaritimo.java create mode 100644 src/main/java/io/facturapi/models/CartaPorteDerechosDePaso.java create mode 100644 src/main/java/io/facturapi/models/CartaPorteDetalleMercancia.java create mode 100644 src/main/java/io/facturapi/models/CartaPorteDocumentacionAduanera.java create mode 100644 src/main/java/io/facturapi/models/CartaPorteDomicilio.java create mode 100644 src/main/java/io/facturapi/models/CartaPorteFiguraTransporte.java create mode 100644 src/main/java/io/facturapi/models/CartaPorteGuiaIdentificacion.java create mode 100644 src/main/java/io/facturapi/models/CartaPorteIdentificacionVehicular.java create mode 100644 src/main/java/io/facturapi/models/CartaPorteMercancia.java create mode 100644 src/main/java/io/facturapi/models/CartaPorteMercancias.java create mode 100644 src/main/java/io/facturapi/models/CartaPorteParteTransporte.java create mode 100644 src/main/java/io/facturapi/models/CartaPorteRemolque.java create mode 100644 src/main/java/io/facturapi/models/CartaPorteRemolqueCcp.java create mode 100644 src/main/java/io/facturapi/models/CartaPorteSeguros.java create mode 100644 src/main/java/io/facturapi/models/CartaPorteTransporteAereo.java create mode 100644 src/main/java/io/facturapi/models/CartaPorteTransporteFerroviario.java create mode 100644 src/main/java/io/facturapi/models/CartaPorteTransporteMaritimo.java create mode 100644 src/main/java/io/facturapi/models/CartaPorteUbicacion.java create mode 100644 src/main/java/io/facturapi/models/CatalogItem.java create mode 100644 src/main/java/io/facturapi/models/Certificate.java create mode 100644 src/main/java/io/facturapi/models/ComercioExteriorComplementData.java create mode 100644 src/main/java/io/facturapi/models/ComercioExteriorDescripcionesEspecificas.java create mode 100644 src/main/java/io/facturapi/models/ComercioExteriorDestinatarioRef.java create mode 100644 src/main/java/io/facturapi/models/ComercioExteriorDomicilio.java create mode 100644 src/main/java/io/facturapi/models/ComercioExteriorEmisor.java create mode 100644 src/main/java/io/facturapi/models/ComercioExteriorMercancia.java create mode 100644 src/main/java/io/facturapi/models/ComercioExteriorMercancias.java create mode 100644 src/main/java/io/facturapi/models/ComercioExteriorPartyRef.java create mode 100644 src/main/java/io/facturapi/models/ComercioExteriorReceptorRef.java create mode 100644 src/main/java/io/facturapi/models/CompletionStep.java create mode 100644 src/main/java/io/facturapi/models/Customer.java create mode 100644 src/main/java/io/facturapi/models/CustomerInfo.java create mode 100644 src/main/java/io/facturapi/models/Customization.java create mode 100644 src/main/java/io/facturapi/models/DomainAvailability.java create mode 100644 src/main/java/io/facturapi/models/GenericResponse.java create mode 100644 src/main/java/io/facturapi/models/GlobalInfo.java create mode 100644 src/main/java/io/facturapi/models/Invoice.java create mode 100644 src/main/java/io/facturapi/models/InvoiceCancellation.java create mode 100644 src/main/java/io/facturapi/models/InvoiceComplement.java create mode 100644 src/main/java/io/facturapi/models/InvoiceItem.java create mode 100644 src/main/java/io/facturapi/models/InvoiceItemPart.java create mode 100644 src/main/java/io/facturapi/models/InvoiceItemThirdParty.java create mode 100644 src/main/java/io/facturapi/models/Legal.java create mode 100644 src/main/java/io/facturapi/models/LocalTax.java create mode 100644 src/main/java/io/facturapi/models/NominaAcciones.java create mode 100644 src/main/java/io/facturapi/models/NominaCompensacion.java create mode 100644 src/main/java/io/facturapi/models/NominaComplementData.java create mode 100644 src/main/java/io/facturapi/models/NominaDeduccion.java create mode 100644 src/main/java/io/facturapi/models/NominaEmisor.java create mode 100644 src/main/java/io/facturapi/models/NominaEntidadSncf.java create mode 100644 src/main/java/io/facturapi/models/NominaHorasExtra.java create mode 100644 src/main/java/io/facturapi/models/NominaIncapacidad.java create mode 100644 src/main/java/io/facturapi/models/NominaJubilacion.java create mode 100644 src/main/java/io/facturapi/models/NominaOtroPago.java create mode 100644 src/main/java/io/facturapi/models/NominaPercepcion.java create mode 100644 src/main/java/io/facturapi/models/NominaPercepciones.java create mode 100644 src/main/java/io/facturapi/models/NominaReceptor.java create mode 100644 src/main/java/io/facturapi/models/NominaSeparacion.java create mode 100644 src/main/java/io/facturapi/models/NominaSubcontratacion.java create mode 100644 src/main/java/io/facturapi/models/Organization.java create mode 100644 src/main/java/io/facturapi/models/OrganizationInvite.java create mode 100644 src/main/java/io/facturapi/models/OrganizationTeamRole.java create mode 100644 src/main/java/io/facturapi/models/OrganizationTeamRoleTemplate.java create mode 100644 src/main/java/io/facturapi/models/OrganizationUserAccess.java create mode 100644 src/main/java/io/facturapi/models/PagoComplementData.java create mode 100644 src/main/java/io/facturapi/models/Payment.java create mode 100644 src/main/java/io/facturapi/models/PaymentRelated.java create mode 100644 src/main/java/io/facturapi/models/PaymentRelatedDocument.java create mode 100644 src/main/java/io/facturapi/models/PaymentRelatedDocumentTax.java create mode 100644 src/main/java/io/facturapi/models/PdfExtra.java create mode 100644 src/main/java/io/facturapi/models/PendingPlanUpdate.java create mode 100644 src/main/java/io/facturapi/models/Product.java create mode 100644 src/main/java/io/facturapi/models/ProductInfo.java create mode 100644 src/main/java/io/facturapi/models/Receipt.java create mode 100644 src/main/java/io/facturapi/models/ReceiptSettings.java create mode 100644 src/main/java/io/facturapi/models/RelatedDocument.java create mode 100644 src/main/java/io/facturapi/models/Retention.java create mode 100644 src/main/java/io/facturapi/models/RetentionPeriod.java create mode 100644 src/main/java/io/facturapi/models/RetentionRetainedTax.java create mode 100644 src/main/java/io/facturapi/models/RetentionTotals.java create mode 100644 src/main/java/io/facturapi/models/SearchResult.java create mode 100644 src/main/java/io/facturapi/models/SelfInvoiceSettings.java create mode 100644 src/main/java/io/facturapi/models/Series.java create mode 100644 src/main/java/io/facturapi/models/Stamp.java create mode 100644 src/main/java/io/facturapi/models/Tax.java create mode 100644 src/main/java/io/facturapi/models/TaxInfoValidation.java create mode 100644 src/main/java/io/facturapi/models/TaxInfoValidationError.java create mode 100644 src/main/java/io/facturapi/models/Webhook.java create mode 100644 src/main/java/io/facturapi/models/XmlNamespace.java create mode 100644 src/main/java/io/facturapi/resources/BaseResource.java create mode 100644 src/main/java/io/facturapi/resources/CustomersResource.java create mode 100644 src/main/java/io/facturapi/resources/InvoicesResource.java create mode 100644 src/main/java/io/facturapi/resources/OrganizationsResource.java create mode 100644 src/main/java/io/facturapi/resources/ProductsResource.java create mode 100644 src/main/java/io/facturapi/resources/ReceiptsResource.java create mode 100644 src/main/java/io/facturapi/resources/RetentionsResource.java create mode 100644 src/main/java/io/facturapi/resources/WebhooksResource.java create mode 100644 src/main/java/io/facturapi/tools/CartaPorteCatalogsTool.java create mode 100644 src/main/java/io/facturapi/tools/CatalogsTool.java create mode 100644 src/main/java/io/facturapi/tools/ComercioExteriorCatalogsTool.java create mode 100644 src/main/java/io/facturapi/tools/ToolsResource.java delete mode 100644 src/test/java/com/facturapi/FacturapiHttpClientTest.java delete mode 100644 src/test/java/com/facturapi/FacturapiResourcesTest.java create mode 100644 src/test/java/io/facturapi/FacturapiHttpClientTest.java create mode 100644 src/test/java/io/facturapi/FacturapiResourcesTest.java create mode 100644 src/test/java/io/facturapi/StubHttpClient.java rename src/test/java/{com => io}/facturapi/WebhooksResourceTest.java (82%) diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c68e2ee --- /dev/null +++ b/.gitignore @@ -0,0 +1,13 @@ +# Build artifacts +target/ + +# Local Maven cache override used in this workspace +.m2/ + +# IDE files +.idea/ +*.iml +.vscode/ + +# OS files +.DS_Store diff --git a/README.md b/README.md index 38690cb..b5ed407 100644 --- a/README.md +++ b/README.md @@ -2,25 +2,36 @@ Official Java SDK for [Facturapi](https://www.facturapi.io). +[![CI](https://img.shields.io/github/actions/workflow/status/facturapi/facturapi-java/ci.yml?branch=main&style=for-the-badge&label=CI)](https://github.com/facturapi/facturapi-java/actions/workflows/ci.yml) +[![Maven Central](https://img.shields.io/maven-central/v/io.facturapi/facturapi-java?style=for-the-badge&label=Maven%20Central)](https://central.sonatype.com/artifact/io.facturapi/facturapi-java) +[![Java](https://img.shields.io/badge/Java-11%2B-ED8B00?style=for-the-badge&logo=openjdk&logoColor=white)](https://openjdk.org/) + ## Requirements - Java 11+ -- Maven 3.8+ ## Installation +Maven: + ```xml io.facturapi facturapi-java - 1.0.0 + 0.1.0 ``` +Gradle: + +```gradle +implementation("io.facturapi:facturapi-java:0.1.0") +``` + ## Quickstart ```java -import com.facturapi.Facturapi; +import io.facturapi.Facturapi; import java.util.Map; Facturapi facturapi = new Facturapi("sk_test_..."); @@ -33,11 +44,19 @@ var customer = facturapi.customers.create(Map.of( ), null); var invoice = facturapi.invoices.create(Map.of( - "customer", customer.get("id").asText(), + "customer", customer.getId(), "items", java.util.List.of(Map.of("quantity", 1, "product", "prod_123")) ), null); + +System.out.println(invoice.getId()); ``` +## Design + +- Inputs use flexible JSON dictionaries (`Map`). +- Outputs are typed Java models (`Invoice`, `Customer`, `SearchResult`, etc.). +- Auth uses `Authorization: Bearer `. + ## Configuration ```java @@ -46,9 +65,3 @@ Facturapi facturapi = Facturapi.builder("sk_test_...") .timeout(java.time.Duration.ofSeconds(20)) .build(); ``` - -## Notes - -- Uses `Authorization: Bearer `. -- Supports custom base URL for integration testing. -- Includes compatibility aliases (`all`, `del`, `lisLiveApiKeys`). diff --git a/pom.xml b/pom.xml index ca75150..39cde6f 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ io.facturapi facturapi-java - 1.0.0-SNAPSHOT + 0.1.0-SNAPSHOT facturapi-java Official Java SDK for Facturapi https://github.com/facturapi/facturapi-java @@ -22,7 +22,6 @@ UTF-8 2.17.2 5.11.0 - 4.12.0 @@ -38,12 +37,6 @@ ${junit.version} test - - com.squareup.okhttp3 - mockwebserver - ${okhttp.version} - test - diff --git a/src/main/java/com/facturapi/resources/BaseResource.java b/src/main/java/com/facturapi/resources/BaseResource.java deleted file mode 100644 index 9797c98..0000000 --- a/src/main/java/com/facturapi/resources/BaseResource.java +++ /dev/null @@ -1,29 +0,0 @@ -package com.facturapi.resources; - -import com.fasterxml.jackson.databind.JsonNode; -import com.facturapi.http.FacturapiHttpClient; -import java.util.Map; - -public abstract class BaseResource { - protected final FacturapiHttpClient client; - - protected BaseResource(FacturapiHttpClient client) { - this.client = client; - } - - protected JsonNode get(String path, Map params) { - return client.getJson(path, params); - } - - protected JsonNode post(String path, Object body, Map params) { - return client.postJson(path, body, params); - } - - protected JsonNode put(String path, Object body, Map params) { - return client.putJson(path, body, params); - } - - protected JsonNode delete(String path, Map params) { - return client.deleteJson(path, params); - } -} diff --git a/src/main/java/com/facturapi/resources/CustomersResource.java b/src/main/java/com/facturapi/resources/CustomersResource.java deleted file mode 100644 index 739ea75..0000000 --- a/src/main/java/com/facturapi/resources/CustomersResource.java +++ /dev/null @@ -1,49 +0,0 @@ -package com.facturapi.resources; - -import com.fasterxml.jackson.databind.JsonNode; -import com.facturapi.http.FacturapiHttpClient; -import java.util.Map; - -public class CustomersResource extends BaseResource { - public CustomersResource(FacturapiHttpClient client) { - super(client); - } - - public JsonNode create(Object data, Map params) { - return post("/customers", data, params); - } - - public JsonNode list(Map params) { - return get("/customers", params); - } - - // PHP-compatible alias - public JsonNode all(Map params) { - return list(params); - } - - public JsonNode retrieve(String id) { - return get("/customers/" + id, null); - } - - public JsonNode update(String id, Object data, Map params) { - return put("/customers/" + id, data, params); - } - - public JsonNode delete(String id) { - return delete("/customers/" + id, null); - } - - // Node-compatible alias - public JsonNode del(String id) { - return delete(id); - } - - public JsonNode validateTaxInfo(String id) { - return get("/customers/" + id + "/tax-info-validation", null); - } - - public JsonNode sendEditLinkByEmail(String id, String email) { - return post("/customers/" + id + "/email-edit-link", Map.of("email", email), null); - } -} diff --git a/src/main/java/com/facturapi/resources/InvoicesResource.java b/src/main/java/com/facturapi/resources/InvoicesResource.java deleted file mode 100644 index d123a41..0000000 --- a/src/main/java/com/facturapi/resources/InvoicesResource.java +++ /dev/null @@ -1,75 +0,0 @@ -package com.facturapi.resources; - -import com.fasterxml.jackson.databind.JsonNode; -import com.facturapi.http.FacturapiHttpClient; -import java.util.Map; - -public class InvoicesResource extends BaseResource { - public InvoicesResource(FacturapiHttpClient client) { - super(client); - } - - public JsonNode create(Object body, Map params) { - return post("/invoices", body, params); - } - - public JsonNode list(Map params) { - return get("/invoices", params); - } - - public JsonNode all(Map params) { - return list(params); - } - - public JsonNode retrieve(String id) { - return get("/invoices/" + id, null); - } - - public JsonNode cancel(String id, Map params) { - return delete("/invoices/" + id, params); - } - - public JsonNode sendByEmail(String id, Map options) { - return post("/invoices/" + id + "/email", options, null); - } - - public byte[] downloadPdf(String id) { - return client.getBytes("/invoices/" + id + "/pdf"); - } - - public byte[] downloadXml(String id) { - return client.getBytes("/invoices/" + id + "/xml"); - } - - public byte[] downloadZip(String id) { - return client.getBytes("/invoices/" + id + "/zip"); - } - - public byte[] downloadCancellationReceiptXml(String id) { - return client.getBytes("/invoices/" + id + "/cancellation_receipt/xml"); - } - - public byte[] downloadCancellationReceiptPdf(String id) { - return client.getBytes("/invoices/" + id + "/cancellation_receipt/pdf"); - } - - public JsonNode updateDraft(String id, Object data) { - return put("/invoices/" + id, data, null); - } - - public JsonNode stampDraft(String id, Map params) { - return post("/invoices/" + id + "/stamp", null, params); - } - - public JsonNode updateStatus(String id) { - return put("/invoices/" + id + "/status", null, null); - } - - public JsonNode copyToDraft(String id) { - return post("/invoices/" + id + "/copy", null, null); - } - - public byte[] previewPdf(Object body) { - return client.postBytes("/invoices/preview/pdf", body); - } -} diff --git a/src/main/java/com/facturapi/resources/OrganizationsResource.java b/src/main/java/com/facturapi/resources/OrganizationsResource.java deleted file mode 100644 index 31376d0..0000000 --- a/src/main/java/com/facturapi/resources/OrganizationsResource.java +++ /dev/null @@ -1,199 +0,0 @@ -package com.facturapi.resources; - -import com.fasterxml.jackson.databind.JsonNode; -import com.facturapi.http.FacturapiHttpClient; -import com.facturapi.http.MultipartBody; -import com.facturapi.http.MultipartBodyBuilder; -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.Map; - -public class OrganizationsResource extends BaseResource { - public OrganizationsResource(FacturapiHttpClient client) { - super(client); - } - - public JsonNode create(Object data) { - return post("/organizations", data, null); - } - - public JsonNode list(Map params) { - return get("/organizations", params); - } - - public JsonNode all(Map params) { - return list(params); - } - - public JsonNode retrieve(String id) { - return get("/organizations/" + id, null); - } - - public JsonNode updateLegal(String id, Object data) { - return put("/organizations/" + id + "/legal", data, null); - } - - public JsonNode updateCustomization(String id, Object data) { - return put("/organizations/" + id + "/customization", data, null); - } - - public JsonNode updateReceiptSettings(String id, Object data) { - return put("/organizations/" + id + "/receipts", data, null); - } - - public JsonNode updateDomain(String id, Object data) { - return put("/organizations/" + id + "/domain", data, null); - } - - public JsonNode checkDomainAvailability(Map query) { - return get("/organizations/domain-check", query); - } - - @Deprecated - public JsonNode checkDomainIsAvailable(Map query) { - return checkDomainAvailability(query); - } - - public JsonNode uploadLogo(String id, Path filePath) throws IOException { - byte[] fileBytes = Files.readAllBytes(filePath); - MultipartBody multipartBody = new MultipartBodyBuilder() - .addFile("file", filePath.getFileName().toString(), fileBytes, "application/octet-stream") - .build(); - return client.putMultipart("/organizations/" + id + "/logo", multipartBody); - } - - public JsonNode uploadCertificate(String id, Path cerFile, Path keyFile, String password) throws IOException { - MultipartBody multipartBody = new MultipartBodyBuilder() - .addFile("cer", cerFile.getFileName().toString(), Files.readAllBytes(cerFile), "application/octet-stream") - .addFile("key", keyFile.getFileName().toString(), Files.readAllBytes(keyFile), "application/octet-stream") - .addField("password", password) - .build(); - return client.putMultipart("/organizations/" + id + "/certificate", multipartBody); - } - - public JsonNode deleteCertificate(String id) { - return delete("/organizations/" + id + "/certificate", null); - } - - public JsonNode delete(String id) { - return delete("/organizations/" + id, null); - } - - public JsonNode del(String id) { - return delete(id); - } - - public JsonNode getTestApiKey(String id) { - return get("/organizations/" + id + "/apikeys/test", null); - } - - public JsonNode renewTestApiKey(String id) { - return put("/organizations/" + id + "/apikeys/test", null, null); - } - - public JsonNode listLiveApiKeys(String id) { - return get("/organizations/" + id + "/apikeys/live", null); - } - - @Deprecated - public JsonNode lisLiveApiKeys(String id) { - return listLiveApiKeys(id); - } - - public JsonNode renewLiveApiKey(String id) { - return put("/organizations/" + id + "/apikeys/live", null, null); - } - - public JsonNode deleteLiveApiKey(String organizationId, String apiKeyId) { - return delete("/organizations/" + organizationId + "/apikeys/live/" + apiKeyId, null); - } - - public JsonNode listSeriesGroup(String organizationId) { - return get("/organizations/" + organizationId + "/series-group", null); - } - - public JsonNode createSeriesGroup(String organizationId, Object seriesData) { - return post("/organizations/" + organizationId + "/series-group", seriesData, null); - } - - public JsonNode updateSeriesGroup(String organizationId, String seriesName, Object data) { - return put("/organizations/" + organizationId + "/series-group/" + seriesName, data, null); - } - - public JsonNode deleteSeriesGroup(String organizationId, String seriesName) { - return delete("/organizations/" + organizationId + "/series-group/" + seriesName, null); - } - - public JsonNode me() { - return get("/organizations/me", null); - } - - public JsonNode updateSelfInvoiceSettings(String id, Object data) { - return put("/organizations/" + id + "/self-invoice", data, null); - } - - public JsonNode listTeamAccess(String organizationId) { - return get("/organizations/" + organizationId + "/team", null); - } - - public JsonNode retrieveTeamAccess(String organizationId, String accessId) { - return get("/organizations/" + organizationId + "/team/" + accessId, null); - } - - public JsonNode updateTeamAccessRole(String organizationId, String accessId, String role) { - return put("/organizations/" + organizationId + "/team/" + accessId + "/role", Map.of("role", role), null); - } - - public JsonNode removeTeamAccess(String organizationId, String accessId) { - return delete("/organizations/" + organizationId + "/team/" + accessId, null); - } - - public JsonNode listSentTeamInvites(String organizationId) { - return get("/organizations/" + organizationId + "/team/invites", null); - } - - public JsonNode inviteUserToTeam(String organizationId, Object data) { - return post("/organizations/" + organizationId + "/team/invites", data, null); - } - - public JsonNode cancelTeamInvite(String organizationId, String inviteKey) { - return delete("/organizations/" + organizationId + "/team/invites/" + inviteKey, null); - } - - public JsonNode listReceivedTeamInvites() { - return get("/organizations/invites/pending", null); - } - - public JsonNode respondTeamInvite(String inviteKey, Object data) { - return post("/organizations/invites/" + inviteKey + "/response", data, null); - } - - public JsonNode listTeamRoles(String organizationId) { - return get("/organizations/" + organizationId + "/team/roles", null); - } - - public JsonNode listTeamRoleTemplates(String organizationId) { - return get("/organizations/" + organizationId + "/team/roles/templates", null); - } - - public JsonNode listTeamRoleOperations(String organizationId) { - return get("/organizations/" + organizationId + "/team/roles/operations", null); - } - - public JsonNode retrieveTeamRole(String organizationId, String roleId) { - return get("/organizations/" + organizationId + "/team/roles/" + roleId, null); - } - - public JsonNode createTeamRole(String organizationId, Object data) { - return post("/organizations/" + organizationId + "/team/roles", data, null); - } - - public JsonNode updateTeamRole(String organizationId, String roleId, Object data) { - return put("/organizations/" + organizationId + "/team/roles/" + roleId, data, null); - } - - public JsonNode deleteTeamRole(String organizationId, String roleId) { - return delete("/organizations/" + organizationId + "/team/roles/" + roleId, null); - } -} diff --git a/src/main/java/com/facturapi/resources/ProductsResource.java b/src/main/java/com/facturapi/resources/ProductsResource.java deleted file mode 100644 index f918c4b..0000000 --- a/src/main/java/com/facturapi/resources/ProductsResource.java +++ /dev/null @@ -1,39 +0,0 @@ -package com.facturapi.resources; - -import com.fasterxml.jackson.databind.JsonNode; -import com.facturapi.http.FacturapiHttpClient; -import java.util.Map; - -public class ProductsResource extends BaseResource { - public ProductsResource(FacturapiHttpClient client) { - super(client); - } - - public JsonNode create(Object data) { - return post("/products", data, null); - } - - public JsonNode list(Map params) { - return get("/products", params); - } - - public JsonNode all(Map params) { - return list(params); - } - - public JsonNode retrieve(String id) { - return get("/products/" + id, null); - } - - public JsonNode update(String id, Object data) { - return put("/products/" + id, data, null); - } - - public JsonNode delete(String id) { - return delete("/products/" + id, null); - } - - public JsonNode del(String id) { - return delete(id); - } -} diff --git a/src/main/java/com/facturapi/resources/ReceiptsResource.java b/src/main/java/com/facturapi/resources/ReceiptsResource.java deleted file mode 100644 index 65f7a9e..0000000 --- a/src/main/java/com/facturapi/resources/ReceiptsResource.java +++ /dev/null @@ -1,47 +0,0 @@ -package com.facturapi.resources; - -import com.fasterxml.jackson.databind.JsonNode; -import com.facturapi.http.FacturapiHttpClient; -import java.util.Map; - -public class ReceiptsResource extends BaseResource { - public ReceiptsResource(FacturapiHttpClient client) { - super(client); - } - - public JsonNode create(Object data) { - return post("/receipts", data, null); - } - - public JsonNode list(Map params) { - return get("/receipts", params); - } - - public JsonNode all(Map params) { - return list(params); - } - - public JsonNode retrieve(String id) { - return get("/receipts/" + id, null); - } - - public JsonNode invoice(String id, Object data) { - return post("/receipts/" + id + "/invoice", data, null); - } - - public JsonNode createGlobalInvoice(Object data) { - return post("/receipts/global-invoice", data, null); - } - - public JsonNode cancel(String id) { - return delete("/receipts/" + id, null); - } - - public JsonNode sendByEmail(String id, Map data) { - return post("/receipts/" + id + "/email", data, null); - } - - public byte[] downloadPdf(String id) { - return client.getBytes("/receipts/" + id + "/pdf"); - } -} diff --git a/src/main/java/com/facturapi/resources/RetentionsResource.java b/src/main/java/com/facturapi/resources/RetentionsResource.java deleted file mode 100644 index c57acc5..0000000 --- a/src/main/java/com/facturapi/resources/RetentionsResource.java +++ /dev/null @@ -1,47 +0,0 @@ -package com.facturapi.resources; - -import com.fasterxml.jackson.databind.JsonNode; -import com.facturapi.http.FacturapiHttpClient; -import java.util.Map; - -public class RetentionsResource extends BaseResource { - public RetentionsResource(FacturapiHttpClient client) { - super(client); - } - - public JsonNode create(Object data) { - return post("/retentions", data, null); - } - - public JsonNode list(Map params) { - return get("/retentions", params); - } - - public JsonNode all(Map params) { - return list(params); - } - - public JsonNode retrieve(String id) { - return get("/retentions/" + id, null); - } - - public JsonNode cancel(String id, Map params) { - return delete("/retentions/" + id, params); - } - - public JsonNode sendByEmail(String id, Map data) { - return post("/retentions/" + id + "/email", data, null); - } - - public byte[] downloadPdf(String id) { - return client.getBytes("/retentions/" + id + "/pdf"); - } - - public byte[] downloadXml(String id) { - return client.getBytes("/retentions/" + id + "/xml"); - } - - public byte[] downloadZip(String id) { - return client.getBytes("/retentions/" + id + "/zip"); - } -} diff --git a/src/main/java/com/facturapi/resources/WebhooksResource.java b/src/main/java/com/facturapi/resources/WebhooksResource.java deleted file mode 100644 index 5532a98..0000000 --- a/src/main/java/com/facturapi/resources/WebhooksResource.java +++ /dev/null @@ -1,97 +0,0 @@ -package com.facturapi.resources; - -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.facturapi.FacturapiException; -import com.facturapi.http.FacturapiHttpClient; -import java.nio.charset.StandardCharsets; -import java.security.InvalidKeyException; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; -import java.util.Map; -import javax.crypto.Mac; -import javax.crypto.spec.SecretKeySpec; - -public class WebhooksResource extends BaseResource { - private final ObjectMapper objectMapper = new ObjectMapper(); - - public WebhooksResource(FacturapiHttpClient client) { - super(client); - } - - public JsonNode create(Object data) { - return post("/webhooks", data, null); - } - - public JsonNode list(Map params) { - return get("/webhooks", params); - } - - public JsonNode all(Map params) { - return list(params); - } - - public JsonNode retrieve(String id) { - return get("/webhooks/" + id, null); - } - - public JsonNode update(String id, Object data) { - return put("/webhooks/" + id, data, null); - } - - public JsonNode delete(String id) { - return delete("/webhooks/" + id, null); - } - - public JsonNode del(String id) { - return delete(id); - } - - public JsonNode validateSignature(String secret, String signatureHex, String payload) { - try { - byte[] expected = hmacSha256(secret, payload); - byte[] provided = hexToBytes(signatureHex); - if (!MessageDigest.isEqual(expected, provided)) { - throw new FacturapiException("Invalid signature"); - } - return objectMapper.readTree(payload); - } catch (IllegalArgumentException e) { - throw new FacturapiException("Invalid signature", e); - } catch (NoSuchAlgorithmException | InvalidKeyException e) { - throw new FacturapiException("Signature validation failure", e); - } catch (Exception e) { - if (e instanceof FacturapiException) { - throw (FacturapiException) e; - } - throw new FacturapiException("Invalid payload", e); - } - } - - public JsonNode validateSignature(String secret, String signatureHex, JsonNode payload) { - return validateSignature(secret, signatureHex, payload.toString()); - } - - private static byte[] hmacSha256(String secret, String payload) - throws NoSuchAlgorithmException, InvalidKeyException { - Mac mac = Mac.getInstance("HmacSHA256"); - mac.init(new SecretKeySpec(secret.getBytes(StandardCharsets.UTF_8), "HmacSHA256")); - return mac.doFinal(payload.getBytes(StandardCharsets.UTF_8)); - } - - private static byte[] hexToBytes(String hex) { - if (hex == null || hex.length() % 2 != 0) { - throw new IllegalArgumentException("Invalid signature"); - } - int length = hex.length(); - byte[] bytes = new byte[length / 2]; - for (int i = 0; i < length; i += 2) { - int high = Character.digit(hex.charAt(i), 16); - int low = Character.digit(hex.charAt(i + 1), 16); - if (high < 0 || low < 0) { - throw new IllegalArgumentException("Invalid signature"); - } - bytes[i / 2] = (byte) ((high << 4) + low); - } - return bytes; - } -} diff --git a/src/main/java/com/facturapi/tools/CartaPorteCatalogsTool.java b/src/main/java/com/facturapi/tools/CartaPorteCatalogsTool.java deleted file mode 100644 index 45cd752..0000000 --- a/src/main/java/com/facturapi/tools/CartaPorteCatalogsTool.java +++ /dev/null @@ -1,54 +0,0 @@ -package com.facturapi.tools; - -import com.fasterxml.jackson.databind.JsonNode; -import com.facturapi.http.FacturapiHttpClient; -import java.util.Map; - -public class CartaPorteCatalogsTool { - private static final String BASE_PATH = "/catalogs/cartaporte/3.1"; - private final FacturapiHttpClient client; - - public CartaPorteCatalogsTool(FacturapiHttpClient client) { - this.client = client; - } - - public JsonNode searchAirTransportCodes(Map params) { - return client.getJson(BASE_PATH + "/air-transport-codes", params); - } - - public JsonNode searchTransportConfigs(Map params) { - return client.getJson(BASE_PATH + "/transport-configs", params); - } - - public JsonNode searchRightsOfPassage(Map params) { - return client.getJson(BASE_PATH + "/rights-of-passage", params); - } - - public JsonNode searchCustomsDocuments(Map params) { - return client.getJson(BASE_PATH + "/customs-documents", params); - } - - public JsonNode searchPackagingTypes(Map params) { - return client.getJson(BASE_PATH + "/packaging-types", params); - } - - public JsonNode searchTrailerTypes(Map params) { - return client.getJson(BASE_PATH + "/trailer-types", params); - } - - public JsonNode searchHazardousMaterials(Map params) { - return client.getJson(BASE_PATH + "/hazardous-materials", params); - } - - public JsonNode searchNavalAuthorizations(Map params) { - return client.getJson(BASE_PATH + "/naval-authorizations", params); - } - - public JsonNode searchPortStations(Map params) { - return client.getJson(BASE_PATH + "/port-stations", params); - } - - public JsonNode searchMarineContainers(Map params) { - return client.getJson(BASE_PATH + "/marine-containers", params); - } -} diff --git a/src/main/java/com/facturapi/tools/CatalogsTool.java b/src/main/java/com/facturapi/tools/CatalogsTool.java deleted file mode 100644 index ced095e..0000000 --- a/src/main/java/com/facturapi/tools/CatalogsTool.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.facturapi.tools; - -import com.fasterxml.jackson.databind.JsonNode; -import com.facturapi.http.FacturapiHttpClient; -import java.util.Map; - -public class CatalogsTool { - private final FacturapiHttpClient client; - - public CatalogsTool(FacturapiHttpClient client) { - this.client = client; - } - - public JsonNode searchProducts(Map params) { - return client.getJson("/catalogs/products", params); - } - - public JsonNode searchUnits(Map params) { - return client.getJson("/catalogs/units", params); - } -} diff --git a/src/main/java/com/facturapi/tools/ComercioExteriorCatalogsTool.java b/src/main/java/com/facturapi/tools/ComercioExteriorCatalogsTool.java deleted file mode 100644 index 14ed9ec..0000000 --- a/src/main/java/com/facturapi/tools/ComercioExteriorCatalogsTool.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.facturapi.tools; - -import com.fasterxml.jackson.databind.JsonNode; -import com.facturapi.http.FacturapiHttpClient; -import java.util.Map; - -public class ComercioExteriorCatalogsTool { - private final FacturapiHttpClient client; - - public ComercioExteriorCatalogsTool(FacturapiHttpClient client) { - this.client = client; - } - - public JsonNode searchTariffFractions(Map params) { - return client.getJson("/catalogs/comercioexterior/2.0/tariff-fractions", params); - } -} diff --git a/src/main/java/com/facturapi/tools/ToolsResource.java b/src/main/java/com/facturapi/tools/ToolsResource.java deleted file mode 100644 index c2aec91..0000000 --- a/src/main/java/com/facturapi/tools/ToolsResource.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.facturapi.tools; - -import com.fasterxml.jackson.databind.JsonNode; -import com.facturapi.http.FacturapiHttpClient; -import java.util.Map; - -public class ToolsResource { - private final FacturapiHttpClient client; - - public ToolsResource(FacturapiHttpClient client) { - this.client = client; - } - - public JsonNode validateTaxId(String taxId) { - return client.getJson("/tools/tax_id_validation", Map.of("tax_id", taxId)); - } -} diff --git a/src/main/java/com/facturapi/ApiVersion.java b/src/main/java/io/facturapi/ApiVersion.java similarity index 95% rename from src/main/java/com/facturapi/ApiVersion.java rename to src/main/java/io/facturapi/ApiVersion.java index a5e5215..8a3424d 100644 --- a/src/main/java/com/facturapi/ApiVersion.java +++ b/src/main/java/io/facturapi/ApiVersion.java @@ -1,4 +1,4 @@ -package com.facturapi; +package io.facturapi; public enum ApiVersion { V1("v1"), diff --git a/src/main/java/com/facturapi/Facturapi.java b/src/main/java/io/facturapi/Facturapi.java similarity index 67% rename from src/main/java/com/facturapi/Facturapi.java rename to src/main/java/io/facturapi/Facturapi.java index 5a0f7b2..dd9c33e 100644 --- a/src/main/java/com/facturapi/Facturapi.java +++ b/src/main/java/io/facturapi/Facturapi.java @@ -1,23 +1,23 @@ -package com.facturapi; - -import com.facturapi.enums.CancellationMotive; -import com.facturapi.enums.InvoiceType; -import com.facturapi.enums.PaymentForm; -import com.facturapi.enums.TaxFactor; -import com.facturapi.enums.TaxType; -import com.facturapi.http.FacturapiConfig; -import com.facturapi.http.FacturapiHttpClient; -import com.facturapi.resources.CustomersResource; -import com.facturapi.resources.InvoicesResource; -import com.facturapi.resources.OrganizationsResource; -import com.facturapi.resources.ProductsResource; -import com.facturapi.resources.ReceiptsResource; -import com.facturapi.resources.RetentionsResource; -import com.facturapi.resources.WebhooksResource; -import com.facturapi.tools.CartaPorteCatalogsTool; -import com.facturapi.tools.CatalogsTool; -import com.facturapi.tools.ComercioExteriorCatalogsTool; -import com.facturapi.tools.ToolsResource; +package io.facturapi; + +import io.facturapi.enums.CancellationMotive; +import io.facturapi.enums.InvoiceType; +import io.facturapi.enums.PaymentForm; +import io.facturapi.enums.TaxFactor; +import io.facturapi.enums.TaxType; +import io.facturapi.http.FacturapiConfig; +import io.facturapi.http.FacturapiHttpClient; +import io.facturapi.resources.CustomersResource; +import io.facturapi.resources.InvoicesResource; +import io.facturapi.resources.OrganizationsResource; +import io.facturapi.resources.ProductsResource; +import io.facturapi.resources.ReceiptsResource; +import io.facturapi.resources.RetentionsResource; +import io.facturapi.resources.WebhooksResource; +import io.facturapi.tools.CartaPorteCatalogsTool; +import io.facturapi.tools.CatalogsTool; +import io.facturapi.tools.ComercioExteriorCatalogsTool; +import io.facturapi.tools.ToolsResource; import java.time.Duration; public class Facturapi { @@ -36,15 +36,30 @@ public class Facturapi { public final ComercioExteriorCatalogsTool comercioExteriorCatalogs; public final ToolsResource tools; + /** + * Creates a client using API v2. + * + * @param apiKey Facturapi API key. + */ public Facturapi(String apiKey) { this(FacturapiConfig.builder(apiKey).build()); } - // Backward-compatible constructor + /** + * Creates a client with an explicit API version. + * + * @param apiKey Facturapi API key. + * @param apiVersion API version: v1 or v2. + */ public Facturapi(String apiKey, String apiVersion) { this(FacturapiConfig.builder(apiKey).apiVersion(apiVersion).build()); } + /** + * Creates a client using a custom SDK configuration. + * + * @param config SDK configuration. + */ public Facturapi(FacturapiConfig config) { this.httpClient = new FacturapiHttpClient(config); this.customers = new CustomersResource(httpClient); @@ -61,6 +76,12 @@ public Facturapi(FacturapiConfig config) { this.tools = new ToolsResource(httpClient); } + /** + * Creates a builder for client initialization. + * + * @param apiKey Facturapi API key. + * @return Builder instance. + */ public static Builder builder(String apiKey) { return new Builder(apiKey); } @@ -82,21 +103,11 @@ public Builder apiVersion(String apiVersion) { return this; } - public Builder baseUrl(String baseUrl) { - this.configBuilder.baseUrl(baseUrl); - return this; - } - public Builder timeout(Duration timeout) { this.configBuilder.timeout(timeout); return this; } - public Builder userAgent(String userAgent) { - this.configBuilder.userAgent(userAgent); - return this; - } - public Facturapi build() { return new Facturapi(configBuilder.build()); } diff --git a/src/main/java/com/facturapi/FacturapiException.java b/src/main/java/io/facturapi/FacturapiException.java similarity index 96% rename from src/main/java/com/facturapi/FacturapiException.java rename to src/main/java/io/facturapi/FacturapiException.java index b56c4c5..e9f3030 100644 --- a/src/main/java/com/facturapi/FacturapiException.java +++ b/src/main/java/io/facturapi/FacturapiException.java @@ -1,4 +1,4 @@ -package com.facturapi; +package io.facturapi; public class FacturapiException extends RuntimeException { private final int statusCode; diff --git a/src/main/java/com/facturapi/constants/FacturapiConstants.java b/src/main/java/io/facturapi/constants/FacturapiConstants.java similarity index 87% rename from src/main/java/com/facturapi/constants/FacturapiConstants.java rename to src/main/java/io/facturapi/constants/FacturapiConstants.java index 2955174..76bde44 100644 --- a/src/main/java/com/facturapi/constants/FacturapiConstants.java +++ b/src/main/java/io/facturapi/constants/FacturapiConstants.java @@ -1,4 +1,4 @@ -package com.facturapi.constants; +package io.facturapi.constants; public final class FacturapiConstants { public static final String BASE_URL_V1 = "https://www.facturapi.io/v1"; diff --git a/src/main/java/com/facturapi/enums/CancellationMotive.java b/src/main/java/io/facturapi/enums/CancellationMotive.java similarity index 90% rename from src/main/java/com/facturapi/enums/CancellationMotive.java rename to src/main/java/io/facturapi/enums/CancellationMotive.java index 61f0362..9f4a60a 100644 --- a/src/main/java/com/facturapi/enums/CancellationMotive.java +++ b/src/main/java/io/facturapi/enums/CancellationMotive.java @@ -1,4 +1,4 @@ -package com.facturapi.enums; +package io.facturapi.enums; public enum CancellationMotive { ERRORES_CON_RELACION("01"), diff --git a/src/main/java/com/facturapi/enums/InvoiceType.java b/src/main/java/io/facturapi/enums/InvoiceType.java similarity index 89% rename from src/main/java/com/facturapi/enums/InvoiceType.java rename to src/main/java/io/facturapi/enums/InvoiceType.java index 0487742..bed4f8f 100644 --- a/src/main/java/com/facturapi/enums/InvoiceType.java +++ b/src/main/java/io/facturapi/enums/InvoiceType.java @@ -1,4 +1,4 @@ -package com.facturapi.enums; +package io.facturapi.enums; public enum InvoiceType { INGRESO("I"), diff --git a/src/main/java/com/facturapi/enums/PaymentForm.java b/src/main/java/io/facturapi/enums/PaymentForm.java similarity index 92% rename from src/main/java/com/facturapi/enums/PaymentForm.java rename to src/main/java/io/facturapi/enums/PaymentForm.java index e67fc1e..76a036e 100644 --- a/src/main/java/com/facturapi/enums/PaymentForm.java +++ b/src/main/java/io/facturapi/enums/PaymentForm.java @@ -1,4 +1,4 @@ -package com.facturapi.enums; +package io.facturapi.enums; public enum PaymentForm { EFECTIVO("01"), diff --git a/src/main/java/com/facturapi/enums/TaxFactor.java b/src/main/java/io/facturapi/enums/TaxFactor.java similarity index 59% rename from src/main/java/com/facturapi/enums/TaxFactor.java rename to src/main/java/io/facturapi/enums/TaxFactor.java index 2898cf5..416e3ae 100644 --- a/src/main/java/com/facturapi/enums/TaxFactor.java +++ b/src/main/java/io/facturapi/enums/TaxFactor.java @@ -1,4 +1,4 @@ -package com.facturapi.enums; +package io.facturapi.enums; public enum TaxFactor { Tasa, diff --git a/src/main/java/com/facturapi/enums/TaxType.java b/src/main/java/io/facturapi/enums/TaxType.java similarity index 61% rename from src/main/java/com/facturapi/enums/TaxType.java rename to src/main/java/io/facturapi/enums/TaxType.java index a56c26c..cc9ca14 100644 --- a/src/main/java/com/facturapi/enums/TaxType.java +++ b/src/main/java/io/facturapi/enums/TaxType.java @@ -1,4 +1,4 @@ -package com.facturapi.enums; +package io.facturapi.enums; public enum TaxType { IVA, diff --git a/src/main/java/com/facturapi/http/FacturapiConfig.java b/src/main/java/io/facturapi/http/FacturapiConfig.java similarity index 62% rename from src/main/java/com/facturapi/http/FacturapiConfig.java rename to src/main/java/io/facturapi/http/FacturapiConfig.java index 9f3d7d3..ee67bef 100644 --- a/src/main/java/com/facturapi/http/FacturapiConfig.java +++ b/src/main/java/io/facturapi/http/FacturapiConfig.java @@ -1,8 +1,9 @@ -package com.facturapi.http; +package io.facturapi.http; import com.fasterxml.jackson.databind.ObjectMapper; -import com.facturapi.ApiVersion; -import com.facturapi.constants.FacturapiConstants; +import com.fasterxml.jackson.databind.DeserializationFeature; +import io.facturapi.ApiVersion; +import io.facturapi.constants.FacturapiConstants; import java.net.http.HttpClient; import java.time.Duration; import java.util.Objects; @@ -63,7 +64,7 @@ public static final class Builder { private ApiVersion apiVersion = ApiVersion.V2; private String baseUrl; private Duration timeout = Duration.ofSeconds(30); - private String userAgent = "facturapi-java/1.x"; + private final String userAgent = "facturapi-java/0.1.x"; private HttpClient httpClient; private ObjectMapper objectMapper; @@ -84,53 +85,32 @@ public Builder apiVersion(String apiVersion) { return this; } - public Builder baseUrl(String baseUrl) { - this.baseUrl = Objects.requireNonNull(baseUrl, "baseUrl is required"); - return this; - } - public Builder timeout(Duration timeout) { this.timeout = Objects.requireNonNull(timeout, "timeout is required"); return this; } - public Builder userAgent(String userAgent) { - this.userAgent = Objects.requireNonNull(userAgent, "userAgent is required"); - return this; - } - public Builder httpClient(HttpClient httpClient) { this.httpClient = Objects.requireNonNull(httpClient, "httpClient is required"); return this; } - public Builder objectMapper(ObjectMapper objectMapper) { - this.objectMapper = Objects.requireNonNull(objectMapper, "objectMapper is required"); - return this; - } - public FacturapiConfig build() { - String resolvedBaseUrl = this.baseUrl; - if (resolvedBaseUrl == null || resolvedBaseUrl.trim().isEmpty()) { - resolvedBaseUrl = apiVersion == ApiVersion.V1 - ? FacturapiConstants.BASE_URL_V1 - : FacturapiConstants.BASE_URL_V2; - } - HttpClient resolvedClient = this.httpClient; - if (resolvedClient == null) { - resolvedClient = HttpClient.newBuilder() - .connectTimeout(timeout) - .build(); - } - ObjectMapper resolvedMapper = this.objectMapper == null ? new ObjectMapper() : this.objectMapper; - return new FacturapiConfig(new Builder(apiKey) - .apiVersion(apiVersion) - .baseUrl(resolvedBaseUrl) - .timeout(timeout) - .userAgent(userAgent) - .httpClient(resolvedClient) - .objectMapper(resolvedMapper) - ); + String resolvedBaseUrl = apiVersion == ApiVersion.V1 + ? FacturapiConstants.BASE_URL_V1 + : FacturapiConstants.BASE_URL_V2; + + HttpClient resolvedClient = this.httpClient == null + ? HttpClient.newBuilder().connectTimeout(timeout).build() + : this.httpClient; + + ObjectMapper resolvedMapper = new ObjectMapper() + .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + + this.baseUrl = resolvedBaseUrl; + this.httpClient = resolvedClient; + this.objectMapper = resolvedMapper; + return new FacturapiConfig(this); } } } diff --git a/src/main/java/com/facturapi/http/FacturapiHttpClient.java b/src/main/java/io/facturapi/http/FacturapiHttpClient.java similarity index 61% rename from src/main/java/com/facturapi/http/FacturapiHttpClient.java rename to src/main/java/io/facturapi/http/FacturapiHttpClient.java index 7f483a7..b0754a7 100644 --- a/src/main/java/com/facturapi/http/FacturapiHttpClient.java +++ b/src/main/java/io/facturapi/http/FacturapiHttpClient.java @@ -1,8 +1,9 @@ -package com.facturapi.http; +package io.facturapi.http; +import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; -import com.facturapi.FacturapiException; +import io.facturapi.FacturapiException; import java.io.IOException; import java.net.URI; import java.net.URLEncoder; @@ -33,28 +34,44 @@ public FacturapiHttpClient(FacturapiConfig config) { this.userAgent = config.getUserAgent(); } - public JsonNode getJson(String path, Map queryParams) { - return requestJson("GET", path, queryParams, null, null); + public ObjectMapper getObjectMapper() { + return objectMapper; } - public JsonNode postJson(String path, Object body, Map queryParams) { - return requestJson("POST", path, queryParams, body, null); + public T get(String path, Map queryParams, Class responseType) { + return convert(requestJsonNode("GET", path, queryParams, null, null), responseType); } - public JsonNode putJson(String path, Object body, Map queryParams) { - return requestJson("PUT", path, queryParams, body, null); + public T get(String path, Map queryParams, TypeReference typeReference) { + return convert(requestJsonNode("GET", path, queryParams, null, null), typeReference); } - public JsonNode deleteJson(String path, Map queryParams) { - return requestJson("DELETE", path, queryParams, null, null); + public T post(String path, Object body, Map queryParams, Class responseType) { + return convert(requestJsonNode("POST", path, queryParams, body, null), responseType); } - public JsonNode putMultipart(String path, MultipartBody multipartBody) { - return requestJson("PUT", path, null, null, multipartBody); + public T post(String path, Object body, Map queryParams, TypeReference typeReference) { + return convert(requestJsonNode("POST", path, queryParams, body, null), typeReference); } - public JsonNode postMultipart(String path, MultipartBody multipartBody) { - return requestJson("POST", path, null, null, multipartBody); + public T put(String path, Object body, Map queryParams, Class responseType) { + return convert(requestJsonNode("PUT", path, queryParams, body, null), responseType); + } + + public T put(String path, Object body, Map queryParams, TypeReference typeReference) { + return convert(requestJsonNode("PUT", path, queryParams, body, null), typeReference); + } + + public T delete(String path, Map queryParams, Class responseType) { + return convert(requestJsonNode("DELETE", path, queryParams, null, null), responseType); + } + + public T delete(String path, Map queryParams, TypeReference typeReference) { + return convert(requestJsonNode("DELETE", path, queryParams, null, null), typeReference); + } + + public T putMultipart(String path, MultipartBody multipartBody, Class responseType) { + return convert(requestJsonNode("PUT", path, null, null, multipartBody), responseType); } public byte[] getBytes(String path) { @@ -65,7 +82,7 @@ public byte[] postBytes(String path, Object body) { return requestBytes("POST", path, body); } - private JsonNode requestJson( + private JsonNode requestJsonNode( String method, String path, Map queryParams, @@ -76,13 +93,15 @@ private JsonNode requestJson( HttpRequest request = buildRequest(method, path, queryParams, body, multipartBody); HttpResponse response = httpClient.send(request, HttpResponse.BodyHandlers.ofByteArray()); validateResponse(response); + byte[] responseBytes = response.body(); if (responseBytes == null || responseBytes.length == 0) { - return objectMapper.createObjectNode(); + return objectMapper.nullNode(); } + String contentType = response.headers().firstValue("Content-Type").orElse(""); if (!contentType.contains("application/json")) { - return objectMapper.createObjectNode().put("value", new String(responseBytes, StandardCharsets.UTF_8)); + return objectMapper.valueToTree(new String(responseBytes, StandardCharsets.UTF_8)); } return objectMapper.readTree(responseBytes); } catch (IOException e) { @@ -107,6 +126,50 @@ private byte[] requestBytes(String method, String path, Object body) { } } + private T convert(JsonNode node, Class type) { + if (type == Void.class) { + return null; + } + if (type == String.class) { + if (node == null || node.isNull()) { + return type.cast(""); + } + if (node.isTextual()) { + return type.cast(node.asText()); + } + if (node.isObject()) { + JsonNode value = firstDefined(node, "api_key", "key", "token", "value"); + if (value != null && value.isTextual()) { + return type.cast(value.asText()); + } + } + return type.cast(node.toString()); + } + try { + return objectMapper.convertValue(node, type); + } catch (IllegalArgumentException e) { + throw new FacturapiException("Could not deserialize response to " + type.getSimpleName(), e); + } + } + + private T convert(JsonNode node, TypeReference typeReference) { + try { + return objectMapper.convertValue(node, typeReference); + } catch (IllegalArgumentException e) { + throw new FacturapiException("Could not deserialize response", e); + } + } + + private static JsonNode firstDefined(JsonNode node, String... keys) { + for (String key : keys) { + JsonNode value = node.get(key); + if (value != null && !value.isNull()) { + return value; + } + } + return null; + } + private HttpRequest buildRequest( String method, String path, @@ -140,11 +203,12 @@ private void validateResponse(HttpResponse response) { int statusCode = response.statusCode(); if (statusCode < 200 || statusCode >= 300) { String bodyText = response.body() == null ? "" : new String(response.body(), StandardCharsets.UTF_8); - String message = statusCode + " " + response.headers().firstValue(":status").orElse("Request failed"); + String message = "Request failed with status " + statusCode; try { JsonNode error = objectMapper.readTree(bodyText); - if (error.has("message") && error.get("message").isTextual()) { - message = error.get("message").asText(); + JsonNode messageNode = firstDefined(error, "message", "error", "detail"); + if (messageNode != null && messageNode.isTextual()) { + message = messageNode.asText(); } else if (!bodyText.isEmpty()) { message = bodyText; } diff --git a/src/main/java/com/facturapi/http/MultipartBody.java b/src/main/java/io/facturapi/http/MultipartBody.java similarity index 94% rename from src/main/java/com/facturapi/http/MultipartBody.java rename to src/main/java/io/facturapi/http/MultipartBody.java index 288997c..314c18f 100644 --- a/src/main/java/com/facturapi/http/MultipartBody.java +++ b/src/main/java/io/facturapi/http/MultipartBody.java @@ -1,4 +1,4 @@ -package com.facturapi.http; +package io.facturapi.http; import java.net.http.HttpRequest; diff --git a/src/main/java/com/facturapi/http/MultipartBodyBuilder.java b/src/main/java/io/facturapi/http/MultipartBodyBuilder.java similarity index 98% rename from src/main/java/com/facturapi/http/MultipartBodyBuilder.java rename to src/main/java/io/facturapi/http/MultipartBodyBuilder.java index f139a38..8829318 100644 --- a/src/main/java/com/facturapi/http/MultipartBodyBuilder.java +++ b/src/main/java/io/facturapi/http/MultipartBodyBuilder.java @@ -1,4 +1,4 @@ -package com.facturapi.http; +package io.facturapi.http; import java.net.http.HttpRequest; import java.nio.charset.StandardCharsets; diff --git a/src/main/java/io/facturapi/models/Address.java b/src/main/java/io/facturapi/models/Address.java new file mode 100644 index 0000000..2833c5c --- /dev/null +++ b/src/main/java/io/facturapi/models/Address.java @@ -0,0 +1,88 @@ +package io.facturapi.models; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class Address { + private String street; + private String exterior; + private String interior; + private String neighborhood; + private String city; + private String municipality; + private String state; + private String country; + private String zip; + + public String getStreet() { + return street; + } + + public void setStreet(String street) { + this.street = street; + } + + public String getExterior() { + return exterior; + } + + public void setExterior(String exterior) { + this.exterior = exterior; + } + + public String getInterior() { + return interior; + } + + public void setInterior(String interior) { + this.interior = interior; + } + + public String getNeighborhood() { + return neighborhood; + } + + public void setNeighborhood(String neighborhood) { + this.neighborhood = neighborhood; + } + + public String getCity() { + return city; + } + + public void setCity(String city) { + this.city = city; + } + + public String getMunicipality() { + return municipality; + } + + public void setMunicipality(String municipality) { + this.municipality = municipality; + } + + public String getState() { + return state; + } + + public void setState(String state) { + this.state = state; + } + + public String getCountry() { + return country; + } + + public void setCountry(String country) { + this.country = country; + } + + public String getZip() { + return zip; + } + + public void setZip(String zip) { + this.zip = zip; + } +} diff --git a/src/main/java/io/facturapi/models/ApiEvent.java b/src/main/java/io/facturapi/models/ApiEvent.java new file mode 100644 index 0000000..c1cd047 --- /dev/null +++ b/src/main/java/io/facturapi/models/ApiEvent.java @@ -0,0 +1,25 @@ +package io.facturapi.models; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class ApiEvent { + @JsonProperty("created_at") + private String createdAt; + private String organization; + private Boolean livemode; + private String type; + private ApiEventData data; + + public String getCreatedAt() { return createdAt; } + public void setCreatedAt(String createdAt) { this.createdAt = createdAt; } + public String getOrganization() { return organization; } + public void setOrganization(String organization) { this.organization = organization; } + public Boolean getLivemode() { return livemode; } + public void setLivemode(Boolean livemode) { this.livemode = livemode; } + public String getType() { return type; } + public void setType(String type) { this.type = type; } + public ApiEventData getData() { return data; } + public void setData(ApiEventData data) { this.data = data; } +} diff --git a/src/main/java/io/facturapi/models/ApiEventData.java b/src/main/java/io/facturapi/models/ApiEventData.java new file mode 100644 index 0000000..21bc22e --- /dev/null +++ b/src/main/java/io/facturapi/models/ApiEventData.java @@ -0,0 +1,14 @@ +package io.facturapi.models; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class ApiEventData { + private String type; + private Object object; + + public String getType() { return type; } + public void setType(String type) { this.type = type; } + public Object getObject() { return object; } + public void setObject(Object object) { this.object = object; } +} diff --git a/src/main/java/io/facturapi/models/ApiKey.java b/src/main/java/io/facturapi/models/ApiKey.java new file mode 100644 index 0000000..c4ae528 --- /dev/null +++ b/src/main/java/io/facturapi/models/ApiKey.java @@ -0,0 +1,25 @@ +package io.facturapi.models; + +import com.fasterxml.jackson.annotation.JsonAlias; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class ApiKey { + private String id; + @JsonProperty("first_12") + private String first12; + @JsonProperty("created_at") + private String createdAt; + @JsonAlias({"key", "api_key", "token"}) + private String key; + + public String getId() { return id; } + public void setId(String id) { this.id = id; } + public String getFirst12() { return first12; } + public void setFirst12(String first12) { this.first12 = first12; } + public String getCreatedAt() { return createdAt; } + public void setCreatedAt(String createdAt) { this.createdAt = createdAt; } + public String getKey() { return key; } + public void setKey(String key) { this.key = key; } +} diff --git a/src/main/java/io/facturapi/models/CartaPorteAutotransporte.java b/src/main/java/io/facturapi/models/CartaPorteAutotransporte.java new file mode 100644 index 0000000..01dd907 --- /dev/null +++ b/src/main/java/io/facturapi/models/CartaPorteAutotransporte.java @@ -0,0 +1,31 @@ +package io.facturapi.models; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import java.util.ArrayList; +import java.util.List; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class CartaPorteAutotransporte { + @JsonProperty("PermSCT") + private String permSct; + @JsonProperty("NumPermisoSCT") + private String numPermisoSct; + @JsonProperty("IdentificacionVehicular") + private CartaPorteIdentificacionVehicular identificacionVehicular; + @JsonProperty("Seguros") + private CartaPorteSeguros seguros; + @JsonProperty("Remolques") + private List remolques = new ArrayList<>(); + + public String getPermSct() { return permSct; } + public void setPermSct(String permSct) { this.permSct = permSct; } + public String getNumPermisoSct() { return numPermisoSct; } + public void setNumPermisoSct(String numPermisoSct) { this.numPermisoSct = numPermisoSct; } + public CartaPorteIdentificacionVehicular getIdentificacionVehicular() { return identificacionVehicular; } + public void setIdentificacionVehicular(CartaPorteIdentificacionVehicular identificacionVehicular) { this.identificacionVehicular = identificacionVehicular; } + public CartaPorteSeguros getSeguros() { return seguros; } + public void setSeguros(CartaPorteSeguros seguros) { this.seguros = seguros; } + public List getRemolques() { return remolques; } + public void setRemolques(List remolques) { this.remolques = remolques; } +} diff --git a/src/main/java/io/facturapi/models/CartaPorteCantidadTransporta.java b/src/main/java/io/facturapi/models/CartaPorteCantidadTransporta.java new file mode 100644 index 0000000..7bf5ec4 --- /dev/null +++ b/src/main/java/io/facturapi/models/CartaPorteCantidadTransporta.java @@ -0,0 +1,25 @@ +package io.facturapi.models; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class CartaPorteCantidadTransporta { + @JsonProperty("Cantidad") + private Double cantidad; + @JsonProperty("IDOrigen") + private String idOrigen; + @JsonProperty("IDDestino") + private String idDestino; + @JsonProperty("CvesTransporte") + private String cvesTransporte; + + public Double getCantidad() { return cantidad; } + public void setCantidad(Double cantidad) { this.cantidad = cantidad; } + public String getIdOrigen() { return idOrigen; } + public void setIdOrigen(String idOrigen) { this.idOrigen = idOrigen; } + public String getIdDestino() { return idDestino; } + public void setIdDestino(String idDestino) { this.idDestino = idDestino; } + public String getCvesTransporte() { return cvesTransporte; } + public void setCvesTransporte(String cvesTransporte) { this.cvesTransporte = cvesTransporte; } +} diff --git a/src/main/java/io/facturapi/models/CartaPorteCarroFerroviario.java b/src/main/java/io/facturapi/models/CartaPorteCarroFerroviario.java new file mode 100644 index 0000000..38a98ee --- /dev/null +++ b/src/main/java/io/facturapi/models/CartaPorteCarroFerroviario.java @@ -0,0 +1,31 @@ +package io.facturapi.models; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import java.util.ArrayList; +import java.util.List; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class CartaPorteCarroFerroviario { + @JsonProperty("TipoCarro") + private String tipoCarro; + @JsonProperty("MatriculaCarro") + private String matriculaCarro; + @JsonProperty("GuiaCarro") + private String guiaCarro; + @JsonProperty("ToneladasNetasCarro") + private Double toneladasNetasCarro; + @JsonProperty("Contenedor") + private List contenedor = new ArrayList<>(); + + public String getTipoCarro() { return tipoCarro; } + public void setTipoCarro(String tipoCarro) { this.tipoCarro = tipoCarro; } + public String getMatriculaCarro() { return matriculaCarro; } + public void setMatriculaCarro(String matriculaCarro) { this.matriculaCarro = matriculaCarro; } + public String getGuiaCarro() { return guiaCarro; } + public void setGuiaCarro(String guiaCarro) { this.guiaCarro = guiaCarro; } + public Double getToneladasNetasCarro() { return toneladasNetasCarro; } + public void setToneladasNetasCarro(Double toneladasNetasCarro) { this.toneladasNetasCarro = toneladasNetasCarro; } + public List getContenedor() { return contenedor; } + public void setContenedor(List contenedor) { this.contenedor = contenedor; } +} diff --git a/src/main/java/io/facturapi/models/CartaPorteComplementData.java b/src/main/java/io/facturapi/models/CartaPorteComplementData.java new file mode 100644 index 0000000..3d20323 --- /dev/null +++ b/src/main/java/io/facturapi/models/CartaPorteComplementData.java @@ -0,0 +1,65 @@ +package io.facturapi.models; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class CartaPorteComplementData { + @JsonProperty("IdCCP") + private String idCcp; + @JsonProperty("TranspInternac") + private String transpInternac; + @JsonProperty("EntradaSalidaMerc") + private String entradaSalidaMerc; + @JsonProperty("PaisOrigenDestino") + private String paisOrigenDestino; + @JsonProperty("ViaEntradaSalida") + private String viaEntradaSalida; + @JsonProperty("TotalDistRec") + private Double totalDistRec; + @JsonProperty("RegistroISTMO") + private String registroIstmo; + @JsonProperty("UbicacionPoloOrigen") + private String ubicacionPoloOrigen; + @JsonProperty("UbicacionPoloDestino") + private String ubicacionPoloDestino; + @JsonProperty("RegimenesAduaneros") + private Map regimenesAduaneros = new HashMap<>(); + @JsonProperty("Ubicaciones") + private List ubicaciones = new ArrayList<>(); + @JsonProperty("Mercancias") + private CartaPorteMercancias mercancias; + @JsonProperty("FiguraTransporte") + private List figuraTransporte = new ArrayList<>(); + + public String getIdCcp() { return idCcp; } + public void setIdCcp(String idCcp) { this.idCcp = idCcp; } + public String getTranspInternac() { return transpInternac; } + public void setTranspInternac(String transpInternac) { this.transpInternac = transpInternac; } + public String getEntradaSalidaMerc() { return entradaSalidaMerc; } + public void setEntradaSalidaMerc(String entradaSalidaMerc) { this.entradaSalidaMerc = entradaSalidaMerc; } + public String getPaisOrigenDestino() { return paisOrigenDestino; } + public void setPaisOrigenDestino(String paisOrigenDestino) { this.paisOrigenDestino = paisOrigenDestino; } + public String getViaEntradaSalida() { return viaEntradaSalida; } + public void setViaEntradaSalida(String viaEntradaSalida) { this.viaEntradaSalida = viaEntradaSalida; } + public Double getTotalDistRec() { return totalDistRec; } + public void setTotalDistRec(Double totalDistRec) { this.totalDistRec = totalDistRec; } + public String getRegistroIstmo() { return registroIstmo; } + public void setRegistroIstmo(String registroIstmo) { this.registroIstmo = registroIstmo; } + public String getUbicacionPoloOrigen() { return ubicacionPoloOrigen; } + public void setUbicacionPoloOrigen(String ubicacionPoloOrigen) { this.ubicacionPoloOrigen = ubicacionPoloOrigen; } + public String getUbicacionPoloDestino() { return ubicacionPoloDestino; } + public void setUbicacionPoloDestino(String ubicacionPoloDestino) { this.ubicacionPoloDestino = ubicacionPoloDestino; } + public Map getRegimenesAduaneros() { return regimenesAduaneros; } + public void setRegimenesAduaneros(Map regimenesAduaneros) { this.regimenesAduaneros = regimenesAduaneros; } + public List getUbicaciones() { return ubicaciones; } + public void setUbicaciones(List ubicaciones) { this.ubicaciones = ubicaciones; } + public CartaPorteMercancias getMercancias() { return mercancias; } + public void setMercancias(CartaPorteMercancias mercancias) { this.mercancias = mercancias; } + public List getFiguraTransporte() { return figuraTransporte; } + public void setFiguraTransporte(List figuraTransporte) { this.figuraTransporte = figuraTransporte; } +} diff --git a/src/main/java/io/facturapi/models/CartaPorteContenedorFerroviario.java b/src/main/java/io/facturapi/models/CartaPorteContenedorFerroviario.java new file mode 100644 index 0000000..af2e6b8 --- /dev/null +++ b/src/main/java/io/facturapi/models/CartaPorteContenedorFerroviario.java @@ -0,0 +1,21 @@ +package io.facturapi.models; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class CartaPorteContenedorFerroviario { + @JsonProperty("TipoContenedor") + private String tipoContenedor; + @JsonProperty("PesoContenedorVacio") + private Double pesoContenedorVacio; + @JsonProperty("PesoNetoMercancia") + private Double pesoNetoMercancia; + + public String getTipoContenedor() { return tipoContenedor; } + public void setTipoContenedor(String tipoContenedor) { this.tipoContenedor = tipoContenedor; } + public Double getPesoContenedorVacio() { return pesoContenedorVacio; } + public void setPesoContenedorVacio(Double pesoContenedorVacio) { this.pesoContenedorVacio = pesoContenedorVacio; } + public Double getPesoNetoMercancia() { return pesoNetoMercancia; } + public void setPesoNetoMercancia(Double pesoNetoMercancia) { this.pesoNetoMercancia = pesoNetoMercancia; } +} diff --git a/src/main/java/io/facturapi/models/CartaPorteContenedorMaritimo.java b/src/main/java/io/facturapi/models/CartaPorteContenedorMaritimo.java new file mode 100644 index 0000000..21f306f --- /dev/null +++ b/src/main/java/io/facturapi/models/CartaPorteContenedorMaritimo.java @@ -0,0 +1,39 @@ +package io.facturapi.models; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import java.util.ArrayList; +import java.util.List; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class CartaPorteContenedorMaritimo { + @JsonProperty("TipoContenedor") + private String tipoContenedor; + @JsonProperty("MatriculaContenedor") + private String matriculaContenedor; + @JsonProperty("NumPrecinto") + private String numPrecinto; + @JsonProperty("IdCCPRelacionado") + private String idCcpRelacionado; + @JsonProperty("PlacaVMCCP") + private String placaVmCcp; + @JsonProperty("FechaCertificacionCCP") + private String fechaCertificacionCcp; + @JsonProperty("RemolquesCCP") + private List remolquesCcp = new ArrayList<>(); + + public String getTipoContenedor() { return tipoContenedor; } + public void setTipoContenedor(String tipoContenedor) { this.tipoContenedor = tipoContenedor; } + public String getMatriculaContenedor() { return matriculaContenedor; } + public void setMatriculaContenedor(String matriculaContenedor) { this.matriculaContenedor = matriculaContenedor; } + public String getNumPrecinto() { return numPrecinto; } + public void setNumPrecinto(String numPrecinto) { this.numPrecinto = numPrecinto; } + public String getIdCcpRelacionado() { return idCcpRelacionado; } + public void setIdCcpRelacionado(String idCcpRelacionado) { this.idCcpRelacionado = idCcpRelacionado; } + public String getPlacaVmCcp() { return placaVmCcp; } + public void setPlacaVmCcp(String placaVmCcp) { this.placaVmCcp = placaVmCcp; } + public String getFechaCertificacionCcp() { return fechaCertificacionCcp; } + public void setFechaCertificacionCcp(String fechaCertificacionCcp) { this.fechaCertificacionCcp = fechaCertificacionCcp; } + public List getRemolquesCcp() { return remolquesCcp; } + public void setRemolquesCcp(List remolquesCcp) { this.remolquesCcp = remolquesCcp; } +} diff --git a/src/main/java/io/facturapi/models/CartaPorteDerechosDePaso.java b/src/main/java/io/facturapi/models/CartaPorteDerechosDePaso.java new file mode 100644 index 0000000..a35c287 --- /dev/null +++ b/src/main/java/io/facturapi/models/CartaPorteDerechosDePaso.java @@ -0,0 +1,17 @@ +package io.facturapi.models; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class CartaPorteDerechosDePaso { + @JsonProperty("TipoDerechoDePaso") + private String tipoDerechoDePaso; + @JsonProperty("KilometrajePagado") + private Double kilometrajePagado; + + public String getTipoDerechoDePaso() { return tipoDerechoDePaso; } + public void setTipoDerechoDePaso(String tipoDerechoDePaso) { this.tipoDerechoDePaso = tipoDerechoDePaso; } + public Double getKilometrajePagado() { return kilometrajePagado; } + public void setKilometrajePagado(Double kilometrajePagado) { this.kilometrajePagado = kilometrajePagado; } +} diff --git a/src/main/java/io/facturapi/models/CartaPorteDetalleMercancia.java b/src/main/java/io/facturapi/models/CartaPorteDetalleMercancia.java new file mode 100644 index 0000000..538eac2 --- /dev/null +++ b/src/main/java/io/facturapi/models/CartaPorteDetalleMercancia.java @@ -0,0 +1,29 @@ +package io.facturapi.models; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class CartaPorteDetalleMercancia { + @JsonProperty("UnidadPesoMerc") + private String unidadPesoMerc; + @JsonProperty("PesoBruto") + private Double pesoBruto; + @JsonProperty("PesoNeto") + private Double pesoNeto; + @JsonProperty("PesoTara") + private Double pesoTara; + @JsonProperty("NumPiezas") + private Double numPiezas; + + public String getUnidadPesoMerc() { return unidadPesoMerc; } + public void setUnidadPesoMerc(String unidadPesoMerc) { this.unidadPesoMerc = unidadPesoMerc; } + public Double getPesoBruto() { return pesoBruto; } + public void setPesoBruto(Double pesoBruto) { this.pesoBruto = pesoBruto; } + public Double getPesoNeto() { return pesoNeto; } + public void setPesoNeto(Double pesoNeto) { this.pesoNeto = pesoNeto; } + public Double getPesoTara() { return pesoTara; } + public void setPesoTara(Double pesoTara) { this.pesoTara = pesoTara; } + public Double getNumPiezas() { return numPiezas; } + public void setNumPiezas(Double numPiezas) { this.numPiezas = numPiezas; } +} diff --git a/src/main/java/io/facturapi/models/CartaPorteDocumentacionAduanera.java b/src/main/java/io/facturapi/models/CartaPorteDocumentacionAduanera.java new file mode 100644 index 0000000..312bec9 --- /dev/null +++ b/src/main/java/io/facturapi/models/CartaPorteDocumentacionAduanera.java @@ -0,0 +1,25 @@ +package io.facturapi.models; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class CartaPorteDocumentacionAduanera { + @JsonProperty("TipoDocumento") + private String tipoDocumento; + @JsonProperty("NumPedimento") + private String numPedimento; + @JsonProperty("IdentDocAduanero") + private String identDocAduanero; + @JsonProperty("RFCImpo") + private String rfcImpo; + + public String getTipoDocumento() { return tipoDocumento; } + public void setTipoDocumento(String tipoDocumento) { this.tipoDocumento = tipoDocumento; } + public String getNumPedimento() { return numPedimento; } + public void setNumPedimento(String numPedimento) { this.numPedimento = numPedimento; } + public String getIdentDocAduanero() { return identDocAduanero; } + public void setIdentDocAduanero(String identDocAduanero) { this.identDocAduanero = identDocAduanero; } + public String getRfcImpo() { return rfcImpo; } + public void setRfcImpo(String rfcImpo) { this.rfcImpo = rfcImpo; } +} diff --git a/src/main/java/io/facturapi/models/CartaPorteDomicilio.java b/src/main/java/io/facturapi/models/CartaPorteDomicilio.java new file mode 100644 index 0000000..ba8c0fb --- /dev/null +++ b/src/main/java/io/facturapi/models/CartaPorteDomicilio.java @@ -0,0 +1,49 @@ +package io.facturapi.models; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class CartaPorteDomicilio { + @JsonProperty("Calle") + private String calle; + @JsonProperty("NumeroExterior") + private String numeroExterior; + @JsonProperty("NumeroInterior") + private String numeroInterior; + @JsonProperty("Colonia") + private String colonia; + @JsonProperty("Localidad") + private String localidad; + @JsonProperty("Referencia") + private String referencia; + @JsonProperty("Municipio") + private String municipio; + @JsonProperty("Estado") + private String estado; + @JsonProperty("Pais") + private String pais; + @JsonProperty("CodigoPostal") + private String codigoPostal; + + public String getCalle() { return calle; } + public void setCalle(String calle) { this.calle = calle; } + public String getNumeroExterior() { return numeroExterior; } + public void setNumeroExterior(String numeroExterior) { this.numeroExterior = numeroExterior; } + public String getNumeroInterior() { return numeroInterior; } + public void setNumeroInterior(String numeroInterior) { this.numeroInterior = numeroInterior; } + public String getColonia() { return colonia; } + public void setColonia(String colonia) { this.colonia = colonia; } + public String getLocalidad() { return localidad; } + public void setLocalidad(String localidad) { this.localidad = localidad; } + public String getReferencia() { return referencia; } + public void setReferencia(String referencia) { this.referencia = referencia; } + public String getMunicipio() { return municipio; } + public void setMunicipio(String municipio) { this.municipio = municipio; } + public String getEstado() { return estado; } + public void setEstado(String estado) { this.estado = estado; } + public String getPais() { return pais; } + public void setPais(String pais) { this.pais = pais; } + public String getCodigoPostal() { return codigoPostal; } + public void setCodigoPostal(String codigoPostal) { this.codigoPostal = codigoPostal; } +} diff --git a/src/main/java/io/facturapi/models/CartaPorteFiguraTransporte.java b/src/main/java/io/facturapi/models/CartaPorteFiguraTransporte.java new file mode 100644 index 0000000..d6ae821 --- /dev/null +++ b/src/main/java/io/facturapi/models/CartaPorteFiguraTransporte.java @@ -0,0 +1,43 @@ +package io.facturapi.models; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import java.util.ArrayList; +import java.util.List; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class CartaPorteFiguraTransporte { + @JsonProperty("TipoFigura") + private String tipoFigura; + @JsonProperty("RFCFigura") + private String rfcFigura; + @JsonProperty("NumLicencia") + private String numLicencia; + @JsonProperty("NombreFigura") + private String nombreFigura; + @JsonProperty("NumRegIdTribFigura") + private String numRegIdTribFigura; + @JsonProperty("ResidenciaFiscalFigura") + private String residenciaFiscalFigura; + @JsonProperty("PartesTransporte") + private List partesTransporte = new ArrayList<>(); + @JsonProperty("Domicilio") + private CartaPorteDomicilio domicilio; + + public String getTipoFigura() { return tipoFigura; } + public void setTipoFigura(String tipoFigura) { this.tipoFigura = tipoFigura; } + public String getRfcFigura() { return rfcFigura; } + public void setRfcFigura(String rfcFigura) { this.rfcFigura = rfcFigura; } + public String getNumLicencia() { return numLicencia; } + public void setNumLicencia(String numLicencia) { this.numLicencia = numLicencia; } + public String getNombreFigura() { return nombreFigura; } + public void setNombreFigura(String nombreFigura) { this.nombreFigura = nombreFigura; } + public String getNumRegIdTribFigura() { return numRegIdTribFigura; } + public void setNumRegIdTribFigura(String numRegIdTribFigura) { this.numRegIdTribFigura = numRegIdTribFigura; } + public String getResidenciaFiscalFigura() { return residenciaFiscalFigura; } + public void setResidenciaFiscalFigura(String residenciaFiscalFigura) { this.residenciaFiscalFigura = residenciaFiscalFigura; } + public List getPartesTransporte() { return partesTransporte; } + public void setPartesTransporte(List partesTransporte) { this.partesTransporte = partesTransporte; } + public CartaPorteDomicilio getDomicilio() { return domicilio; } + public void setDomicilio(CartaPorteDomicilio domicilio) { this.domicilio = domicilio; } +} diff --git a/src/main/java/io/facturapi/models/CartaPorteGuiaIdentificacion.java b/src/main/java/io/facturapi/models/CartaPorteGuiaIdentificacion.java new file mode 100644 index 0000000..8560435 --- /dev/null +++ b/src/main/java/io/facturapi/models/CartaPorteGuiaIdentificacion.java @@ -0,0 +1,21 @@ +package io.facturapi.models; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class CartaPorteGuiaIdentificacion { + @JsonProperty("NumeroGuiaIdentificacion") + private String numeroGuiaIdentificacion; + @JsonProperty("DescripGuiaIdentificacion") + private String descripGuiaIdentificacion; + @JsonProperty("PesoGuiaIdentificacion") + private Double pesoGuiaIdentificacion; + + public String getNumeroGuiaIdentificacion() { return numeroGuiaIdentificacion; } + public void setNumeroGuiaIdentificacion(String numeroGuiaIdentificacion) { this.numeroGuiaIdentificacion = numeroGuiaIdentificacion; } + public String getDescripGuiaIdentificacion() { return descripGuiaIdentificacion; } + public void setDescripGuiaIdentificacion(String descripGuiaIdentificacion) { this.descripGuiaIdentificacion = descripGuiaIdentificacion; } + public Double getPesoGuiaIdentificacion() { return pesoGuiaIdentificacion; } + public void setPesoGuiaIdentificacion(Double pesoGuiaIdentificacion) { this.pesoGuiaIdentificacion = pesoGuiaIdentificacion; } +} diff --git a/src/main/java/io/facturapi/models/CartaPorteIdentificacionVehicular.java b/src/main/java/io/facturapi/models/CartaPorteIdentificacionVehicular.java new file mode 100644 index 0000000..4e4e8fd --- /dev/null +++ b/src/main/java/io/facturapi/models/CartaPorteIdentificacionVehicular.java @@ -0,0 +1,25 @@ +package io.facturapi.models; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class CartaPorteIdentificacionVehicular { + @JsonProperty("ConfigVehicular") + private String configVehicular; + @JsonProperty("PesoBrutoVehicular") + private Double pesoBrutoVehicular; + @JsonProperty("PlacaVM") + private String placaVm; + @JsonProperty("AnioModeloVM") + private String anioModeloVm; + + public String getConfigVehicular() { return configVehicular; } + public void setConfigVehicular(String configVehicular) { this.configVehicular = configVehicular; } + public Double getPesoBrutoVehicular() { return pesoBrutoVehicular; } + public void setPesoBrutoVehicular(Double pesoBrutoVehicular) { this.pesoBrutoVehicular = pesoBrutoVehicular; } + public String getPlacaVm() { return placaVm; } + public void setPlacaVm(String placaVm) { this.placaVm = placaVm; } + public String getAnioModeloVm() { return anioModeloVm; } + public void setAnioModeloVm(String anioModeloVm) { this.anioModeloVm = anioModeloVm; } +} diff --git a/src/main/java/io/facturapi/models/CartaPorteMercancia.java b/src/main/java/io/facturapi/models/CartaPorteMercancia.java new file mode 100644 index 0000000..1bda357 --- /dev/null +++ b/src/main/java/io/facturapi/models/CartaPorteMercancia.java @@ -0,0 +1,179 @@ +package io.facturapi.models; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import java.util.ArrayList; +import java.util.List; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class CartaPorteMercancia { + @JsonProperty("BienesTransp") + private String bienesTransp; + @JsonProperty("ClaveSTCC") + private String claveStcc; + @JsonProperty("Descripcion") + private String descripcion; + @JsonProperty("Cantidad") + private Double cantidad; + @JsonProperty("ClaveUnidad") + private String claveUnidad; + @JsonProperty("Unidad") + private String unidad; + @JsonProperty("Dimensiones") + private String dimensiones; + @JsonProperty("MaterialPeligroso") + private String materialPeligroso; + @JsonProperty("CveMaterialPeligroso") + private String cveMaterialPeligroso; + @JsonProperty("Embalaje") + private String embalaje; + @JsonProperty("DescripEmbalaje") + private String descripEmbalaje; + @JsonProperty("SectorCOFEPRIS") + private String sectorCofepris; + @JsonProperty("NombreIngredienteActivo") + private String nombreIngredienteActivo; + @JsonProperty("NomQuimico") + private String nomQuimico; + @JsonProperty("DenominacionGenericaProd") + private String denominacionGenericaProd; + @JsonProperty("DenominacionDistintivaProd") + private String denominacionDistintivaProd; + @JsonProperty("Fabricante") + private String fabricante; + @JsonProperty("FechaCaducidad") + private String fechaCaducidad; + @JsonProperty("LoteMedicamento") + private String loteMedicamento; + @JsonProperty("FormaFarmaceutica") + private String formaFarmaceutica; + @JsonProperty("CondicionesEspTransp") + private String condicionesEspTransp; + @JsonProperty("RegistroSanitarioFolioAutorizacion") + private String registroSanitarioFolioAutorizacion; + @JsonProperty("PermisoImportacion") + private String permisoImportacion; + @JsonProperty("FolioImpoVUCEM") + private String folioImpoVucem; + @JsonProperty("NumCAS") + private String numCas; + @JsonProperty("RazonSocialEmpImp") + private String razonSocialEmpImp; + @JsonProperty("NumRegSanPlagCOFEPRIS") + private String numRegSanPlagCofepris; + @JsonProperty("DatosFabricante") + private String datosFabricante; + @JsonProperty("DatosFormulador") + private String datosFormulador; + @JsonProperty("DatosMaquilador") + private String datosMaquilador; + @JsonProperty("UsoAutorizado") + private String usoAutorizado; + @JsonProperty("PesoEnKg") + private Double pesoEnKg; + @JsonProperty("ValorMercancia") + private Double valorMercancia; + @JsonProperty("Moneda") + private String moneda; + @JsonProperty("FraccionArancelaria") + private String fraccionArancelaria; + @JsonProperty("UUIDComercioExt") + private String uuidComercioExt; + @JsonProperty("TipoMateria") + private String tipoMateria; + @JsonProperty("DescripcionMateria") + private String descripcionMateria; + @JsonProperty("DocumentacionAduanera") + private List documentacionAduanera = new ArrayList<>(); + @JsonProperty("GuiasIdentificacion") + private List guiasIdentificacion = new ArrayList<>(); + @JsonProperty("CantidadTransporta") + private List cantidadTransporta = new ArrayList<>(); + @JsonProperty("DetalleMercancia") + private List detalleMercancia = new ArrayList<>(); + + public String getBienesTransp() { return bienesTransp; } + public void setBienesTransp(String bienesTransp) { this.bienesTransp = bienesTransp; } + public String getClaveStcc() { return claveStcc; } + public void setClaveStcc(String claveStcc) { this.claveStcc = claveStcc; } + public String getDescripcion() { return descripcion; } + public void setDescripcion(String descripcion) { this.descripcion = descripcion; } + public Double getCantidad() { return cantidad; } + public void setCantidad(Double cantidad) { this.cantidad = cantidad; } + public String getClaveUnidad() { return claveUnidad; } + public void setClaveUnidad(String claveUnidad) { this.claveUnidad = claveUnidad; } + public String getUnidad() { return unidad; } + public void setUnidad(String unidad) { this.unidad = unidad; } + public String getDimensiones() { return dimensiones; } + public void setDimensiones(String dimensiones) { this.dimensiones = dimensiones; } + public String getMaterialPeligroso() { return materialPeligroso; } + public void setMaterialPeligroso(String materialPeligroso) { this.materialPeligroso = materialPeligroso; } + public String getCveMaterialPeligroso() { return cveMaterialPeligroso; } + public void setCveMaterialPeligroso(String cveMaterialPeligroso) { this.cveMaterialPeligroso = cveMaterialPeligroso; } + public String getEmbalaje() { return embalaje; } + public void setEmbalaje(String embalaje) { this.embalaje = embalaje; } + public String getDescripEmbalaje() { return descripEmbalaje; } + public void setDescripEmbalaje(String descripEmbalaje) { this.descripEmbalaje = descripEmbalaje; } + public String getSectorCofepris() { return sectorCofepris; } + public void setSectorCofepris(String sectorCofepris) { this.sectorCofepris = sectorCofepris; } + public String getNombreIngredienteActivo() { return nombreIngredienteActivo; } + public void setNombreIngredienteActivo(String nombreIngredienteActivo) { this.nombreIngredienteActivo = nombreIngredienteActivo; } + public String getNomQuimico() { return nomQuimico; } + public void setNomQuimico(String nomQuimico) { this.nomQuimico = nomQuimico; } + public String getDenominacionGenericaProd() { return denominacionGenericaProd; } + public void setDenominacionGenericaProd(String denominacionGenericaProd) { this.denominacionGenericaProd = denominacionGenericaProd; } + public String getDenominacionDistintivaProd() { return denominacionDistintivaProd; } + public void setDenominacionDistintivaProd(String denominacionDistintivaProd) { this.denominacionDistintivaProd = denominacionDistintivaProd; } + public String getFabricante() { return fabricante; } + public void setFabricante(String fabricante) { this.fabricante = fabricante; } + public String getFechaCaducidad() { return fechaCaducidad; } + public void setFechaCaducidad(String fechaCaducidad) { this.fechaCaducidad = fechaCaducidad; } + public String getLoteMedicamento() { return loteMedicamento; } + public void setLoteMedicamento(String loteMedicamento) { this.loteMedicamento = loteMedicamento; } + public String getFormaFarmaceutica() { return formaFarmaceutica; } + public void setFormaFarmaceutica(String formaFarmaceutica) { this.formaFarmaceutica = formaFarmaceutica; } + public String getCondicionesEspTransp() { return condicionesEspTransp; } + public void setCondicionesEspTransp(String condicionesEspTransp) { this.condicionesEspTransp = condicionesEspTransp; } + public String getRegistroSanitarioFolioAutorizacion() { return registroSanitarioFolioAutorizacion; } + public void setRegistroSanitarioFolioAutorizacion(String registroSanitarioFolioAutorizacion) { this.registroSanitarioFolioAutorizacion = registroSanitarioFolioAutorizacion; } + public String getPermisoImportacion() { return permisoImportacion; } + public void setPermisoImportacion(String permisoImportacion) { this.permisoImportacion = permisoImportacion; } + public String getFolioImpoVucem() { return folioImpoVucem; } + public void setFolioImpoVucem(String folioImpoVucem) { this.folioImpoVucem = folioImpoVucem; } + public String getNumCas() { return numCas; } + public void setNumCas(String numCas) { this.numCas = numCas; } + public String getRazonSocialEmpImp() { return razonSocialEmpImp; } + public void setRazonSocialEmpImp(String razonSocialEmpImp) { this.razonSocialEmpImp = razonSocialEmpImp; } + public String getNumRegSanPlagCofepris() { return numRegSanPlagCofepris; } + public void setNumRegSanPlagCofepris(String numRegSanPlagCofepris) { this.numRegSanPlagCofepris = numRegSanPlagCofepris; } + public String getDatosFabricante() { return datosFabricante; } + public void setDatosFabricante(String datosFabricante) { this.datosFabricante = datosFabricante; } + public String getDatosFormulador() { return datosFormulador; } + public void setDatosFormulador(String datosFormulador) { this.datosFormulador = datosFormulador; } + public String getDatosMaquilador() { return datosMaquilador; } + public void setDatosMaquilador(String datosMaquilador) { this.datosMaquilador = datosMaquilador; } + public String getUsoAutorizado() { return usoAutorizado; } + public void setUsoAutorizado(String usoAutorizado) { this.usoAutorizado = usoAutorizado; } + public Double getPesoEnKg() { return pesoEnKg; } + public void setPesoEnKg(Double pesoEnKg) { this.pesoEnKg = pesoEnKg; } + public Double getValorMercancia() { return valorMercancia; } + public void setValorMercancia(Double valorMercancia) { this.valorMercancia = valorMercancia; } + public String getMoneda() { return moneda; } + public void setMoneda(String moneda) { this.moneda = moneda; } + public String getFraccionArancelaria() { return fraccionArancelaria; } + public void setFraccionArancelaria(String fraccionArancelaria) { this.fraccionArancelaria = fraccionArancelaria; } + public String getUuidComercioExt() { return uuidComercioExt; } + public void setUuidComercioExt(String uuidComercioExt) { this.uuidComercioExt = uuidComercioExt; } + public String getTipoMateria() { return tipoMateria; } + public void setTipoMateria(String tipoMateria) { this.tipoMateria = tipoMateria; } + public String getDescripcionMateria() { return descripcionMateria; } + public void setDescripcionMateria(String descripcionMateria) { this.descripcionMateria = descripcionMateria; } + public List getDocumentacionAduanera() { return documentacionAduanera; } + public void setDocumentacionAduanera(List documentacionAduanera) { this.documentacionAduanera = documentacionAduanera; } + public List getGuiasIdentificacion() { return guiasIdentificacion; } + public void setGuiasIdentificacion(List guiasIdentificacion) { this.guiasIdentificacion = guiasIdentificacion; } + public List getCantidadTransporta() { return cantidadTransporta; } + public void setCantidadTransporta(List cantidadTransporta) { this.cantidadTransporta = cantidadTransporta; } + public List getDetalleMercancia() { return detalleMercancia; } + public void setDetalleMercancia(List detalleMercancia) { this.detalleMercancia = detalleMercancia; } +} diff --git a/src/main/java/io/facturapi/models/CartaPorteMercancias.java b/src/main/java/io/facturapi/models/CartaPorteMercancias.java new file mode 100644 index 0000000..535776e --- /dev/null +++ b/src/main/java/io/facturapi/models/CartaPorteMercancias.java @@ -0,0 +1,55 @@ +package io.facturapi.models; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import java.util.ArrayList; +import java.util.List; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class CartaPorteMercancias { + @JsonProperty("PesoBrutoTotal") + private Double pesoBrutoTotal; + @JsonProperty("UnidadPeso") + private String unidadPeso; + @JsonProperty("PesoNetoTotal") + private Double pesoNetoTotal; + @JsonProperty("NumTotalMercancias") + private Double numTotalMercancias; + @JsonProperty("CargoPorTasacion") + private Double cargoPorTasacion; + @JsonProperty("LogisticaInversaRecoleccionDevolucion") + private String logisticaInversaRecoleccionDevolucion; + @JsonProperty("Mercancia") + private List mercancia = new ArrayList<>(); + @JsonProperty("Autotransporte") + private CartaPorteAutotransporte autotransporte; + @JsonProperty("TransporteMaritimo") + private CartaPorteTransporteMaritimo transporteMaritimo; + @JsonProperty("TransporteAereo") + private CartaPorteTransporteAereo transporteAereo; + @JsonProperty("TransporteFerroviario") + private CartaPorteTransporteFerroviario transporteFerroviario; + + public Double getPesoBrutoTotal() { return pesoBrutoTotal; } + public void setPesoBrutoTotal(Double pesoBrutoTotal) { this.pesoBrutoTotal = pesoBrutoTotal; } + public String getUnidadPeso() { return unidadPeso; } + public void setUnidadPeso(String unidadPeso) { this.unidadPeso = unidadPeso; } + public Double getPesoNetoTotal() { return pesoNetoTotal; } + public void setPesoNetoTotal(Double pesoNetoTotal) { this.pesoNetoTotal = pesoNetoTotal; } + public Double getNumTotalMercancias() { return numTotalMercancias; } + public void setNumTotalMercancias(Double numTotalMercancias) { this.numTotalMercancias = numTotalMercancias; } + public Double getCargoPorTasacion() { return cargoPorTasacion; } + public void setCargoPorTasacion(Double cargoPorTasacion) { this.cargoPorTasacion = cargoPorTasacion; } + public String getLogisticaInversaRecoleccionDevolucion() { return logisticaInversaRecoleccionDevolucion; } + public void setLogisticaInversaRecoleccionDevolucion(String logisticaInversaRecoleccionDevolucion) { this.logisticaInversaRecoleccionDevolucion = logisticaInversaRecoleccionDevolucion; } + public List getMercancia() { return mercancia; } + public void setMercancia(List mercancia) { this.mercancia = mercancia; } + public CartaPorteAutotransporte getAutotransporte() { return autotransporte; } + public void setAutotransporte(CartaPorteAutotransporte autotransporte) { this.autotransporte = autotransporte; } + public CartaPorteTransporteMaritimo getTransporteMaritimo() { return transporteMaritimo; } + public void setTransporteMaritimo(CartaPorteTransporteMaritimo transporteMaritimo) { this.transporteMaritimo = transporteMaritimo; } + public CartaPorteTransporteAereo getTransporteAereo() { return transporteAereo; } + public void setTransporteAereo(CartaPorteTransporteAereo transporteAereo) { this.transporteAereo = transporteAereo; } + public CartaPorteTransporteFerroviario getTransporteFerroviario() { return transporteFerroviario; } + public void setTransporteFerroviario(CartaPorteTransporteFerroviario transporteFerroviario) { this.transporteFerroviario = transporteFerroviario; } +} diff --git a/src/main/java/io/facturapi/models/CartaPorteParteTransporte.java b/src/main/java/io/facturapi/models/CartaPorteParteTransporte.java new file mode 100644 index 0000000..a22d03e --- /dev/null +++ b/src/main/java/io/facturapi/models/CartaPorteParteTransporte.java @@ -0,0 +1,13 @@ +package io.facturapi.models; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class CartaPorteParteTransporte { + @JsonProperty("ParteTransporte") + private String parteTransporte; + + public String getParteTransporte() { return parteTransporte; } + public void setParteTransporte(String parteTransporte) { this.parteTransporte = parteTransporte; } +} diff --git a/src/main/java/io/facturapi/models/CartaPorteRemolque.java b/src/main/java/io/facturapi/models/CartaPorteRemolque.java new file mode 100644 index 0000000..9eed617 --- /dev/null +++ b/src/main/java/io/facturapi/models/CartaPorteRemolque.java @@ -0,0 +1,17 @@ +package io.facturapi.models; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class CartaPorteRemolque { + @JsonProperty("SubTipoRem") + private String subTipoRem; + @JsonProperty("Placa") + private String placa; + + public String getSubTipoRem() { return subTipoRem; } + public void setSubTipoRem(String subTipoRem) { this.subTipoRem = subTipoRem; } + public String getPlaca() { return placa; } + public void setPlaca(String placa) { this.placa = placa; } +} diff --git a/src/main/java/io/facturapi/models/CartaPorteRemolqueCcp.java b/src/main/java/io/facturapi/models/CartaPorteRemolqueCcp.java new file mode 100644 index 0000000..bbeaac7 --- /dev/null +++ b/src/main/java/io/facturapi/models/CartaPorteRemolqueCcp.java @@ -0,0 +1,17 @@ +package io.facturapi.models; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class CartaPorteRemolqueCcp { + @JsonProperty("SubTipoRemCCP") + private String subTipoRemCcp; + @JsonProperty("PlacaCCP") + private String placaCcp; + + public String getSubTipoRemCcp() { return subTipoRemCcp; } + public void setSubTipoRemCcp(String subTipoRemCcp) { this.subTipoRemCcp = subTipoRemCcp; } + public String getPlacaCcp() { return placaCcp; } + public void setPlacaCcp(String placaCcp) { this.placaCcp = placaCcp; } +} diff --git a/src/main/java/io/facturapi/models/CartaPorteSeguros.java b/src/main/java/io/facturapi/models/CartaPorteSeguros.java new file mode 100644 index 0000000..e2f29a8 --- /dev/null +++ b/src/main/java/io/facturapi/models/CartaPorteSeguros.java @@ -0,0 +1,37 @@ +package io.facturapi.models; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class CartaPorteSeguros { + @JsonProperty("AseguraRespCivil") + private String aseguraRespCivil; + @JsonProperty("PolizaRespCivil") + private String polizaRespCivil; + @JsonProperty("AseguraMedAmbiente") + private String aseguraMedAmbiente; + @JsonProperty("PolizaMedAmbiente") + private String polizaMedAmbiente; + @JsonProperty("AseguraCarga") + private String aseguraCarga; + @JsonProperty("PolizaCarga") + private String polizaCarga; + @JsonProperty("PrimaSeguro") + private Double primaSeguro; + + public String getAseguraRespCivil() { return aseguraRespCivil; } + public void setAseguraRespCivil(String aseguraRespCivil) { this.aseguraRespCivil = aseguraRespCivil; } + public String getPolizaRespCivil() { return polizaRespCivil; } + public void setPolizaRespCivil(String polizaRespCivil) { this.polizaRespCivil = polizaRespCivil; } + public String getAseguraMedAmbiente() { return aseguraMedAmbiente; } + public void setAseguraMedAmbiente(String aseguraMedAmbiente) { this.aseguraMedAmbiente = aseguraMedAmbiente; } + public String getPolizaMedAmbiente() { return polizaMedAmbiente; } + public void setPolizaMedAmbiente(String polizaMedAmbiente) { this.polizaMedAmbiente = polizaMedAmbiente; } + public String getAseguraCarga() { return aseguraCarga; } + public void setAseguraCarga(String aseguraCarga) { this.aseguraCarga = aseguraCarga; } + public String getPolizaCarga() { return polizaCarga; } + public void setPolizaCarga(String polizaCarga) { this.polizaCarga = polizaCarga; } + public Double getPrimaSeguro() { return primaSeguro; } + public void setPrimaSeguro(Double primaSeguro) { this.primaSeguro = primaSeguro; } +} diff --git a/src/main/java/io/facturapi/models/CartaPorteTransporteAereo.java b/src/main/java/io/facturapi/models/CartaPorteTransporteAereo.java new file mode 100644 index 0000000..33cebf7 --- /dev/null +++ b/src/main/java/io/facturapi/models/CartaPorteTransporteAereo.java @@ -0,0 +1,57 @@ +package io.facturapi.models; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class CartaPorteTransporteAereo { + @JsonProperty("PermSCT") + private String permSct; + @JsonProperty("NumPermisoSCT") + private String numPermisoSct; + @JsonProperty("MatriculaAeronave") + private String matriculaAeronave; + @JsonProperty("NombreAseg") + private String nombreAseg; + @JsonProperty("NumPolizaSeguro") + private String numPolizaSeguro; + @JsonProperty("NumeroGuia") + private String numeroGuia; + @JsonProperty("LugarContrato") + private String lugarContrato; + @JsonProperty("CodigoTransportista") + private String codigoTransportista; + @JsonProperty("RFCEmbarcador") + private String rfcEmbarcador; + @JsonProperty("NumRegIdTribEmbarc") + private String numRegIdTribEmbarc; + @JsonProperty("ResidenciaFiscalEmbarc") + private String residenciaFiscalEmbarc; + @JsonProperty("NombreEmbarcador") + private String nombreEmbarcador; + + public String getPermSct() { return permSct; } + public void setPermSct(String permSct) { this.permSct = permSct; } + public String getNumPermisoSct() { return numPermisoSct; } + public void setNumPermisoSct(String numPermisoSct) { this.numPermisoSct = numPermisoSct; } + public String getMatriculaAeronave() { return matriculaAeronave; } + public void setMatriculaAeronave(String matriculaAeronave) { this.matriculaAeronave = matriculaAeronave; } + public String getNombreAseg() { return nombreAseg; } + public void setNombreAseg(String nombreAseg) { this.nombreAseg = nombreAseg; } + public String getNumPolizaSeguro() { return numPolizaSeguro; } + public void setNumPolizaSeguro(String numPolizaSeguro) { this.numPolizaSeguro = numPolizaSeguro; } + public String getNumeroGuia() { return numeroGuia; } + public void setNumeroGuia(String numeroGuia) { this.numeroGuia = numeroGuia; } + public String getLugarContrato() { return lugarContrato; } + public void setLugarContrato(String lugarContrato) { this.lugarContrato = lugarContrato; } + public String getCodigoTransportista() { return codigoTransportista; } + public void setCodigoTransportista(String codigoTransportista) { this.codigoTransportista = codigoTransportista; } + public String getRfcEmbarcador() { return rfcEmbarcador; } + public void setRfcEmbarcador(String rfcEmbarcador) { this.rfcEmbarcador = rfcEmbarcador; } + public String getNumRegIdTribEmbarc() { return numRegIdTribEmbarc; } + public void setNumRegIdTribEmbarc(String numRegIdTribEmbarc) { this.numRegIdTribEmbarc = numRegIdTribEmbarc; } + public String getResidenciaFiscalEmbarc() { return residenciaFiscalEmbarc; } + public void setResidenciaFiscalEmbarc(String residenciaFiscalEmbarc) { this.residenciaFiscalEmbarc = residenciaFiscalEmbarc; } + public String getNombreEmbarcador() { return nombreEmbarcador; } + public void setNombreEmbarcador(String nombreEmbarcador) { this.nombreEmbarcador = nombreEmbarcador; } +} diff --git a/src/main/java/io/facturapi/models/CartaPorteTransporteFerroviario.java b/src/main/java/io/facturapi/models/CartaPorteTransporteFerroviario.java new file mode 100644 index 0000000..4fe6c7b --- /dev/null +++ b/src/main/java/io/facturapi/models/CartaPorteTransporteFerroviario.java @@ -0,0 +1,35 @@ +package io.facturapi.models; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import java.util.ArrayList; +import java.util.List; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class CartaPorteTransporteFerroviario { + @JsonProperty("TipoDeServicio") + private String tipoDeServicio; + @JsonProperty("TipoDeTrafico") + private String tipoDeTrafico; + @JsonProperty("NombreAseg") + private String nombreAseg; + @JsonProperty("NumPolizaSeguro") + private String numPolizaSeguro; + @JsonProperty("DerechosDePaso") + private List derechosDePaso = new ArrayList<>(); + @JsonProperty("Carro") + private List carro = new ArrayList<>(); + + public String getTipoDeServicio() { return tipoDeServicio; } + public void setTipoDeServicio(String tipoDeServicio) { this.tipoDeServicio = tipoDeServicio; } + public String getTipoDeTrafico() { return tipoDeTrafico; } + public void setTipoDeTrafico(String tipoDeTrafico) { this.tipoDeTrafico = tipoDeTrafico; } + public String getNombreAseg() { return nombreAseg; } + public void setNombreAseg(String nombreAseg) { this.nombreAseg = nombreAseg; } + public String getNumPolizaSeguro() { return numPolizaSeguro; } + public void setNumPolizaSeguro(String numPolizaSeguro) { this.numPolizaSeguro = numPolizaSeguro; } + public List getDerechosDePaso() { return derechosDePaso; } + public void setDerechosDePaso(List derechosDePaso) { this.derechosDePaso = derechosDePaso; } + public List getCarro() { return carro; } + public void setCarro(List carro) { this.carro = carro; } +} diff --git a/src/main/java/io/facturapi/models/CartaPorteTransporteMaritimo.java b/src/main/java/io/facturapi/models/CartaPorteTransporteMaritimo.java new file mode 100644 index 0000000..3ab59cb --- /dev/null +++ b/src/main/java/io/facturapi/models/CartaPorteTransporteMaritimo.java @@ -0,0 +1,103 @@ +package io.facturapi.models; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import java.util.ArrayList; +import java.util.List; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class CartaPorteTransporteMaritimo { + @JsonProperty("PermSCT") + private String permSct; + @JsonProperty("NumPermisoSCT") + private String numPermisoSct; + @JsonProperty("NombreAseg") + private String nombreAseg; + @JsonProperty("NumPolizaSeguro") + private String numPolizaSeguro; + @JsonProperty("TipoEmbarcacion") + private String tipoEmbarcacion; + @JsonProperty("Matricula") + private String matricula; + @JsonProperty("NumeroOMI") + private String numeroOmi; + @JsonProperty("AnioEmbarcacion") + private String anioEmbarcacion; + @JsonProperty("NombreEmbarc") + private String nombreEmbarc; + @JsonProperty("NacionalidadEmbarc") + private String nacionalidadEmbarc; + @JsonProperty("UnidadesDeArqBruto") + private Double unidadesDeArqBruto; + @JsonProperty("TipoCarga") + private String tipoCarga; + @JsonProperty("Eslora") + private Double eslora; + @JsonProperty("Manga") + private Double manga; + @JsonProperty("Calado") + private Double calado; + @JsonProperty("Puntal") + private Double puntal; + @JsonProperty("LineaNaviera") + private String lineaNaviera; + @JsonProperty("NombreAgenteNaviero") + private String nombreAgenteNaviero; + @JsonProperty("NumAutorizacionNaviero") + private String numAutorizacionNaviero; + @JsonProperty("NumViaje") + private String numViaje; + @JsonProperty("NumConocEmbarc") + private String numConocEmbarc; + @JsonProperty("PermisoTempNavegacion") + private String permisoTempNavegacion; + @JsonProperty("Contenedor") + private List contenedor = new ArrayList<>(); + + public String getPermSct() { return permSct; } + public void setPermSct(String permSct) { this.permSct = permSct; } + public String getNumPermisoSct() { return numPermisoSct; } + public void setNumPermisoSct(String numPermisoSct) { this.numPermisoSct = numPermisoSct; } + public String getNombreAseg() { return nombreAseg; } + public void setNombreAseg(String nombreAseg) { this.nombreAseg = nombreAseg; } + public String getNumPolizaSeguro() { return numPolizaSeguro; } + public void setNumPolizaSeguro(String numPolizaSeguro) { this.numPolizaSeguro = numPolizaSeguro; } + public String getTipoEmbarcacion() { return tipoEmbarcacion; } + public void setTipoEmbarcacion(String tipoEmbarcacion) { this.tipoEmbarcacion = tipoEmbarcacion; } + public String getMatricula() { return matricula; } + public void setMatricula(String matricula) { this.matricula = matricula; } + public String getNumeroOmi() { return numeroOmi; } + public void setNumeroOmi(String numeroOmi) { this.numeroOmi = numeroOmi; } + public String getAnioEmbarcacion() { return anioEmbarcacion; } + public void setAnioEmbarcacion(String anioEmbarcacion) { this.anioEmbarcacion = anioEmbarcacion; } + public String getNombreEmbarc() { return nombreEmbarc; } + public void setNombreEmbarc(String nombreEmbarc) { this.nombreEmbarc = nombreEmbarc; } + public String getNacionalidadEmbarc() { return nacionalidadEmbarc; } + public void setNacionalidadEmbarc(String nacionalidadEmbarc) { this.nacionalidadEmbarc = nacionalidadEmbarc; } + public Double getUnidadesDeArqBruto() { return unidadesDeArqBruto; } + public void setUnidadesDeArqBruto(Double unidadesDeArqBruto) { this.unidadesDeArqBruto = unidadesDeArqBruto; } + public String getTipoCarga() { return tipoCarga; } + public void setTipoCarga(String tipoCarga) { this.tipoCarga = tipoCarga; } + public Double getEslora() { return eslora; } + public void setEslora(Double eslora) { this.eslora = eslora; } + public Double getManga() { return manga; } + public void setManga(Double manga) { this.manga = manga; } + public Double getCalado() { return calado; } + public void setCalado(Double calado) { this.calado = calado; } + public Double getPuntal() { return puntal; } + public void setPuntal(Double puntal) { this.puntal = puntal; } + public String getLineaNaviera() { return lineaNaviera; } + public void setLineaNaviera(String lineaNaviera) { this.lineaNaviera = lineaNaviera; } + public String getNombreAgenteNaviero() { return nombreAgenteNaviero; } + public void setNombreAgenteNaviero(String nombreAgenteNaviero) { this.nombreAgenteNaviero = nombreAgenteNaviero; } + public String getNumAutorizacionNaviero() { return numAutorizacionNaviero; } + public void setNumAutorizacionNaviero(String numAutorizacionNaviero) { this.numAutorizacionNaviero = numAutorizacionNaviero; } + public String getNumViaje() { return numViaje; } + public void setNumViaje(String numViaje) { this.numViaje = numViaje; } + public String getNumConocEmbarc() { return numConocEmbarc; } + public void setNumConocEmbarc(String numConocEmbarc) { this.numConocEmbarc = numConocEmbarc; } + public String getPermisoTempNavegacion() { return permisoTempNavegacion; } + public void setPermisoTempNavegacion(String permisoTempNavegacion) { this.permisoTempNavegacion = permisoTempNavegacion; } + public List getContenedor() { return contenedor; } + public void setContenedor(List contenedor) { this.contenedor = contenedor; } +} diff --git a/src/main/java/io/facturapi/models/CartaPorteUbicacion.java b/src/main/java/io/facturapi/models/CartaPorteUbicacion.java new file mode 100644 index 0000000..72c5a83 --- /dev/null +++ b/src/main/java/io/facturapi/models/CartaPorteUbicacion.java @@ -0,0 +1,61 @@ +package io.facturapi.models; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class CartaPorteUbicacion { + @JsonProperty("TipoUbicacion") + private String tipoUbicacion; + @JsonProperty("IDUbicacion") + private String idUbicacion; + @JsonProperty("RFCRemitenteDestinatario") + private String rfcRemitenteDestinatario; + @JsonProperty("NombreRemitenteDestinatario") + private String nombreRemitenteDestinatario; + @JsonProperty("NumRegIdTrib") + private String numRegIdTrib; + @JsonProperty("ResidenciaFiscal") + private String residenciaFiscal; + @JsonProperty("NumEstacion") + private String numEstacion; + @JsonProperty("NombreEstacion") + private String nombreEstacion; + @JsonProperty("NavegacionTrafico") + private String navegacionTrafico; + @JsonProperty("FechaHoraSalidaLlegada") + private String fechaHoraSalidaLlegada; + @JsonProperty("TipoEstacion") + private String tipoEstacion; + @JsonProperty("DistanciaRecorrida") + private Double distanciaRecorrida; + @JsonProperty("Domicilio") + private CartaPorteDomicilio domicilio; + + public String getTipoUbicacion() { return tipoUbicacion; } + public void setTipoUbicacion(String tipoUbicacion) { this.tipoUbicacion = tipoUbicacion; } + public String getIdUbicacion() { return idUbicacion; } + public void setIdUbicacion(String idUbicacion) { this.idUbicacion = idUbicacion; } + public String getRfcRemitenteDestinatario() { return rfcRemitenteDestinatario; } + public void setRfcRemitenteDestinatario(String rfcRemitenteDestinatario) { this.rfcRemitenteDestinatario = rfcRemitenteDestinatario; } + public String getNombreRemitenteDestinatario() { return nombreRemitenteDestinatario; } + public void setNombreRemitenteDestinatario(String nombreRemitenteDestinatario) { this.nombreRemitenteDestinatario = nombreRemitenteDestinatario; } + public String getNumRegIdTrib() { return numRegIdTrib; } + public void setNumRegIdTrib(String numRegIdTrib) { this.numRegIdTrib = numRegIdTrib; } + public String getResidenciaFiscal() { return residenciaFiscal; } + public void setResidenciaFiscal(String residenciaFiscal) { this.residenciaFiscal = residenciaFiscal; } + public String getNumEstacion() { return numEstacion; } + public void setNumEstacion(String numEstacion) { this.numEstacion = numEstacion; } + public String getNombreEstacion() { return nombreEstacion; } + public void setNombreEstacion(String nombreEstacion) { this.nombreEstacion = nombreEstacion; } + public String getNavegacionTrafico() { return navegacionTrafico; } + public void setNavegacionTrafico(String navegacionTrafico) { this.navegacionTrafico = navegacionTrafico; } + public String getFechaHoraSalidaLlegada() { return fechaHoraSalidaLlegada; } + public void setFechaHoraSalidaLlegada(String fechaHoraSalidaLlegada) { this.fechaHoraSalidaLlegada = fechaHoraSalidaLlegada; } + public String getTipoEstacion() { return tipoEstacion; } + public void setTipoEstacion(String tipoEstacion) { this.tipoEstacion = tipoEstacion; } + public Double getDistanciaRecorrida() { return distanciaRecorrida; } + public void setDistanciaRecorrida(Double distanciaRecorrida) { this.distanciaRecorrida = distanciaRecorrida; } + public CartaPorteDomicilio getDomicilio() { return domicilio; } + public void setDomicilio(CartaPorteDomicilio domicilio) { this.domicilio = domicilio; } +} diff --git a/src/main/java/io/facturapi/models/CatalogItem.java b/src/main/java/io/facturapi/models/CatalogItem.java new file mode 100644 index 0000000..078e20f --- /dev/null +++ b/src/main/java/io/facturapi/models/CatalogItem.java @@ -0,0 +1,39 @@ +package io.facturapi.models; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonAlias; +import com.fasterxml.jackson.annotation.JsonProperty; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class CatalogItem { + @JsonAlias({"code", "key", "value"}) + private String code; + @JsonAlias({"label", "description", "name"}) + private String label; + @JsonProperty("score") + private Double score; + + public String getCode() { + return code; + } + + public void setCode(String code) { + this.code = code; + } + + public String getLabel() { + return label; + } + + public void setLabel(String label) { + this.label = label; + } + + public Double getScore() { + return score; + } + + public void setScore(Double score) { + this.score = score; + } +} diff --git a/src/main/java/io/facturapi/models/Certificate.java b/src/main/java/io/facturapi/models/Certificate.java new file mode 100644 index 0000000..e6f29be --- /dev/null +++ b/src/main/java/io/facturapi/models/Certificate.java @@ -0,0 +1,25 @@ +package io.facturapi.models; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class Certificate { + @JsonProperty("has_certificate") + private Boolean hasCertificate; + @JsonProperty("updated_at") + private String updatedAt; + @JsonProperty("expires_at") + private String expiresAt; + @JsonProperty("serial_number") + private String serialNumber; + + public Boolean getHasCertificate() { return hasCertificate; } + public void setHasCertificate(Boolean hasCertificate) { this.hasCertificate = hasCertificate; } + public String getUpdatedAt() { return updatedAt; } + public void setUpdatedAt(String updatedAt) { this.updatedAt = updatedAt; } + public String getExpiresAt() { return expiresAt; } + public void setExpiresAt(String expiresAt) { this.expiresAt = expiresAt; } + public String getSerialNumber() { return serialNumber; } + public void setSerialNumber(String serialNumber) { this.serialNumber = serialNumber; } +} diff --git a/src/main/java/io/facturapi/models/ComercioExteriorComplementData.java b/src/main/java/io/facturapi/models/ComercioExteriorComplementData.java new file mode 100644 index 0000000..b59839a --- /dev/null +++ b/src/main/java/io/facturapi/models/ComercioExteriorComplementData.java @@ -0,0 +1,106 @@ +package io.facturapi.models; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonSetter; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import java.util.ArrayList; +import java.util.List; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class ComercioExteriorComplementData { + private static final ObjectMapper MAPPER = new ObjectMapper() + .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + + @JsonProperty("Version") + private String version; + @JsonProperty("MotivoTraslado") + private String motivoTraslado; + @JsonProperty("ClaveDePedimento") + private String claveDePedimento; + @JsonProperty("CertificadoOrigen") + private Integer certificadoOrigen; + @JsonProperty("NumCertificadoOrigen") + private String numCertificadoOrigen; + @JsonProperty("NumeroExportadorConfiable") + private String numeroExportadorConfiable; + @JsonProperty("Incoterm") + private String incoterm; + @JsonProperty("Observaciones") + private String observaciones; + @JsonProperty("TipoCambioUSD") + private Double tipoCambioUsd; + @JsonProperty("TotalUSD") + private Double totalUsd; + + @JsonIgnore + private Boolean emisorFromOrganization; + @JsonIgnore + private ComercioExteriorEmisor emisor; + + @JsonProperty("Propietario") + private List propietario = new ArrayList<>(); + @JsonProperty("Receptor") + private ComercioExteriorReceptorRef receptor; + @JsonProperty("Destinatario") + private List destinatario = new ArrayList<>(); + @JsonProperty("Mercancias") + private ComercioExteriorMercancias mercancias; + + public String getVersion() { return version; } + public void setVersion(String version) { this.version = version; } + public String getMotivoTraslado() { return motivoTraslado; } + public void setMotivoTraslado(String motivoTraslado) { this.motivoTraslado = motivoTraslado; } + public String getClaveDePedimento() { return claveDePedimento; } + public void setClaveDePedimento(String claveDePedimento) { this.claveDePedimento = claveDePedimento; } + public Integer getCertificadoOrigen() { return certificadoOrigen; } + public void setCertificadoOrigen(Integer certificadoOrigen) { this.certificadoOrigen = certificadoOrigen; } + public String getNumCertificadoOrigen() { return numCertificadoOrigen; } + public void setNumCertificadoOrigen(String numCertificadoOrigen) { this.numCertificadoOrigen = numCertificadoOrigen; } + public String getNumeroExportadorConfiable() { return numeroExportadorConfiable; } + public void setNumeroExportadorConfiable(String numeroExportadorConfiable) { this.numeroExportadorConfiable = numeroExportadorConfiable; } + public String getIncoterm() { return incoterm; } + public void setIncoterm(String incoterm) { this.incoterm = incoterm; } + public String getObservaciones() { return observaciones; } + public void setObservaciones(String observaciones) { this.observaciones = observaciones; } + public Double getTipoCambioUsd() { return tipoCambioUsd; } + public void setTipoCambioUsd(Double tipoCambioUsd) { this.tipoCambioUsd = tipoCambioUsd; } + public Double getTotalUsd() { return totalUsd; } + public void setTotalUsd(Double totalUsd) { this.totalUsd = totalUsd; } + + @JsonSetter("Emisor") + private void setEmisorNode(JsonNode node) { + this.emisorFromOrganization = null; + this.emisor = null; + if (node == null || node.isNull()) { + return; + } + if (node.isBoolean()) { + this.emisorFromOrganization = node.asBoolean(); + } else if (node.isObject()) { + this.emisor = MAPPER.convertValue(node, ComercioExteriorEmisor.class); + } + } + + @JsonProperty("Emisor") + public Object getEmisor() { + if (emisorFromOrganization != null) { + return emisorFromOrganization; + } + return emisor; + } + + public Boolean getEmisorFromOrganization() { return emisorFromOrganization; } + public ComercioExteriorEmisor getEmisorData() { return emisor; } + public List getPropietario() { return propietario; } + public void setPropietario(List propietario) { this.propietario = propietario; } + public ComercioExteriorReceptorRef getReceptor() { return receptor; } + public void setReceptor(ComercioExteriorReceptorRef receptor) { this.receptor = receptor; } + public List getDestinatario() { return destinatario; } + public void setDestinatario(List destinatario) { this.destinatario = destinatario; } + public ComercioExteriorMercancias getMercancias() { return mercancias; } + public void setMercancias(ComercioExteriorMercancias mercancias) { this.mercancias = mercancias; } +} diff --git a/src/main/java/io/facturapi/models/ComercioExteriorDescripcionesEspecificas.java b/src/main/java/io/facturapi/models/ComercioExteriorDescripcionesEspecificas.java new file mode 100644 index 0000000..5525e0a --- /dev/null +++ b/src/main/java/io/facturapi/models/ComercioExteriorDescripcionesEspecificas.java @@ -0,0 +1,25 @@ +package io.facturapi.models; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class ComercioExteriorDescripcionesEspecificas { + @JsonProperty("Marca") + private String marca; + @JsonProperty("Modelo") + private String modelo; + @JsonProperty("SubModelo") + private String subModelo; + @JsonProperty("NumeroSerie") + private String numeroSerie; + + public String getMarca() { return marca; } + public void setMarca(String marca) { this.marca = marca; } + public String getModelo() { return modelo; } + public void setModelo(String modelo) { this.modelo = modelo; } + public String getSubModelo() { return subModelo; } + public void setSubModelo(String subModelo) { this.subModelo = subModelo; } + public String getNumeroSerie() { return numeroSerie; } + public void setNumeroSerie(String numeroSerie) { this.numeroSerie = numeroSerie; } +} diff --git a/src/main/java/io/facturapi/models/ComercioExteriorDestinatarioRef.java b/src/main/java/io/facturapi/models/ComercioExteriorDestinatarioRef.java new file mode 100644 index 0000000..87d684d --- /dev/null +++ b/src/main/java/io/facturapi/models/ComercioExteriorDestinatarioRef.java @@ -0,0 +1,26 @@ +package io.facturapi.models; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import java.util.ArrayList; +import java.util.List; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class ComercioExteriorDestinatarioRef { + private String id; + @JsonProperty("Domicilio") + private List domicilio = new ArrayList<>(); + @JsonProperty("NumRegIdTrib") + private String numRegIdTrib; + @JsonProperty("Nombre") + private String nombre; + + public String getId() { return id; } + public void setId(String id) { this.id = id; } + public List getDomicilio() { return domicilio; } + public void setDomicilio(List domicilio) { this.domicilio = domicilio; } + public String getNumRegIdTrib() { return numRegIdTrib; } + public void setNumRegIdTrib(String numRegIdTrib) { this.numRegIdTrib = numRegIdTrib; } + public String getNombre() { return nombre; } + public void setNombre(String nombre) { this.nombre = nombre; } +} diff --git a/src/main/java/io/facturapi/models/ComercioExteriorDomicilio.java b/src/main/java/io/facturapi/models/ComercioExteriorDomicilio.java new file mode 100644 index 0000000..fb5568d --- /dev/null +++ b/src/main/java/io/facturapi/models/ComercioExteriorDomicilio.java @@ -0,0 +1,49 @@ +package io.facturapi.models; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class ComercioExteriorDomicilio { + @JsonProperty("Calle") + private String calle; + @JsonProperty("NumeroExterior") + private String numeroExterior; + @JsonProperty("NumeroInterior") + private String numeroInterior; + @JsonProperty("Colonia") + private String colonia; + @JsonProperty("Localidad") + private String localidad; + @JsonProperty("Referencia") + private String referencia; + @JsonProperty("Municipio") + private String municipio; + @JsonProperty("Estado") + private String estado; + @JsonProperty("Pais") + private String pais; + @JsonProperty("CodigoPostal") + private String codigoPostal; + + public String getCalle() { return calle; } + public void setCalle(String calle) { this.calle = calle; } + public String getNumeroExterior() { return numeroExterior; } + public void setNumeroExterior(String numeroExterior) { this.numeroExterior = numeroExterior; } + public String getNumeroInterior() { return numeroInterior; } + public void setNumeroInterior(String numeroInterior) { this.numeroInterior = numeroInterior; } + public String getColonia() { return colonia; } + public void setColonia(String colonia) { this.colonia = colonia; } + public String getLocalidad() { return localidad; } + public void setLocalidad(String localidad) { this.localidad = localidad; } + public String getReferencia() { return referencia; } + public void setReferencia(String referencia) { this.referencia = referencia; } + public String getMunicipio() { return municipio; } + public void setMunicipio(String municipio) { this.municipio = municipio; } + public String getEstado() { return estado; } + public void setEstado(String estado) { this.estado = estado; } + public String getPais() { return pais; } + public void setPais(String pais) { this.pais = pais; } + public String getCodigoPostal() { return codigoPostal; } + public void setCodigoPostal(String codigoPostal) { this.codigoPostal = codigoPostal; } +} diff --git a/src/main/java/io/facturapi/models/ComercioExteriorEmisor.java b/src/main/java/io/facturapi/models/ComercioExteriorEmisor.java new file mode 100644 index 0000000..a305a24 --- /dev/null +++ b/src/main/java/io/facturapi/models/ComercioExteriorEmisor.java @@ -0,0 +1,17 @@ +package io.facturapi.models; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class ComercioExteriorEmisor { + @JsonProperty("Domicilio") + private ComercioExteriorDomicilio domicilio; + @JsonProperty("Curp") + private String curp; + + public ComercioExteriorDomicilio getDomicilio() { return domicilio; } + public void setDomicilio(ComercioExteriorDomicilio domicilio) { this.domicilio = domicilio; } + public String getCurp() { return curp; } + public void setCurp(String curp) { this.curp = curp; } +} diff --git a/src/main/java/io/facturapi/models/ComercioExteriorMercancia.java b/src/main/java/io/facturapi/models/ComercioExteriorMercancia.java new file mode 100644 index 0000000..f4ce5de --- /dev/null +++ b/src/main/java/io/facturapi/models/ComercioExteriorMercancia.java @@ -0,0 +1,39 @@ +package io.facturapi.models; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import java.util.ArrayList; +import java.util.List; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class ComercioExteriorMercancia { + @JsonProperty("DescripcionesEspecificas") + private List descripcionesEspecificas = new ArrayList<>(); + @JsonProperty("NoIdentificacion") + private String noIdentificacion; + @JsonProperty("FraccionArancelaria") + private String fraccionArancelaria; + @JsonProperty("CantidadAduana") + private Double cantidadAduana; + @JsonProperty("UnidadAduana") + private String unidadAduana; + @JsonProperty("ValorUnitarioAduana") + private Double valorUnitarioAduana; + @JsonProperty("ValorDolares") + private Double valorDolares; + + public List getDescripcionesEspecificas() { return descripcionesEspecificas; } + public void setDescripcionesEspecificas(List descripcionesEspecificas) { this.descripcionesEspecificas = descripcionesEspecificas; } + public String getNoIdentificacion() { return noIdentificacion; } + public void setNoIdentificacion(String noIdentificacion) { this.noIdentificacion = noIdentificacion; } + public String getFraccionArancelaria() { return fraccionArancelaria; } + public void setFraccionArancelaria(String fraccionArancelaria) { this.fraccionArancelaria = fraccionArancelaria; } + public Double getCantidadAduana() { return cantidadAduana; } + public void setCantidadAduana(Double cantidadAduana) { this.cantidadAduana = cantidadAduana; } + public String getUnidadAduana() { return unidadAduana; } + public void setUnidadAduana(String unidadAduana) { this.unidadAduana = unidadAduana; } + public Double getValorUnitarioAduana() { return valorUnitarioAduana; } + public void setValorUnitarioAduana(Double valorUnitarioAduana) { this.valorUnitarioAduana = valorUnitarioAduana; } + public Double getValorDolares() { return valorDolares; } + public void setValorDolares(Double valorDolares) { this.valorDolares = valorDolares; } +} diff --git a/src/main/java/io/facturapi/models/ComercioExteriorMercancias.java b/src/main/java/io/facturapi/models/ComercioExteriorMercancias.java new file mode 100644 index 0000000..8af3559 --- /dev/null +++ b/src/main/java/io/facturapi/models/ComercioExteriorMercancias.java @@ -0,0 +1,15 @@ +package io.facturapi.models; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import java.util.ArrayList; +import java.util.List; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class ComercioExteriorMercancias { + @JsonProperty("Mercancia") + private List mercancia = new ArrayList<>(); + + public List getMercancia() { return mercancia; } + public void setMercancia(List mercancia) { this.mercancia = mercancia; } +} diff --git a/src/main/java/io/facturapi/models/ComercioExteriorPartyRef.java b/src/main/java/io/facturapi/models/ComercioExteriorPartyRef.java new file mode 100644 index 0000000..4dac82e --- /dev/null +++ b/src/main/java/io/facturapi/models/ComercioExteriorPartyRef.java @@ -0,0 +1,20 @@ +package io.facturapi.models; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class ComercioExteriorPartyRef { + private String id; + @JsonProperty("NumRegIdTrib") + private String numRegIdTrib; + @JsonProperty("ResidenciaFiscal") + private String residenciaFiscal; + + public String getId() { return id; } + public void setId(String id) { this.id = id; } + public String getNumRegIdTrib() { return numRegIdTrib; } + public void setNumRegIdTrib(String numRegIdTrib) { this.numRegIdTrib = numRegIdTrib; } + public String getResidenciaFiscal() { return residenciaFiscal; } + public void setResidenciaFiscal(String residenciaFiscal) { this.residenciaFiscal = residenciaFiscal; } +} diff --git a/src/main/java/io/facturapi/models/ComercioExteriorReceptorRef.java b/src/main/java/io/facturapi/models/ComercioExteriorReceptorRef.java new file mode 100644 index 0000000..ffd871e --- /dev/null +++ b/src/main/java/io/facturapi/models/ComercioExteriorReceptorRef.java @@ -0,0 +1,20 @@ +package io.facturapi.models; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class ComercioExteriorReceptorRef { + private String id; + @JsonProperty("Domicilio") + private ComercioExteriorDomicilio domicilio; + @JsonProperty("NumRegIdTrib") + private String numRegIdTrib; + + public String getId() { return id; } + public void setId(String id) { this.id = id; } + public ComercioExteriorDomicilio getDomicilio() { return domicilio; } + public void setDomicilio(ComercioExteriorDomicilio domicilio) { this.domicilio = domicilio; } + public String getNumRegIdTrib() { return numRegIdTrib; } + public void setNumRegIdTrib(String numRegIdTrib) { this.numRegIdTrib = numRegIdTrib; } +} diff --git a/src/main/java/io/facturapi/models/CompletionStep.java b/src/main/java/io/facturapi/models/CompletionStep.java new file mode 100644 index 0000000..56c4581 --- /dev/null +++ b/src/main/java/io/facturapi/models/CompletionStep.java @@ -0,0 +1,14 @@ +package io.facturapi.models; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class CompletionStep { + private String type; + private String description; + + public String getType() { return type; } + public void setType(String type) { this.type = type; } + public String getDescription() { return description; } + public void setDescription(String description) { this.description = description; } +} diff --git a/src/main/java/io/facturapi/models/Customer.java b/src/main/java/io/facturapi/models/Customer.java new file mode 100644 index 0000000..45b1527 --- /dev/null +++ b/src/main/java/io/facturapi/models/Customer.java @@ -0,0 +1,66 @@ +package io.facturapi.models; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class Customer { + private String id; + private String organization; + private Boolean livemode; + @JsonProperty("created_at") + private String createdAt; + @JsonProperty("tax_id") + private String taxId; + @JsonProperty("tax_system") + private String taxSystem; + @JsonProperty("legal_name") + private String legalName; + private String email; + private String phone; + private String curp; + private Address address; + @JsonProperty("external_id") + private String externalId; + @JsonProperty("default_invoice_use") + private String defaultInvoiceUse; + @JsonProperty("sat_validated_at") + private String satValidatedAt; + @JsonProperty("edit_link") + private String editLink; + @JsonProperty("edit_link_expires_at") + private String editLinkExpiresAt; + + public String getId() { return id; } + public void setId(String id) { this.id = id; } + public String getOrganization() { return organization; } + public void setOrganization(String organization) { this.organization = organization; } + public Boolean getLivemode() { return livemode; } + public void setLivemode(Boolean livemode) { this.livemode = livemode; } + public String getCreatedAt() { return createdAt; } + public void setCreatedAt(String createdAt) { this.createdAt = createdAt; } + public String getTaxId() { return taxId; } + public void setTaxId(String taxId) { this.taxId = taxId; } + public String getTaxSystem() { return taxSystem; } + public void setTaxSystem(String taxSystem) { this.taxSystem = taxSystem; } + public String getLegalName() { return legalName; } + public void setLegalName(String legalName) { this.legalName = legalName; } + public String getEmail() { return email; } + public void setEmail(String email) { this.email = email; } + public String getPhone() { return phone; } + public void setPhone(String phone) { this.phone = phone; } + public String getCurp() { return curp; } + public void setCurp(String curp) { this.curp = curp; } + public Address getAddress() { return address; } + public void setAddress(Address address) { this.address = address; } + public String getExternalId() { return externalId; } + public void setExternalId(String externalId) { this.externalId = externalId; } + public String getDefaultInvoiceUse() { return defaultInvoiceUse; } + public void setDefaultInvoiceUse(String defaultInvoiceUse) { this.defaultInvoiceUse = defaultInvoiceUse; } + public String getSatValidatedAt() { return satValidatedAt; } + public void setSatValidatedAt(String satValidatedAt) { this.satValidatedAt = satValidatedAt; } + public String getEditLink() { return editLink; } + public void setEditLink(String editLink) { this.editLink = editLink; } + public String getEditLinkExpiresAt() { return editLinkExpiresAt; } + public void setEditLinkExpiresAt(String editLinkExpiresAt) { this.editLinkExpiresAt = editLinkExpiresAt; } +} diff --git a/src/main/java/io/facturapi/models/CustomerInfo.java b/src/main/java/io/facturapi/models/CustomerInfo.java new file mode 100644 index 0000000..283dd58 --- /dev/null +++ b/src/main/java/io/facturapi/models/CustomerInfo.java @@ -0,0 +1,27 @@ +package io.facturapi.models; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class CustomerInfo { + private String id; + @JsonProperty("legal_name") + private String legalName; + @JsonProperty("tax_id") + private String taxId; + @JsonProperty("tax_system") + private String taxSystem; + private Address address; + + public String getId() { return id; } + public void setId(String id) { this.id = id; } + public String getLegalName() { return legalName; } + public void setLegalName(String legalName) { this.legalName = legalName; } + public String getTaxId() { return taxId; } + public void setTaxId(String taxId) { this.taxId = taxId; } + public String getTaxSystem() { return taxSystem; } + public void setTaxSystem(String taxSystem) { this.taxSystem = taxSystem; } + public Address getAddress() { return address; } + public void setAddress(Address address) { this.address = address; } +} diff --git a/src/main/java/io/facturapi/models/Customization.java b/src/main/java/io/facturapi/models/Customization.java new file mode 100644 index 0000000..869c205 --- /dev/null +++ b/src/main/java/io/facturapi/models/Customization.java @@ -0,0 +1,26 @@ +package io.facturapi.models; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import java.util.HashMap; +import java.util.Map; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class Customization { + private String color; + @JsonProperty("pdf_extra") + private PdfExtra pdfExtra; + @JsonProperty("default_series") + private Map defaultSeries = new HashMap<>(); + @JsonProperty("has_logo") + private Boolean hasLogo; + + public String getColor() { return color; } + public void setColor(String color) { this.color = color; } + public PdfExtra getPdfExtra() { return pdfExtra; } + public void setPdfExtra(PdfExtra pdfExtra) { this.pdfExtra = pdfExtra; } + public Map getDefaultSeries() { return defaultSeries; } + public void setDefaultSeries(Map defaultSeries) { this.defaultSeries = defaultSeries; } + public Boolean getHasLogo() { return hasLogo; } + public void setHasLogo(Boolean hasLogo) { this.hasLogo = hasLogo; } +} diff --git a/src/main/java/io/facturapi/models/DomainAvailability.java b/src/main/java/io/facturapi/models/DomainAvailability.java new file mode 100644 index 0000000..4e58919 --- /dev/null +++ b/src/main/java/io/facturapi/models/DomainAvailability.java @@ -0,0 +1,16 @@ +package io.facturapi.models; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class DomainAvailability { + private boolean available; + + public boolean isAvailable() { + return available; + } + + public void setAvailable(boolean available) { + this.available = available; + } +} diff --git a/src/main/java/io/facturapi/models/GenericResponse.java b/src/main/java/io/facturapi/models/GenericResponse.java new file mode 100644 index 0000000..220aa89 --- /dev/null +++ b/src/main/java/io/facturapi/models/GenericResponse.java @@ -0,0 +1,16 @@ +package io.facturapi.models; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class GenericResponse { + private boolean ok; + + public boolean isOk() { + return ok; + } + + public void setOk(boolean ok) { + this.ok = ok; + } +} diff --git a/src/main/java/io/facturapi/models/GlobalInfo.java b/src/main/java/io/facturapi/models/GlobalInfo.java new file mode 100644 index 0000000..0facab2 --- /dev/null +++ b/src/main/java/io/facturapi/models/GlobalInfo.java @@ -0,0 +1,17 @@ +package io.facturapi.models; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class GlobalInfo { + private String periodicity; + private String months; + private Integer year; + + public String getPeriodicity() { return periodicity; } + public void setPeriodicity(String periodicity) { this.periodicity = periodicity; } + public String getMonths() { return months; } + public void setMonths(String months) { this.months = months; } + public Integer getYear() { return year; } + public void setYear(Integer year) { this.year = year; } +} diff --git a/src/main/java/io/facturapi/models/Invoice.java b/src/main/java/io/facturapi/models/Invoice.java new file mode 100644 index 0000000..94f060d --- /dev/null +++ b/src/main/java/io/facturapi/models/Invoice.java @@ -0,0 +1,153 @@ +package io.facturapi.models; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import java.util.ArrayList; +import java.util.List; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class Invoice { + private String id; + private String organization; + private Boolean livemode; + @JsonProperty("created_at") + private String createdAt; + private String date; + @JsonProperty("issuer_type") + private String issuerType; + private String type; + private String status; + @JsonProperty("cfdi_version") + private Integer cfdiVersion; + @JsonProperty("issuer_info") + private CustomerInfo issuerInfo; + @JsonProperty("payment_form") + private String paymentForm; + @JsonProperty("payment_method") + private String paymentMethod; + private String currency; + private Double exchange; + private String uuid; + private CustomerInfo customer; + private Double total; + private String use; + @JsonProperty("folio_number") + private String folioNumber; + private String series; + @JsonProperty("is_ready_to_stamp") + private Boolean readyToStamp; + private List items = new ArrayList<>(); + private Address address; + @JsonProperty("amount_due") + private Double amountDue; + @JsonProperty("verification_url") + private String verificationUrl; + @JsonProperty("verification_carta_porte") + private String verificationCartaPorte; + @JsonProperty("cancellation_status") + private String cancellationStatus; + @JsonProperty("external_id") + private String externalId; + @JsonProperty("idempotency_key") + private String idempotencyKey; + private Stamp stamp; + private String addenda; + private String conditions; + @JsonProperty("pdf_custom_section") + private String pdfCustomSection; + @JsonProperty("export") + private String exportReference; + private GlobalInfo global; + private InvoiceCancellation cancellation; + private List complements = new ArrayList<>(); + @JsonProperty("related_documents") + private List relatedDocuments = new ArrayList<>(); + private List namespaces = new ArrayList<>(); + @JsonProperty("received_payment_ids") + private List receivedPaymentIds = new ArrayList<>(); + @JsonProperty("target_invoice_ids") + private List targetInvoiceIds = new ArrayList<>(); + + public String getId() { return id; } + public void setId(String id) { this.id = id; } + public String getOrganization() { return organization; } + public void setOrganization(String organization) { this.organization = organization; } + public Boolean getLivemode() { return livemode; } + public void setLivemode(Boolean livemode) { this.livemode = livemode; } + public String getCreatedAt() { return createdAt; } + public void setCreatedAt(String createdAt) { this.createdAt = createdAt; } + public String getDate() { return date; } + public void setDate(String date) { this.date = date; } + public String getIssuerType() { return issuerType; } + public void setIssuerType(String issuerType) { this.issuerType = issuerType; } + public String getType() { return type; } + public void setType(String type) { this.type = type; } + public String getStatus() { return status; } + public void setStatus(String status) { this.status = status; } + public Integer getCfdiVersion() { return cfdiVersion; } + public void setCfdiVersion(Integer cfdiVersion) { this.cfdiVersion = cfdiVersion; } + public CustomerInfo getIssuerInfo() { return issuerInfo; } + public void setIssuerInfo(CustomerInfo issuerInfo) { this.issuerInfo = issuerInfo; } + public String getPaymentForm() { return paymentForm; } + public void setPaymentForm(String paymentForm) { this.paymentForm = paymentForm; } + public String getPaymentMethod() { return paymentMethod; } + public void setPaymentMethod(String paymentMethod) { this.paymentMethod = paymentMethod; } + public String getCurrency() { return currency; } + public void setCurrency(String currency) { this.currency = currency; } + public Double getExchange() { return exchange; } + public void setExchange(Double exchange) { this.exchange = exchange; } + public String getUuid() { return uuid; } + public void setUuid(String uuid) { this.uuid = uuid; } + public CustomerInfo getCustomer() { return customer; } + public void setCustomer(CustomerInfo customer) { this.customer = customer; } + public Double getTotal() { return total; } + public void setTotal(Double total) { this.total = total; } + public String getUse() { return use; } + public void setUse(String use) { this.use = use; } + public String getFolioNumber() { return folioNumber; } + public void setFolioNumber(String folioNumber) { this.folioNumber = folioNumber; } + public String getSeries() { return series; } + public void setSeries(String series) { this.series = series; } + public Boolean getReadyToStamp() { return readyToStamp; } + public void setReadyToStamp(Boolean readyToStamp) { this.readyToStamp = readyToStamp; } + public List getItems() { return items; } + public void setItems(List items) { this.items = items; } + public Address getAddress() { return address; } + public void setAddress(Address address) { this.address = address; } + public Double getAmountDue() { return amountDue; } + public void setAmountDue(Double amountDue) { this.amountDue = amountDue; } + public String getVerificationUrl() { return verificationUrl; } + public void setVerificationUrl(String verificationUrl) { this.verificationUrl = verificationUrl; } + public String getVerificationCartaPorte() { return verificationCartaPorte; } + public void setVerificationCartaPorte(String verificationCartaPorte) { this.verificationCartaPorte = verificationCartaPorte; } + public String getCancellationStatus() { return cancellationStatus; } + public void setCancellationStatus(String cancellationStatus) { this.cancellationStatus = cancellationStatus; } + public String getExternalId() { return externalId; } + public void setExternalId(String externalId) { this.externalId = externalId; } + public String getIdempotencyKey() { return idempotencyKey; } + public void setIdempotencyKey(String idempotencyKey) { this.idempotencyKey = idempotencyKey; } + public Stamp getStamp() { return stamp; } + public void setStamp(Stamp stamp) { this.stamp = stamp; } + public String getAddenda() { return addenda; } + public void setAddenda(String addenda) { this.addenda = addenda; } + public String getConditions() { return conditions; } + public void setConditions(String conditions) { this.conditions = conditions; } + public String getPdfCustomSection() { return pdfCustomSection; } + public void setPdfCustomSection(String pdfCustomSection) { this.pdfCustomSection = pdfCustomSection; } + public String getExportReference() { return exportReference; } + public void setExportReference(String exportReference) { this.exportReference = exportReference; } + public GlobalInfo getGlobal() { return global; } + public void setGlobal(GlobalInfo global) { this.global = global; } + public InvoiceCancellation getCancellation() { return cancellation; } + public void setCancellation(InvoiceCancellation cancellation) { this.cancellation = cancellation; } + public List getComplements() { return complements; } + public void setComplements(List complements) { this.complements = complements; } + public List getRelatedDocuments() { return relatedDocuments; } + public void setRelatedDocuments(List relatedDocuments) { this.relatedDocuments = relatedDocuments; } + public List getNamespaces() { return namespaces; } + public void setNamespaces(List namespaces) { this.namespaces = namespaces; } + public List getReceivedPaymentIds() { return receivedPaymentIds; } + public void setReceivedPaymentIds(List receivedPaymentIds) { this.receivedPaymentIds = receivedPaymentIds; } + public List getTargetInvoiceIds() { return targetInvoiceIds; } + public void setTargetInvoiceIds(List targetInvoiceIds) { this.targetInvoiceIds = targetInvoiceIds; } +} diff --git a/src/main/java/io/facturapi/models/InvoiceCancellation.java b/src/main/java/io/facturapi/models/InvoiceCancellation.java new file mode 100644 index 0000000..3bb4827 --- /dev/null +++ b/src/main/java/io/facturapi/models/InvoiceCancellation.java @@ -0,0 +1,27 @@ +package io.facturapi.models; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class InvoiceCancellation { + @JsonProperty("requested_at") + private String requestedAt; + private String status; + @JsonProperty("last_checked") + private String lastChecked; + private String motive; + @JsonProperty("substitution_uuid") + private String substitutionUuid; + + public String getRequestedAt() { return requestedAt; } + public void setRequestedAt(String requestedAt) { this.requestedAt = requestedAt; } + public String getStatus() { return status; } + public void setStatus(String status) { this.status = status; } + public String getLastChecked() { return lastChecked; } + public void setLastChecked(String lastChecked) { this.lastChecked = lastChecked; } + public String getMotive() { return motive; } + public void setMotive(String motive) { this.motive = motive; } + public String getSubstitutionUuid() { return substitutionUuid; } + public void setSubstitutionUuid(String substitutionUuid) { this.substitutionUuid = substitutionUuid; } +} diff --git a/src/main/java/io/facturapi/models/InvoiceComplement.java b/src/main/java/io/facturapi/models/InvoiceComplement.java new file mode 100644 index 0000000..0b5ed10 --- /dev/null +++ b/src/main/java/io/facturapi/models/InvoiceComplement.java @@ -0,0 +1,149 @@ +package io.facturapi.models; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonSetter; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import java.util.List; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class InvoiceComplement { + private static final ObjectMapper MAPPER = new ObjectMapper() + .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + + private String type; + @JsonIgnore + private JsonNode rawData; + @JsonIgnore + private List pagoData; + @JsonIgnore + private NominaComplementData nominaData; + @JsonIgnore + private CartaPorteComplementData cartaPorteData; + @JsonIgnore + private ComercioExteriorComplementData comercioExteriorData; + @JsonIgnore + private String customData; + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + parseRawData(); + } + + @JsonSetter("data") + private void setRawData(JsonNode rawData) { + this.rawData = rawData; + parseRawData(); + } + + @JsonProperty("data") + public Object getData() { + if ("pago".equals(type)) { + return pagoData; + } + if ("nomina".equals(type)) { + return nominaData; + } + if ("custom".equals(type)) { + return customData; + } + if ("carta_porte".equals(type)) { + return cartaPorteData; + } + if ("comercio_exterior".equals(type)) { + return comercioExteriorData; + } + if (pagoData != null) { + return pagoData; + } + if (nominaData != null) { + return nominaData; + } + if (cartaPorteData != null) { + return cartaPorteData; + } + if (comercioExteriorData != null) { + return comercioExteriorData; + } + return customData; + } + + public List getPagoData() { + return pagoData; + } + + public NominaComplementData getNominaData() { + return nominaData; + } + + public CartaPorteComplementData getCartaPorteData() { + return cartaPorteData; + } + + public ComercioExteriorComplementData getComercioExteriorData() { + return comercioExteriorData; + } + + public String getCustomData() { + return customData; + } + + private void parseRawData() { + this.pagoData = null; + this.nominaData = null; + this.cartaPorteData = null; + this.comercioExteriorData = null; + this.customData = null; + + if (rawData == null || rawData.isNull()) { + return; + } + + try { + if ("pago".equals(type) && rawData.isArray()) { + this.pagoData = MAPPER.convertValue(rawData, new TypeReference>() {}); + return; + } + if ("nomina".equals(type) && rawData.isObject()) { + this.nominaData = MAPPER.convertValue(rawData, NominaComplementData.class); + return; + } + if ("custom".equals(type) && rawData.isTextual()) { + this.customData = rawData.asText(); + return; + } + if ("carta_porte".equals(type) && rawData.isObject()) { + this.cartaPorteData = MAPPER.convertValue(rawData, CartaPorteComplementData.class); + return; + } + if ("comercio_exterior".equals(type) && rawData.isObject()) { + this.comercioExteriorData = MAPPER.convertValue(rawData, ComercioExteriorComplementData.class); + return; + } + + if (rawData.isArray()) { + this.pagoData = MAPPER.convertValue(rawData, new TypeReference>() {}); + } else if (rawData.isObject()) { + if (rawData.has("IdCCP") || rawData.has("TranspInternac")) { + this.cartaPorteData = MAPPER.convertValue(rawData, CartaPorteComplementData.class); + } else if (rawData.has("ClaveDePedimento") || rawData.has("TipoCambioUSD") || rawData.has("TotalUSD")) { + this.comercioExteriorData = MAPPER.convertValue(rawData, ComercioExteriorComplementData.class); + } else { + this.nominaData = MAPPER.convertValue(rawData, NominaComplementData.class); + } + } else if (rawData.isTextual()) { + this.customData = rawData.asText(); + } + } catch (IllegalArgumentException ignored) { + // Keep null typed fields on malformed payloads. + } + } +} diff --git a/src/main/java/io/facturapi/models/InvoiceItem.java b/src/main/java/io/facturapi/models/InvoiceItem.java new file mode 100644 index 0000000..104ad21 --- /dev/null +++ b/src/main/java/io/facturapi/models/InvoiceItem.java @@ -0,0 +1,38 @@ +package io.facturapi.models; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import java.util.ArrayList; +import java.util.List; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class InvoiceItem { + private Double quantity; + private ProductInfo product; + private Double discount; + @JsonProperty("customs_keys") + private List customsKeys = new ArrayList<>(); + @JsonProperty("third_party") + private InvoiceItemThirdParty thirdParty; + private String complement; + private List parts = new ArrayList<>(); + @JsonProperty("property_tax_account") + private String propertyTaxAccount; + + public Double getQuantity() { return quantity; } + public void setQuantity(Double quantity) { this.quantity = quantity; } + public ProductInfo getProduct() { return product; } + public void setProduct(ProductInfo product) { this.product = product; } + public Double getDiscount() { return discount; } + public void setDiscount(Double discount) { this.discount = discount; } + public List getCustomsKeys() { return customsKeys; } + public void setCustomsKeys(List customsKeys) { this.customsKeys = customsKeys; } + public InvoiceItemThirdParty getThirdParty() { return thirdParty; } + public void setThirdParty(InvoiceItemThirdParty thirdParty) { this.thirdParty = thirdParty; } + public String getComplement() { return complement; } + public void setComplement(String complement) { this.complement = complement; } + public List getParts() { return parts; } + public void setParts(List parts) { this.parts = parts; } + public String getPropertyTaxAccount() { return propertyTaxAccount; } + public void setPropertyTaxAccount(String propertyTaxAccount) { this.propertyTaxAccount = propertyTaxAccount; } +} diff --git a/src/main/java/io/facturapi/models/InvoiceItemPart.java b/src/main/java/io/facturapi/models/InvoiceItemPart.java new file mode 100644 index 0000000..e73c7bd --- /dev/null +++ b/src/main/java/io/facturapi/models/InvoiceItemPart.java @@ -0,0 +1,30 @@ +package io.facturapi.models; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class InvoiceItemPart { + private Double quantity; + @JsonProperty("product_key") + private String productKey; + private String description; + @JsonProperty("unit_name") + private String unitName; + private String sku; + @JsonProperty("unit_price") + private Double unitPrice; + + public Double getQuantity() { return quantity; } + public void setQuantity(Double quantity) { this.quantity = quantity; } + public String getProductKey() { return productKey; } + public void setProductKey(String productKey) { this.productKey = productKey; } + public String getDescription() { return description; } + public void setDescription(String description) { this.description = description; } + public String getUnitName() { return unitName; } + public void setUnitName(String unitName) { this.unitName = unitName; } + public String getSku() { return sku; } + public void setSku(String sku) { this.sku = sku; } + public Double getUnitPrice() { return unitPrice; } + public void setUnitPrice(Double unitPrice) { this.unitPrice = unitPrice; } +} diff --git a/src/main/java/io/facturapi/models/InvoiceItemThirdParty.java b/src/main/java/io/facturapi/models/InvoiceItemThirdParty.java new file mode 100644 index 0000000..3e33a2e --- /dev/null +++ b/src/main/java/io/facturapi/models/InvoiceItemThirdParty.java @@ -0,0 +1,24 @@ +package io.facturapi.models; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class InvoiceItemThirdParty { + @JsonProperty("tax_id") + private String taxId; + @JsonProperty("legal_name") + private String legalName; + @JsonProperty("tax_system") + private String taxSystem; + private String zip; + + public String getTaxId() { return taxId; } + public void setTaxId(String taxId) { this.taxId = taxId; } + public String getLegalName() { return legalName; } + public void setLegalName(String legalName) { this.legalName = legalName; } + public String getTaxSystem() { return taxSystem; } + public void setTaxSystem(String taxSystem) { this.taxSystem = taxSystem; } + public String getZip() { return zip; } + public void setZip(String zip) { this.zip = zip; } +} diff --git a/src/main/java/io/facturapi/models/Legal.java b/src/main/java/io/facturapi/models/Legal.java new file mode 100644 index 0000000..0c2c91c --- /dev/null +++ b/src/main/java/io/facturapi/models/Legal.java @@ -0,0 +1,40 @@ +package io.facturapi.models; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class Legal { + private String name; + @JsonProperty("legal_name") + private String legalName; + @JsonProperty("tax_id") + private String taxId; + @JsonProperty("tax_system") + private String taxSystem; + private Address address; + private String phone; + private String website; + @JsonProperty("support_email") + private String supportEmail; + private String curp; + + public String getName() { return name; } + public void setName(String name) { this.name = name; } + public String getLegalName() { return legalName; } + public void setLegalName(String legalName) { this.legalName = legalName; } + public String getTaxId() { return taxId; } + public void setTaxId(String taxId) { this.taxId = taxId; } + public String getTaxSystem() { return taxSystem; } + public void setTaxSystem(String taxSystem) { this.taxSystem = taxSystem; } + public Address getAddress() { return address; } + public void setAddress(Address address) { this.address = address; } + public String getPhone() { return phone; } + public void setPhone(String phone) { this.phone = phone; } + public String getWebsite() { return website; } + public void setWebsite(String website) { this.website = website; } + public String getSupportEmail() { return supportEmail; } + public void setSupportEmail(String supportEmail) { this.supportEmail = supportEmail; } + public String getCurp() { return curp; } + public void setCurp(String curp) { this.curp = curp; } +} diff --git a/src/main/java/io/facturapi/models/LocalTax.java b/src/main/java/io/facturapi/models/LocalTax.java new file mode 100644 index 0000000..bee5119 --- /dev/null +++ b/src/main/java/io/facturapi/models/LocalTax.java @@ -0,0 +1,52 @@ +package io.facturapi.models; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class LocalTax { + private Double base; + private Double rate; + private String type; + private Boolean withholding; + private String factor; + + public Double getBase() { + return base; + } + + public void setBase(Double base) { + this.base = base; + } + + public Double getRate() { + return rate; + } + + public void setRate(Double rate) { + this.rate = rate; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public Boolean getWithholding() { + return withholding; + } + + public void setWithholding(Boolean withholding) { + this.withholding = withholding; + } + + public String getFactor() { + return factor; + } + + public void setFactor(String factor) { + this.factor = factor; + } +} diff --git a/src/main/java/io/facturapi/models/NominaAcciones.java b/src/main/java/io/facturapi/models/NominaAcciones.java new file mode 100644 index 0000000..7574ac9 --- /dev/null +++ b/src/main/java/io/facturapi/models/NominaAcciones.java @@ -0,0 +1,17 @@ +package io.facturapi.models; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class NominaAcciones { + @JsonProperty("valor_mercado") + private Double valorMercado; + @JsonProperty("precio_al_otorgarse") + private Double precioAlOtorgarse; + + public Double getValorMercado() { return valorMercado; } + public void setValorMercado(Double valorMercado) { this.valorMercado = valorMercado; } + public Double getPrecioAlOtorgarse() { return precioAlOtorgarse; } + public void setPrecioAlOtorgarse(Double precioAlOtorgarse) { this.precioAlOtorgarse = precioAlOtorgarse; } +} diff --git a/src/main/java/io/facturapi/models/NominaCompensacion.java b/src/main/java/io/facturapi/models/NominaCompensacion.java new file mode 100644 index 0000000..8e07b0a --- /dev/null +++ b/src/main/java/io/facturapi/models/NominaCompensacion.java @@ -0,0 +1,20 @@ +package io.facturapi.models; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class NominaCompensacion { + @JsonProperty("saldo_a_favor") + private Double saldoAFavor; + private Integer ano; + @JsonProperty("remanente_sal_fav") + private Double remanenteSalFav; + + public Double getSaldoAFavor() { return saldoAFavor; } + public void setSaldoAFavor(Double saldoAFavor) { this.saldoAFavor = saldoAFavor; } + public Integer getAno() { return ano; } + public void setAno(Integer ano) { this.ano = ano; } + public Double getRemanenteSalFav() { return remanenteSalFav; } + public void setRemanenteSalFav(Double remanenteSalFav) { this.remanenteSalFav = remanenteSalFav; } +} diff --git a/src/main/java/io/facturapi/models/NominaComplementData.java b/src/main/java/io/facturapi/models/NominaComplementData.java new file mode 100644 index 0000000..7ca85b7 --- /dev/null +++ b/src/main/java/io/facturapi/models/NominaComplementData.java @@ -0,0 +1,50 @@ +package io.facturapi.models; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import java.util.ArrayList; +import java.util.List; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class NominaComplementData { + @JsonProperty("fecha_inicial_pago") + private String fechaInicialPago; + @JsonProperty("fecha_final_pago") + private String fechaFinalPago; + private NominaPercepciones percepciones; + private List deducciones = new ArrayList<>(); + @JsonProperty("otros_pagos") + private List otrosPagos = new ArrayList<>(); + private List incapacidades = new ArrayList<>(); + private NominaEmisor emisor; + private NominaReceptor receptor; + @JsonProperty("tipo_nomina") + private String tipoNomina; + @JsonProperty("fecha_pago") + private String fechaPago; + @JsonProperty("num_dias_pagados") + private Double numDiasPagados; + + public String getFechaInicialPago() { return fechaInicialPago; } + public void setFechaInicialPago(String fechaInicialPago) { this.fechaInicialPago = fechaInicialPago; } + public String getFechaFinalPago() { return fechaFinalPago; } + public void setFechaFinalPago(String fechaFinalPago) { this.fechaFinalPago = fechaFinalPago; } + public NominaPercepciones getPercepciones() { return percepciones; } + public void setPercepciones(NominaPercepciones percepciones) { this.percepciones = percepciones; } + public List getDeducciones() { return deducciones; } + public void setDeducciones(List deducciones) { this.deducciones = deducciones; } + public List getOtrosPagos() { return otrosPagos; } + public void setOtrosPagos(List otrosPagos) { this.otrosPagos = otrosPagos; } + public List getIncapacidades() { return incapacidades; } + public void setIncapacidades(List incapacidades) { this.incapacidades = incapacidades; } + public NominaEmisor getEmisor() { return emisor; } + public void setEmisor(NominaEmisor emisor) { this.emisor = emisor; } + public NominaReceptor getReceptor() { return receptor; } + public void setReceptor(NominaReceptor receptor) { this.receptor = receptor; } + public String getTipoNomina() { return tipoNomina; } + public void setTipoNomina(String tipoNomina) { this.tipoNomina = tipoNomina; } + public String getFechaPago() { return fechaPago; } + public void setFechaPago(String fechaPago) { this.fechaPago = fechaPago; } + public Double getNumDiasPagados() { return numDiasPagados; } + public void setNumDiasPagados(Double numDiasPagados) { this.numDiasPagados = numDiasPagados; } +} diff --git a/src/main/java/io/facturapi/models/NominaDeduccion.java b/src/main/java/io/facturapi/models/NominaDeduccion.java new file mode 100644 index 0000000..b76cbda --- /dev/null +++ b/src/main/java/io/facturapi/models/NominaDeduccion.java @@ -0,0 +1,22 @@ +package io.facturapi.models; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class NominaDeduccion { + @JsonProperty("tipo_deduccion") + private String tipoDeduccion; + private String concepto; + private String clave; + private Double importe; + + public String getTipoDeduccion() { return tipoDeduccion; } + public void setTipoDeduccion(String tipoDeduccion) { this.tipoDeduccion = tipoDeduccion; } + public String getConcepto() { return concepto; } + public void setConcepto(String concepto) { this.concepto = concepto; } + public String getClave() { return clave; } + public void setClave(String clave) { this.clave = clave; } + public Double getImporte() { return importe; } + public void setImporte(Double importe) { this.importe = importe; } +} diff --git a/src/main/java/io/facturapi/models/NominaEmisor.java b/src/main/java/io/facturapi/models/NominaEmisor.java new file mode 100644 index 0000000..545ba3c --- /dev/null +++ b/src/main/java/io/facturapi/models/NominaEmisor.java @@ -0,0 +1,24 @@ +package io.facturapi.models; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class NominaEmisor { + private String curp; + @JsonProperty("registro_patronal") + private String registroPatronal; + @JsonProperty("rfc_patron_origen") + private String rfcPatronOrigen; + @JsonProperty("entidad_sncf") + private NominaEntidadSncf entidadSncf; + + public String getCurp() { return curp; } + public void setCurp(String curp) { this.curp = curp; } + public String getRegistroPatronal() { return registroPatronal; } + public void setRegistroPatronal(String registroPatronal) { this.registroPatronal = registroPatronal; } + public String getRfcPatronOrigen() { return rfcPatronOrigen; } + public void setRfcPatronOrigen(String rfcPatronOrigen) { this.rfcPatronOrigen = rfcPatronOrigen; } + public NominaEntidadSncf getEntidadSncf() { return entidadSncf; } + public void setEntidadSncf(NominaEntidadSncf entidadSncf) { this.entidadSncf = entidadSncf; } +} diff --git a/src/main/java/io/facturapi/models/NominaEntidadSncf.java b/src/main/java/io/facturapi/models/NominaEntidadSncf.java new file mode 100644 index 0000000..aade868 --- /dev/null +++ b/src/main/java/io/facturapi/models/NominaEntidadSncf.java @@ -0,0 +1,17 @@ +package io.facturapi.models; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class NominaEntidadSncf { + @JsonProperty("origen_recurso") + private String origenRecurso; + @JsonProperty("monto_recurso_propio") + private Double montoRecursoPropio; + + public String getOrigenRecurso() { return origenRecurso; } + public void setOrigenRecurso(String origenRecurso) { this.origenRecurso = origenRecurso; } + public Double getMontoRecursoPropio() { return montoRecursoPropio; } + public void setMontoRecursoPropio(Double montoRecursoPropio) { this.montoRecursoPropio = montoRecursoPropio; } +} diff --git a/src/main/java/io/facturapi/models/NominaHorasExtra.java b/src/main/java/io/facturapi/models/NominaHorasExtra.java new file mode 100644 index 0000000..8f82717 --- /dev/null +++ b/src/main/java/io/facturapi/models/NominaHorasExtra.java @@ -0,0 +1,24 @@ +package io.facturapi.models; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class NominaHorasExtra { + private Integer dias; + @JsonProperty("tipo_horas") + private String tipoHoras; + @JsonProperty("horas_extra") + private Integer horasExtra; + @JsonProperty("importe_pagado") + private Double importePagado; + + public Integer getDias() { return dias; } + public void setDias(Integer dias) { this.dias = dias; } + public String getTipoHoras() { return tipoHoras; } + public void setTipoHoras(String tipoHoras) { this.tipoHoras = tipoHoras; } + public Integer getHorasExtra() { return horasExtra; } + public void setHorasExtra(Integer horasExtra) { this.horasExtra = horasExtra; } + public Double getImportePagado() { return importePagado; } + public void setImportePagado(Double importePagado) { this.importePagado = importePagado; } +} diff --git a/src/main/java/io/facturapi/models/NominaIncapacidad.java b/src/main/java/io/facturapi/models/NominaIncapacidad.java new file mode 100644 index 0000000..092bde1 --- /dev/null +++ b/src/main/java/io/facturapi/models/NominaIncapacidad.java @@ -0,0 +1,21 @@ +package io.facturapi.models; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class NominaIncapacidad { + @JsonProperty("dias_incapacidad") + private Integer diasIncapacidad; + @JsonProperty("tipo_incapacidad") + private String tipoIncapacidad; + @JsonProperty("importe_monetario") + private Double importeMonetario; + + public Integer getDiasIncapacidad() { return diasIncapacidad; } + public void setDiasIncapacidad(Integer diasIncapacidad) { this.diasIncapacidad = diasIncapacidad; } + public String getTipoIncapacidad() { return tipoIncapacidad; } + public void setTipoIncapacidad(String tipoIncapacidad) { this.tipoIncapacidad = tipoIncapacidad; } + public Double getImporteMonetario() { return importeMonetario; } + public void setImporteMonetario(Double importeMonetario) { this.importeMonetario = importeMonetario; } +} diff --git a/src/main/java/io/facturapi/models/NominaJubilacion.java b/src/main/java/io/facturapi/models/NominaJubilacion.java new file mode 100644 index 0000000..69afefd --- /dev/null +++ b/src/main/java/io/facturapi/models/NominaJubilacion.java @@ -0,0 +1,29 @@ +package io.facturapi.models; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class NominaJubilacion { + @JsonProperty("total_una_exhibicion") + private Double totalUnaExhibicion; + @JsonProperty("total_parcialidad") + private Double totalParcialidad; + @JsonProperty("monto_diario") + private Double montoDiario; + @JsonProperty("ingreso_acumulable") + private Double ingresoAcumulable; + @JsonProperty("ingreso_no_acumulable") + private Double ingresoNoAcumulable; + + public Double getTotalUnaExhibicion() { return totalUnaExhibicion; } + public void setTotalUnaExhibicion(Double totalUnaExhibicion) { this.totalUnaExhibicion = totalUnaExhibicion; } + public Double getTotalParcialidad() { return totalParcialidad; } + public void setTotalParcialidad(Double totalParcialidad) { this.totalParcialidad = totalParcialidad; } + public Double getMontoDiario() { return montoDiario; } + public void setMontoDiario(Double montoDiario) { this.montoDiario = montoDiario; } + public Double getIngresoAcumulable() { return ingresoAcumulable; } + public void setIngresoAcumulable(Double ingresoAcumulable) { this.ingresoAcumulable = ingresoAcumulable; } + public Double getIngresoNoAcumulable() { return ingresoNoAcumulable; } + public void setIngresoNoAcumulable(Double ingresoNoAcumulable) { this.ingresoNoAcumulable = ingresoNoAcumulable; } +} diff --git a/src/main/java/io/facturapi/models/NominaOtroPago.java b/src/main/java/io/facturapi/models/NominaOtroPago.java new file mode 100644 index 0000000..fc8e40c --- /dev/null +++ b/src/main/java/io/facturapi/models/NominaOtroPago.java @@ -0,0 +1,30 @@ +package io.facturapi.models; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class NominaOtroPago { + @JsonProperty("tipo_otro_pago") + private String tipoOtroPago; + private String clave; + private String concepto; + private Double importe; + @JsonProperty("subsidio_causado") + private Double subsidioCausado; + @JsonProperty("compensacion_saldos_a_favor") + private NominaCompensacion compensacionSaldosAFavor; + + public String getTipoOtroPago() { return tipoOtroPago; } + public void setTipoOtroPago(String tipoOtroPago) { this.tipoOtroPago = tipoOtroPago; } + public String getClave() { return clave; } + public void setClave(String clave) { this.clave = clave; } + public String getConcepto() { return concepto; } + public void setConcepto(String concepto) { this.concepto = concepto; } + public Double getImporte() { return importe; } + public void setImporte(Double importe) { this.importe = importe; } + public Double getSubsidioCausado() { return subsidioCausado; } + public void setSubsidioCausado(Double subsidioCausado) { this.subsidioCausado = subsidioCausado; } + public NominaCompensacion getCompensacionSaldosAFavor() { return compensacionSaldosAFavor; } + public void setCompensacionSaldosAFavor(NominaCompensacion compensacionSaldosAFavor) { this.compensacionSaldosAFavor = compensacionSaldosAFavor; } +} diff --git a/src/main/java/io/facturapi/models/NominaPercepcion.java b/src/main/java/io/facturapi/models/NominaPercepcion.java new file mode 100644 index 0000000..d0ce886 --- /dev/null +++ b/src/main/java/io/facturapi/models/NominaPercepcion.java @@ -0,0 +1,37 @@ +package io.facturapi.models; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import java.util.ArrayList; +import java.util.List; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class NominaPercepcion { + @JsonProperty("tipo_percepcion") + private String tipoPercepcion; + private String concepto; + private String clave; + @JsonProperty("importe_gravado") + private Double importeGravado; + @JsonProperty("importe_exento") + private Double importeExento; + @JsonProperty("acciones_o_titulos") + private NominaAcciones accionesOTitulos; + @JsonProperty("horas_extra") + private List horasExtra = new ArrayList<>(); + + public String getTipoPercepcion() { return tipoPercepcion; } + public void setTipoPercepcion(String tipoPercepcion) { this.tipoPercepcion = tipoPercepcion; } + public String getConcepto() { return concepto; } + public void setConcepto(String concepto) { this.concepto = concepto; } + public String getClave() { return clave; } + public void setClave(String clave) { this.clave = clave; } + public Double getImporteGravado() { return importeGravado; } + public void setImporteGravado(Double importeGravado) { this.importeGravado = importeGravado; } + public Double getImporteExento() { return importeExento; } + public void setImporteExento(Double importeExento) { this.importeExento = importeExento; } + public NominaAcciones getAccionesOTitulos() { return accionesOTitulos; } + public void setAccionesOTitulos(NominaAcciones accionesOTitulos) { this.accionesOTitulos = accionesOTitulos; } + public List getHorasExtra() { return horasExtra; } + public void setHorasExtra(List horasExtra) { this.horasExtra = horasExtra; } +} diff --git a/src/main/java/io/facturapi/models/NominaPercepciones.java b/src/main/java/io/facturapi/models/NominaPercepciones.java new file mode 100644 index 0000000..ee3730e --- /dev/null +++ b/src/main/java/io/facturapi/models/NominaPercepciones.java @@ -0,0 +1,23 @@ +package io.facturapi.models; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import java.util.ArrayList; +import java.util.List; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class NominaPercepciones { + @JsonProperty("percepcion") + private List percepcion = new ArrayList<>(); + @JsonProperty("jubilacion_pension_retiro") + private NominaJubilacion jubilacionPensionRetiro; + @JsonProperty("separacion_indemnizacion") + private NominaSeparacion separacionIndemnizacion; + + public List getPercepcion() { return percepcion; } + public void setPercepcion(List percepcion) { this.percepcion = percepcion; } + public NominaJubilacion getJubilacionPensionRetiro() { return jubilacionPensionRetiro; } + public void setJubilacionPensionRetiro(NominaJubilacion jubilacionPensionRetiro) { this.jubilacionPensionRetiro = jubilacionPensionRetiro; } + public NominaSeparacion getSeparacionIndemnizacion() { return separacionIndemnizacion; } + public void setSeparacionIndemnizacion(NominaSeparacion separacionIndemnizacion) { this.separacionIndemnizacion = separacionIndemnizacion; } +} diff --git a/src/main/java/io/facturapi/models/NominaReceptor.java b/src/main/java/io/facturapi/models/NominaReceptor.java new file mode 100644 index 0000000..3bf2593 --- /dev/null +++ b/src/main/java/io/facturapi/models/NominaReceptor.java @@ -0,0 +1,85 @@ +package io.facturapi.models; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import java.util.ArrayList; +import java.util.List; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class NominaReceptor { + private String curp; + @JsonProperty("num_seguridad_social") + private String numSeguridadSocial; + @JsonProperty("fecha_inicio_rel_laboral") + private String fechaInicioRelLaboral; + private Object antiguedad; + @JsonProperty("tipo_contrato") + private String tipoContrato; + private Boolean sindicalizado; + @JsonProperty("tipo_jornada") + private String tipoJornada; + @JsonProperty("tipo_regimen") + private String tipoRegimen; + @JsonProperty("num_empleado") + private String numEmpleado; + private String departamento; + private String puesto; + @JsonProperty("riesgo_puesto") + private String riesgoPuesto; + @JsonProperty("periodicidad_pago") + private String periodicidadPago; + private String banco; + @JsonProperty("nombre_banco") + private String nombreBanco; + @JsonProperty("cuenta_bancaria") + private String cuentaBancaria; + @JsonProperty("salario_base_cot_apor") + private Double salarioBaseCotApor; + @JsonProperty("salario_diario_integrado") + private Double salarioDiarioIntegrado; + @JsonProperty("clave_ent_fed") + private String claveEntFed; + @JsonProperty("sub_contratacion") + private List subContratacion = new ArrayList<>(); + + public String getCurp() { return curp; } + public void setCurp(String curp) { this.curp = curp; } + public String getNumSeguridadSocial() { return numSeguridadSocial; } + public void setNumSeguridadSocial(String numSeguridadSocial) { this.numSeguridadSocial = numSeguridadSocial; } + public String getFechaInicioRelLaboral() { return fechaInicioRelLaboral; } + public void setFechaInicioRelLaboral(String fechaInicioRelLaboral) { this.fechaInicioRelLaboral = fechaInicioRelLaboral; } + public Object getAntiguedad() { return antiguedad; } + public void setAntiguedad(Object antiguedad) { this.antiguedad = antiguedad; } + public String getTipoContrato() { return tipoContrato; } + public void setTipoContrato(String tipoContrato) { this.tipoContrato = tipoContrato; } + public Boolean getSindicalizado() { return sindicalizado; } + public void setSindicalizado(Boolean sindicalizado) { this.sindicalizado = sindicalizado; } + public String getTipoJornada() { return tipoJornada; } + public void setTipoJornada(String tipoJornada) { this.tipoJornada = tipoJornada; } + public String getTipoRegimen() { return tipoRegimen; } + public void setTipoRegimen(String tipoRegimen) { this.tipoRegimen = tipoRegimen; } + public String getNumEmpleado() { return numEmpleado; } + public void setNumEmpleado(String numEmpleado) { this.numEmpleado = numEmpleado; } + public String getDepartamento() { return departamento; } + public void setDepartamento(String departamento) { this.departamento = departamento; } + public String getPuesto() { return puesto; } + public void setPuesto(String puesto) { this.puesto = puesto; } + public String getRiesgoPuesto() { return riesgoPuesto; } + public void setRiesgoPuesto(String riesgoPuesto) { this.riesgoPuesto = riesgoPuesto; } + public String getPeriodicidadPago() { return periodicidadPago; } + public void setPeriodicidadPago(String periodicidadPago) { this.periodicidadPago = periodicidadPago; } + public String getBanco() { return banco; } + public void setBanco(String banco) { this.banco = banco; } + public String getNombreBanco() { return nombreBanco; } + public void setNombreBanco(String nombreBanco) { this.nombreBanco = nombreBanco; } + public String getCuentaBancaria() { return cuentaBancaria; } + public void setCuentaBancaria(String cuentaBancaria) { this.cuentaBancaria = cuentaBancaria; } + public Double getSalarioBaseCotApor() { return salarioBaseCotApor; } + public void setSalarioBaseCotApor(Double salarioBaseCotApor) { this.salarioBaseCotApor = salarioBaseCotApor; } + public Double getSalarioDiarioIntegrado() { return salarioDiarioIntegrado; } + public void setSalarioDiarioIntegrado(Double salarioDiarioIntegrado) { this.salarioDiarioIntegrado = salarioDiarioIntegrado; } + public String getClaveEntFed() { return claveEntFed; } + public void setClaveEntFed(String claveEntFed) { this.claveEntFed = claveEntFed; } + public List getSubContratacion() { return subContratacion; } + public void setSubContratacion(List subContratacion) { this.subContratacion = subContratacion; } +} diff --git a/src/main/java/io/facturapi/models/NominaSeparacion.java b/src/main/java/io/facturapi/models/NominaSeparacion.java new file mode 100644 index 0000000..2c444ba --- /dev/null +++ b/src/main/java/io/facturapi/models/NominaSeparacion.java @@ -0,0 +1,29 @@ +package io.facturapi.models; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class NominaSeparacion { + @JsonProperty("total_pagado") + private Double totalPagado; + @JsonProperty("num_anos_servicio") + private Integer numAnosServicio; + @JsonProperty("ultimo_sueldo_mens_ord") + private Double ultimoSueldoMensOrd; + @JsonProperty("ingreso_acumulable") + private Double ingresoAcumulable; + @JsonProperty("ingreso_no_acumulable") + private Double ingresoNoAcumulable; + + public Double getTotalPagado() { return totalPagado; } + public void setTotalPagado(Double totalPagado) { this.totalPagado = totalPagado; } + public Integer getNumAnosServicio() { return numAnosServicio; } + public void setNumAnosServicio(Integer numAnosServicio) { this.numAnosServicio = numAnosServicio; } + public Double getUltimoSueldoMensOrd() { return ultimoSueldoMensOrd; } + public void setUltimoSueldoMensOrd(Double ultimoSueldoMensOrd) { this.ultimoSueldoMensOrd = ultimoSueldoMensOrd; } + public Double getIngresoAcumulable() { return ingresoAcumulable; } + public void setIngresoAcumulable(Double ingresoAcumulable) { this.ingresoAcumulable = ingresoAcumulable; } + public Double getIngresoNoAcumulable() { return ingresoNoAcumulable; } + public void setIngresoNoAcumulable(Double ingresoNoAcumulable) { this.ingresoNoAcumulable = ingresoNoAcumulable; } +} diff --git a/src/main/java/io/facturapi/models/NominaSubcontratacion.java b/src/main/java/io/facturapi/models/NominaSubcontratacion.java new file mode 100644 index 0000000..5a4b0e1 --- /dev/null +++ b/src/main/java/io/facturapi/models/NominaSubcontratacion.java @@ -0,0 +1,17 @@ +package io.facturapi.models; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class NominaSubcontratacion { + @JsonProperty("rfc_labora") + private String rfcLabora; + @JsonProperty("porcentaje_tiempo") + private Double porcentajeTiempo; + + public String getRfcLabora() { return rfcLabora; } + public void setRfcLabora(String rfcLabora) { this.rfcLabora = rfcLabora; } + public Double getPorcentajeTiempo() { return porcentajeTiempo; } + public void setPorcentajeTiempo(Double porcentajeTiempo) { this.porcentajeTiempo = porcentajeTiempo; } +} diff --git a/src/main/java/io/facturapi/models/Organization.java b/src/main/java/io/facturapi/models/Organization.java new file mode 100644 index 0000000..bdcb4bc --- /dev/null +++ b/src/main/java/io/facturapi/models/Organization.java @@ -0,0 +1,70 @@ +package io.facturapi.models; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import java.util.ArrayList; +import java.util.List; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class Organization { + private String id; + @JsonProperty("created_at") + private String createdAt; + private String plan; + @JsonProperty("add_ons") + private List addOns = new ArrayList<>(); + @JsonProperty("is_production_ready") + private Boolean productionReady; + @JsonProperty("pending_steps") + private List pendingSteps = new ArrayList<>(); + @JsonProperty("logo_url") + private String logoUrl; + private String domain; + @JsonProperty("custom_domain") + private String customDomain; + private String timezone; + private Legal legal; + private Customization customization; + private Certificate certificate; + private Certificate fiel; + private ReceiptSettings receipts; + @JsonProperty("self_invoice") + private SelfInvoiceSettings selfInvoice; + @JsonProperty("pending_plan_update") + private PendingPlanUpdate pendingPlanUpdate; + + public String getId() { return id; } + public void setId(String id) { this.id = id; } + public String getCreatedAt() { return createdAt; } + public void setCreatedAt(String createdAt) { this.createdAt = createdAt; } + public String getPlan() { return plan; } + public void setPlan(String plan) { this.plan = plan; } + public List getAddOns() { return addOns; } + public void setAddOns(List addOns) { this.addOns = addOns; } + public Boolean getProductionReady() { return productionReady; } + public void setProductionReady(Boolean productionReady) { this.productionReady = productionReady; } + public List getPendingSteps() { return pendingSteps; } + public void setPendingSteps(List pendingSteps) { this.pendingSteps = pendingSteps; } + public String getLogoUrl() { return logoUrl; } + public void setLogoUrl(String logoUrl) { this.logoUrl = logoUrl; } + public String getDomain() { return domain; } + public void setDomain(String domain) { this.domain = domain; } + public String getCustomDomain() { return customDomain; } + public void setCustomDomain(String customDomain) { this.customDomain = customDomain; } + public String getTimezone() { return timezone; } + public void setTimezone(String timezone) { this.timezone = timezone; } + public Legal getLegal() { return legal; } + public void setLegal(Legal legal) { this.legal = legal; } + public Customization getCustomization() { return customization; } + public void setCustomization(Customization customization) { this.customization = customization; } + public Certificate getCertificate() { return certificate; } + public void setCertificate(Certificate certificate) { this.certificate = certificate; } + public Certificate getFiel() { return fiel; } + public void setFiel(Certificate fiel) { this.fiel = fiel; } + public ReceiptSettings getReceipts() { return receipts; } + public void setReceipts(ReceiptSettings receipts) { this.receipts = receipts; } + public SelfInvoiceSettings getSelfInvoice() { return selfInvoice; } + public void setSelfInvoice(SelfInvoiceSettings selfInvoice) { this.selfInvoice = selfInvoice; } + public PendingPlanUpdate getPendingPlanUpdate() { return pendingPlanUpdate; } + public void setPendingPlanUpdate(PendingPlanUpdate pendingPlanUpdate) { this.pendingPlanUpdate = pendingPlanUpdate; } +} diff --git a/src/main/java/io/facturapi/models/OrganizationInvite.java b/src/main/java/io/facturapi/models/OrganizationInvite.java new file mode 100644 index 0000000..4621f78 --- /dev/null +++ b/src/main/java/io/facturapi/models/OrganizationInvite.java @@ -0,0 +1,42 @@ +package io.facturapi.models; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import java.util.ArrayList; +import java.util.List; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class OrganizationInvite { + private String id; + @JsonProperty("created_at") + private String createdAt; + private String email; + @JsonProperty("organization_name") + private String organizationName; + private String role; + @JsonProperty("role_name") + private String roleName; + private List roles = new ArrayList<>(); + @JsonProperty("expires_at") + private String expiresAt; + private String status; + + public String getId() { return id; } + public void setId(String id) { this.id = id; } + public String getCreatedAt() { return createdAt; } + public void setCreatedAt(String createdAt) { this.createdAt = createdAt; } + public String getEmail() { return email; } + public void setEmail(String email) { this.email = email; } + public String getOrganizationName() { return organizationName; } + public void setOrganizationName(String organizationName) { this.organizationName = organizationName; } + public String getRole() { return role; } + public void setRole(String role) { this.role = role; } + public String getRoleName() { return roleName; } + public void setRoleName(String roleName) { this.roleName = roleName; } + public List getRoles() { return roles; } + public void setRoles(List roles) { this.roles = roles; } + public String getExpiresAt() { return expiresAt; } + public void setExpiresAt(String expiresAt) { this.expiresAt = expiresAt; } + public String getStatus() { return status; } + public void setStatus(String status) { this.status = status; } +} diff --git a/src/main/java/io/facturapi/models/OrganizationTeamRole.java b/src/main/java/io/facturapi/models/OrganizationTeamRole.java new file mode 100644 index 0000000..ca719e5 --- /dev/null +++ b/src/main/java/io/facturapi/models/OrganizationTeamRole.java @@ -0,0 +1,51 @@ +package io.facturapi.models; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class OrganizationTeamRole { + private String id; + private String name; + @JsonProperty("template_code") + private String templateCode; + private String scope; + private String organization; + private List operations = new ArrayList<>(); + @JsonProperty("used_by") + private Integer usedBy; + @JsonProperty("created_at") + private String createdAt; + @JsonProperty("updated_at") + private String updatedAt; + @JsonProperty("created_by") + private Map createdBy; + @JsonProperty("updated_by") + private Map updatedBy; + + public String getId() { return id; } + public void setId(String id) { this.id = id; } + public String getName() { return name; } + public void setName(String name) { this.name = name; } + public String getTemplateCode() { return templateCode; } + public void setTemplateCode(String templateCode) { this.templateCode = templateCode; } + public String getScope() { return scope; } + public void setScope(String scope) { this.scope = scope; } + public String getOrganization() { return organization; } + public void setOrganization(String organization) { this.organization = organization; } + public List getOperations() { return operations; } + public void setOperations(List operations) { this.operations = operations; } + public Integer getUsedBy() { return usedBy; } + public void setUsedBy(Integer usedBy) { this.usedBy = usedBy; } + public String getCreatedAt() { return createdAt; } + public void setCreatedAt(String createdAt) { this.createdAt = createdAt; } + public String getUpdatedAt() { return updatedAt; } + public void setUpdatedAt(String updatedAt) { this.updatedAt = updatedAt; } + public Map getCreatedBy() { return createdBy; } + public void setCreatedBy(Map createdBy) { this.createdBy = createdBy; } + public Map getUpdatedBy() { return updatedBy; } + public void setUpdatedBy(Map updatedBy) { this.updatedBy = updatedBy; } +} diff --git a/src/main/java/io/facturapi/models/OrganizationTeamRoleTemplate.java b/src/main/java/io/facturapi/models/OrganizationTeamRoleTemplate.java new file mode 100644 index 0000000..71042e9 --- /dev/null +++ b/src/main/java/io/facturapi/models/OrganizationTeamRoleTemplate.java @@ -0,0 +1,22 @@ +package io.facturapi.models; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import java.util.ArrayList; +import java.util.List; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class OrganizationTeamRoleTemplate { + private String code; + private String name; + private String description; + private List operations = new ArrayList<>(); + + public String getCode() { return code; } + public void setCode(String code) { this.code = code; } + public String getName() { return name; } + public void setName(String name) { this.name = name; } + public String getDescription() { return description; } + public void setDescription(String description) { this.description = description; } + public List getOperations() { return operations; } + public void setOperations(List operations) { this.operations = operations; } +} diff --git a/src/main/java/io/facturapi/models/OrganizationUserAccess.java b/src/main/java/io/facturapi/models/OrganizationUserAccess.java new file mode 100644 index 0000000..463de72 --- /dev/null +++ b/src/main/java/io/facturapi/models/OrganizationUserAccess.java @@ -0,0 +1,42 @@ +package io.facturapi.models; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import java.util.ArrayList; +import java.util.List; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class OrganizationUserAccess { + private String id; + @JsonProperty("full_name") + private String fullName; + private String email; + private String role; + @JsonProperty("role_name") + private String roleName; + private String organization; + private List operations = new ArrayList<>(); + @JsonProperty("created_at") + private String createdAt; + @JsonProperty("updated_at") + private String updatedAt; + + public String getId() { return id; } + public void setId(String id) { this.id = id; } + public String getFullName() { return fullName; } + public void setFullName(String fullName) { this.fullName = fullName; } + public String getEmail() { return email; } + public void setEmail(String email) { this.email = email; } + public String getRole() { return role; } + public void setRole(String role) { this.role = role; } + public String getRoleName() { return roleName; } + public void setRoleName(String roleName) { this.roleName = roleName; } + public String getOrganization() { return organization; } + public void setOrganization(String organization) { this.organization = organization; } + public List getOperations() { return operations; } + public void setOperations(List operations) { this.operations = operations; } + public String getCreatedAt() { return createdAt; } + public void setCreatedAt(String createdAt) { this.createdAt = createdAt; } + public String getUpdatedAt() { return updatedAt; } + public void setUpdatedAt(String updatedAt) { this.updatedAt = updatedAt; } +} diff --git a/src/main/java/io/facturapi/models/PagoComplementData.java b/src/main/java/io/facturapi/models/PagoComplementData.java new file mode 100644 index 0000000..a0d4771 --- /dev/null +++ b/src/main/java/io/facturapi/models/PagoComplementData.java @@ -0,0 +1,58 @@ +package io.facturapi.models; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import java.util.ArrayList; +import java.util.List; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class PagoComplementData { + @JsonProperty("payment_form") + private String paymentForm; + private String date; + @JsonProperty("related_documents") + private List relatedDocuments = new ArrayList<>(); + private String currency; + private Double exchange; + private String numOperacion; + private String rfcEmisorCtaOrd; + private String nomBancoOrdExt; + private String ctaOrdenante; + private String rfcEmisorCtaBen; + private String ctaBeneficiario; + private String tipoCadPago; + private String certPago; + private String cadPago; + private String selloPago; + + public String getPaymentForm() { return paymentForm; } + public void setPaymentForm(String paymentForm) { this.paymentForm = paymentForm; } + public String getDate() { return date; } + public void setDate(String date) { this.date = date; } + public List getRelatedDocuments() { return relatedDocuments; } + public void setRelatedDocuments(List relatedDocuments) { this.relatedDocuments = relatedDocuments; } + public String getCurrency() { return currency; } + public void setCurrency(String currency) { this.currency = currency; } + public Double getExchange() { return exchange; } + public void setExchange(Double exchange) { this.exchange = exchange; } + public String getNumOperacion() { return numOperacion; } + public void setNumOperacion(String numOperacion) { this.numOperacion = numOperacion; } + public String getRfcEmisorCtaOrd() { return rfcEmisorCtaOrd; } + public void setRfcEmisorCtaOrd(String rfcEmisorCtaOrd) { this.rfcEmisorCtaOrd = rfcEmisorCtaOrd; } + public String getNomBancoOrdExt() { return nomBancoOrdExt; } + public void setNomBancoOrdExt(String nomBancoOrdExt) { this.nomBancoOrdExt = nomBancoOrdExt; } + public String getCtaOrdenante() { return ctaOrdenante; } + public void setCtaOrdenante(String ctaOrdenante) { this.ctaOrdenante = ctaOrdenante; } + public String getRfcEmisorCtaBen() { return rfcEmisorCtaBen; } + public void setRfcEmisorCtaBen(String rfcEmisorCtaBen) { this.rfcEmisorCtaBen = rfcEmisorCtaBen; } + public String getCtaBeneficiario() { return ctaBeneficiario; } + public void setCtaBeneficiario(String ctaBeneficiario) { this.ctaBeneficiario = ctaBeneficiario; } + public String getTipoCadPago() { return tipoCadPago; } + public void setTipoCadPago(String tipoCadPago) { this.tipoCadPago = tipoCadPago; } + public String getCertPago() { return certPago; } + public void setCertPago(String certPago) { this.certPago = certPago; } + public String getCadPago() { return cadPago; } + public void setCadPago(String cadPago) { this.cadPago = cadPago; } + public String getSelloPago() { return selloPago; } + public void setSelloPago(String selloPago) { this.selloPago = selloPago; } +} diff --git a/src/main/java/io/facturapi/models/Payment.java b/src/main/java/io/facturapi/models/Payment.java new file mode 100644 index 0000000..dbdc50c --- /dev/null +++ b/src/main/java/io/facturapi/models/Payment.java @@ -0,0 +1,27 @@ +package io.facturapi.models; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import java.util.ArrayList; +import java.util.List; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class Payment { + @JsonProperty("payment_form") + private String paymentForm; + private String currency; + private Double exchange; + private String date; + private List related = new ArrayList<>(); + + public String getPaymentForm() { return paymentForm; } + public void setPaymentForm(String paymentForm) { this.paymentForm = paymentForm; } + public String getCurrency() { return currency; } + public void setCurrency(String currency) { this.currency = currency; } + public Double getExchange() { return exchange; } + public void setExchange(Double exchange) { this.exchange = exchange; } + public String getDate() { return date; } + public void setDate(String date) { this.date = date; } + public List getRelated() { return related; } + public void setRelated(List related) { this.related = related; } +} diff --git a/src/main/java/io/facturapi/models/PaymentRelated.java b/src/main/java/io/facturapi/models/PaymentRelated.java new file mode 100644 index 0000000..c8cadd9 --- /dev/null +++ b/src/main/java/io/facturapi/models/PaymentRelated.java @@ -0,0 +1,27 @@ +package io.facturapi.models; + +import com.fasterxml.jackson.annotation.JsonProperty; + +public class PaymentRelated { + private String uuid; + @JsonProperty("installment") + private Integer installment; + @JsonProperty("last_balance") + private Double lastBalance; + private Double amount; + private String currency; + private Double exchange; + + public String getUuid() { return uuid; } + public void setUuid(String uuid) { this.uuid = uuid; } + public Integer getInstallment() { return installment; } + public void setInstallment(Integer installment) { this.installment = installment; } + public Double getLastBalance() { return lastBalance; } + public void setLastBalance(Double lastBalance) { this.lastBalance = lastBalance; } + public Double getAmount() { return amount; } + public void setAmount(Double amount) { this.amount = amount; } + public String getCurrency() { return currency; } + public void setCurrency(String currency) { this.currency = currency; } + public Double getExchange() { return exchange; } + public void setExchange(Double exchange) { this.exchange = exchange; } +} diff --git a/src/main/java/io/facturapi/models/PaymentRelatedDocument.java b/src/main/java/io/facturapi/models/PaymentRelatedDocument.java new file mode 100644 index 0000000..acb9729 --- /dev/null +++ b/src/main/java/io/facturapi/models/PaymentRelatedDocument.java @@ -0,0 +1,43 @@ +package io.facturapi.models; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import java.util.ArrayList; +import java.util.List; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class PaymentRelatedDocument { + private String uuid; + private Double amount; + private Integer installment; + @JsonProperty("last_balance") + private Double lastBalance; + private String currency; + private Double exchange; + @JsonProperty("folio_number") + private String folioNumber; + private String series; + private String taxability; + private List taxes = new ArrayList<>(); + + public String getUuid() { return uuid; } + public void setUuid(String uuid) { this.uuid = uuid; } + public Double getAmount() { return amount; } + public void setAmount(Double amount) { this.amount = amount; } + public Integer getInstallment() { return installment; } + public void setInstallment(Integer installment) { this.installment = installment; } + public Double getLastBalance() { return lastBalance; } + public void setLastBalance(Double lastBalance) { this.lastBalance = lastBalance; } + public String getCurrency() { return currency; } + public void setCurrency(String currency) { this.currency = currency; } + public Double getExchange() { return exchange; } + public void setExchange(Double exchange) { this.exchange = exchange; } + public String getFolioNumber() { return folioNumber; } + public void setFolioNumber(String folioNumber) { this.folioNumber = folioNumber; } + public String getSeries() { return series; } + public void setSeries(String series) { this.series = series; } + public String getTaxability() { return taxability; } + public void setTaxability(String taxability) { this.taxability = taxability; } + public List getTaxes() { return taxes; } + public void setTaxes(List taxes) { this.taxes = taxes; } +} diff --git a/src/main/java/io/facturapi/models/PaymentRelatedDocumentTax.java b/src/main/java/io/facturapi/models/PaymentRelatedDocumentTax.java new file mode 100644 index 0000000..68598c6 --- /dev/null +++ b/src/main/java/io/facturapi/models/PaymentRelatedDocumentTax.java @@ -0,0 +1,23 @@ +package io.facturapi.models; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class PaymentRelatedDocumentTax { + private Double base; + private Double rate; + private String type; + private String factor; + private Boolean withholding; + + public Double getBase() { return base; } + public void setBase(Double base) { this.base = base; } + public Double getRate() { return rate; } + public void setRate(Double rate) { this.rate = rate; } + public String getType() { return type; } + public void setType(String type) { this.type = type; } + public String getFactor() { return factor; } + public void setFactor(String factor) { this.factor = factor; } + public Boolean getWithholding() { return withholding; } + public void setWithholding(Boolean withholding) { this.withholding = withholding; } +} diff --git a/src/main/java/io/facturapi/models/PdfExtra.java b/src/main/java/io/facturapi/models/PdfExtra.java new file mode 100644 index 0000000..ce5e1c3 --- /dev/null +++ b/src/main/java/io/facturapi/models/PdfExtra.java @@ -0,0 +1,40 @@ +package io.facturapi.models; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class PdfExtra { + private Boolean codes; + @JsonProperty("address_codes") + private Boolean addressCodes; + @JsonProperty("product_key") + private Boolean productKey; + @JsonProperty("round_unit_price") + private Boolean roundUnitPrice; + @JsonProperty("tax_breakdown") + private Boolean taxBreakdown; + @JsonProperty("ieps_breakdown") + private Boolean iepsBreakdown; + @JsonProperty("render_carta_porte") + private Boolean renderCartaPorte; + @JsonProperty("repeat_signature") + private Boolean repeatSignature; + + public Boolean getCodes() { return codes; } + public void setCodes(Boolean codes) { this.codes = codes; } + public Boolean getAddressCodes() { return addressCodes; } + public void setAddressCodes(Boolean addressCodes) { this.addressCodes = addressCodes; } + public Boolean getProductKey() { return productKey; } + public void setProductKey(Boolean productKey) { this.productKey = productKey; } + public Boolean getRoundUnitPrice() { return roundUnitPrice; } + public void setRoundUnitPrice(Boolean roundUnitPrice) { this.roundUnitPrice = roundUnitPrice; } + public Boolean getTaxBreakdown() { return taxBreakdown; } + public void setTaxBreakdown(Boolean taxBreakdown) { this.taxBreakdown = taxBreakdown; } + public Boolean getIepsBreakdown() { return iepsBreakdown; } + public void setIepsBreakdown(Boolean iepsBreakdown) { this.iepsBreakdown = iepsBreakdown; } + public Boolean getRenderCartaPorte() { return renderCartaPorte; } + public void setRenderCartaPorte(Boolean renderCartaPorte) { this.renderCartaPorte = renderCartaPorte; } + public Boolean getRepeatSignature() { return repeatSignature; } + public void setRepeatSignature(Boolean repeatSignature) { this.repeatSignature = repeatSignature; } +} diff --git a/src/main/java/io/facturapi/models/PendingPlanUpdate.java b/src/main/java/io/facturapi/models/PendingPlanUpdate.java new file mode 100644 index 0000000..cc104e4 --- /dev/null +++ b/src/main/java/io/facturapi/models/PendingPlanUpdate.java @@ -0,0 +1,16 @@ +package io.facturapi.models; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class PendingPlanUpdate { + private String plan; + @JsonProperty("scheduled_for") + private String scheduledFor; + + public String getPlan() { return plan; } + public void setPlan(String plan) { this.plan = plan; } + public String getScheduledFor() { return scheduledFor; } + public void setScheduledFor(String scheduledFor) { this.scheduledFor = scheduledFor; } +} diff --git a/src/main/java/io/facturapi/models/Product.java b/src/main/java/io/facturapi/models/Product.java new file mode 100644 index 0000000..7f1dbcd --- /dev/null +++ b/src/main/java/io/facturapi/models/Product.java @@ -0,0 +1,59 @@ +package io.facturapi.models; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import java.util.ArrayList; +import java.util.List; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class Product { + private String id; + private String organization; + private Boolean livemode; + @JsonProperty("product_key") + private String productKey; + private String description; + private Double price; + @JsonProperty("created_at") + private String createdAt; + @JsonProperty("tax_included") + private Boolean taxIncluded; + private List taxes = new ArrayList<>(); + @JsonProperty("local_taxes") + private List localTaxes = new ArrayList<>(); + @JsonProperty("unit_key") + private String unitKey; + @JsonProperty("unit_name") + private String unitName; + private String sku; + private String taxability; + + public String getId() { return id; } + public void setId(String id) { this.id = id; } + public String getOrganization() { return organization; } + public void setOrganization(String organization) { this.organization = organization; } + public Boolean getLivemode() { return livemode; } + public void setLivemode(Boolean livemode) { this.livemode = livemode; } + public String getProductKey() { return productKey; } + public void setProductKey(String productKey) { this.productKey = productKey; } + public String getDescription() { return description; } + public void setDescription(String description) { this.description = description; } + public Double getPrice() { return price; } + public void setPrice(Double price) { this.price = price; } + public String getCreatedAt() { return createdAt; } + public void setCreatedAt(String createdAt) { this.createdAt = createdAt; } + public Boolean getTaxIncluded() { return taxIncluded; } + public void setTaxIncluded(Boolean taxIncluded) { this.taxIncluded = taxIncluded; } + public List getTaxes() { return taxes; } + public void setTaxes(List taxes) { this.taxes = taxes; } + public List getLocalTaxes() { return localTaxes; } + public void setLocalTaxes(List localTaxes) { this.localTaxes = localTaxes; } + public String getUnitKey() { return unitKey; } + public void setUnitKey(String unitKey) { this.unitKey = unitKey; } + public String getUnitName() { return unitName; } + public void setUnitName(String unitName) { this.unitName = unitName; } + public String getSku() { return sku; } + public void setSku(String sku) { this.sku = sku; } + public String getTaxability() { return taxability; } + public void setTaxability(String taxability) { this.taxability = taxability; } +} diff --git a/src/main/java/io/facturapi/models/ProductInfo.java b/src/main/java/io/facturapi/models/ProductInfo.java new file mode 100644 index 0000000..b73c139 --- /dev/null +++ b/src/main/java/io/facturapi/models/ProductInfo.java @@ -0,0 +1,49 @@ +package io.facturapi.models; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import java.util.ArrayList; +import java.util.List; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class ProductInfo { + private String id; + @JsonProperty("product_key") + private String productKey; + private String description; + @JsonProperty("unit_key") + private String unitKey; + @JsonProperty("unit_name") + private String unitName; + private Double price; + private String taxability; + @JsonProperty("tax_included") + private Boolean taxIncluded; + private List taxes = new ArrayList<>(); + @JsonProperty("local_taxes") + private List localTaxes = new ArrayList<>(); + private String sku; + + public String getId() { return id; } + public void setId(String id) { this.id = id; } + public String getProductKey() { return productKey; } + public void setProductKey(String productKey) { this.productKey = productKey; } + public String getDescription() { return description; } + public void setDescription(String description) { this.description = description; } + public String getUnitKey() { return unitKey; } + public void setUnitKey(String unitKey) { this.unitKey = unitKey; } + public String getUnitName() { return unitName; } + public void setUnitName(String unitName) { this.unitName = unitName; } + public Double getPrice() { return price; } + public void setPrice(Double price) { this.price = price; } + public String getTaxability() { return taxability; } + public void setTaxability(String taxability) { this.taxability = taxability; } + public Boolean getTaxIncluded() { return taxIncluded; } + public void setTaxIncluded(Boolean taxIncluded) { this.taxIncluded = taxIncluded; } + public List getTaxes() { return taxes; } + public void setTaxes(List taxes) { this.taxes = taxes; } + public List getLocalTaxes() { return localTaxes; } + public void setLocalTaxes(List localTaxes) { this.localTaxes = localTaxes; } + public String getSku() { return sku; } + public void setSku(String sku) { this.sku = sku; } +} diff --git a/src/main/java/io/facturapi/models/Receipt.java b/src/main/java/io/facturapi/models/Receipt.java new file mode 100644 index 0000000..ca613b1 --- /dev/null +++ b/src/main/java/io/facturapi/models/Receipt.java @@ -0,0 +1,79 @@ +package io.facturapi.models; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import java.util.ArrayList; +import java.util.List; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class Receipt { + private String id; + @JsonProperty("created_at") + private String createdAt; + private String date; + @JsonProperty("api_version") + private Integer apiVersion; + private Boolean livemode; + private String organization; + @JsonProperty("folio_number") + private Integer folioNumber; + @JsonProperty("external_id") + private String externalId; + @JsonProperty("idempotency_key") + private String idempotencyKey; + private String branch; + @JsonProperty("payment_form") + private String paymentForm; + private List items = new ArrayList<>(); + private String currency; + private Double exchange; + private Double total; + private String invoice; + @JsonProperty("expires_at") + private String expiresAt; + private String key; + private String status; + @JsonProperty("self_invoice_url") + private String selfInvoiceUrl; + + public String getId() { return id; } + public void setId(String id) { this.id = id; } + public String getCreatedAt() { return createdAt; } + public void setCreatedAt(String createdAt) { this.createdAt = createdAt; } + public String getDate() { return date; } + public void setDate(String date) { this.date = date; } + public Integer getApiVersion() { return apiVersion; } + public void setApiVersion(Integer apiVersion) { this.apiVersion = apiVersion; } + public Boolean getLivemode() { return livemode; } + public void setLivemode(Boolean livemode) { this.livemode = livemode; } + public String getOrganization() { return organization; } + public void setOrganization(String organization) { this.organization = organization; } + public Integer getFolioNumber() { return folioNumber; } + public void setFolioNumber(Integer folioNumber) { this.folioNumber = folioNumber; } + public String getExternalId() { return externalId; } + public void setExternalId(String externalId) { this.externalId = externalId; } + public String getIdempotencyKey() { return idempotencyKey; } + public void setIdempotencyKey(String idempotencyKey) { this.idempotencyKey = idempotencyKey; } + public String getBranch() { return branch; } + public void setBranch(String branch) { this.branch = branch; } + public String getPaymentForm() { return paymentForm; } + public void setPaymentForm(String paymentForm) { this.paymentForm = paymentForm; } + public List getItems() { return items; } + public void setItems(List items) { this.items = items; } + public String getCurrency() { return currency; } + public void setCurrency(String currency) { this.currency = currency; } + public Double getExchange() { return exchange; } + public void setExchange(Double exchange) { this.exchange = exchange; } + public Double getTotal() { return total; } + public void setTotal(Double total) { this.total = total; } + public String getInvoice() { return invoice; } + public void setInvoice(String invoice) { this.invoice = invoice; } + public String getExpiresAt() { return expiresAt; } + public void setExpiresAt(String expiresAt) { this.expiresAt = expiresAt; } + public String getKey() { return key; } + public void setKey(String key) { this.key = key; } + public String getStatus() { return status; } + public void setStatus(String status) { this.status = status; } + public String getSelfInvoiceUrl() { return selfInvoiceUrl; } + public void setSelfInvoiceUrl(String selfInvoiceUrl) { this.selfInvoiceUrl = selfInvoiceUrl; } +} diff --git a/src/main/java/io/facturapi/models/ReceiptSettings.java b/src/main/java/io/facturapi/models/ReceiptSettings.java new file mode 100644 index 0000000..522b80d --- /dev/null +++ b/src/main/java/io/facturapi/models/ReceiptSettings.java @@ -0,0 +1,24 @@ +package io.facturapi.models; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class ReceiptSettings { + private String periodicity; + @JsonProperty("duration_days") + private Integer durationDays; + @JsonProperty("next_folio_number") + private Integer nextFolioNumber; + @JsonProperty("next_folio_number_test") + private Integer nextFolioNumberTest; + + public String getPeriodicity() { return periodicity; } + public void setPeriodicity(String periodicity) { this.periodicity = periodicity; } + public Integer getDurationDays() { return durationDays; } + public void setDurationDays(Integer durationDays) { this.durationDays = durationDays; } + public Integer getNextFolioNumber() { return nextFolioNumber; } + public void setNextFolioNumber(Integer nextFolioNumber) { this.nextFolioNumber = nextFolioNumber; } + public Integer getNextFolioNumberTest() { return nextFolioNumberTest; } + public void setNextFolioNumberTest(Integer nextFolioNumberTest) { this.nextFolioNumberTest = nextFolioNumberTest; } +} diff --git a/src/main/java/io/facturapi/models/RelatedDocument.java b/src/main/java/io/facturapi/models/RelatedDocument.java new file mode 100644 index 0000000..c75932c --- /dev/null +++ b/src/main/java/io/facturapi/models/RelatedDocument.java @@ -0,0 +1,14 @@ +package io.facturapi.models; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class RelatedDocument { + private String relationship; + private String uuid; + + public String getRelationship() { return relationship; } + public void setRelationship(String relationship) { this.relationship = relationship; } + public String getUuid() { return uuid; } + public void setUuid(String uuid) { this.uuid = uuid; } +} diff --git a/src/main/java/io/facturapi/models/Retention.java b/src/main/java/io/facturapi/models/Retention.java new file mode 100644 index 0000000..f7d3fe9 --- /dev/null +++ b/src/main/java/io/facturapi/models/Retention.java @@ -0,0 +1,87 @@ +package io.facturapi.models; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import java.util.ArrayList; +import java.util.List; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class Retention { + private String id; + @JsonProperty("created_at") + private String createdAt; + private CustomerInfo customer; + private String organization; + private Boolean livemode; + private String status; + private String uuid; + @JsonProperty("external_id") + private String externalId; + @JsonProperty("fecha_exp") + private String fechaExp; + @JsonProperty("cve_retenc") + private String cveRetenc; + @JsonProperty("folio_int") + private String folioInt; + @JsonProperty("desc_retenc") + private String descRetenc; + private RetentionPeriod periodo; + private RetentionTotals totales; + private List namespaces = new ArrayList<>(); + @JsonProperty("related_documents") + private List relatedDocuments = new ArrayList<>(); + private List complements = new ArrayList<>(); + private List addenda = new ArrayList<>(); + @JsonProperty("cancellation_receipt") + private String cancellationReceipt; + private Stamp stamp; + @JsonProperty("pdf_custom_section") + private String pdfCustomSection; + @JsonProperty("verification_url") + private String verificationUrl; + + public String getId() { return id; } + public void setId(String id) { this.id = id; } + public String getCreatedAt() { return createdAt; } + public void setCreatedAt(String createdAt) { this.createdAt = createdAt; } + public CustomerInfo getCustomer() { return customer; } + public void setCustomer(CustomerInfo customer) { this.customer = customer; } + public String getOrganization() { return organization; } + public void setOrganization(String organization) { this.organization = organization; } + public Boolean getLivemode() { return livemode; } + public void setLivemode(Boolean livemode) { this.livemode = livemode; } + public String getStatus() { return status; } + public void setStatus(String status) { this.status = status; } + public String getUuid() { return uuid; } + public void setUuid(String uuid) { this.uuid = uuid; } + public String getExternalId() { return externalId; } + public void setExternalId(String externalId) { this.externalId = externalId; } + public String getFechaExp() { return fechaExp; } + public void setFechaExp(String fechaExp) { this.fechaExp = fechaExp; } + public String getCveRetenc() { return cveRetenc; } + public void setCveRetenc(String cveRetenc) { this.cveRetenc = cveRetenc; } + public String getFolioInt() { return folioInt; } + public void setFolioInt(String folioInt) { this.folioInt = folioInt; } + public String getDescRetenc() { return descRetenc; } + public void setDescRetenc(String descRetenc) { this.descRetenc = descRetenc; } + public RetentionPeriod getPeriodo() { return periodo; } + public void setPeriodo(RetentionPeriod periodo) { this.periodo = periodo; } + public RetentionTotals getTotales() { return totales; } + public void setTotales(RetentionTotals totales) { this.totales = totales; } + public List getNamespaces() { return namespaces; } + public void setNamespaces(List namespaces) { this.namespaces = namespaces; } + public List getRelatedDocuments() { return relatedDocuments; } + public void setRelatedDocuments(List relatedDocuments) { this.relatedDocuments = relatedDocuments; } + public List getComplements() { return complements; } + public void setComplements(List complements) { this.complements = complements; } + public List getAddenda() { return addenda; } + public void setAddenda(List addenda) { this.addenda = addenda; } + public String getCancellationReceipt() { return cancellationReceipt; } + public void setCancellationReceipt(String cancellationReceipt) { this.cancellationReceipt = cancellationReceipt; } + public Stamp getStamp() { return stamp; } + public void setStamp(Stamp stamp) { this.stamp = stamp; } + public String getPdfCustomSection() { return pdfCustomSection; } + public void setPdfCustomSection(String pdfCustomSection) { this.pdfCustomSection = pdfCustomSection; } + public String getVerificationUrl() { return verificationUrl; } + public void setVerificationUrl(String verificationUrl) { this.verificationUrl = verificationUrl; } +} diff --git a/src/main/java/io/facturapi/models/RetentionPeriod.java b/src/main/java/io/facturapi/models/RetentionPeriod.java new file mode 100644 index 0000000..0931f6b --- /dev/null +++ b/src/main/java/io/facturapi/models/RetentionPeriod.java @@ -0,0 +1,20 @@ +package io.facturapi.models; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class RetentionPeriod { + @JsonProperty("mes_ini") + private Integer mesIni; + @JsonProperty("mes_fin") + private Integer mesFin; + private Integer ejerc; + + public Integer getMesIni() { return mesIni; } + public void setMesIni(Integer mesIni) { this.mesIni = mesIni; } + public Integer getMesFin() { return mesFin; } + public void setMesFin(Integer mesFin) { this.mesFin = mesFin; } + public Integer getEjerc() { return ejerc; } + public void setEjerc(Integer ejerc) { this.ejerc = ejerc; } +} diff --git a/src/main/java/io/facturapi/models/RetentionRetainedTax.java b/src/main/java/io/facturapi/models/RetentionRetainedTax.java new file mode 100644 index 0000000..8b046f8 --- /dev/null +++ b/src/main/java/io/facturapi/models/RetentionRetainedTax.java @@ -0,0 +1,28 @@ +package io.facturapi.models; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class RetentionRetainedTax { + @JsonProperty("base_ret") + private Double baseRet; + private String impuesto; + @JsonProperty("tipo_pago_ret") + private String tipoPagoRet; + @JsonProperty("monto_ret") + private Double montoRet; + @JsonProperty("pago_provisional") + private Boolean pagoProvisional; + + public Double getBaseRet() { return baseRet; } + public void setBaseRet(Double baseRet) { this.baseRet = baseRet; } + public String getImpuesto() { return impuesto; } + public void setImpuesto(String impuesto) { this.impuesto = impuesto; } + public String getTipoPagoRet() { return tipoPagoRet; } + public void setTipoPagoRet(String tipoPagoRet) { this.tipoPagoRet = tipoPagoRet; } + public Double getMontoRet() { return montoRet; } + public void setMontoRet(Double montoRet) { this.montoRet = montoRet; } + public Boolean getPagoProvisional() { return pagoProvisional; } + public void setPagoProvisional(Boolean pagoProvisional) { this.pagoProvisional = pagoProvisional; } +} diff --git a/src/main/java/io/facturapi/models/RetentionTotals.java b/src/main/java/io/facturapi/models/RetentionTotals.java new file mode 100644 index 0000000..dc7cd47 --- /dev/null +++ b/src/main/java/io/facturapi/models/RetentionTotals.java @@ -0,0 +1,31 @@ +package io.facturapi.models; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import java.util.ArrayList; +import java.util.List; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class RetentionTotals { + @JsonProperty("monto_tot_grav") + private Double montoTotGrav; + @JsonProperty("monto_tot_exent") + private Double montoTotExent; + @JsonProperty("monto_tot_operacion") + private Double montoTotOperacion; + @JsonProperty("monto_tot_ret") + private Double montoTotRet; + @JsonProperty("imp_retenidos") + private List impRetenidos = new ArrayList<>(); + + public Double getMontoTotGrav() { return montoTotGrav; } + public void setMontoTotGrav(Double montoTotGrav) { this.montoTotGrav = montoTotGrav; } + public Double getMontoTotExent() { return montoTotExent; } + public void setMontoTotExent(Double montoTotExent) { this.montoTotExent = montoTotExent; } + public Double getMontoTotOperacion() { return montoTotOperacion; } + public void setMontoTotOperacion(Double montoTotOperacion) { this.montoTotOperacion = montoTotOperacion; } + public Double getMontoTotRet() { return montoTotRet; } + public void setMontoTotRet(Double montoTotRet) { this.montoTotRet = montoTotRet; } + public List getImpRetenidos() { return impRetenidos; } + public void setImpRetenidos(List impRetenidos) { this.impRetenidos = impRetenidos; } +} diff --git a/src/main/java/io/facturapi/models/SearchResult.java b/src/main/java/io/facturapi/models/SearchResult.java new file mode 100644 index 0000000..e358e70 --- /dev/null +++ b/src/main/java/io/facturapi/models/SearchResult.java @@ -0,0 +1,60 @@ +package io.facturapi.models; + +import com.fasterxml.jackson.annotation.JsonAlias; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import java.util.ArrayList; +import java.util.List; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class SearchResult { + private Integer page; + @JsonProperty("total_pages") + private Integer totalPages; + @JsonProperty("total_results") + @JsonAlias({"total"}) + private Integer totalResults; + @JsonProperty("has_more") + private Boolean hasMore; + private List data = new ArrayList<>(); + + public Integer getPage() { + return page; + } + + public void setPage(Integer page) { + this.page = page; + } + + public Integer getTotalPages() { + return totalPages; + } + + public void setTotalPages(Integer totalPages) { + this.totalPages = totalPages; + } + + public Integer getTotalResults() { + return totalResults; + } + + public void setTotalResults(Integer totalResults) { + this.totalResults = totalResults; + } + + public Boolean getHasMore() { + return hasMore; + } + + public void setHasMore(Boolean hasMore) { + this.hasMore = hasMore; + } + + public List getData() { + return data; + } + + public void setData(List data) { + this.data = data; + } +} diff --git a/src/main/java/io/facturapi/models/SelfInvoiceSettings.java b/src/main/java/io/facturapi/models/SelfInvoiceSettings.java new file mode 100644 index 0000000..dcb8e1a --- /dev/null +++ b/src/main/java/io/facturapi/models/SelfInvoiceSettings.java @@ -0,0 +1,27 @@ +package io.facturapi.models; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import java.util.ArrayList; +import java.util.List; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class SelfInvoiceSettings { + @JsonProperty("allowed_cfdi_uses") + private List allowedCfdiUses = new ArrayList<>(); + @JsonProperty("apply_resico_isr") + private Boolean applyResicoIsr; + @JsonProperty("support_email") + private String supportEmail; + @JsonProperty("support_email_verified") + private Boolean supportEmailVerified; + + public List getAllowedCfdiUses() { return allowedCfdiUses; } + public void setAllowedCfdiUses(List allowedCfdiUses) { this.allowedCfdiUses = allowedCfdiUses; } + public Boolean getApplyResicoIsr() { return applyResicoIsr; } + public void setApplyResicoIsr(Boolean applyResicoIsr) { this.applyResicoIsr = applyResicoIsr; } + public String getSupportEmail() { return supportEmail; } + public void setSupportEmail(String supportEmail) { this.supportEmail = supportEmail; } + public Boolean getSupportEmailVerified() { return supportEmailVerified; } + public void setSupportEmailVerified(Boolean supportEmailVerified) { this.supportEmailVerified = supportEmailVerified; } +} diff --git a/src/main/java/io/facturapi/models/Series.java b/src/main/java/io/facturapi/models/Series.java new file mode 100644 index 0000000..483e935 --- /dev/null +++ b/src/main/java/io/facturapi/models/Series.java @@ -0,0 +1,22 @@ +package io.facturapi.models; + +import com.fasterxml.jackson.annotation.JsonAlias; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class Series { + @JsonAlias({"series", "name"}) + private String series; + @JsonProperty("next_folio") + private Integer nextFolio; + @JsonProperty("next_folio_test") + private Integer nextFolioTest; + + public String getSeries() { return series; } + public void setSeries(String series) { this.series = series; } + public Integer getNextFolio() { return nextFolio; } + public void setNextFolio(Integer nextFolio) { this.nextFolio = nextFolio; } + public Integer getNextFolioTest() { return nextFolioTest; } + public void setNextFolioTest(Integer nextFolioTest) { this.nextFolioTest = nextFolioTest; } +} diff --git a/src/main/java/io/facturapi/models/Stamp.java b/src/main/java/io/facturapi/models/Stamp.java new file mode 100644 index 0000000..ad3e884 --- /dev/null +++ b/src/main/java/io/facturapi/models/Stamp.java @@ -0,0 +1,31 @@ +package io.facturapi.models; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class Stamp { + private String date; + @JsonProperty("sat_signature") + private String satSignature; + @JsonProperty("sat_cert_number") + private String satCertNumber; + private String signature; + @JsonProperty("complement_string") + private String complementString; + @JsonProperty("rfc_provider_cert") + private String rfcProviderCert; + + public String getDate() { return date; } + public void setDate(String date) { this.date = date; } + public String getSatSignature() { return satSignature; } + public void setSatSignature(String satSignature) { this.satSignature = satSignature; } + public String getSatCertNumber() { return satCertNumber; } + public void setSatCertNumber(String satCertNumber) { this.satCertNumber = satCertNumber; } + public String getSignature() { return signature; } + public void setSignature(String signature) { this.signature = signature; } + public String getComplementString() { return complementString; } + public void setComplementString(String complementString) { this.complementString = complementString; } + public String getRfcProviderCert() { return rfcProviderCert; } + public void setRfcProviderCert(String rfcProviderCert) { this.rfcProviderCert = rfcProviderCert; } +} diff --git a/src/main/java/io/facturapi/models/Tax.java b/src/main/java/io/facturapi/models/Tax.java new file mode 100644 index 0000000..5ef0a41 --- /dev/null +++ b/src/main/java/io/facturapi/models/Tax.java @@ -0,0 +1,61 @@ +package io.facturapi.models; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class Tax { + private Double base; + private Double amount; + private Double rate; + private String type; + private Boolean withholding; + private String factor; + + public Double getBase() { + return base; + } + + public void setBase(Double base) { + this.base = base; + } + + public Double getAmount() { + return amount; + } + + public void setAmount(Double amount) { + this.amount = amount; + } + + public Double getRate() { + return rate; + } + + public void setRate(Double rate) { + this.rate = rate; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public Boolean getWithholding() { + return withholding; + } + + public void setWithholding(Boolean withholding) { + this.withholding = withholding; + } + + public String getFactor() { + return factor; + } + + public void setFactor(String factor) { + this.factor = factor; + } +} diff --git a/src/main/java/io/facturapi/models/TaxInfoValidation.java b/src/main/java/io/facturapi/models/TaxInfoValidation.java new file mode 100644 index 0000000..8a005db --- /dev/null +++ b/src/main/java/io/facturapi/models/TaxInfoValidation.java @@ -0,0 +1,23 @@ +package io.facturapi.models; + +import com.fasterxml.jackson.annotation.JsonAlias; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import java.util.ArrayList; +import java.util.List; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class TaxInfoValidation { + @JsonProperty("is_valid") + @JsonAlias({"valid"}) + private Boolean isValid; + private List errors = new ArrayList<>(); + private String status; + + public Boolean getIsValid() { return isValid; } + public void setIsValid(Boolean isValid) { this.isValid = isValid; } + public List getErrors() { return errors; } + public void setErrors(List errors) { this.errors = errors; } + public String getStatus() { return status; } + public void setStatus(String status) { this.status = status; } +} diff --git a/src/main/java/io/facturapi/models/TaxInfoValidationError.java b/src/main/java/io/facturapi/models/TaxInfoValidationError.java new file mode 100644 index 0000000..cff5c4e --- /dev/null +++ b/src/main/java/io/facturapi/models/TaxInfoValidationError.java @@ -0,0 +1,14 @@ +package io.facturapi.models; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class TaxInfoValidationError { + private String path; + private String message; + + public String getPath() { return path; } + public void setPath(String path) { this.path = path; } + public String getMessage() { return message; } + public void setMessage(String message) { this.message = message; } +} diff --git a/src/main/java/io/facturapi/models/Webhook.java b/src/main/java/io/facturapi/models/Webhook.java new file mode 100644 index 0000000..c1c33eb --- /dev/null +++ b/src/main/java/io/facturapi/models/Webhook.java @@ -0,0 +1,40 @@ +package io.facturapi.models; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import java.util.ArrayList; +import java.util.List; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class Webhook { + private String id; + @JsonProperty("created_at") + private String createdAt; + private String organization; + private Boolean livemode; + @JsonProperty("enabled_events") + private List enabledEvents = new ArrayList<>(); + private String description; + private String url; + private String secret; + private String status; + + public String getId() { return id; } + public void setId(String id) { this.id = id; } + public String getCreatedAt() { return createdAt; } + public void setCreatedAt(String createdAt) { this.createdAt = createdAt; } + public String getOrganization() { return organization; } + public void setOrganization(String organization) { this.organization = organization; } + public Boolean getLivemode() { return livemode; } + public void setLivemode(Boolean livemode) { this.livemode = livemode; } + public List getEnabledEvents() { return enabledEvents; } + public void setEnabledEvents(List enabledEvents) { this.enabledEvents = enabledEvents; } + public String getDescription() { return description; } + public void setDescription(String description) { this.description = description; } + public String getUrl() { return url; } + public void setUrl(String url) { this.url = url; } + public String getSecret() { return secret; } + public void setSecret(String secret) { this.secret = secret; } + public String getStatus() { return status; } + public void setStatus(String status) { this.status = status; } +} diff --git a/src/main/java/io/facturapi/models/XmlNamespace.java b/src/main/java/io/facturapi/models/XmlNamespace.java new file mode 100644 index 0000000..64b68d7 --- /dev/null +++ b/src/main/java/io/facturapi/models/XmlNamespace.java @@ -0,0 +1,19 @@ +package io.facturapi.models; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class XmlNamespace { + private String prefix; + private String uri; + @JsonProperty("schema_location") + private String schemaLocation; + + public String getPrefix() { return prefix; } + public void setPrefix(String prefix) { this.prefix = prefix; } + public String getUri() { return uri; } + public void setUri(String uri) { this.uri = uri; } + public String getSchemaLocation() { return schemaLocation; } + public void setSchemaLocation(String schemaLocation) { this.schemaLocation = schemaLocation; } +} diff --git a/src/main/java/io/facturapi/resources/BaseResource.java b/src/main/java/io/facturapi/resources/BaseResource.java new file mode 100644 index 0000000..a438343 --- /dev/null +++ b/src/main/java/io/facturapi/resources/BaseResource.java @@ -0,0 +1,45 @@ +package io.facturapi.resources; + +import com.fasterxml.jackson.core.type.TypeReference; +import io.facturapi.http.FacturapiHttpClient; +import java.util.Map; + +public abstract class BaseResource { + protected final FacturapiHttpClient client; + + protected BaseResource(FacturapiHttpClient client) { + this.client = client; + } + + protected T get(String path, Map params, Class responseType) { + return client.get(path, params, responseType); + } + + protected T get(String path, Map params, TypeReference typeReference) { + return client.get(path, params, typeReference); + } + + protected T post(String path, Object body, Map params, Class responseType) { + return client.post(path, body, params, responseType); + } + + protected T post(String path, Object body, Map params, TypeReference typeReference) { + return client.post(path, body, params, typeReference); + } + + protected T put(String path, Object body, Map params, Class responseType) { + return client.put(path, body, params, responseType); + } + + protected T put(String path, Object body, Map params, TypeReference typeReference) { + return client.put(path, body, params, typeReference); + } + + protected T delete(String path, Map params, Class responseType) { + return client.delete(path, params, responseType); + } + + protected T delete(String path, Map params, TypeReference typeReference) { + return client.delete(path, params, typeReference); + } +} diff --git a/src/main/java/io/facturapi/resources/CustomersResource.java b/src/main/java/io/facturapi/resources/CustomersResource.java new file mode 100644 index 0000000..07a1c44 --- /dev/null +++ b/src/main/java/io/facturapi/resources/CustomersResource.java @@ -0,0 +1,101 @@ +package io.facturapi.resources; + +import com.fasterxml.jackson.core.type.TypeReference; +import io.facturapi.http.FacturapiHttpClient; +import io.facturapi.models.Customer; +import io.facturapi.models.GenericResponse; +import io.facturapi.models.SearchResult; +import io.facturapi.models.TaxInfoValidation; +import java.util.Map; + +public class CustomersResource extends BaseResource { + /** + * Customer endpoints. + * + * @see API reference + */ + public CustomersResource(FacturapiHttpClient client) { + super(client); + } + + /** + * Creates a new customer in your organization. + * + * @param data Customer payload. + * @param params Optional query parameters. + * @return Created customer. + * @see API reference + */ + public Customer create(Map data, Map params) { + return post("/customers", data, params, Customer.class); + } + + /** + * Gets a paginated list of customers in your organization. + * + * @param params Search and pagination parameters. + * @return Paginated customer result. + * @see API reference + */ + public SearchResult list(Map params) { + return get("/customers", params, new TypeReference>() {}); + } + + /** + * Gets a single customer by id. + * + * @param id Customer id. + * @return Customer object. + * @see API reference + */ + public Customer retrieve(String id) { + return get("/customers/" + id, null, Customer.class); + } + + /** + * Updates a customer. + * + * @param id Customer id. + * @param data Customer payload updates. + * @param params Optional query parameters. + * @return Updated customer. + * @see API reference + */ + public Customer update(String id, Map data, Map params) { + return put("/customers/" + id, data, params, Customer.class); + } + + /** + * Permanently removes a customer. + * + * @param id Customer id. + * @return Deleted customer. + * @see API reference + */ + public Customer delete(String id) { + return delete("/customers/" + id, null, Customer.class); + } + + /** + * Validates customer tax information with SAT. + * + * @param id Customer id. + * @return Validation result. + * @see API reference + */ + public TaxInfoValidation validateTaxInfo(String id) { + return get("/customers/" + id + "/tax-info-validation", null, TaxInfoValidation.class); + } + + /** + * Sends an email to the customer with an edit link. + * + * @param id Customer id. + * @param email Destination email. + * @return Operation response. + * @see API reference + */ + public GenericResponse sendEditLinkByEmail(String id, String email) { + return post("/customers/" + id + "/email-edit-link", Map.of("email", email), null, GenericResponse.class); + } +} diff --git a/src/main/java/io/facturapi/resources/InvoicesResource.java b/src/main/java/io/facturapi/resources/InvoicesResource.java new file mode 100644 index 0000000..9befb3a --- /dev/null +++ b/src/main/java/io/facturapi/resources/InvoicesResource.java @@ -0,0 +1,189 @@ +package io.facturapi.resources; + +import com.fasterxml.jackson.core.type.TypeReference; +import io.facturapi.http.FacturapiHttpClient; +import io.facturapi.models.GenericResponse; +import io.facturapi.models.Invoice; +import io.facturapi.models.SearchResult; +import java.util.Map; + +public class InvoicesResource extends BaseResource { + /** + * Invoice endpoints. + * + * @see API reference + */ + public InvoicesResource(FacturapiHttpClient client) { + super(client); + } + + /** + * Creates a new valid invoice (CFDI). + * + * @param body Invoice payload. + * @param params Optional query parameters. + * @return Created invoice. + * @see API reference + */ + public Invoice create(Map body, Map params) { + return post("/invoices", body, params, Invoice.class); + } + + /** + * Gets a paginated list of invoices created by your organization. + * + * @param params Search and pagination parameters. + * @return Paginated invoice result. + * @see API reference + */ + public SearchResult list(Map params) { + return get("/invoices", params, new TypeReference>() {}); + } + + /** + * Gets a single invoice by id. + * + * @param id Invoice id. + * @return Invoice object. + * @see API reference + */ + public Invoice retrieve(String id) { + return get("/invoices/" + id, null, Invoice.class); + } + + /** + * Cancels an invoice. + * + * @param id Invoice id. + * @param params Cancellation options. + * @return Canceled invoice. + * @see API reference + */ + public Invoice cancel(String id, Map params) { + return delete("/invoices/" + id, params, Invoice.class); + } + + /** + * Sends the invoice to the customer's email. + * + * @param id Invoice id. + * @param options Email options. + * @return Operation response. + * @see API reference + */ + public GenericResponse sendByEmail(String id, Map options) { + return post("/invoices/" + id + "/email", options, null, GenericResponse.class); + } + + /** + * Downloads an invoice PDF file. + * + * @param id Invoice id. + * @return PDF bytes. + * @see API reference + */ + public byte[] downloadPdf(String id) { + return client.getBytes("/invoices/" + id + "/pdf"); + } + + /** + * Downloads an invoice XML file. + * + * @param id Invoice id. + * @return XML bytes. + * @see API reference + */ + public byte[] downloadXml(String id) { + return client.getBytes("/invoices/" + id + "/xml"); + } + + /** + * Downloads an invoice ZIP package with PDF and XML. + * + * @param id Invoice id. + * @return ZIP bytes. + * @see API reference + */ + public byte[] downloadZip(String id) { + return client.getBytes("/invoices/" + id + "/zip"); + } + + /** + * Downloads the cancellation receipt XML file. + * + * @param id Invoice id. + * @return XML bytes. + * @see API reference + */ + public byte[] downloadCancellationReceiptXml(String id) { + return client.getBytes("/invoices/" + id + "/cancellation_receipt/xml"); + } + + /** + * Downloads the cancellation receipt PDF file. + * + * @param id Invoice id. + * @return PDF bytes. + * @see API reference + */ + public byte[] downloadCancellationReceiptPdf(String id) { + return client.getBytes("/invoices/" + id + "/cancellation_receipt/pdf"); + } + + /** + * Updates a draft invoice. + * + * @param id Invoice id. + * @param data Invoice updates. + * @return Updated draft invoice. + * @see API reference + */ + public Invoice updateDraft(String id, Map data) { + return put("/invoices/" + id, data, null, Invoice.class); + } + + /** + * Stamps an existing draft invoice. + * + * @param id Invoice id. + * @param params Optional query parameters. + * @return Stamped invoice. + * @see API reference + */ + public Invoice stampDraft(String id, Map params) { + return post("/invoices/" + id + "/stamp", null, params, Invoice.class); + } + + /** + * Refreshes invoice status from SAT. + * + * @param id Invoice id. + * @return Updated invoice. + * @see API reference + */ + public Invoice updateStatus(String id) { + return put("/invoices/" + id + "/status", null, null, Invoice.class); + } + + /** + * Creates a draft copy from an existing invoice. + * + * @param id Invoice id. + * @return Draft invoice. + * @see API reference + */ + public Invoice copyToDraft(String id) { + return post("/invoices/" + id + "/copy", null, null, Invoice.class); + } + + /** + * Generates a PDF preview for invoice payload before stamping. + * + * @param body Invoice payload. + * @return PDF bytes. + * @see API reference + */ + public byte[] previewPdf(Map body) { + return client.postBytes("/invoices/preview/pdf", body); + } +} diff --git a/src/main/java/io/facturapi/resources/OrganizationsResource.java b/src/main/java/io/facturapi/resources/OrganizationsResource.java new file mode 100644 index 0000000..62aabab --- /dev/null +++ b/src/main/java/io/facturapi/resources/OrganizationsResource.java @@ -0,0 +1,331 @@ +package io.facturapi.resources; + +import com.fasterxml.jackson.core.type.TypeReference; +import io.facturapi.http.FacturapiHttpClient; +import io.facturapi.http.MultipartBody; +import io.facturapi.http.MultipartBodyBuilder; +import io.facturapi.models.ApiKey; +import io.facturapi.models.DomainAvailability; +import io.facturapi.models.GenericResponse; +import io.facturapi.models.Organization; +import io.facturapi.models.OrganizationInvite; +import io.facturapi.models.OrganizationTeamRole; +import io.facturapi.models.OrganizationTeamRoleTemplate; +import io.facturapi.models.OrganizationUserAccess; +import io.facturapi.models.SearchResult; +import io.facturapi.models.Series; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.List; +import java.util.Map; + +public class OrganizationsResource extends BaseResource { + /** + * Organization endpoints. + * + * @see API reference + */ + public OrganizationsResource(FacturapiHttpClient client) { + super(client); + } + + /** + * Creates a new organization for your account. + */ + public Organization create(Map data) { + return post("/organizations", data, null, Organization.class); + } + + /** + * Gets a paginated list of organizations for your account. + */ + public SearchResult list(Map params) { + return get("/organizations", params, new TypeReference>() {}); + } + + /** + * Gets a single organization by id. + */ + public Organization retrieve(String id) { + return get("/organizations/" + id, null, Organization.class); + } + + /** + * Updates the organization's legal information. + */ + public Organization updateLegal(String id, Map data) { + return put("/organizations/" + id + "/legal", data, null, Organization.class); + } + + /** + * Updates the organization's customization settings. + */ + public Organization updateCustomization(String id, Map data) { + return put("/organizations/" + id + "/customization", data, null, Organization.class); + } + + /** + * Updates receipt settings for an organization. + */ + public Organization updateReceiptSettings(String id, Map data) { + return put("/organizations/" + id + "/receipts", data, null, Organization.class); + } + + /** + * Updates domain settings for self-invoice. + */ + public Organization updateDomain(String id, Map data) { + return put("/organizations/" + id + "/domain", data, null, Organization.class); + } + + /** + * Checks whether a domain is available. + */ + public DomainAvailability checkDomainAvailability(Map query) { + return get("/organizations/domain-check", query, DomainAvailability.class); + } + + /** + * Uploads organization logo file. + */ + public Organization uploadLogo(String id, Path filePath) throws IOException { + byte[] fileBytes = Files.readAllBytes(filePath); + MultipartBody multipartBody = new MultipartBodyBuilder() + .addFile("file", filePath.getFileName().toString(), fileBytes, "application/octet-stream") + .build(); + return client.putMultipart("/organizations/" + id + "/logo", multipartBody, Organization.class); + } + + /** + * Uploads organization CSD certificate files. + */ + public Organization uploadCertificate(String id, Path cerFile, Path keyFile, String password) throws IOException { + MultipartBody multipartBody = new MultipartBodyBuilder() + .addFile("cer", cerFile.getFileName().toString(), Files.readAllBytes(cerFile), "application/octet-stream") + .addFile("key", keyFile.getFileName().toString(), Files.readAllBytes(keyFile), "application/octet-stream") + .addField("password", password) + .build(); + return client.putMultipart("/organizations/" + id + "/certificate", multipartBody, Organization.class); + } + + /** + * Deletes organization CSD certificate. + */ + public Organization deleteCertificate(String id) { + return delete("/organizations/" + id + "/certificate", null, Organization.class); + } + + /** + * Permanently removes an organization. + */ + public Organization delete(String id) { + return delete("/organizations/" + id, null, Organization.class); + } + + /** + * Gets test API key for an organization. + */ + public String getTestApiKey(String id) { + return get("/organizations/" + id + "/apikeys/test", null, String.class); + } + + /** + * Renews test API key for an organization. + */ + public String renewTestApiKey(String id) { + return put("/organizations/" + id + "/apikeys/test", null, null, String.class); + } + + /** + * Lists live API keys for an organization. + */ + public List listLiveApiKeys(String id) { + return get("/organizations/" + id + "/apikeys/live", null, new TypeReference>() {}); + } + + /** + * Renews live API key for an organization. + */ + public String renewLiveApiKey(String id) { + return put("/organizations/" + id + "/apikeys/live", null, null, String.class); + } + + /** + * Deletes one live API key by id. + */ + public List deleteLiveApiKey(String organizationId, String apiKeyId) { + return delete( + "/organizations/" + organizationId + "/apikeys/live/" + apiKeyId, + null, + new TypeReference>() {} + ); + } + + /** + * Lists invoice series configured in the organization. + */ + public List listSeriesGroup(String organizationId) { + return get("/organizations/" + organizationId + "/series-group", null, new TypeReference>() {}); + } + + /** + * Creates a new invoice series in the organization. + */ + public Series createSeriesGroup(String organizationId, Map seriesData) { + return post("/organizations/" + organizationId + "/series-group", seriesData, null, Series.class); + } + + /** + * Updates an existing invoice series. + */ + public Series updateSeriesGroup(String organizationId, String seriesName, Map data) { + return put("/organizations/" + organizationId + "/series-group/" + seriesName, data, null, Series.class); + } + + /** + * Deletes an invoice series. + */ + public Series deleteSeriesGroup(String organizationId, String seriesName) { + return delete("/organizations/" + organizationId + "/series-group/" + seriesName, null, Series.class); + } + + /** + * Gets the organization associated with the current API key. + */ + public Organization me() { + return get("/organizations/me", null, Organization.class); + } + + /** + * Updates self-invoice settings. + */ + public Organization updateSelfInvoiceSettings(String id, Map data) { + return put("/organizations/" + id + "/self-invoice", data, null, Organization.class); + } + + /** + * Lists users with organization access. + */ + public List listTeamAccess(String organizationId) { + return get("/organizations/" + organizationId + "/team", null, new TypeReference>() {}); + } + + /** + * Retrieves one organization access record. + */ + public OrganizationUserAccess retrieveTeamAccess(String organizationId, String accessId) { + return get("/organizations/" + organizationId + "/team/" + accessId, null, OrganizationUserAccess.class); + } + + /** + * Updates role assignment for a team access. + */ + public OrganizationUserAccess updateTeamAccessRole(String organizationId, String accessId, String role) { + return put( + "/organizations/" + organizationId + "/team/" + accessId + "/role", + Map.of("role", role), + null, + OrganizationUserAccess.class + ); + } + + /** + * Removes user access from the organization. + */ + public GenericResponse removeTeamAccess(String organizationId, String accessId) { + return delete("/organizations/" + organizationId + "/team/" + accessId, null, GenericResponse.class); + } + + /** + * Lists invites sent by an organization. + */ + public List listSentTeamInvites(String organizationId) { + return get("/organizations/" + organizationId + "/team/invites", null, new TypeReference>() {}); + } + + /** + * Creates or updates a team invite. + */ + public OrganizationInvite inviteUserToTeam(String organizationId, Map data) { + return post("/organizations/" + organizationId + "/team/invites", data, null, OrganizationInvite.class); + } + + /** + * Cancels a sent team invite. + */ + public GenericResponse cancelTeamInvite(String organizationId, String inviteKey) { + return delete( + "/organizations/" + organizationId + "/team/invites/" + inviteKey, + null, + GenericResponse.class + ); + } + + /** + * Lists invites pending response for current user. + */ + public List listReceivedTeamInvites() { + return get("/organizations/invites/pending", null, new TypeReference>() {}); + } + + /** + * Accepts or rejects a pending invite. + */ + public GenericResponse respondTeamInvite(String inviteKey, Map data) { + return post("/organizations/invites/" + inviteKey + "/response", data, null, GenericResponse.class); + } + + /** + * Lists custom roles configured for an organization. + */ + public List listTeamRoles(String organizationId) { + return get("/organizations/" + organizationId + "/team/roles", null, new TypeReference>() {}); + } + + /** + * Lists role templates available for an organization. + */ + public List listTeamRoleTemplates(String organizationId) { + return get( + "/organizations/" + organizationId + "/team/roles/templates", + null, + new TypeReference>() {} + ); + } + + /** + * Lists operation codes available for role permissions. + */ + public List listTeamRoleOperations(String organizationId) { + return get("/organizations/" + organizationId + "/team/roles/operations", null, new TypeReference>() {}); + } + + /** + * Retrieves a team role by id. + */ + public OrganizationTeamRole retrieveTeamRole(String organizationId, String roleId) { + return get("/organizations/" + organizationId + "/team/roles/" + roleId, null, OrganizationTeamRole.class); + } + + /** + * Creates a team role. + */ + public OrganizationTeamRole createTeamRole(String organizationId, Map data) { + return post("/organizations/" + organizationId + "/team/roles", data, null, OrganizationTeamRole.class); + } + + /** + * Updates a team role. + */ + public OrganizationTeamRole updateTeamRole(String organizationId, String roleId, Map data) { + return put("/organizations/" + organizationId + "/team/roles/" + roleId, data, null, OrganizationTeamRole.class); + } + + /** + * Deletes a team role. + */ + public GenericResponse deleteTeamRole(String organizationId, String roleId) { + return delete("/organizations/" + organizationId + "/team/roles/" + roleId, null, GenericResponse.class); + } +} diff --git a/src/main/java/io/facturapi/resources/ProductsResource.java b/src/main/java/io/facturapi/resources/ProductsResource.java new file mode 100644 index 0000000..553c76b --- /dev/null +++ b/src/main/java/io/facturapi/resources/ProductsResource.java @@ -0,0 +1,74 @@ +package io.facturapi.resources; + +import com.fasterxml.jackson.core.type.TypeReference; +import io.facturapi.http.FacturapiHttpClient; +import io.facturapi.models.Product; +import io.facturapi.models.SearchResult; +import java.util.Map; + +public class ProductsResource extends BaseResource { + /** + * Product endpoints. + * + * @see API reference + */ + public ProductsResource(FacturapiHttpClient client) { + super(client); + } + + /** + * Creates a new product in your organization. + * + * @param data Product payload. + * @return Created product. + * @see API reference + */ + public Product create(Map data) { + return post("/products", data, null, Product.class); + } + + /** + * Gets a paginated list of products in your organization. + * + * @param params Search and pagination parameters. + * @return Paginated product result. + * @see API reference + */ + public SearchResult list(Map params) { + return get("/products", params, new TypeReference>() {}); + } + + /** + * Gets a single product by id. + * + * @param id Product id. + * @return Product object. + * @see API reference + */ + public Product retrieve(String id) { + return get("/products/" + id, null, Product.class); + } + + /** + * Updates a product. + * + * @param id Product id. + * @param data Product payload updates. + * @return Updated product. + * @see API reference + */ + public Product update(String id, Map data) { + return put("/products/" + id, data, null, Product.class); + } + + /** + * Permanently removes a product. + * + * @param id Product id. + * @return Deleted product. + * @see API reference + */ + public Product delete(String id) { + return delete("/products/" + id, null, Product.class); + } +} diff --git a/src/main/java/io/facturapi/resources/ReceiptsResource.java b/src/main/java/io/facturapi/resources/ReceiptsResource.java new file mode 100644 index 0000000..17d3357 --- /dev/null +++ b/src/main/java/io/facturapi/resources/ReceiptsResource.java @@ -0,0 +1,110 @@ +package io.facturapi.resources; + +import com.fasterxml.jackson.core.type.TypeReference; +import io.facturapi.http.FacturapiHttpClient; +import io.facturapi.models.GenericResponse; +import io.facturapi.models.Invoice; +import io.facturapi.models.Receipt; +import io.facturapi.models.SearchResult; +import java.util.Map; + +public class ReceiptsResource extends BaseResource { + /** + * Receipt endpoints. + * + * @see API reference + */ + public ReceiptsResource(FacturapiHttpClient client) { + super(client); + } + + /** + * Creates a new receipt. + * + * @param data Receipt payload. + * @return Created receipt. + * @see API reference + */ + public Receipt create(Map data) { + return post("/receipts", data, null, Receipt.class); + } + + /** + * Gets a paginated list of receipts in your organization. + * + * @param params Search and pagination parameters. + * @return Paginated receipt result. + * @see API reference + */ + public SearchResult list(Map params) { + return get("/receipts", params, new TypeReference>() {}); + } + + /** + * Gets a single receipt by id. + * + * @param id Receipt id. + * @return Receipt object. + * @see API reference + */ + public Receipt retrieve(String id) { + return get("/receipts/" + id, null, Receipt.class); + } + + /** + * Creates an invoice for a receipt. + * + * @param id Receipt id. + * @param data Invoice payload. + * @return Created invoice. + * @see API reference + */ + public Invoice invoice(String id, Map data) { + return post("/receipts/" + id + "/invoice", data, null, Invoice.class); + } + + /** + * Creates a global invoice for open receipts. + * + * @param data Global invoice payload. + * @return Created invoice. + * @see API reference + */ + public Invoice createGlobalInvoice(Map data) { + return post("/receipts/global-invoice", data, null, Invoice.class); + } + + /** + * Cancels a receipt. + * + * @param id Receipt id. + * @return Canceled receipt. + * @see API reference + */ + public Receipt cancel(String id) { + return delete("/receipts/" + id, null, Receipt.class); + } + + /** + * Sends the receipt to the customer's email. + * + * @param id Receipt id. + * @param data Email options. + * @return Operation response. + * @see API reference + */ + public GenericResponse sendByEmail(String id, Map data) { + return post("/receipts/" + id + "/email", data, null, GenericResponse.class); + } + + /** + * Downloads a receipt PDF file. + * + * @param id Receipt id. + * @return PDF bytes. + * @see API reference + */ + public byte[] downloadPdf(String id) { + return client.getBytes("/receipts/" + id + "/pdf"); + } +} diff --git a/src/main/java/io/facturapi/resources/RetentionsResource.java b/src/main/java/io/facturapi/resources/RetentionsResource.java new file mode 100644 index 0000000..64653f4 --- /dev/null +++ b/src/main/java/io/facturapi/resources/RetentionsResource.java @@ -0,0 +1,109 @@ +package io.facturapi.resources; + +import com.fasterxml.jackson.core.type.TypeReference; +import io.facturapi.http.FacturapiHttpClient; +import io.facturapi.models.GenericResponse; +import io.facturapi.models.Retention; +import io.facturapi.models.SearchResult; +import java.util.Map; + +public class RetentionsResource extends BaseResource { + /** + * Retention endpoints. + * + * @see API reference + */ + public RetentionsResource(FacturapiHttpClient client) { + super(client); + } + + /** + * Creates a new valid retention (CFDI). + * + * @param data Retention payload. + * @return Created retention. + * @see API reference + */ + public Retention create(Map data) { + return post("/retentions", data, null, Retention.class); + } + + /** + * Gets a paginated list of retentions. + * + * @param params Search and pagination parameters. + * @return Paginated retention result. + * @see API reference + */ + public SearchResult list(Map params) { + return get("/retentions", params, new TypeReference>() {}); + } + + /** + * Gets a single retention by id. + * + * @param id Retention id. + * @return Retention object. + * @see API reference + */ + public Retention retrieve(String id) { + return get("/retentions/" + id, null, Retention.class); + } + + /** + * Cancels a retention. + * + * @param id Retention id. + * @param params Cancellation options. + * @return Canceled retention. + * @see API reference + */ + public Retention cancel(String id, Map params) { + return delete("/retentions/" + id, params, Retention.class); + } + + /** + * Sends the retention to the customer's email. + * + * @param id Retention id. + * @param data Email options. + * @return Operation response. + * @see API reference + */ + public GenericResponse sendByEmail(String id, Map data) { + return post("/retentions/" + id + "/email", data, null, GenericResponse.class); + } + + /** + * Downloads a retention PDF file. + * + * @param id Retention id. + * @return PDF bytes. + * @see API reference + */ + public byte[] downloadPdf(String id) { + return client.getBytes("/retentions/" + id + "/pdf"); + } + + /** + * Downloads a retention XML file. + * + * @param id Retention id. + * @return XML bytes. + * @see API reference + */ + public byte[] downloadXml(String id) { + return client.getBytes("/retentions/" + id + "/xml"); + } + + /** + * Downloads a retention ZIP package with PDF and XML. + * + * @param id Retention id. + * @return ZIP bytes. + * @see API reference + */ + public byte[] downloadZip(String id) { + return client.getBytes("/retentions/" + id + "/zip"); + } +} diff --git a/src/main/java/io/facturapi/resources/WebhooksResource.java b/src/main/java/io/facturapi/resources/WebhooksResource.java new file mode 100644 index 0000000..9408bf1 --- /dev/null +++ b/src/main/java/io/facturapi/resources/WebhooksResource.java @@ -0,0 +1,135 @@ +package io.facturapi.resources; + +import com.fasterxml.jackson.core.type.TypeReference; +import io.facturapi.FacturapiException; +import io.facturapi.http.FacturapiHttpClient; +import io.facturapi.models.ApiEvent; +import io.facturapi.models.SearchResult; +import io.facturapi.models.Webhook; +import java.nio.charset.StandardCharsets; +import java.security.InvalidKeyException; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.Map; +import javax.crypto.Mac; +import javax.crypto.spec.SecretKeySpec; + +public class WebhooksResource extends BaseResource { + /** + * Webhook endpoints. + * + * @see API reference + */ + public WebhooksResource(FacturapiHttpClient client) { + super(client); + } + + /** + * Creates a new webhook in your organization. + * + * @param data Webhook payload. + * @return Created webhook. + * @see API reference + */ + public Webhook create(Map data) { + return post("/webhooks", data, null, Webhook.class); + } + + /** + * Gets a paginated list of webhooks. + * + * @param params Search and pagination parameters. + * @return Paginated webhook result. + * @see API reference + */ + public SearchResult list(Map params) { + return get("/webhooks", params, new TypeReference>() {}); + } + + /** + * Gets a single webhook by id. + * + * @param id Webhook id. + * @return Webhook object. + * @see API reference + */ + public Webhook retrieve(String id) { + return get("/webhooks/" + id, null, Webhook.class); + } + + /** + * Updates a webhook. + * + * @param id Webhook id. + * @param data Webhook payload updates. + * @return Updated webhook. + * @see API reference + */ + public Webhook update(String id, Map data) { + return put("/webhooks/" + id, data, null, Webhook.class); + } + + /** + * Permanently removes a webhook. + * + * @param id Webhook id. + * @return Deleted webhook. + * @see API reference + */ + public Webhook delete(String id) { + return delete("/webhooks/" + id, null, Webhook.class); + } + + /** + * Validates webhook signature and returns parsed event when valid. + * + * @param secret Webhook secret. + * @param signatureHex Value from `facturapi-signature` header. + * @param payload Raw request payload. + * @return Parsed API event. + * @see API reference + */ + public ApiEvent validateSignature(String secret, String signatureHex, String payload) { + try { + byte[] expected = hmacSha256(secret, payload); + byte[] provided = hexToBytes(signatureHex); + if (!MessageDigest.isEqual(expected, provided)) { + throw new FacturapiException("Invalid signature"); + } + return client.getObjectMapper().readValue(payload, ApiEvent.class); + } catch (IllegalArgumentException e) { + throw new FacturapiException("Invalid signature", e); + } catch (NoSuchAlgorithmException | InvalidKeyException e) { + throw new FacturapiException("Signature validation failure", e); + } catch (Exception e) { + if (e instanceof FacturapiException) { + throw (FacturapiException) e; + } + throw new FacturapiException("Invalid payload", e); + } + } + + private static byte[] hmacSha256(String secret, String payload) + throws NoSuchAlgorithmException, InvalidKeyException { + Mac mac = Mac.getInstance("HmacSHA256"); + mac.init(new SecretKeySpec(secret.getBytes(StandardCharsets.UTF_8), "HmacSHA256")); + return mac.doFinal(payload.getBytes(StandardCharsets.UTF_8)); + } + + private static byte[] hexToBytes(String hex) { + if (hex == null || hex.length() % 2 != 0) { + throw new IllegalArgumentException("Invalid signature"); + } + int length = hex.length(); + byte[] bytes = new byte[length / 2]; + for (int i = 0; i < length; i += 2) { + int high = Character.digit(hex.charAt(i), 16); + int low = Character.digit(hex.charAt(i + 1), 16); + if (high < 0 || low < 0) { + throw new IllegalArgumentException("Invalid signature"); + } + bytes[i / 2] = (byte) ((high << 4) + low); + } + return bytes; + } +} diff --git a/src/main/java/io/facturapi/tools/CartaPorteCatalogsTool.java b/src/main/java/io/facturapi/tools/CartaPorteCatalogsTool.java new file mode 100644 index 0000000..fdc89a6 --- /dev/null +++ b/src/main/java/io/facturapi/tools/CartaPorteCatalogsTool.java @@ -0,0 +1,126 @@ +package io.facturapi.tools; + +import com.fasterxml.jackson.core.type.TypeReference; +import io.facturapi.http.FacturapiHttpClient; +import io.facturapi.models.CatalogItem; +import io.facturapi.models.SearchResult; +import java.util.Map; + +public class CartaPorteCatalogsTool { + private static final String BASE_PATH = "/catalogs/cartaporte/3.1"; + private final FacturapiHttpClient client; + + /** + * Carta Porte catalogs endpoints. + * + * @see API reference + */ + public CartaPorteCatalogsTool(FacturapiHttpClient client) { + this.client = client; + } + + /** + * Searches air transport codes (Carta Porte 3.1). + * + * @param params Search and pagination parameters. + * @return Paginated catalog result. + * @see API reference + */ + public SearchResult searchAirTransportCodes(Map params) { + return search(BASE_PATH + "/air-transport-codes", params); + } + + /** + * Searches transport configurations (Carta Porte 3.1). + * + * @param params Search and pagination parameters. + * @return Paginated catalog result. + */ + public SearchResult searchTransportConfigs(Map params) { + return search(BASE_PATH + "/transport-configs", params); + } + + /** + * Searches rights of passage catalog (Carta Porte 3.1). + * + * @param params Search and pagination parameters. + * @return Paginated catalog result. + */ + public SearchResult searchRightsOfPassage(Map params) { + return search(BASE_PATH + "/rights-of-passage", params); + } + + /** + * Searches customs documents catalog (Carta Porte 3.1). + * + * @param params Search and pagination parameters. + * @return Paginated catalog result. + */ + public SearchResult searchCustomsDocuments(Map params) { + return search(BASE_PATH + "/customs-documents", params); + } + + /** + * Searches packaging types catalog (Carta Porte 3.1). + * + * @param params Search and pagination parameters. + * @return Paginated catalog result. + */ + public SearchResult searchPackagingTypes(Map params) { + return search(BASE_PATH + "/packaging-types", params); + } + + /** + * Searches trailer types catalog (Carta Porte 3.1). + * + * @param params Search and pagination parameters. + * @return Paginated catalog result. + */ + public SearchResult searchTrailerTypes(Map params) { + return search(BASE_PATH + "/trailer-types", params); + } + + /** + * Searches hazardous materials catalog (Carta Porte 3.1). + * + * @param params Search and pagination parameters. + * @return Paginated catalog result. + */ + public SearchResult searchHazardousMaterials(Map params) { + return search(BASE_PATH + "/hazardous-materials", params); + } + + /** + * Searches naval authorizations catalog (Carta Porte 3.1). + * + * @param params Search and pagination parameters. + * @return Paginated catalog result. + */ + public SearchResult searchNavalAuthorizations(Map params) { + return search(BASE_PATH + "/naval-authorizations", params); + } + + /** + * Searches port stations catalog (Carta Porte 3.1). + * + * @param params Search and pagination parameters. + * @return Paginated catalog result. + */ + public SearchResult searchPortStations(Map params) { + return search(BASE_PATH + "/port-stations", params); + } + + /** + * Searches marine containers catalog (Carta Porte 3.1). + * + * @param params Search and pagination parameters. + * @return Paginated catalog result. + */ + public SearchResult searchMarineContainers(Map params) { + return search(BASE_PATH + "/marine-containers", params); + } + + private SearchResult search(String path, Map params) { + return client.get(path, params, new TypeReference>() {}); + } +} diff --git a/src/main/java/io/facturapi/tools/CatalogsTool.java b/src/main/java/io/facturapi/tools/CatalogsTool.java new file mode 100644 index 0000000..6070add --- /dev/null +++ b/src/main/java/io/facturapi/tools/CatalogsTool.java @@ -0,0 +1,42 @@ +package io.facturapi.tools; + +import com.fasterxml.jackson.core.type.TypeReference; +import io.facturapi.http.FacturapiHttpClient; +import io.facturapi.models.CatalogItem; +import io.facturapi.models.SearchResult; +import java.util.Map; + +public class CatalogsTool { + private final FacturapiHttpClient client; + + /** + * SAT catalogs endpoints. + * + * @see API reference + */ + public CatalogsTool(FacturapiHttpClient client) { + this.client = client; + } + + /** + * Searches SAT product/service catalog entries. + * + * @param params Search and pagination parameters. + * @return Paginated catalog result. + * @see API reference + */ + public SearchResult searchProducts(Map params) { + return client.get("/catalogs/products", params, new TypeReference>() {}); + } + + /** + * Searches SAT unit catalog entries. + * + * @param params Search and pagination parameters. + * @return Paginated catalog result. + * @see API reference + */ + public SearchResult searchUnits(Map params) { + return client.get("/catalogs/units", params, new TypeReference>() {}); + } +} diff --git a/src/main/java/io/facturapi/tools/ComercioExteriorCatalogsTool.java b/src/main/java/io/facturapi/tools/ComercioExteriorCatalogsTool.java new file mode 100644 index 0000000..c2829f4 --- /dev/null +++ b/src/main/java/io/facturapi/tools/ComercioExteriorCatalogsTool.java @@ -0,0 +1,35 @@ +package io.facturapi.tools; + +import com.fasterxml.jackson.core.type.TypeReference; +import io.facturapi.http.FacturapiHttpClient; +import io.facturapi.models.CatalogItem; +import io.facturapi.models.SearchResult; +import java.util.Map; + +public class ComercioExteriorCatalogsTool { + private final FacturapiHttpClient client; + + /** + * Comercio Exterior catalogs endpoints. + * + * @see API reference + */ + public ComercioExteriorCatalogsTool(FacturapiHttpClient client) { + this.client = client; + } + + /** + * Searches tariff fractions catalog entries (Comercio Exterior 2.0). + * + * @param params Search and pagination parameters. + * @return Paginated catalog result. + * @see API reference + */ + public SearchResult searchTariffFractions(Map params) { + return client.get( + "/catalogs/comercioexterior/2.0/tariff-fractions", + params, + new TypeReference>() {} + ); + } +} diff --git a/src/main/java/io/facturapi/tools/ToolsResource.java b/src/main/java/io/facturapi/tools/ToolsResource.java new file mode 100644 index 0000000..4856640 --- /dev/null +++ b/src/main/java/io/facturapi/tools/ToolsResource.java @@ -0,0 +1,29 @@ +package io.facturapi.tools; + +import io.facturapi.http.FacturapiHttpClient; +import io.facturapi.models.TaxInfoValidation; +import java.util.Map; + +public class ToolsResource { + private final FacturapiHttpClient client; + + /** + * Utility endpoints. + * + * @see API reference + */ + public ToolsResource(FacturapiHttpClient client) { + this.client = client; + } + + /** + * Validates a tax id against EFOS list. + * + * @param taxId RFC or tax id value. + * @return Validation result. + * @see API reference + */ + public TaxInfoValidation validateTaxId(String taxId) { + return client.get("/tools/tax_id_validation", Map.of("tax_id", taxId), TaxInfoValidation.class); + } +} diff --git a/src/test/java/com/facturapi/FacturapiHttpClientTest.java b/src/test/java/com/facturapi/FacturapiHttpClientTest.java deleted file mode 100644 index 010d6fa..0000000 --- a/src/test/java/com/facturapi/FacturapiHttpClientTest.java +++ /dev/null @@ -1,91 +0,0 @@ -package com.facturapi; - -import static org.junit.jupiter.api.Assertions.assertArrayEquals; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.junit.jupiter.api.Assertions.assertTrue; - -import com.facturapi.http.FacturapiConfig; -import com.facturapi.http.FacturapiHttpClient; -import java.io.IOException; -import java.util.Map; -import okhttp3.mockwebserver.MockResponse; -import okhttp3.mockwebserver.MockWebServer; -import okhttp3.mockwebserver.RecordedRequest; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -class FacturapiHttpClientTest { - private MockWebServer server; - - @BeforeEach - void setUp() throws IOException { - server = new MockWebServer(); - server.start(); - } - - @AfterEach - void tearDown() throws IOException { - server.shutdown(); - } - - @Test - void sendsBearerAuthAndParsesJson() throws Exception { - server.enqueue(new MockResponse() - .setHeader("Content-Type", "application/json") - .setBody("{\"ok\":true}")); - - FacturapiHttpClient client = new FacturapiHttpClient( - FacturapiConfig.builder("sk_test_123") - .baseUrl(server.url("/").toString()) - .build() - ); - - var response = client.postJson("/invoices", Map.of("foo", "bar"), Map.of("page", 1)); - assertTrue(response.get("ok").asBoolean()); - - RecordedRequest request = server.takeRequest(); - assertEquals("Bearer sk_test_123", request.getHeader("Authorization")); - assertEquals("POST", request.getMethod()); - assertEquals("/invoices?page=1", request.getPath()); - } - - @Test - void returnsBinaryBytesForPdf() { - byte[] payload = "PDF-CONTENT".getBytes(); - server.enqueue(new MockResponse() - .setHeader("Content-Type", "application/pdf") - .setBody(new okio.Buffer().write(payload))); - - FacturapiHttpClient client = new FacturapiHttpClient( - FacturapiConfig.builder("sk_test_123") - .baseUrl(server.url("/").toString()) - .build() - ); - - assertArrayEquals(payload, client.getBytes("/invoices/inv_1/pdf")); - } - - @Test - void throwsFacturapiExceptionWithApiMessage() { - server.enqueue(new MockResponse() - .setResponseCode(400) - .setHeader("Content-Type", "application/json") - .setBody("{\"message\":\"Invalid customer\"}")); - - FacturapiHttpClient client = new FacturapiHttpClient( - FacturapiConfig.builder("sk_test_123") - .baseUrl(server.url("/").toString()) - .build() - ); - - FacturapiException ex = assertThrows( - FacturapiException.class, - () -> client.getJson("/customers/cus_1", null) - ); - - assertEquals(400, ex.getStatusCode()); - assertTrue(ex.getMessage().contains("Invalid customer")); - } -} diff --git a/src/test/java/com/facturapi/FacturapiResourcesTest.java b/src/test/java/com/facturapi/FacturapiResourcesTest.java deleted file mode 100644 index 0a9eeae..0000000 --- a/src/test/java/com/facturapi/FacturapiResourcesTest.java +++ /dev/null @@ -1,59 +0,0 @@ -package com.facturapi; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertTrue; - -import java.io.IOException; -import java.util.Map; -import okhttp3.mockwebserver.MockResponse; -import okhttp3.mockwebserver.MockWebServer; -import okhttp3.mockwebserver.RecordedRequest; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -class FacturapiResourcesTest { - private MockWebServer server; - - @BeforeEach - void setUp() throws IOException { - server = new MockWebServer(); - server.start(); - } - - @AfterEach - void tearDown() throws IOException { - server.shutdown(); - } - - @Test - void invoiceCreateUsesExpectedPathAndBody() throws Exception { - server.enqueue(new MockResponse() - .setHeader("Content-Type", "application/json") - .setBody("{\"id\":\"inv_1\"}")); - - Facturapi sdk = Facturapi.builder("sk_test").baseUrl(server.url("/").toString()).build(); - var response = sdk.invoices.create(Map.of("customer", "cus_1"), Map.of("test", true)); - - assertEquals("inv_1", response.get("id").asText()); - - RecordedRequest request = server.takeRequest(); - assertEquals("POST", request.getMethod()); - assertEquals("/invoices?test=true", request.getPath()); - assertTrue(request.getBody().readUtf8().contains("\"customer\":\"cus_1\"")); - } - - @Test - void organizationBackwardCompatibleAliasWorks() throws Exception { - server.enqueue(new MockResponse() - .setHeader("Content-Type", "application/json") - .setBody("[{\"id\":\"live_1\"}]")); - - Facturapi sdk = Facturapi.builder("sk_test").baseUrl(server.url("/").toString()).build(); - var response = sdk.organizations.lisLiveApiKeys("org_1"); - - assertTrue(response.isArray()); - RecordedRequest request = server.takeRequest(); - assertEquals("/organizations/org_1/apikeys/live", request.getPath()); - } -} diff --git a/src/test/java/io/facturapi/FacturapiHttpClientTest.java b/src/test/java/io/facturapi/FacturapiHttpClientTest.java new file mode 100644 index 0000000..853b602 --- /dev/null +++ b/src/test/java/io/facturapi/FacturapiHttpClientTest.java @@ -0,0 +1,69 @@ +package io.facturapi; + +import static org.junit.jupiter.api.Assertions.assertArrayEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import io.facturapi.http.FacturapiConfig; +import io.facturapi.http.FacturapiHttpClient; +import io.facturapi.models.GenericResponse; +import java.util.Map; +import org.junit.jupiter.api.Test; + +class FacturapiHttpClientTest { + @Test + void sendsBearerAuthAndParsesTypedJson() throws Exception { + StubHttpClient httpClient = new StubHttpClient(); + httpClient.enqueueJson(200, "{\"ok\":true}"); + + FacturapiHttpClient client = new FacturapiHttpClient( + FacturapiConfig.builder("sk_test_123") + .httpClient(httpClient) + .build() + ); + + GenericResponse response = client.post("/invoices", Map.of("foo", "bar"), Map.of("page", 1), GenericResponse.class); + assertTrue(response.isOk()); + + var request = httpClient.requests().get(0); + assertEquals("Bearer sk_test_123", request.headers().firstValue("Authorization").orElse("")); + assertEquals("POST", request.method()); + assertEquals("/v2/invoices?page=1", request.uri().getPath() + "?" + request.uri().getQuery()); + } + + @Test + void returnsBinaryBytesForPdf() { + StubHttpClient httpClient = new StubHttpClient(); + byte[] payload = "PDF-CONTENT".getBytes(); + httpClient.enqueueBinary(200, payload, "application/pdf"); + + FacturapiHttpClient client = new FacturapiHttpClient( + FacturapiConfig.builder("sk_test_123") + .httpClient(httpClient) + .build() + ); + + assertArrayEquals(payload, client.getBytes("/invoices/inv_1/pdf")); + } + + @Test + void throwsFacturapiExceptionWithApiMessage() { + StubHttpClient httpClient = new StubHttpClient(); + httpClient.enqueueJson(400, "{\"message\":\"Invalid customer\"}"); + + FacturapiHttpClient client = new FacturapiHttpClient( + FacturapiConfig.builder("sk_test_123") + .httpClient(httpClient) + .build() + ); + + FacturapiException ex = assertThrows( + FacturapiException.class, + () -> client.get("/customers/cus_1", null, GenericResponse.class) + ); + + assertEquals(400, ex.getStatusCode()); + assertTrue(ex.getMessage().contains("Invalid customer")); + } +} diff --git a/src/test/java/io/facturapi/FacturapiResourcesTest.java b/src/test/java/io/facturapi/FacturapiResourcesTest.java new file mode 100644 index 0000000..8dc4d5d --- /dev/null +++ b/src/test/java/io/facturapi/FacturapiResourcesTest.java @@ -0,0 +1,112 @@ +package io.facturapi; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertInstanceOf; +import static org.junit.jupiter.api.Assertions.assertNotNull; + +import io.facturapi.http.FacturapiConfig; +import java.util.Map; +import org.junit.jupiter.api.Test; + +class FacturapiResourcesTest { + @Test + void invoiceCreateUsesExpectedPath() { + StubHttpClient httpClient = new StubHttpClient(); + httpClient.enqueueJson(200, "{\"id\":\"inv_1\"}"); + + Facturapi sdk = new Facturapi( + FacturapiConfig.builder("sk_test") + .httpClient(httpClient) + .build() + ); + + var response = sdk.invoices.create(Map.of("customer", "cus_1"), Map.of("test", true)); + + assertEquals("inv_1", response.getId()); + + var request = httpClient.requests().get(0); + assertEquals("POST", request.method()); + assertEquals("/v2/invoices?test=true", request.uri().getPath() + "?" + request.uri().getQuery()); + } + + @Test + void organizationListLiveApiKeysIsTyped() { + StubHttpClient httpClient = new StubHttpClient(); + httpClient.enqueueJson(200, "[{\"id\":\"live_1\",\"key\":\"sk_live_x\"}]"); + + Facturapi sdk = new Facturapi( + FacturapiConfig.builder("sk_test") + .httpClient(httpClient) + .build() + ); + + var response = sdk.organizations.listLiveApiKeys("org_1"); + + assertEquals(1, response.size()); + assertNotNull(response.get(0).getId()); + var request = httpClient.requests().get(0); + assertEquals("/v2/organizations/org_1/apikeys/live", request.uri().getPath()); + } + + @Test + void invoiceComplementsAreTypedForPagoNominaAndCustom() { + StubHttpClient httpClient = new StubHttpClient(); + httpClient.enqueueJson( + 200, + "{\"id\":\"inv_1\",\"complements\":[" + + "{\"type\":\"pago\",\"data\":[{\"payment_form\":\"03\",\"date\":\"2026-04-07\",\"currency\":\"MXN\",\"exchange\":1,\"related_documents\":[{\"uuid\":\"f03d5c3f-a93b-443f-927f-e89db2f7f58a\",\"amount\":100,\"installment\":1,\"last_balance\":100,\"currency\":\"MXN\",\"exchange\":1,\"taxes\":[{\"base\":100,\"rate\":0.16,\"type\":\"IVA\",\"factor\":\"Tasa\",\"withholding\":false}]}]}]}," + + "{\"type\":\"nomina\",\"data\":{\"tipo_nomina\":\"O\",\"fecha_pago\":\"2026-04-01\",\"fecha_inicial_pago\":\"2026-03-16\",\"fecha_final_pago\":\"2026-03-31\",\"num_dias_pagados\":15,\"receptor\":{\"curp\":\"TEST900101HDFABC01\",\"tipo_contrato\":\"01\",\"tipo_regimen\":\"02\",\"num_empleado\":\"EMP-1\",\"periodicidad_pago\":\"04\",\"clave_ent_fed\":\"CMX\"},\"percepciones\":{\"percepcion\":[{\"tipo_percepcion\":\"001\",\"clave\":\"P001\",\"importe_gravado\":1000,\"importe_exento\":0}]},\"deducciones\":[{\"tipo_deduccion\":\"002\",\"clave\":\"D001\",\"importe\":100}]}}," + + "{\"type\":\"custom\",\"data\":\"\"}," + + "{\"type\":\"carta_porte\",\"data\":{\"IdCCP\":\"CPC2026040700001\",\"TranspInternac\":\"No\",\"TotalDistRec\":15.4,\"Ubicaciones\":[],\"Mercancias\":{\"Mercancia\":[]}}}," + + "{\"type\":\"comercio_exterior\",\"data\":{\"Version\":\"2.0\",\"ClaveDePedimento\":\"A1\",\"CertificadoOrigen\":0,\"TipoCambioUSD\":16.9,\"TotalUSD\":100.5,\"Emisor\":true,\"Propietario\":[{\"id\":\"cus_owner_1\"}],\"Receptor\":{\"NumRegIdTrib\":\"EXT12345\"},\"Destinatario\":[{\"Nombre\":\"Receiver Inc\",\"Domicilio\":[{\"Calle\":\"Main\",\"Estado\":\"TX\",\"Pais\":\"USA\",\"CodigoPostal\":\"77001\"}]}],\"Mercancias\":{\"Mercancia\":[{\"NoIdentificacion\":\"SKU-1\",\"ValorDolares\":100.5}]}}}" + + "]}" + ); + + Facturapi sdk = new Facturapi( + FacturapiConfig.builder("sk_test") + .httpClient(httpClient) + .build() + ); + + var invoice = sdk.invoices.retrieve("inv_1"); + assertEquals(5, invoice.getComplements().size()); + + var pago = invoice.getComplements().get(0); + assertEquals("pago", pago.getType()); + assertNotNull(pago.getPagoData()); + assertEquals(1, pago.getPagoData().size()); + assertEquals("03", pago.getPagoData().get(0).getPaymentForm()); + assertEquals("f03d5c3f-a93b-443f-927f-e89db2f7f58a", pago.getPagoData().get(0).getRelatedDocuments().get(0).getUuid()); + assertInstanceOf(java.util.List.class, pago.getData()); + + var nomina = invoice.getComplements().get(1); + assertEquals("nomina", nomina.getType()); + assertNotNull(nomina.getNominaData()); + assertEquals("O", nomina.getNominaData().getTipoNomina()); + assertEquals("EMP-1", nomina.getNominaData().getReceptor().getNumEmpleado()); + assertEquals("001", nomina.getNominaData().getPercepciones().getPercepcion().get(0).getTipoPercepcion()); + + var custom = invoice.getComplements().get(2); + assertEquals("custom", custom.getType()); + assertNotNull(custom.getCustomData()); + assertEquals("", custom.getCustomData()); + assertInstanceOf(String.class, custom.getData()); + + var cartaPorte = invoice.getComplements().get(3); + assertEquals("carta_porte", cartaPorte.getType()); + assertNotNull(cartaPorte.getCartaPorteData()); + assertEquals("CPC2026040700001", cartaPorte.getCartaPorteData().getIdCcp()); + assertEquals("No", cartaPorte.getCartaPorteData().getTranspInternac()); + assertNotNull(cartaPorte.getCartaPorteData().getMercancias()); + assertEquals(0, cartaPorte.getCartaPorteData().getMercancias().getMercancia().size()); + + var comercioExterior = invoice.getComplements().get(4); + assertEquals("comercio_exterior", comercioExterior.getType()); + assertNotNull(comercioExterior.getComercioExteriorData()); + assertEquals("A1", comercioExterior.getComercioExteriorData().getClaveDePedimento()); + assertEquals(100.5, comercioExterior.getComercioExteriorData().getTotalUsd(), 0.0001); + assertEquals(Boolean.TRUE, comercioExterior.getComercioExteriorData().getEmisorFromOrganization()); + assertEquals("cus_owner_1", comercioExterior.getComercioExteriorData().getPropietario().get(0).getId()); + assertEquals("SKU-1", comercioExterior.getComercioExteriorData().getMercancias().getMercancia().get(0).getNoIdentificacion()); + } +} diff --git a/src/test/java/io/facturapi/StubHttpClient.java b/src/test/java/io/facturapi/StubHttpClient.java new file mode 100644 index 0000000..ce65d17 --- /dev/null +++ b/src/test/java/io/facturapi/StubHttpClient.java @@ -0,0 +1,191 @@ +package io.facturapi; + +import java.io.IOException; +import java.net.Authenticator; +import java.net.CookieHandler; +import java.net.ProxySelector; +import java.net.URI; +import java.net.http.HttpClient; +import java.net.http.HttpHeaders; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.time.Duration; +import java.util.ArrayDeque; +import java.util.ArrayList; +import java.util.Deque; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.Executor; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLParameters; +import javax.net.ssl.SSLSession; + +final class StubHttpClient extends HttpClient { + static final class QueuedResponse { + final int statusCode; + final byte[] body; + final Map> headers; + + QueuedResponse(int statusCode, byte[] body, Map> headers) { + this.statusCode = statusCode; + this.body = body; + this.headers = headers; + } + } + + private final Deque queue = new ArrayDeque<>(); + private final List requests = new ArrayList<>(); + + void enqueueJson(int statusCode, String json) { + queue.add(new QueuedResponse(statusCode, json.getBytes(), Map.of("Content-Type", List.of("application/json")))); + } + + void enqueueBinary(int statusCode, byte[] bytes, String contentType) { + queue.add(new QueuedResponse(statusCode, bytes, Map.of("Content-Type", List.of(contentType)))); + } + + List requests() { + return requests; + } + + @Override + public Optional cookieHandler() { + return Optional.empty(); + } + + @Override + public Optional connectTimeout() { + return Optional.empty(); + } + + @Override + public Redirect followRedirects() { + return Redirect.NEVER; + } + + @Override + public Optional proxy() { + return Optional.empty(); + } + + @Override + public SSLContext sslContext() { + try { + return SSLContext.getDefault(); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + @Override + public SSLParameters sslParameters() { + return new SSLParameters(); + } + + @Override + public Optional authenticator() { + return Optional.empty(); + } + + @Override + public Version version() { + return Version.HTTP_1_1; + } + + @Override + public Optional executor() { + return Optional.empty(); + } + + @Override + public HttpResponse send(HttpRequest request, HttpResponse.BodyHandler responseBodyHandler) + throws IOException, InterruptedException { + requests.add(request); + QueuedResponse queued = queue.poll(); + if (queued == null) { + throw new IOException("No queued response"); + } + @SuppressWarnings("unchecked") + T body = (T) queued.body; + return new StubHttpResponse<>(request, queued.statusCode, body, queued.headers); + } + + @Override + public CompletableFuture> sendAsync( + HttpRequest request, + HttpResponse.BodyHandler responseBodyHandler + ) { + try { + return CompletableFuture.completedFuture(send(request, responseBodyHandler)); + } catch (IOException | InterruptedException e) { + CompletableFuture> future = new CompletableFuture<>(); + future.completeExceptionally(e); + return future; + } + } + + @Override + public CompletableFuture> sendAsync( + HttpRequest request, + HttpResponse.BodyHandler responseBodyHandler, + HttpResponse.PushPromiseHandler pushPromiseHandler + ) { + return sendAsync(request, responseBodyHandler); + } + + private static final class StubHttpResponse implements HttpResponse { + private final HttpRequest request; + private final int statusCode; + private final T body; + private final HttpHeaders headers; + + StubHttpResponse(HttpRequest request, int statusCode, T body, Map> headers) { + this.request = request; + this.statusCode = statusCode; + this.body = body; + this.headers = HttpHeaders.of(headers, (k, v) -> true); + } + + @Override + public int statusCode() { + return statusCode; + } + + @Override + public HttpRequest request() { + return request; + } + + @Override + public Optional> previousResponse() { + return Optional.empty(); + } + + @Override + public HttpHeaders headers() { + return headers; + } + + @Override + public T body() { + return body; + } + + @Override + public Optional sslSession() { + return Optional.empty(); + } + + @Override + public URI uri() { + return request.uri(); + } + + @Override + public Version version() { + return Version.HTTP_1_1; + } + } +} diff --git a/src/test/java/com/facturapi/WebhooksResourceTest.java b/src/test/java/io/facturapi/WebhooksResourceTest.java similarity index 82% rename from src/test/java/com/facturapi/WebhooksResourceTest.java rename to src/test/java/io/facturapi/WebhooksResourceTest.java index f658fa3..025f832 100644 --- a/src/test/java/com/facturapi/WebhooksResourceTest.java +++ b/src/test/java/io/facturapi/WebhooksResourceTest.java @@ -1,11 +1,11 @@ -package com.facturapi; +package io.facturapi; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; -import com.facturapi.http.FacturapiConfig; -import com.facturapi.http.FacturapiHttpClient; -import com.facturapi.resources.WebhooksResource; +import io.facturapi.http.FacturapiConfig; +import io.facturapi.http.FacturapiHttpClient; +import io.facturapi.resources.WebhooksResource; import java.nio.charset.StandardCharsets; import javax.crypto.Mac; import javax.crypto.spec.SecretKeySpec; @@ -15,7 +15,7 @@ class WebhooksResourceTest { @Test void validatesWebhookSignature() throws Exception { WebhooksResource webhooks = new WebhooksResource( - new FacturapiHttpClient(FacturapiConfig.builder("sk_test").baseUrl("https://example.com").build()) + new FacturapiHttpClient(FacturapiConfig.builder("sk_test").build()) ); String payload = "{\"type\":\"invoice.created\"}"; @@ -23,13 +23,13 @@ void validatesWebhookSignature() throws Exception { String signature = hmacHex(secret, payload); var event = webhooks.validateSignature(secret, signature, payload); - assertEquals("invoice.created", event.get("type").asText()); + assertEquals("invoice.created", event.getType()); } @Test void rejectsInvalidWebhookSignature() { WebhooksResource webhooks = new WebhooksResource( - new FacturapiHttpClient(FacturapiConfig.builder("sk_test").baseUrl("https://example.com").build()) + new FacturapiHttpClient(FacturapiConfig.builder("sk_test").build()) ); assertThrows( From 8f4498e4c3b4df73075150c9031e5eaac0d17d79 Mon Sep 17 00:00:00 2001 From: javorosas Date: Tue, 7 Apr 2026 11:25:28 +0200 Subject: [PATCH 02/22] refactor: group complement models into dedicated folders --- src/main/java/io/facturapi/models/Invoice.java | 1 + .../models/{ => complements}/InvoiceComplement.java | 6 +++++- .../carta_porte}/CartaPorteAutotransporte.java | 2 +- .../carta_porte}/CartaPorteCantidadTransporta.java | 2 +- .../carta_porte}/CartaPorteCarroFerroviario.java | 2 +- .../carta_porte}/CartaPorteComplementData.java | 2 +- .../carta_porte}/CartaPorteContenedorFerroviario.java | 2 +- .../carta_porte}/CartaPorteContenedorMaritimo.java | 2 +- .../carta_porte}/CartaPorteDerechosDePaso.java | 2 +- .../carta_porte}/CartaPorteDetalleMercancia.java | 2 +- .../carta_porte}/CartaPorteDocumentacionAduanera.java | 2 +- .../{ => complements/carta_porte}/CartaPorteDomicilio.java | 2 +- .../carta_porte}/CartaPorteFiguraTransporte.java | 2 +- .../carta_porte}/CartaPorteGuiaIdentificacion.java | 2 +- .../carta_porte}/CartaPorteIdentificacionVehicular.java | 2 +- .../{ => complements/carta_porte}/CartaPorteMercancia.java | 2 +- .../{ => complements/carta_porte}/CartaPorteMercancias.java | 2 +- .../carta_porte}/CartaPorteParteTransporte.java | 2 +- .../{ => complements/carta_porte}/CartaPorteRemolque.java | 2 +- .../carta_porte}/CartaPorteRemolqueCcp.java | 2 +- .../{ => complements/carta_porte}/CartaPorteSeguros.java | 2 +- .../carta_porte}/CartaPorteTransporteAereo.java | 2 +- .../carta_porte}/CartaPorteTransporteFerroviario.java | 2 +- .../carta_porte}/CartaPorteTransporteMaritimo.java | 2 +- .../{ => complements/carta_porte}/CartaPorteUbicacion.java | 2 +- .../comercio_exterior}/ComercioExteriorComplementData.java | 2 +- .../ComercioExteriorDescripcionesEspecificas.java | 2 +- .../comercio_exterior}/ComercioExteriorDestinatarioRef.java | 2 +- .../comercio_exterior}/ComercioExteriorDomicilio.java | 2 +- .../comercio_exterior}/ComercioExteriorEmisor.java | 2 +- .../comercio_exterior}/ComercioExteriorMercancia.java | 2 +- .../comercio_exterior}/ComercioExteriorMercancias.java | 2 +- .../comercio_exterior}/ComercioExteriorPartyRef.java | 2 +- .../comercio_exterior}/ComercioExteriorReceptorRef.java | 2 +- .../models/{ => complements/nomina}/NominaAcciones.java | 2 +- .../models/{ => complements/nomina}/NominaCompensacion.java | 2 +- .../{ => complements/nomina}/NominaComplementData.java | 2 +- .../models/{ => complements/nomina}/NominaDeduccion.java | 2 +- .../models/{ => complements/nomina}/NominaEmisor.java | 2 +- .../models/{ => complements/nomina}/NominaEntidadSncf.java | 2 +- .../models/{ => complements/nomina}/NominaHorasExtra.java | 2 +- .../models/{ => complements/nomina}/NominaIncapacidad.java | 2 +- .../models/{ => complements/nomina}/NominaJubilacion.java | 2 +- .../models/{ => complements/nomina}/NominaOtroPago.java | 2 +- .../models/{ => complements/nomina}/NominaPercepcion.java | 2 +- .../models/{ => complements/nomina}/NominaPercepciones.java | 2 +- .../models/{ => complements/nomina}/NominaReceptor.java | 2 +- .../models/{ => complements/nomina}/NominaSeparacion.java | 2 +- .../{ => complements/nomina}/NominaSubcontratacion.java | 2 +- .../models/{ => complements/pago}/PagoComplementData.java | 2 +- .../{ => complements/pago}/PaymentRelatedDocument.java | 2 +- .../{ => complements/pago}/PaymentRelatedDocumentTax.java | 2 +- 52 files changed, 56 insertions(+), 51 deletions(-) rename src/main/java/io/facturapi/models/{ => complements}/InvoiceComplement.java (92%) rename src/main/java/io/facturapi/models/{ => complements/carta_porte}/CartaPorteAutotransporte.java (96%) rename src/main/java/io/facturapi/models/{ => complements/carta_porte}/CartaPorteCantidadTransporta.java (94%) rename src/main/java/io/facturapi/models/{ => complements/carta_porte}/CartaPorteCarroFerroviario.java (96%) rename src/main/java/io/facturapi/models/{ => complements/carta_porte}/CartaPorteComplementData.java (98%) rename src/main/java/io/facturapi/models/{ => complements/carta_porte}/CartaPorteContenedorFerroviario.java (94%) rename src/main/java/io/facturapi/models/{ => complements/carta_porte}/CartaPorteContenedorMaritimo.java (97%) rename src/main/java/io/facturapi/models/{ => complements/carta_porte}/CartaPorteDerechosDePaso.java (93%) rename src/main/java/io/facturapi/models/{ => complements/carta_porte}/CartaPorteDetalleMercancia.java (95%) rename src/main/java/io/facturapi/models/{ => complements/carta_porte}/CartaPorteDocumentacionAduanera.java (95%) rename src/main/java/io/facturapi/models/{ => complements/carta_porte}/CartaPorteDomicilio.java (97%) rename src/main/java/io/facturapi/models/{ => complements/carta_porte}/CartaPorteFiguraTransporte.java (97%) rename src/main/java/io/facturapi/models/{ => complements/carta_porte}/CartaPorteGuiaIdentificacion.java (95%) rename src/main/java/io/facturapi/models/{ => complements/carta_porte}/CartaPorteIdentificacionVehicular.java (95%) rename src/main/java/io/facturapi/models/{ => complements/carta_porte}/CartaPorteMercancia.java (99%) rename src/main/java/io/facturapi/models/{ => complements/carta_porte}/CartaPorteMercancias.java (98%) rename src/main/java/io/facturapi/models/{ => complements/carta_porte}/CartaPorteParteTransporte.java (89%) rename src/main/java/io/facturapi/models/{ => complements/carta_porte}/CartaPorteRemolque.java (91%) rename src/main/java/io/facturapi/models/{ => complements/carta_porte}/CartaPorteRemolqueCcp.java (91%) rename src/main/java/io/facturapi/models/{ => complements/carta_porte}/CartaPorteSeguros.java (97%) rename src/main/java/io/facturapi/models/{ => complements/carta_porte}/CartaPorteTransporteAereo.java (98%) rename src/main/java/io/facturapi/models/{ => complements/carta_porte}/CartaPorteTransporteFerroviario.java (96%) rename src/main/java/io/facturapi/models/{ => complements/carta_porte}/CartaPorteTransporteMaritimo.java (98%) rename src/main/java/io/facturapi/models/{ => complements/carta_porte}/CartaPorteUbicacion.java (98%) rename src/main/java/io/facturapi/models/{ => complements/comercio_exterior}/ComercioExteriorComplementData.java (98%) rename src/main/java/io/facturapi/models/{ => complements/comercio_exterior}/ComercioExteriorDescripcionesEspecificas.java (94%) rename src/main/java/io/facturapi/models/{ => complements/comercio_exterior}/ComercioExteriorDestinatarioRef.java (94%) rename src/main/java/io/facturapi/models/{ => complements/comercio_exterior}/ComercioExteriorDomicilio.java (97%) rename src/main/java/io/facturapi/models/{ => complements/comercio_exterior}/ComercioExteriorEmisor.java (90%) rename src/main/java/io/facturapi/models/{ => complements/comercio_exterior}/ComercioExteriorMercancia.java (97%) rename src/main/java/io/facturapi/models/{ => complements/comercio_exterior}/ComercioExteriorMercancias.java (90%) rename src/main/java/io/facturapi/models/{ => complements/comercio_exterior}/ComercioExteriorPartyRef.java (92%) rename src/main/java/io/facturapi/models/{ => complements/comercio_exterior}/ComercioExteriorReceptorRef.java (92%) rename src/main/java/io/facturapi/models/{ => complements/nomina}/NominaAcciones.java (93%) rename src/main/java/io/facturapi/models/{ => complements/nomina}/NominaCompensacion.java (94%) rename src/main/java/io/facturapi/models/{ => complements/nomina}/NominaComplementData.java (98%) rename src/main/java/io/facturapi/models/{ => complements/nomina}/NominaDeduccion.java (94%) rename src/main/java/io/facturapi/models/{ => complements/nomina}/NominaEmisor.java (95%) rename src/main/java/io/facturapi/models/{ => complements/nomina}/NominaEntidadSncf.java (93%) rename src/main/java/io/facturapi/models/{ => complements/nomina}/NominaHorasExtra.java (95%) rename src/main/java/io/facturapi/models/{ => complements/nomina}/NominaIncapacidad.java (95%) rename src/main/java/io/facturapi/models/{ => complements/nomina}/NominaJubilacion.java (96%) rename src/main/java/io/facturapi/models/{ => complements/nomina}/NominaOtroPago.java (96%) rename src/main/java/io/facturapi/models/{ => complements/nomina}/NominaPercepcion.java (97%) rename src/main/java/io/facturapi/models/{ => complements/nomina}/NominaPercepciones.java (96%) rename src/main/java/io/facturapi/models/{ => complements/nomina}/NominaReceptor.java (98%) rename src/main/java/io/facturapi/models/{ => complements/nomina}/NominaSeparacion.java (96%) rename src/main/java/io/facturapi/models/{ => complements/nomina}/NominaSubcontratacion.java (92%) rename src/main/java/io/facturapi/models/{ => complements/pago}/PagoComplementData.java (98%) rename src/main/java/io/facturapi/models/{ => complements/pago}/PaymentRelatedDocument.java (97%) rename src/main/java/io/facturapi/models/{ => complements/pago}/PaymentRelatedDocumentTax.java (94%) diff --git a/src/main/java/io/facturapi/models/Invoice.java b/src/main/java/io/facturapi/models/Invoice.java index 94f060d..5332906 100644 --- a/src/main/java/io/facturapi/models/Invoice.java +++ b/src/main/java/io/facturapi/models/Invoice.java @@ -4,6 +4,7 @@ import com.fasterxml.jackson.annotation.JsonProperty; import java.util.ArrayList; import java.util.List; +import io.facturapi.models.complements.InvoiceComplement; @JsonIgnoreProperties(ignoreUnknown = true) public class Invoice { diff --git a/src/main/java/io/facturapi/models/InvoiceComplement.java b/src/main/java/io/facturapi/models/complements/InvoiceComplement.java similarity index 92% rename from src/main/java/io/facturapi/models/InvoiceComplement.java rename to src/main/java/io/facturapi/models/complements/InvoiceComplement.java index 0b5ed10..ec80c8d 100644 --- a/src/main/java/io/facturapi/models/InvoiceComplement.java +++ b/src/main/java/io/facturapi/models/complements/InvoiceComplement.java @@ -1,4 +1,4 @@ -package io.facturapi.models; +package io.facturapi.models.complements; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; @@ -8,6 +8,10 @@ import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; +import io.facturapi.models.complements.carta_porte.CartaPorteComplementData; +import io.facturapi.models.complements.comercio_exterior.ComercioExteriorComplementData; +import io.facturapi.models.complements.nomina.NominaComplementData; +import io.facturapi.models.complements.pago.PagoComplementData; import java.util.List; @JsonIgnoreProperties(ignoreUnknown = true) diff --git a/src/main/java/io/facturapi/models/CartaPorteAutotransporte.java b/src/main/java/io/facturapi/models/complements/carta_porte/CartaPorteAutotransporte.java similarity index 96% rename from src/main/java/io/facturapi/models/CartaPorteAutotransporte.java rename to src/main/java/io/facturapi/models/complements/carta_porte/CartaPorteAutotransporte.java index 01dd907..7bbe218 100644 --- a/src/main/java/io/facturapi/models/CartaPorteAutotransporte.java +++ b/src/main/java/io/facturapi/models/complements/carta_porte/CartaPorteAutotransporte.java @@ -1,4 +1,4 @@ -package io.facturapi.models; +package io.facturapi.models.complements.carta_porte; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; diff --git a/src/main/java/io/facturapi/models/CartaPorteCantidadTransporta.java b/src/main/java/io/facturapi/models/complements/carta_porte/CartaPorteCantidadTransporta.java similarity index 94% rename from src/main/java/io/facturapi/models/CartaPorteCantidadTransporta.java rename to src/main/java/io/facturapi/models/complements/carta_porte/CartaPorteCantidadTransporta.java index 7bf5ec4..155fb36 100644 --- a/src/main/java/io/facturapi/models/CartaPorteCantidadTransporta.java +++ b/src/main/java/io/facturapi/models/complements/carta_porte/CartaPorteCantidadTransporta.java @@ -1,4 +1,4 @@ -package io.facturapi.models; +package io.facturapi.models.complements.carta_porte; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; diff --git a/src/main/java/io/facturapi/models/CartaPorteCarroFerroviario.java b/src/main/java/io/facturapi/models/complements/carta_porte/CartaPorteCarroFerroviario.java similarity index 96% rename from src/main/java/io/facturapi/models/CartaPorteCarroFerroviario.java rename to src/main/java/io/facturapi/models/complements/carta_porte/CartaPorteCarroFerroviario.java index 38a98ee..55ec2ae 100644 --- a/src/main/java/io/facturapi/models/CartaPorteCarroFerroviario.java +++ b/src/main/java/io/facturapi/models/complements/carta_porte/CartaPorteCarroFerroviario.java @@ -1,4 +1,4 @@ -package io.facturapi.models; +package io.facturapi.models.complements.carta_porte; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; diff --git a/src/main/java/io/facturapi/models/CartaPorteComplementData.java b/src/main/java/io/facturapi/models/complements/carta_porte/CartaPorteComplementData.java similarity index 98% rename from src/main/java/io/facturapi/models/CartaPorteComplementData.java rename to src/main/java/io/facturapi/models/complements/carta_porte/CartaPorteComplementData.java index 3d20323..f210991 100644 --- a/src/main/java/io/facturapi/models/CartaPorteComplementData.java +++ b/src/main/java/io/facturapi/models/complements/carta_porte/CartaPorteComplementData.java @@ -1,4 +1,4 @@ -package io.facturapi.models; +package io.facturapi.models.complements.carta_porte; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; diff --git a/src/main/java/io/facturapi/models/CartaPorteContenedorFerroviario.java b/src/main/java/io/facturapi/models/complements/carta_porte/CartaPorteContenedorFerroviario.java similarity index 94% rename from src/main/java/io/facturapi/models/CartaPorteContenedorFerroviario.java rename to src/main/java/io/facturapi/models/complements/carta_porte/CartaPorteContenedorFerroviario.java index af2e6b8..247b384 100644 --- a/src/main/java/io/facturapi/models/CartaPorteContenedorFerroviario.java +++ b/src/main/java/io/facturapi/models/complements/carta_porte/CartaPorteContenedorFerroviario.java @@ -1,4 +1,4 @@ -package io.facturapi.models; +package io.facturapi.models.complements.carta_porte; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; diff --git a/src/main/java/io/facturapi/models/CartaPorteContenedorMaritimo.java b/src/main/java/io/facturapi/models/complements/carta_porte/CartaPorteContenedorMaritimo.java similarity index 97% rename from src/main/java/io/facturapi/models/CartaPorteContenedorMaritimo.java rename to src/main/java/io/facturapi/models/complements/carta_porte/CartaPorteContenedorMaritimo.java index 21f306f..90bbaa2 100644 --- a/src/main/java/io/facturapi/models/CartaPorteContenedorMaritimo.java +++ b/src/main/java/io/facturapi/models/complements/carta_porte/CartaPorteContenedorMaritimo.java @@ -1,4 +1,4 @@ -package io.facturapi.models; +package io.facturapi.models.complements.carta_porte; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; diff --git a/src/main/java/io/facturapi/models/CartaPorteDerechosDePaso.java b/src/main/java/io/facturapi/models/complements/carta_porte/CartaPorteDerechosDePaso.java similarity index 93% rename from src/main/java/io/facturapi/models/CartaPorteDerechosDePaso.java rename to src/main/java/io/facturapi/models/complements/carta_porte/CartaPorteDerechosDePaso.java index a35c287..66f64e5 100644 --- a/src/main/java/io/facturapi/models/CartaPorteDerechosDePaso.java +++ b/src/main/java/io/facturapi/models/complements/carta_porte/CartaPorteDerechosDePaso.java @@ -1,4 +1,4 @@ -package io.facturapi.models; +package io.facturapi.models.complements.carta_porte; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; diff --git a/src/main/java/io/facturapi/models/CartaPorteDetalleMercancia.java b/src/main/java/io/facturapi/models/complements/carta_porte/CartaPorteDetalleMercancia.java similarity index 95% rename from src/main/java/io/facturapi/models/CartaPorteDetalleMercancia.java rename to src/main/java/io/facturapi/models/complements/carta_porte/CartaPorteDetalleMercancia.java index 538eac2..d5854dc 100644 --- a/src/main/java/io/facturapi/models/CartaPorteDetalleMercancia.java +++ b/src/main/java/io/facturapi/models/complements/carta_porte/CartaPorteDetalleMercancia.java @@ -1,4 +1,4 @@ -package io.facturapi.models; +package io.facturapi.models.complements.carta_porte; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; diff --git a/src/main/java/io/facturapi/models/CartaPorteDocumentacionAduanera.java b/src/main/java/io/facturapi/models/complements/carta_porte/CartaPorteDocumentacionAduanera.java similarity index 95% rename from src/main/java/io/facturapi/models/CartaPorteDocumentacionAduanera.java rename to src/main/java/io/facturapi/models/complements/carta_porte/CartaPorteDocumentacionAduanera.java index 312bec9..677878f 100644 --- a/src/main/java/io/facturapi/models/CartaPorteDocumentacionAduanera.java +++ b/src/main/java/io/facturapi/models/complements/carta_porte/CartaPorteDocumentacionAduanera.java @@ -1,4 +1,4 @@ -package io.facturapi.models; +package io.facturapi.models.complements.carta_porte; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; diff --git a/src/main/java/io/facturapi/models/CartaPorteDomicilio.java b/src/main/java/io/facturapi/models/complements/carta_porte/CartaPorteDomicilio.java similarity index 97% rename from src/main/java/io/facturapi/models/CartaPorteDomicilio.java rename to src/main/java/io/facturapi/models/complements/carta_porte/CartaPorteDomicilio.java index ba8c0fb..3eda958 100644 --- a/src/main/java/io/facturapi/models/CartaPorteDomicilio.java +++ b/src/main/java/io/facturapi/models/complements/carta_porte/CartaPorteDomicilio.java @@ -1,4 +1,4 @@ -package io.facturapi.models; +package io.facturapi.models.complements.carta_porte; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; diff --git a/src/main/java/io/facturapi/models/CartaPorteFiguraTransporte.java b/src/main/java/io/facturapi/models/complements/carta_porte/CartaPorteFiguraTransporte.java similarity index 97% rename from src/main/java/io/facturapi/models/CartaPorteFiguraTransporte.java rename to src/main/java/io/facturapi/models/complements/carta_porte/CartaPorteFiguraTransporte.java index d6ae821..f2f57cd 100644 --- a/src/main/java/io/facturapi/models/CartaPorteFiguraTransporte.java +++ b/src/main/java/io/facturapi/models/complements/carta_porte/CartaPorteFiguraTransporte.java @@ -1,4 +1,4 @@ -package io.facturapi.models; +package io.facturapi.models.complements.carta_porte; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; diff --git a/src/main/java/io/facturapi/models/CartaPorteGuiaIdentificacion.java b/src/main/java/io/facturapi/models/complements/carta_porte/CartaPorteGuiaIdentificacion.java similarity index 95% rename from src/main/java/io/facturapi/models/CartaPorteGuiaIdentificacion.java rename to src/main/java/io/facturapi/models/complements/carta_porte/CartaPorteGuiaIdentificacion.java index 8560435..41f4b84 100644 --- a/src/main/java/io/facturapi/models/CartaPorteGuiaIdentificacion.java +++ b/src/main/java/io/facturapi/models/complements/carta_porte/CartaPorteGuiaIdentificacion.java @@ -1,4 +1,4 @@ -package io.facturapi.models; +package io.facturapi.models.complements.carta_porte; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; diff --git a/src/main/java/io/facturapi/models/CartaPorteIdentificacionVehicular.java b/src/main/java/io/facturapi/models/complements/carta_porte/CartaPorteIdentificacionVehicular.java similarity index 95% rename from src/main/java/io/facturapi/models/CartaPorteIdentificacionVehicular.java rename to src/main/java/io/facturapi/models/complements/carta_porte/CartaPorteIdentificacionVehicular.java index 4e4e8fd..d63c2a0 100644 --- a/src/main/java/io/facturapi/models/CartaPorteIdentificacionVehicular.java +++ b/src/main/java/io/facturapi/models/complements/carta_porte/CartaPorteIdentificacionVehicular.java @@ -1,4 +1,4 @@ -package io.facturapi.models; +package io.facturapi.models.complements.carta_porte; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; diff --git a/src/main/java/io/facturapi/models/CartaPorteMercancia.java b/src/main/java/io/facturapi/models/complements/carta_porte/CartaPorteMercancia.java similarity index 99% rename from src/main/java/io/facturapi/models/CartaPorteMercancia.java rename to src/main/java/io/facturapi/models/complements/carta_porte/CartaPorteMercancia.java index 1bda357..a57146d 100644 --- a/src/main/java/io/facturapi/models/CartaPorteMercancia.java +++ b/src/main/java/io/facturapi/models/complements/carta_porte/CartaPorteMercancia.java @@ -1,4 +1,4 @@ -package io.facturapi.models; +package io.facturapi.models.complements.carta_porte; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; diff --git a/src/main/java/io/facturapi/models/CartaPorteMercancias.java b/src/main/java/io/facturapi/models/complements/carta_porte/CartaPorteMercancias.java similarity index 98% rename from src/main/java/io/facturapi/models/CartaPorteMercancias.java rename to src/main/java/io/facturapi/models/complements/carta_porte/CartaPorteMercancias.java index 535776e..52e8edd 100644 --- a/src/main/java/io/facturapi/models/CartaPorteMercancias.java +++ b/src/main/java/io/facturapi/models/complements/carta_porte/CartaPorteMercancias.java @@ -1,4 +1,4 @@ -package io.facturapi.models; +package io.facturapi.models.complements.carta_porte; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; diff --git a/src/main/java/io/facturapi/models/CartaPorteParteTransporte.java b/src/main/java/io/facturapi/models/complements/carta_porte/CartaPorteParteTransporte.java similarity index 89% rename from src/main/java/io/facturapi/models/CartaPorteParteTransporte.java rename to src/main/java/io/facturapi/models/complements/carta_porte/CartaPorteParteTransporte.java index a22d03e..e8cd4a9 100644 --- a/src/main/java/io/facturapi/models/CartaPorteParteTransporte.java +++ b/src/main/java/io/facturapi/models/complements/carta_porte/CartaPorteParteTransporte.java @@ -1,4 +1,4 @@ -package io.facturapi.models; +package io.facturapi.models.complements.carta_porte; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; diff --git a/src/main/java/io/facturapi/models/CartaPorteRemolque.java b/src/main/java/io/facturapi/models/complements/carta_porte/CartaPorteRemolque.java similarity index 91% rename from src/main/java/io/facturapi/models/CartaPorteRemolque.java rename to src/main/java/io/facturapi/models/complements/carta_porte/CartaPorteRemolque.java index 9eed617..3808bd9 100644 --- a/src/main/java/io/facturapi/models/CartaPorteRemolque.java +++ b/src/main/java/io/facturapi/models/complements/carta_porte/CartaPorteRemolque.java @@ -1,4 +1,4 @@ -package io.facturapi.models; +package io.facturapi.models.complements.carta_porte; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; diff --git a/src/main/java/io/facturapi/models/CartaPorteRemolqueCcp.java b/src/main/java/io/facturapi/models/complements/carta_porte/CartaPorteRemolqueCcp.java similarity index 91% rename from src/main/java/io/facturapi/models/CartaPorteRemolqueCcp.java rename to src/main/java/io/facturapi/models/complements/carta_porte/CartaPorteRemolqueCcp.java index bbeaac7..1d4edc6 100644 --- a/src/main/java/io/facturapi/models/CartaPorteRemolqueCcp.java +++ b/src/main/java/io/facturapi/models/complements/carta_porte/CartaPorteRemolqueCcp.java @@ -1,4 +1,4 @@ -package io.facturapi.models; +package io.facturapi.models.complements.carta_porte; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; diff --git a/src/main/java/io/facturapi/models/CartaPorteSeguros.java b/src/main/java/io/facturapi/models/complements/carta_porte/CartaPorteSeguros.java similarity index 97% rename from src/main/java/io/facturapi/models/CartaPorteSeguros.java rename to src/main/java/io/facturapi/models/complements/carta_porte/CartaPorteSeguros.java index e2f29a8..300229d 100644 --- a/src/main/java/io/facturapi/models/CartaPorteSeguros.java +++ b/src/main/java/io/facturapi/models/complements/carta_porte/CartaPorteSeguros.java @@ -1,4 +1,4 @@ -package io.facturapi.models; +package io.facturapi.models.complements.carta_porte; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; diff --git a/src/main/java/io/facturapi/models/CartaPorteTransporteAereo.java b/src/main/java/io/facturapi/models/complements/carta_porte/CartaPorteTransporteAereo.java similarity index 98% rename from src/main/java/io/facturapi/models/CartaPorteTransporteAereo.java rename to src/main/java/io/facturapi/models/complements/carta_porte/CartaPorteTransporteAereo.java index 33cebf7..0a9652e 100644 --- a/src/main/java/io/facturapi/models/CartaPorteTransporteAereo.java +++ b/src/main/java/io/facturapi/models/complements/carta_porte/CartaPorteTransporteAereo.java @@ -1,4 +1,4 @@ -package io.facturapi.models; +package io.facturapi.models.complements.carta_porte; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; diff --git a/src/main/java/io/facturapi/models/CartaPorteTransporteFerroviario.java b/src/main/java/io/facturapi/models/complements/carta_porte/CartaPorteTransporteFerroviario.java similarity index 96% rename from src/main/java/io/facturapi/models/CartaPorteTransporteFerroviario.java rename to src/main/java/io/facturapi/models/complements/carta_porte/CartaPorteTransporteFerroviario.java index 4fe6c7b..c18af94 100644 --- a/src/main/java/io/facturapi/models/CartaPorteTransporteFerroviario.java +++ b/src/main/java/io/facturapi/models/complements/carta_porte/CartaPorteTransporteFerroviario.java @@ -1,4 +1,4 @@ -package io.facturapi.models; +package io.facturapi.models.complements.carta_porte; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; diff --git a/src/main/java/io/facturapi/models/CartaPorteTransporteMaritimo.java b/src/main/java/io/facturapi/models/complements/carta_porte/CartaPorteTransporteMaritimo.java similarity index 98% rename from src/main/java/io/facturapi/models/CartaPorteTransporteMaritimo.java rename to src/main/java/io/facturapi/models/complements/carta_porte/CartaPorteTransporteMaritimo.java index 3ab59cb..7b19239 100644 --- a/src/main/java/io/facturapi/models/CartaPorteTransporteMaritimo.java +++ b/src/main/java/io/facturapi/models/complements/carta_porte/CartaPorteTransporteMaritimo.java @@ -1,4 +1,4 @@ -package io.facturapi.models; +package io.facturapi.models.complements.carta_porte; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; diff --git a/src/main/java/io/facturapi/models/CartaPorteUbicacion.java b/src/main/java/io/facturapi/models/complements/carta_porte/CartaPorteUbicacion.java similarity index 98% rename from src/main/java/io/facturapi/models/CartaPorteUbicacion.java rename to src/main/java/io/facturapi/models/complements/carta_porte/CartaPorteUbicacion.java index 72c5a83..d6cc039 100644 --- a/src/main/java/io/facturapi/models/CartaPorteUbicacion.java +++ b/src/main/java/io/facturapi/models/complements/carta_porte/CartaPorteUbicacion.java @@ -1,4 +1,4 @@ -package io.facturapi.models; +package io.facturapi.models.complements.carta_porte; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; diff --git a/src/main/java/io/facturapi/models/ComercioExteriorComplementData.java b/src/main/java/io/facturapi/models/complements/comercio_exterior/ComercioExteriorComplementData.java similarity index 98% rename from src/main/java/io/facturapi/models/ComercioExteriorComplementData.java rename to src/main/java/io/facturapi/models/complements/comercio_exterior/ComercioExteriorComplementData.java index b59839a..5535f5e 100644 --- a/src/main/java/io/facturapi/models/ComercioExteriorComplementData.java +++ b/src/main/java/io/facturapi/models/complements/comercio_exterior/ComercioExteriorComplementData.java @@ -1,4 +1,4 @@ -package io.facturapi.models; +package io.facturapi.models.complements.comercio_exterior; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; diff --git a/src/main/java/io/facturapi/models/ComercioExteriorDescripcionesEspecificas.java b/src/main/java/io/facturapi/models/complements/comercio_exterior/ComercioExteriorDescripcionesEspecificas.java similarity index 94% rename from src/main/java/io/facturapi/models/ComercioExteriorDescripcionesEspecificas.java rename to src/main/java/io/facturapi/models/complements/comercio_exterior/ComercioExteriorDescripcionesEspecificas.java index 5525e0a..7344d39 100644 --- a/src/main/java/io/facturapi/models/ComercioExteriorDescripcionesEspecificas.java +++ b/src/main/java/io/facturapi/models/complements/comercio_exterior/ComercioExteriorDescripcionesEspecificas.java @@ -1,4 +1,4 @@ -package io.facturapi.models; +package io.facturapi.models.complements.comercio_exterior; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; diff --git a/src/main/java/io/facturapi/models/ComercioExteriorDestinatarioRef.java b/src/main/java/io/facturapi/models/complements/comercio_exterior/ComercioExteriorDestinatarioRef.java similarity index 94% rename from src/main/java/io/facturapi/models/ComercioExteriorDestinatarioRef.java rename to src/main/java/io/facturapi/models/complements/comercio_exterior/ComercioExteriorDestinatarioRef.java index 87d684d..a6e5c44 100644 --- a/src/main/java/io/facturapi/models/ComercioExteriorDestinatarioRef.java +++ b/src/main/java/io/facturapi/models/complements/comercio_exterior/ComercioExteriorDestinatarioRef.java @@ -1,4 +1,4 @@ -package io.facturapi.models; +package io.facturapi.models.complements.comercio_exterior; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; diff --git a/src/main/java/io/facturapi/models/ComercioExteriorDomicilio.java b/src/main/java/io/facturapi/models/complements/comercio_exterior/ComercioExteriorDomicilio.java similarity index 97% rename from src/main/java/io/facturapi/models/ComercioExteriorDomicilio.java rename to src/main/java/io/facturapi/models/complements/comercio_exterior/ComercioExteriorDomicilio.java index fb5568d..556e75c 100644 --- a/src/main/java/io/facturapi/models/ComercioExteriorDomicilio.java +++ b/src/main/java/io/facturapi/models/complements/comercio_exterior/ComercioExteriorDomicilio.java @@ -1,4 +1,4 @@ -package io.facturapi.models; +package io.facturapi.models.complements.comercio_exterior; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; diff --git a/src/main/java/io/facturapi/models/ComercioExteriorEmisor.java b/src/main/java/io/facturapi/models/complements/comercio_exterior/ComercioExteriorEmisor.java similarity index 90% rename from src/main/java/io/facturapi/models/ComercioExteriorEmisor.java rename to src/main/java/io/facturapi/models/complements/comercio_exterior/ComercioExteriorEmisor.java index a305a24..65c4355 100644 --- a/src/main/java/io/facturapi/models/ComercioExteriorEmisor.java +++ b/src/main/java/io/facturapi/models/complements/comercio_exterior/ComercioExteriorEmisor.java @@ -1,4 +1,4 @@ -package io.facturapi.models; +package io.facturapi.models.complements.comercio_exterior; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; diff --git a/src/main/java/io/facturapi/models/ComercioExteriorMercancia.java b/src/main/java/io/facturapi/models/complements/comercio_exterior/ComercioExteriorMercancia.java similarity index 97% rename from src/main/java/io/facturapi/models/ComercioExteriorMercancia.java rename to src/main/java/io/facturapi/models/complements/comercio_exterior/ComercioExteriorMercancia.java index f4ce5de..6123e19 100644 --- a/src/main/java/io/facturapi/models/ComercioExteriorMercancia.java +++ b/src/main/java/io/facturapi/models/complements/comercio_exterior/ComercioExteriorMercancia.java @@ -1,4 +1,4 @@ -package io.facturapi.models; +package io.facturapi.models.complements.comercio_exterior; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; diff --git a/src/main/java/io/facturapi/models/ComercioExteriorMercancias.java b/src/main/java/io/facturapi/models/complements/comercio_exterior/ComercioExteriorMercancias.java similarity index 90% rename from src/main/java/io/facturapi/models/ComercioExteriorMercancias.java rename to src/main/java/io/facturapi/models/complements/comercio_exterior/ComercioExteriorMercancias.java index 8af3559..6797dd2 100644 --- a/src/main/java/io/facturapi/models/ComercioExteriorMercancias.java +++ b/src/main/java/io/facturapi/models/complements/comercio_exterior/ComercioExteriorMercancias.java @@ -1,4 +1,4 @@ -package io.facturapi.models; +package io.facturapi.models.complements.comercio_exterior; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; diff --git a/src/main/java/io/facturapi/models/ComercioExteriorPartyRef.java b/src/main/java/io/facturapi/models/complements/comercio_exterior/ComercioExteriorPartyRef.java similarity index 92% rename from src/main/java/io/facturapi/models/ComercioExteriorPartyRef.java rename to src/main/java/io/facturapi/models/complements/comercio_exterior/ComercioExteriorPartyRef.java index 4dac82e..ad6b49a 100644 --- a/src/main/java/io/facturapi/models/ComercioExteriorPartyRef.java +++ b/src/main/java/io/facturapi/models/complements/comercio_exterior/ComercioExteriorPartyRef.java @@ -1,4 +1,4 @@ -package io.facturapi.models; +package io.facturapi.models.complements.comercio_exterior; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; diff --git a/src/main/java/io/facturapi/models/ComercioExteriorReceptorRef.java b/src/main/java/io/facturapi/models/complements/comercio_exterior/ComercioExteriorReceptorRef.java similarity index 92% rename from src/main/java/io/facturapi/models/ComercioExteriorReceptorRef.java rename to src/main/java/io/facturapi/models/complements/comercio_exterior/ComercioExteriorReceptorRef.java index ffd871e..0142345 100644 --- a/src/main/java/io/facturapi/models/ComercioExteriorReceptorRef.java +++ b/src/main/java/io/facturapi/models/complements/comercio_exterior/ComercioExteriorReceptorRef.java @@ -1,4 +1,4 @@ -package io.facturapi.models; +package io.facturapi.models.complements.comercio_exterior; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; diff --git a/src/main/java/io/facturapi/models/NominaAcciones.java b/src/main/java/io/facturapi/models/complements/nomina/NominaAcciones.java similarity index 93% rename from src/main/java/io/facturapi/models/NominaAcciones.java rename to src/main/java/io/facturapi/models/complements/nomina/NominaAcciones.java index 7574ac9..edbc619 100644 --- a/src/main/java/io/facturapi/models/NominaAcciones.java +++ b/src/main/java/io/facturapi/models/complements/nomina/NominaAcciones.java @@ -1,4 +1,4 @@ -package io.facturapi.models; +package io.facturapi.models.complements.nomina; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; diff --git a/src/main/java/io/facturapi/models/NominaCompensacion.java b/src/main/java/io/facturapi/models/complements/nomina/NominaCompensacion.java similarity index 94% rename from src/main/java/io/facturapi/models/NominaCompensacion.java rename to src/main/java/io/facturapi/models/complements/nomina/NominaCompensacion.java index 8e07b0a..46b4a70 100644 --- a/src/main/java/io/facturapi/models/NominaCompensacion.java +++ b/src/main/java/io/facturapi/models/complements/nomina/NominaCompensacion.java @@ -1,4 +1,4 @@ -package io.facturapi.models; +package io.facturapi.models.complements.nomina; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; diff --git a/src/main/java/io/facturapi/models/NominaComplementData.java b/src/main/java/io/facturapi/models/complements/nomina/NominaComplementData.java similarity index 98% rename from src/main/java/io/facturapi/models/NominaComplementData.java rename to src/main/java/io/facturapi/models/complements/nomina/NominaComplementData.java index 7ca85b7..d438001 100644 --- a/src/main/java/io/facturapi/models/NominaComplementData.java +++ b/src/main/java/io/facturapi/models/complements/nomina/NominaComplementData.java @@ -1,4 +1,4 @@ -package io.facturapi.models; +package io.facturapi.models.complements.nomina; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; diff --git a/src/main/java/io/facturapi/models/NominaDeduccion.java b/src/main/java/io/facturapi/models/complements/nomina/NominaDeduccion.java similarity index 94% rename from src/main/java/io/facturapi/models/NominaDeduccion.java rename to src/main/java/io/facturapi/models/complements/nomina/NominaDeduccion.java index b76cbda..c5213dc 100644 --- a/src/main/java/io/facturapi/models/NominaDeduccion.java +++ b/src/main/java/io/facturapi/models/complements/nomina/NominaDeduccion.java @@ -1,4 +1,4 @@ -package io.facturapi.models; +package io.facturapi.models.complements.nomina; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; diff --git a/src/main/java/io/facturapi/models/NominaEmisor.java b/src/main/java/io/facturapi/models/complements/nomina/NominaEmisor.java similarity index 95% rename from src/main/java/io/facturapi/models/NominaEmisor.java rename to src/main/java/io/facturapi/models/complements/nomina/NominaEmisor.java index 545ba3c..2534e19 100644 --- a/src/main/java/io/facturapi/models/NominaEmisor.java +++ b/src/main/java/io/facturapi/models/complements/nomina/NominaEmisor.java @@ -1,4 +1,4 @@ -package io.facturapi.models; +package io.facturapi.models.complements.nomina; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; diff --git a/src/main/java/io/facturapi/models/NominaEntidadSncf.java b/src/main/java/io/facturapi/models/complements/nomina/NominaEntidadSncf.java similarity index 93% rename from src/main/java/io/facturapi/models/NominaEntidadSncf.java rename to src/main/java/io/facturapi/models/complements/nomina/NominaEntidadSncf.java index aade868..1dd44e9 100644 --- a/src/main/java/io/facturapi/models/NominaEntidadSncf.java +++ b/src/main/java/io/facturapi/models/complements/nomina/NominaEntidadSncf.java @@ -1,4 +1,4 @@ -package io.facturapi.models; +package io.facturapi.models.complements.nomina; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; diff --git a/src/main/java/io/facturapi/models/NominaHorasExtra.java b/src/main/java/io/facturapi/models/complements/nomina/NominaHorasExtra.java similarity index 95% rename from src/main/java/io/facturapi/models/NominaHorasExtra.java rename to src/main/java/io/facturapi/models/complements/nomina/NominaHorasExtra.java index 8f82717..cbed048 100644 --- a/src/main/java/io/facturapi/models/NominaHorasExtra.java +++ b/src/main/java/io/facturapi/models/complements/nomina/NominaHorasExtra.java @@ -1,4 +1,4 @@ -package io.facturapi.models; +package io.facturapi.models.complements.nomina; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; diff --git a/src/main/java/io/facturapi/models/NominaIncapacidad.java b/src/main/java/io/facturapi/models/complements/nomina/NominaIncapacidad.java similarity index 95% rename from src/main/java/io/facturapi/models/NominaIncapacidad.java rename to src/main/java/io/facturapi/models/complements/nomina/NominaIncapacidad.java index 092bde1..a9ae1d2 100644 --- a/src/main/java/io/facturapi/models/NominaIncapacidad.java +++ b/src/main/java/io/facturapi/models/complements/nomina/NominaIncapacidad.java @@ -1,4 +1,4 @@ -package io.facturapi.models; +package io.facturapi.models.complements.nomina; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; diff --git a/src/main/java/io/facturapi/models/NominaJubilacion.java b/src/main/java/io/facturapi/models/complements/nomina/NominaJubilacion.java similarity index 96% rename from src/main/java/io/facturapi/models/NominaJubilacion.java rename to src/main/java/io/facturapi/models/complements/nomina/NominaJubilacion.java index 69afefd..303a9b0 100644 --- a/src/main/java/io/facturapi/models/NominaJubilacion.java +++ b/src/main/java/io/facturapi/models/complements/nomina/NominaJubilacion.java @@ -1,4 +1,4 @@ -package io.facturapi.models; +package io.facturapi.models.complements.nomina; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; diff --git a/src/main/java/io/facturapi/models/NominaOtroPago.java b/src/main/java/io/facturapi/models/complements/nomina/NominaOtroPago.java similarity index 96% rename from src/main/java/io/facturapi/models/NominaOtroPago.java rename to src/main/java/io/facturapi/models/complements/nomina/NominaOtroPago.java index fc8e40c..7f48634 100644 --- a/src/main/java/io/facturapi/models/NominaOtroPago.java +++ b/src/main/java/io/facturapi/models/complements/nomina/NominaOtroPago.java @@ -1,4 +1,4 @@ -package io.facturapi.models; +package io.facturapi.models.complements.nomina; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; diff --git a/src/main/java/io/facturapi/models/NominaPercepcion.java b/src/main/java/io/facturapi/models/complements/nomina/NominaPercepcion.java similarity index 97% rename from src/main/java/io/facturapi/models/NominaPercepcion.java rename to src/main/java/io/facturapi/models/complements/nomina/NominaPercepcion.java index d0ce886..a9ee609 100644 --- a/src/main/java/io/facturapi/models/NominaPercepcion.java +++ b/src/main/java/io/facturapi/models/complements/nomina/NominaPercepcion.java @@ -1,4 +1,4 @@ -package io.facturapi.models; +package io.facturapi.models.complements.nomina; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; diff --git a/src/main/java/io/facturapi/models/NominaPercepciones.java b/src/main/java/io/facturapi/models/complements/nomina/NominaPercepciones.java similarity index 96% rename from src/main/java/io/facturapi/models/NominaPercepciones.java rename to src/main/java/io/facturapi/models/complements/nomina/NominaPercepciones.java index ee3730e..b506699 100644 --- a/src/main/java/io/facturapi/models/NominaPercepciones.java +++ b/src/main/java/io/facturapi/models/complements/nomina/NominaPercepciones.java @@ -1,4 +1,4 @@ -package io.facturapi.models; +package io.facturapi.models.complements.nomina; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; diff --git a/src/main/java/io/facturapi/models/NominaReceptor.java b/src/main/java/io/facturapi/models/complements/nomina/NominaReceptor.java similarity index 98% rename from src/main/java/io/facturapi/models/NominaReceptor.java rename to src/main/java/io/facturapi/models/complements/nomina/NominaReceptor.java index 3bf2593..0e18628 100644 --- a/src/main/java/io/facturapi/models/NominaReceptor.java +++ b/src/main/java/io/facturapi/models/complements/nomina/NominaReceptor.java @@ -1,4 +1,4 @@ -package io.facturapi.models; +package io.facturapi.models.complements.nomina; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; diff --git a/src/main/java/io/facturapi/models/NominaSeparacion.java b/src/main/java/io/facturapi/models/complements/nomina/NominaSeparacion.java similarity index 96% rename from src/main/java/io/facturapi/models/NominaSeparacion.java rename to src/main/java/io/facturapi/models/complements/nomina/NominaSeparacion.java index 2c444ba..eb0d1c2 100644 --- a/src/main/java/io/facturapi/models/NominaSeparacion.java +++ b/src/main/java/io/facturapi/models/complements/nomina/NominaSeparacion.java @@ -1,4 +1,4 @@ -package io.facturapi.models; +package io.facturapi.models.complements.nomina; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; diff --git a/src/main/java/io/facturapi/models/NominaSubcontratacion.java b/src/main/java/io/facturapi/models/complements/nomina/NominaSubcontratacion.java similarity index 92% rename from src/main/java/io/facturapi/models/NominaSubcontratacion.java rename to src/main/java/io/facturapi/models/complements/nomina/NominaSubcontratacion.java index 5a4b0e1..b6aa13e 100644 --- a/src/main/java/io/facturapi/models/NominaSubcontratacion.java +++ b/src/main/java/io/facturapi/models/complements/nomina/NominaSubcontratacion.java @@ -1,4 +1,4 @@ -package io.facturapi.models; +package io.facturapi.models.complements.nomina; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; diff --git a/src/main/java/io/facturapi/models/PagoComplementData.java b/src/main/java/io/facturapi/models/complements/pago/PagoComplementData.java similarity index 98% rename from src/main/java/io/facturapi/models/PagoComplementData.java rename to src/main/java/io/facturapi/models/complements/pago/PagoComplementData.java index a0d4771..391e148 100644 --- a/src/main/java/io/facturapi/models/PagoComplementData.java +++ b/src/main/java/io/facturapi/models/complements/pago/PagoComplementData.java @@ -1,4 +1,4 @@ -package io.facturapi.models; +package io.facturapi.models.complements.pago; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; diff --git a/src/main/java/io/facturapi/models/PaymentRelatedDocument.java b/src/main/java/io/facturapi/models/complements/pago/PaymentRelatedDocument.java similarity index 97% rename from src/main/java/io/facturapi/models/PaymentRelatedDocument.java rename to src/main/java/io/facturapi/models/complements/pago/PaymentRelatedDocument.java index acb9729..6b0d2be 100644 --- a/src/main/java/io/facturapi/models/PaymentRelatedDocument.java +++ b/src/main/java/io/facturapi/models/complements/pago/PaymentRelatedDocument.java @@ -1,4 +1,4 @@ -package io.facturapi.models; +package io.facturapi.models.complements.pago; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; diff --git a/src/main/java/io/facturapi/models/PaymentRelatedDocumentTax.java b/src/main/java/io/facturapi/models/complements/pago/PaymentRelatedDocumentTax.java similarity index 94% rename from src/main/java/io/facturapi/models/PaymentRelatedDocumentTax.java rename to src/main/java/io/facturapi/models/complements/pago/PaymentRelatedDocumentTax.java index 68598c6..5c08d6e 100644 --- a/src/main/java/io/facturapi/models/PaymentRelatedDocumentTax.java +++ b/src/main/java/io/facturapi/models/complements/pago/PaymentRelatedDocumentTax.java @@ -1,4 +1,4 @@ -package io.facturapi.models; +package io.facturapi.models.complements.pago; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; From 41f5a68bd5470f69e810ab58bd59c3353d9bd448 Mon Sep 17 00:00:00 2001 From: javorosas Date: Tue, 7 Apr 2026 12:02:13 +0200 Subject: [PATCH 03/22] refactor: use accessor-style sdk surface --- README.md | 4 +- src/main/java/io/facturapi/Facturapi.java | 68 +++++++++++++++---- .../io/facturapi/FacturapiResourcesTest.java | 6 +- 3 files changed, 61 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index b5ed407..811caea 100644 --- a/README.md +++ b/README.md @@ -36,14 +36,14 @@ import java.util.Map; Facturapi facturapi = new Facturapi("sk_test_..."); -var customer = facturapi.customers.create(Map.of( +var customer = facturapi.customers().create(Map.of( "legal_name", "Mi Empresa SA de CV", "tax_id", "XAXX010101000", "tax_system", "601", "email", "cliente@example.com" ), null); -var invoice = facturapi.invoices.create(Map.of( +var invoice = facturapi.invoices().create(Map.of( "customer", customer.getId(), "items", java.util.List.of(Map.of("quantity", 1, "product", "prod_123")) ), null); diff --git a/src/main/java/io/facturapi/Facturapi.java b/src/main/java/io/facturapi/Facturapi.java index dd9c33e..13403cf 100644 --- a/src/main/java/io/facturapi/Facturapi.java +++ b/src/main/java/io/facturapi/Facturapi.java @@ -23,18 +23,18 @@ public class Facturapi { private final FacturapiHttpClient httpClient; - public final CustomersResource customers; - public final ProductsResource products; - public final InvoicesResource invoices; - public final OrganizationsResource organizations; - public final ReceiptsResource receipts; - public final RetentionsResource retentions; - public final WebhooksResource webhooks; - - public final CatalogsTool catalogs; - public final CartaPorteCatalogsTool cartaPorteCatalogs; - public final ComercioExteriorCatalogsTool comercioExteriorCatalogs; - public final ToolsResource tools; + private final CustomersResource customers; + private final ProductsResource products; + private final InvoicesResource invoices; + private final OrganizationsResource organizations; + private final ReceiptsResource receipts; + private final RetentionsResource retentions; + private final WebhooksResource webhooks; + + private final CatalogsTool catalogs; + private final CartaPorteCatalogsTool cartaPorteCatalogs; + private final ComercioExteriorCatalogsTool comercioExteriorCatalogs; + private final ToolsResource tools; /** * Creates a client using API v2. @@ -86,6 +86,50 @@ public static Builder builder(String apiKey) { return new Builder(apiKey); } + public CustomersResource customers() { + return customers; + } + + public ProductsResource products() { + return products; + } + + public InvoicesResource invoices() { + return invoices; + } + + public OrganizationsResource organizations() { + return organizations; + } + + public ReceiptsResource receipts() { + return receipts; + } + + public RetentionsResource retentions() { + return retentions; + } + + public WebhooksResource webhooks() { + return webhooks; + } + + public CatalogsTool catalogs() { + return catalogs; + } + + public CartaPorteCatalogsTool cartaPorteCatalogs() { + return cartaPorteCatalogs; + } + + public ComercioExteriorCatalogsTool comercioExteriorCatalogs() { + return comercioExteriorCatalogs; + } + + public ToolsResource tools() { + return tools; + } + public static final class Builder { private final FacturapiConfig.Builder configBuilder; diff --git a/src/test/java/io/facturapi/FacturapiResourcesTest.java b/src/test/java/io/facturapi/FacturapiResourcesTest.java index 8dc4d5d..82cf536 100644 --- a/src/test/java/io/facturapi/FacturapiResourcesTest.java +++ b/src/test/java/io/facturapi/FacturapiResourcesTest.java @@ -20,7 +20,7 @@ void invoiceCreateUsesExpectedPath() { .build() ); - var response = sdk.invoices.create(Map.of("customer", "cus_1"), Map.of("test", true)); + var response = sdk.invoices().create(Map.of("customer", "cus_1"), Map.of("test", true)); assertEquals("inv_1", response.getId()); @@ -40,7 +40,7 @@ void organizationListLiveApiKeysIsTyped() { .build() ); - var response = sdk.organizations.listLiveApiKeys("org_1"); + var response = sdk.organizations().listLiveApiKeys("org_1"); assertEquals(1, response.size()); assertNotNull(response.get(0).getId()); @@ -68,7 +68,7 @@ void invoiceComplementsAreTypedForPagoNominaAndCustom() { .build() ); - var invoice = sdk.invoices.retrieve("inv_1"); + var invoice = sdk.invoices().retrieve("inv_1"); assertEquals(5, invoice.getComplements().size()); var pago = invoice.getComplements().get(0); From d3c96cddcff9fea8480fc779cd80e22f83006aca Mon Sep 17 00:00:00 2001 From: javorosas Date: Tue, 7 Apr 2026 12:14:49 +0200 Subject: [PATCH 04/22] refactor: adopt java time types for dates --- pom.xml | 6 +++ .../io/facturapi/http/FacturapiConfig.java | 8 ++- .../java/io/facturapi/models/ApiEvent.java | 8 +-- src/main/java/io/facturapi/models/ApiKey.java | 7 +-- .../java/io/facturapi/models/Certificate.java | 13 ++--- .../java/io/facturapi/models/Customer.java | 19 +++---- .../java/io/facturapi/models/Invoice.java | 15 +++--- .../facturapi/models/InvoiceCancellation.java | 13 ++--- .../io/facturapi/models/Organization.java | 7 +-- .../facturapi/models/OrganizationInvite.java | 13 ++--- .../models/OrganizationTeamRole.java | 13 ++--- .../models/OrganizationUserAccess.java | 13 ++--- .../java/io/facturapi/models/Payment.java | 7 +-- .../facturapi/models/PendingPlanUpdate.java | 7 +-- .../java/io/facturapi/models/Product.java | 7 +-- .../java/io/facturapi/models/Receipt.java | 19 +++---- .../java/io/facturapi/models/Retention.java | 13 ++--- src/main/java/io/facturapi/models/Stamp.java | 7 +-- .../java/io/facturapi/models/Webhook.java | 7 +-- .../models/complements/InvoiceComplement.java | 2 + .../ComercioExteriorComplementData.java | 2 + .../nomina/NominaComplementData.java | 19 +++---- .../complements/nomina/NominaReceptor.java | 7 +-- .../complements/pago/PagoComplementData.java | 7 +-- .../io/facturapi/FacturapiResourcesTest.java | 50 +++++++++++++++++-- 25 files changed, 184 insertions(+), 105 deletions(-) diff --git a/pom.xml b/pom.xml index 39cde6f..3afce5a 100644 --- a/pom.xml +++ b/pom.xml @@ -31,6 +31,12 @@ ${jackson.version} + + com.fasterxml.jackson.datatype + jackson-datatype-jsr310 + ${jackson.version} + + org.junit.jupiter junit-jupiter diff --git a/src/main/java/io/facturapi/http/FacturapiConfig.java b/src/main/java/io/facturapi/http/FacturapiConfig.java index ee67bef..09efecc 100644 --- a/src/main/java/io/facturapi/http/FacturapiConfig.java +++ b/src/main/java/io/facturapi/http/FacturapiConfig.java @@ -1,7 +1,9 @@ package io.facturapi.http; -import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; import io.facturapi.ApiVersion; import io.facturapi.constants.FacturapiConstants; import java.net.http.HttpClient; @@ -105,7 +107,9 @@ public FacturapiConfig build() { : this.httpClient; ObjectMapper resolvedMapper = new ObjectMapper() - .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + .registerModule(new JavaTimeModule()) + .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false) + .disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); this.baseUrl = resolvedBaseUrl; this.httpClient = resolvedClient; diff --git a/src/main/java/io/facturapi/models/ApiEvent.java b/src/main/java/io/facturapi/models/ApiEvent.java index c1cd047..dc9ead9 100644 --- a/src/main/java/io/facturapi/models/ApiEvent.java +++ b/src/main/java/io/facturapi/models/ApiEvent.java @@ -1,19 +1,21 @@ package io.facturapi.models; +import java.time.Instant; + import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; @JsonIgnoreProperties(ignoreUnknown = true) public class ApiEvent { @JsonProperty("created_at") - private String createdAt; + private Instant createdAt; private String organization; private Boolean livemode; private String type; private ApiEventData data; - public String getCreatedAt() { return createdAt; } - public void setCreatedAt(String createdAt) { this.createdAt = createdAt; } + public Instant getCreatedAt() { return createdAt; } + public void setCreatedAt(Instant createdAt) { this.createdAt = createdAt; } public String getOrganization() { return organization; } public void setOrganization(String organization) { this.organization = organization; } public Boolean getLivemode() { return livemode; } diff --git a/src/main/java/io/facturapi/models/ApiKey.java b/src/main/java/io/facturapi/models/ApiKey.java index c4ae528..d8b16ab 100644 --- a/src/main/java/io/facturapi/models/ApiKey.java +++ b/src/main/java/io/facturapi/models/ApiKey.java @@ -3,6 +3,7 @@ import com.fasterxml.jackson.annotation.JsonAlias; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; +import java.time.Instant; @JsonIgnoreProperties(ignoreUnknown = true) public class ApiKey { @@ -10,7 +11,7 @@ public class ApiKey { @JsonProperty("first_12") private String first12; @JsonProperty("created_at") - private String createdAt; + private Instant createdAt; @JsonAlias({"key", "api_key", "token"}) private String key; @@ -18,8 +19,8 @@ public class ApiKey { public void setId(String id) { this.id = id; } public String getFirst12() { return first12; } public void setFirst12(String first12) { this.first12 = first12; } - public String getCreatedAt() { return createdAt; } - public void setCreatedAt(String createdAt) { this.createdAt = createdAt; } + public Instant getCreatedAt() { return createdAt; } + public void setCreatedAt(Instant createdAt) { this.createdAt = createdAt; } public String getKey() { return key; } public void setKey(String key) { this.key = key; } } diff --git a/src/main/java/io/facturapi/models/Certificate.java b/src/main/java/io/facturapi/models/Certificate.java index e6f29be..a15cf55 100644 --- a/src/main/java/io/facturapi/models/Certificate.java +++ b/src/main/java/io/facturapi/models/Certificate.java @@ -2,24 +2,25 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; +import java.time.Instant; @JsonIgnoreProperties(ignoreUnknown = true) public class Certificate { @JsonProperty("has_certificate") private Boolean hasCertificate; @JsonProperty("updated_at") - private String updatedAt; + private Instant updatedAt; @JsonProperty("expires_at") - private String expiresAt; + private Instant expiresAt; @JsonProperty("serial_number") private String serialNumber; public Boolean getHasCertificate() { return hasCertificate; } public void setHasCertificate(Boolean hasCertificate) { this.hasCertificate = hasCertificate; } - public String getUpdatedAt() { return updatedAt; } - public void setUpdatedAt(String updatedAt) { this.updatedAt = updatedAt; } - public String getExpiresAt() { return expiresAt; } - public void setExpiresAt(String expiresAt) { this.expiresAt = expiresAt; } + public Instant getUpdatedAt() { return updatedAt; } + public void setUpdatedAt(Instant updatedAt) { this.updatedAt = updatedAt; } + public Instant getExpiresAt() { return expiresAt; } + public void setExpiresAt(Instant expiresAt) { this.expiresAt = expiresAt; } public String getSerialNumber() { return serialNumber; } public void setSerialNumber(String serialNumber) { this.serialNumber = serialNumber; } } diff --git a/src/main/java/io/facturapi/models/Customer.java b/src/main/java/io/facturapi/models/Customer.java index 45b1527..b1a8f55 100644 --- a/src/main/java/io/facturapi/models/Customer.java +++ b/src/main/java/io/facturapi/models/Customer.java @@ -2,6 +2,7 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; +import java.time.Instant; @JsonIgnoreProperties(ignoreUnknown = true) public class Customer { @@ -9,7 +10,7 @@ public class Customer { private String organization; private Boolean livemode; @JsonProperty("created_at") - private String createdAt; + private Instant createdAt; @JsonProperty("tax_id") private String taxId; @JsonProperty("tax_system") @@ -25,11 +26,11 @@ public class Customer { @JsonProperty("default_invoice_use") private String defaultInvoiceUse; @JsonProperty("sat_validated_at") - private String satValidatedAt; + private Instant satValidatedAt; @JsonProperty("edit_link") private String editLink; @JsonProperty("edit_link_expires_at") - private String editLinkExpiresAt; + private Instant editLinkExpiresAt; public String getId() { return id; } public void setId(String id) { this.id = id; } @@ -37,8 +38,8 @@ public class Customer { public void setOrganization(String organization) { this.organization = organization; } public Boolean getLivemode() { return livemode; } public void setLivemode(Boolean livemode) { this.livemode = livemode; } - public String getCreatedAt() { return createdAt; } - public void setCreatedAt(String createdAt) { this.createdAt = createdAt; } + public Instant getCreatedAt() { return createdAt; } + public void setCreatedAt(Instant createdAt) { this.createdAt = createdAt; } public String getTaxId() { return taxId; } public void setTaxId(String taxId) { this.taxId = taxId; } public String getTaxSystem() { return taxSystem; } @@ -57,10 +58,10 @@ public class Customer { public void setExternalId(String externalId) { this.externalId = externalId; } public String getDefaultInvoiceUse() { return defaultInvoiceUse; } public void setDefaultInvoiceUse(String defaultInvoiceUse) { this.defaultInvoiceUse = defaultInvoiceUse; } - public String getSatValidatedAt() { return satValidatedAt; } - public void setSatValidatedAt(String satValidatedAt) { this.satValidatedAt = satValidatedAt; } + public Instant getSatValidatedAt() { return satValidatedAt; } + public void setSatValidatedAt(Instant satValidatedAt) { this.satValidatedAt = satValidatedAt; } public String getEditLink() { return editLink; } public void setEditLink(String editLink) { this.editLink = editLink; } - public String getEditLinkExpiresAt() { return editLinkExpiresAt; } - public void setEditLinkExpiresAt(String editLinkExpiresAt) { this.editLinkExpiresAt = editLinkExpiresAt; } + public Instant getEditLinkExpiresAt() { return editLinkExpiresAt; } + public void setEditLinkExpiresAt(Instant editLinkExpiresAt) { this.editLinkExpiresAt = editLinkExpiresAt; } } diff --git a/src/main/java/io/facturapi/models/Invoice.java b/src/main/java/io/facturapi/models/Invoice.java index 5332906..90076c5 100644 --- a/src/main/java/io/facturapi/models/Invoice.java +++ b/src/main/java/io/facturapi/models/Invoice.java @@ -2,9 +2,10 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; +import io.facturapi.models.complements.InvoiceComplement; +import java.time.Instant; import java.util.ArrayList; import java.util.List; -import io.facturapi.models.complements.InvoiceComplement; @JsonIgnoreProperties(ignoreUnknown = true) public class Invoice { @@ -12,8 +13,8 @@ public class Invoice { private String organization; private Boolean livemode; @JsonProperty("created_at") - private String createdAt; - private String date; + private Instant createdAt; + private Instant date; @JsonProperty("issuer_type") private String issuerType; private String type; @@ -75,10 +76,10 @@ public class Invoice { public void setOrganization(String organization) { this.organization = organization; } public Boolean getLivemode() { return livemode; } public void setLivemode(Boolean livemode) { this.livemode = livemode; } - public String getCreatedAt() { return createdAt; } - public void setCreatedAt(String createdAt) { this.createdAt = createdAt; } - public String getDate() { return date; } - public void setDate(String date) { this.date = date; } + public Instant getCreatedAt() { return createdAt; } + public void setCreatedAt(Instant createdAt) { this.createdAt = createdAt; } + public Instant getDate() { return date; } + public void setDate(Instant date) { this.date = date; } public String getIssuerType() { return issuerType; } public void setIssuerType(String issuerType) { this.issuerType = issuerType; } public String getType() { return type; } diff --git a/src/main/java/io/facturapi/models/InvoiceCancellation.java b/src/main/java/io/facturapi/models/InvoiceCancellation.java index 3bb4827..5fd641f 100644 --- a/src/main/java/io/facturapi/models/InvoiceCancellation.java +++ b/src/main/java/io/facturapi/models/InvoiceCancellation.java @@ -2,24 +2,25 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; +import java.time.Instant; @JsonIgnoreProperties(ignoreUnknown = true) public class InvoiceCancellation { @JsonProperty("requested_at") - private String requestedAt; + private Instant requestedAt; private String status; @JsonProperty("last_checked") - private String lastChecked; + private Instant lastChecked; private String motive; @JsonProperty("substitution_uuid") private String substitutionUuid; - public String getRequestedAt() { return requestedAt; } - public void setRequestedAt(String requestedAt) { this.requestedAt = requestedAt; } + public Instant getRequestedAt() { return requestedAt; } + public void setRequestedAt(Instant requestedAt) { this.requestedAt = requestedAt; } public String getStatus() { return status; } public void setStatus(String status) { this.status = status; } - public String getLastChecked() { return lastChecked; } - public void setLastChecked(String lastChecked) { this.lastChecked = lastChecked; } + public Instant getLastChecked() { return lastChecked; } + public void setLastChecked(Instant lastChecked) { this.lastChecked = lastChecked; } public String getMotive() { return motive; } public void setMotive(String motive) { this.motive = motive; } public String getSubstitutionUuid() { return substitutionUuid; } diff --git a/src/main/java/io/facturapi/models/Organization.java b/src/main/java/io/facturapi/models/Organization.java index bdcb4bc..0ae791f 100644 --- a/src/main/java/io/facturapi/models/Organization.java +++ b/src/main/java/io/facturapi/models/Organization.java @@ -2,6 +2,7 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; +import java.time.Instant; import java.util.ArrayList; import java.util.List; @@ -9,7 +10,7 @@ public class Organization { private String id; @JsonProperty("created_at") - private String createdAt; + private Instant createdAt; private String plan; @JsonProperty("add_ons") private List addOns = new ArrayList<>(); @@ -35,8 +36,8 @@ public class Organization { public String getId() { return id; } public void setId(String id) { this.id = id; } - public String getCreatedAt() { return createdAt; } - public void setCreatedAt(String createdAt) { this.createdAt = createdAt; } + public Instant getCreatedAt() { return createdAt; } + public void setCreatedAt(Instant createdAt) { this.createdAt = createdAt; } public String getPlan() { return plan; } public void setPlan(String plan) { this.plan = plan; } public List getAddOns() { return addOns; } diff --git a/src/main/java/io/facturapi/models/OrganizationInvite.java b/src/main/java/io/facturapi/models/OrganizationInvite.java index 4621f78..bad77f1 100644 --- a/src/main/java/io/facturapi/models/OrganizationInvite.java +++ b/src/main/java/io/facturapi/models/OrganizationInvite.java @@ -2,6 +2,7 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; +import java.time.Instant; import java.util.ArrayList; import java.util.List; @@ -9,7 +10,7 @@ public class OrganizationInvite { private String id; @JsonProperty("created_at") - private String createdAt; + private Instant createdAt; private String email; @JsonProperty("organization_name") private String organizationName; @@ -18,13 +19,13 @@ public class OrganizationInvite { private String roleName; private List roles = new ArrayList<>(); @JsonProperty("expires_at") - private String expiresAt; + private Instant expiresAt; private String status; public String getId() { return id; } public void setId(String id) { this.id = id; } - public String getCreatedAt() { return createdAt; } - public void setCreatedAt(String createdAt) { this.createdAt = createdAt; } + public Instant getCreatedAt() { return createdAt; } + public void setCreatedAt(Instant createdAt) { this.createdAt = createdAt; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } public String getOrganizationName() { return organizationName; } @@ -35,8 +36,8 @@ public class OrganizationInvite { public void setRoleName(String roleName) { this.roleName = roleName; } public List getRoles() { return roles; } public void setRoles(List roles) { this.roles = roles; } - public String getExpiresAt() { return expiresAt; } - public void setExpiresAt(String expiresAt) { this.expiresAt = expiresAt; } + public Instant getExpiresAt() { return expiresAt; } + public void setExpiresAt(Instant expiresAt) { this.expiresAt = expiresAt; } public String getStatus() { return status; } public void setStatus(String status) { this.status = status; } } diff --git a/src/main/java/io/facturapi/models/OrganizationTeamRole.java b/src/main/java/io/facturapi/models/OrganizationTeamRole.java index ca719e5..669e58d 100644 --- a/src/main/java/io/facturapi/models/OrganizationTeamRole.java +++ b/src/main/java/io/facturapi/models/OrganizationTeamRole.java @@ -2,6 +2,7 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; +import java.time.Instant; import java.util.ArrayList; import java.util.List; import java.util.Map; @@ -18,9 +19,9 @@ public class OrganizationTeamRole { @JsonProperty("used_by") private Integer usedBy; @JsonProperty("created_at") - private String createdAt; + private Instant createdAt; @JsonProperty("updated_at") - private String updatedAt; + private Instant updatedAt; @JsonProperty("created_by") private Map createdBy; @JsonProperty("updated_by") @@ -40,10 +41,10 @@ public class OrganizationTeamRole { public void setOperations(List operations) { this.operations = operations; } public Integer getUsedBy() { return usedBy; } public void setUsedBy(Integer usedBy) { this.usedBy = usedBy; } - public String getCreatedAt() { return createdAt; } - public void setCreatedAt(String createdAt) { this.createdAt = createdAt; } - public String getUpdatedAt() { return updatedAt; } - public void setUpdatedAt(String updatedAt) { this.updatedAt = updatedAt; } + public Instant getCreatedAt() { return createdAt; } + public void setCreatedAt(Instant createdAt) { this.createdAt = createdAt; } + public Instant getUpdatedAt() { return updatedAt; } + public void setUpdatedAt(Instant updatedAt) { this.updatedAt = updatedAt; } public Map getCreatedBy() { return createdBy; } public void setCreatedBy(Map createdBy) { this.createdBy = createdBy; } public Map getUpdatedBy() { return updatedBy; } diff --git a/src/main/java/io/facturapi/models/OrganizationUserAccess.java b/src/main/java/io/facturapi/models/OrganizationUserAccess.java index 463de72..ed11f05 100644 --- a/src/main/java/io/facturapi/models/OrganizationUserAccess.java +++ b/src/main/java/io/facturapi/models/OrganizationUserAccess.java @@ -2,6 +2,7 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; +import java.time.Instant; import java.util.ArrayList; import java.util.List; @@ -17,9 +18,9 @@ public class OrganizationUserAccess { private String organization; private List operations = new ArrayList<>(); @JsonProperty("created_at") - private String createdAt; + private Instant createdAt; @JsonProperty("updated_at") - private String updatedAt; + private Instant updatedAt; public String getId() { return id; } public void setId(String id) { this.id = id; } @@ -35,8 +36,8 @@ public class OrganizationUserAccess { public void setOrganization(String organization) { this.organization = organization; } public List getOperations() { return operations; } public void setOperations(List operations) { this.operations = operations; } - public String getCreatedAt() { return createdAt; } - public void setCreatedAt(String createdAt) { this.createdAt = createdAt; } - public String getUpdatedAt() { return updatedAt; } - public void setUpdatedAt(String updatedAt) { this.updatedAt = updatedAt; } + public Instant getCreatedAt() { return createdAt; } + public void setCreatedAt(Instant createdAt) { this.createdAt = createdAt; } + public Instant getUpdatedAt() { return updatedAt; } + public void setUpdatedAt(Instant updatedAt) { this.updatedAt = updatedAt; } } diff --git a/src/main/java/io/facturapi/models/Payment.java b/src/main/java/io/facturapi/models/Payment.java index dbdc50c..908a62c 100644 --- a/src/main/java/io/facturapi/models/Payment.java +++ b/src/main/java/io/facturapi/models/Payment.java @@ -2,6 +2,7 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; +import java.time.Instant; import java.util.ArrayList; import java.util.List; @@ -11,7 +12,7 @@ public class Payment { private String paymentForm; private String currency; private Double exchange; - private String date; + private Instant date; private List related = new ArrayList<>(); public String getPaymentForm() { return paymentForm; } @@ -20,8 +21,8 @@ public class Payment { public void setCurrency(String currency) { this.currency = currency; } public Double getExchange() { return exchange; } public void setExchange(Double exchange) { this.exchange = exchange; } - public String getDate() { return date; } - public void setDate(String date) { this.date = date; } + public Instant getDate() { return date; } + public void setDate(Instant date) { this.date = date; } public List getRelated() { return related; } public void setRelated(List related) { this.related = related; } } diff --git a/src/main/java/io/facturapi/models/PendingPlanUpdate.java b/src/main/java/io/facturapi/models/PendingPlanUpdate.java index cc104e4..dffa847 100644 --- a/src/main/java/io/facturapi/models/PendingPlanUpdate.java +++ b/src/main/java/io/facturapi/models/PendingPlanUpdate.java @@ -2,15 +2,16 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; +import java.time.Instant; @JsonIgnoreProperties(ignoreUnknown = true) public class PendingPlanUpdate { private String plan; @JsonProperty("scheduled_for") - private String scheduledFor; + private Instant scheduledFor; public String getPlan() { return plan; } public void setPlan(String plan) { this.plan = plan; } - public String getScheduledFor() { return scheduledFor; } - public void setScheduledFor(String scheduledFor) { this.scheduledFor = scheduledFor; } + public Instant getScheduledFor() { return scheduledFor; } + public void setScheduledFor(Instant scheduledFor) { this.scheduledFor = scheduledFor; } } diff --git a/src/main/java/io/facturapi/models/Product.java b/src/main/java/io/facturapi/models/Product.java index 7f1dbcd..207e3eb 100644 --- a/src/main/java/io/facturapi/models/Product.java +++ b/src/main/java/io/facturapi/models/Product.java @@ -2,6 +2,7 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; +import java.time.Instant; import java.util.ArrayList; import java.util.List; @@ -15,7 +16,7 @@ public class Product { private String description; private Double price; @JsonProperty("created_at") - private String createdAt; + private Instant createdAt; @JsonProperty("tax_included") private Boolean taxIncluded; private List taxes = new ArrayList<>(); @@ -40,8 +41,8 @@ public class Product { public void setDescription(String description) { this.description = description; } public Double getPrice() { return price; } public void setPrice(Double price) { this.price = price; } - public String getCreatedAt() { return createdAt; } - public void setCreatedAt(String createdAt) { this.createdAt = createdAt; } + public Instant getCreatedAt() { return createdAt; } + public void setCreatedAt(Instant createdAt) { this.createdAt = createdAt; } public Boolean getTaxIncluded() { return taxIncluded; } public void setTaxIncluded(Boolean taxIncluded) { this.taxIncluded = taxIncluded; } public List getTaxes() { return taxes; } diff --git a/src/main/java/io/facturapi/models/Receipt.java b/src/main/java/io/facturapi/models/Receipt.java index ca613b1..50f87c8 100644 --- a/src/main/java/io/facturapi/models/Receipt.java +++ b/src/main/java/io/facturapi/models/Receipt.java @@ -2,6 +2,7 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; +import java.time.Instant; import java.util.ArrayList; import java.util.List; @@ -9,8 +10,8 @@ public class Receipt { private String id; @JsonProperty("created_at") - private String createdAt; - private String date; + private Instant createdAt; + private Instant date; @JsonProperty("api_version") private Integer apiVersion; private Boolean livemode; @@ -30,7 +31,7 @@ public class Receipt { private Double total; private String invoice; @JsonProperty("expires_at") - private String expiresAt; + private Instant expiresAt; private String key; private String status; @JsonProperty("self_invoice_url") @@ -38,10 +39,10 @@ public class Receipt { public String getId() { return id; } public void setId(String id) { this.id = id; } - public String getCreatedAt() { return createdAt; } - public void setCreatedAt(String createdAt) { this.createdAt = createdAt; } - public String getDate() { return date; } - public void setDate(String date) { this.date = date; } + public Instant getCreatedAt() { return createdAt; } + public void setCreatedAt(Instant createdAt) { this.createdAt = createdAt; } + public Instant getDate() { return date; } + public void setDate(Instant date) { this.date = date; } public Integer getApiVersion() { return apiVersion; } public void setApiVersion(Integer apiVersion) { this.apiVersion = apiVersion; } public Boolean getLivemode() { return livemode; } @@ -68,8 +69,8 @@ public class Receipt { public void setTotal(Double total) { this.total = total; } public String getInvoice() { return invoice; } public void setInvoice(String invoice) { this.invoice = invoice; } - public String getExpiresAt() { return expiresAt; } - public void setExpiresAt(String expiresAt) { this.expiresAt = expiresAt; } + public Instant getExpiresAt() { return expiresAt; } + public void setExpiresAt(Instant expiresAt) { this.expiresAt = expiresAt; } public String getKey() { return key; } public void setKey(String key) { this.key = key; } public String getStatus() { return status; } diff --git a/src/main/java/io/facturapi/models/Retention.java b/src/main/java/io/facturapi/models/Retention.java index f7d3fe9..2c87685 100644 --- a/src/main/java/io/facturapi/models/Retention.java +++ b/src/main/java/io/facturapi/models/Retention.java @@ -2,6 +2,7 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; +import java.time.Instant; import java.util.ArrayList; import java.util.List; @@ -9,7 +10,7 @@ public class Retention { private String id; @JsonProperty("created_at") - private String createdAt; + private Instant createdAt; private CustomerInfo customer; private String organization; private Boolean livemode; @@ -18,7 +19,7 @@ public class Retention { @JsonProperty("external_id") private String externalId; @JsonProperty("fecha_exp") - private String fechaExp; + private Instant fechaExp; @JsonProperty("cve_retenc") private String cveRetenc; @JsonProperty("folio_int") @@ -42,8 +43,8 @@ public class Retention { public String getId() { return id; } public void setId(String id) { this.id = id; } - public String getCreatedAt() { return createdAt; } - public void setCreatedAt(String createdAt) { this.createdAt = createdAt; } + public Instant getCreatedAt() { return createdAt; } + public void setCreatedAt(Instant createdAt) { this.createdAt = createdAt; } public CustomerInfo getCustomer() { return customer; } public void setCustomer(CustomerInfo customer) { this.customer = customer; } public String getOrganization() { return organization; } @@ -56,8 +57,8 @@ public class Retention { public void setUuid(String uuid) { this.uuid = uuid; } public String getExternalId() { return externalId; } public void setExternalId(String externalId) { this.externalId = externalId; } - public String getFechaExp() { return fechaExp; } - public void setFechaExp(String fechaExp) { this.fechaExp = fechaExp; } + public Instant getFechaExp() { return fechaExp; } + public void setFechaExp(Instant fechaExp) { this.fechaExp = fechaExp; } public String getCveRetenc() { return cveRetenc; } public void setCveRetenc(String cveRetenc) { this.cveRetenc = cveRetenc; } public String getFolioInt() { return folioInt; } diff --git a/src/main/java/io/facturapi/models/Stamp.java b/src/main/java/io/facturapi/models/Stamp.java index ad3e884..540e071 100644 --- a/src/main/java/io/facturapi/models/Stamp.java +++ b/src/main/java/io/facturapi/models/Stamp.java @@ -2,10 +2,11 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; +import java.time.Instant; @JsonIgnoreProperties(ignoreUnknown = true) public class Stamp { - private String date; + private Instant date; @JsonProperty("sat_signature") private String satSignature; @JsonProperty("sat_cert_number") @@ -16,8 +17,8 @@ public class Stamp { @JsonProperty("rfc_provider_cert") private String rfcProviderCert; - public String getDate() { return date; } - public void setDate(String date) { this.date = date; } + public Instant getDate() { return date; } + public void setDate(Instant date) { this.date = date; } public String getSatSignature() { return satSignature; } public void setSatSignature(String satSignature) { this.satSignature = satSignature; } public String getSatCertNumber() { return satCertNumber; } diff --git a/src/main/java/io/facturapi/models/Webhook.java b/src/main/java/io/facturapi/models/Webhook.java index c1c33eb..5772dad 100644 --- a/src/main/java/io/facturapi/models/Webhook.java +++ b/src/main/java/io/facturapi/models/Webhook.java @@ -2,6 +2,7 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; +import java.time.Instant; import java.util.ArrayList; import java.util.List; @@ -9,7 +10,7 @@ public class Webhook { private String id; @JsonProperty("created_at") - private String createdAt; + private Instant createdAt; private String organization; private Boolean livemode; @JsonProperty("enabled_events") @@ -21,8 +22,8 @@ public class Webhook { public String getId() { return id; } public void setId(String id) { this.id = id; } - public String getCreatedAt() { return createdAt; } - public void setCreatedAt(String createdAt) { this.createdAt = createdAt; } + public Instant getCreatedAt() { return createdAt; } + public void setCreatedAt(Instant createdAt) { this.createdAt = createdAt; } public String getOrganization() { return organization; } public void setOrganization(String organization) { this.organization = organization; } public Boolean getLivemode() { return livemode; } diff --git a/src/main/java/io/facturapi/models/complements/InvoiceComplement.java b/src/main/java/io/facturapi/models/complements/InvoiceComplement.java index ec80c8d..21e7077 100644 --- a/src/main/java/io/facturapi/models/complements/InvoiceComplement.java +++ b/src/main/java/io/facturapi/models/complements/InvoiceComplement.java @@ -8,6 +8,7 @@ import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; import io.facturapi.models.complements.carta_porte.CartaPorteComplementData; import io.facturapi.models.complements.comercio_exterior.ComercioExteriorComplementData; import io.facturapi.models.complements.nomina.NominaComplementData; @@ -17,6 +18,7 @@ @JsonIgnoreProperties(ignoreUnknown = true) public class InvoiceComplement { private static final ObjectMapper MAPPER = new ObjectMapper() + .registerModule(new JavaTimeModule()) .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); private String type; diff --git a/src/main/java/io/facturapi/models/complements/comercio_exterior/ComercioExteriorComplementData.java b/src/main/java/io/facturapi/models/complements/comercio_exterior/ComercioExteriorComplementData.java index 5535f5e..eadae7b 100644 --- a/src/main/java/io/facturapi/models/complements/comercio_exterior/ComercioExteriorComplementData.java +++ b/src/main/java/io/facturapi/models/complements/comercio_exterior/ComercioExteriorComplementData.java @@ -7,12 +7,14 @@ import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; import java.util.ArrayList; import java.util.List; @JsonIgnoreProperties(ignoreUnknown = true) public class ComercioExteriorComplementData { private static final ObjectMapper MAPPER = new ObjectMapper() + .registerModule(new JavaTimeModule()) .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); @JsonProperty("Version") diff --git a/src/main/java/io/facturapi/models/complements/nomina/NominaComplementData.java b/src/main/java/io/facturapi/models/complements/nomina/NominaComplementData.java index d438001..3a6efaf 100644 --- a/src/main/java/io/facturapi/models/complements/nomina/NominaComplementData.java +++ b/src/main/java/io/facturapi/models/complements/nomina/NominaComplementData.java @@ -2,15 +2,16 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; +import java.time.LocalDate; import java.util.ArrayList; import java.util.List; @JsonIgnoreProperties(ignoreUnknown = true) public class NominaComplementData { @JsonProperty("fecha_inicial_pago") - private String fechaInicialPago; + private LocalDate fechaInicialPago; @JsonProperty("fecha_final_pago") - private String fechaFinalPago; + private LocalDate fechaFinalPago; private NominaPercepciones percepciones; private List deducciones = new ArrayList<>(); @JsonProperty("otros_pagos") @@ -21,14 +22,14 @@ public class NominaComplementData { @JsonProperty("tipo_nomina") private String tipoNomina; @JsonProperty("fecha_pago") - private String fechaPago; + private LocalDate fechaPago; @JsonProperty("num_dias_pagados") private Double numDiasPagados; - public String getFechaInicialPago() { return fechaInicialPago; } - public void setFechaInicialPago(String fechaInicialPago) { this.fechaInicialPago = fechaInicialPago; } - public String getFechaFinalPago() { return fechaFinalPago; } - public void setFechaFinalPago(String fechaFinalPago) { this.fechaFinalPago = fechaFinalPago; } + public LocalDate getFechaInicialPago() { return fechaInicialPago; } + public void setFechaInicialPago(LocalDate fechaInicialPago) { this.fechaInicialPago = fechaInicialPago; } + public LocalDate getFechaFinalPago() { return fechaFinalPago; } + public void setFechaFinalPago(LocalDate fechaFinalPago) { this.fechaFinalPago = fechaFinalPago; } public NominaPercepciones getPercepciones() { return percepciones; } public void setPercepciones(NominaPercepciones percepciones) { this.percepciones = percepciones; } public List getDeducciones() { return deducciones; } @@ -43,8 +44,8 @@ public class NominaComplementData { public void setReceptor(NominaReceptor receptor) { this.receptor = receptor; } public String getTipoNomina() { return tipoNomina; } public void setTipoNomina(String tipoNomina) { this.tipoNomina = tipoNomina; } - public String getFechaPago() { return fechaPago; } - public void setFechaPago(String fechaPago) { this.fechaPago = fechaPago; } + public LocalDate getFechaPago() { return fechaPago; } + public void setFechaPago(LocalDate fechaPago) { this.fechaPago = fechaPago; } public Double getNumDiasPagados() { return numDiasPagados; } public void setNumDiasPagados(Double numDiasPagados) { this.numDiasPagados = numDiasPagados; } } diff --git a/src/main/java/io/facturapi/models/complements/nomina/NominaReceptor.java b/src/main/java/io/facturapi/models/complements/nomina/NominaReceptor.java index 0e18628..6379d83 100644 --- a/src/main/java/io/facturapi/models/complements/nomina/NominaReceptor.java +++ b/src/main/java/io/facturapi/models/complements/nomina/NominaReceptor.java @@ -2,6 +2,7 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; +import java.time.LocalDate; import java.util.ArrayList; import java.util.List; @@ -11,7 +12,7 @@ public class NominaReceptor { @JsonProperty("num_seguridad_social") private String numSeguridadSocial; @JsonProperty("fecha_inicio_rel_laboral") - private String fechaInicioRelLaboral; + private LocalDate fechaInicioRelLaboral; private Object antiguedad; @JsonProperty("tipo_contrato") private String tipoContrato; @@ -46,8 +47,8 @@ public class NominaReceptor { public void setCurp(String curp) { this.curp = curp; } public String getNumSeguridadSocial() { return numSeguridadSocial; } public void setNumSeguridadSocial(String numSeguridadSocial) { this.numSeguridadSocial = numSeguridadSocial; } - public String getFechaInicioRelLaboral() { return fechaInicioRelLaboral; } - public void setFechaInicioRelLaboral(String fechaInicioRelLaboral) { this.fechaInicioRelLaboral = fechaInicioRelLaboral; } + public LocalDate getFechaInicioRelLaboral() { return fechaInicioRelLaboral; } + public void setFechaInicioRelLaboral(LocalDate fechaInicioRelLaboral) { this.fechaInicioRelLaboral = fechaInicioRelLaboral; } public Object getAntiguedad() { return antiguedad; } public void setAntiguedad(Object antiguedad) { this.antiguedad = antiguedad; } public String getTipoContrato() { return tipoContrato; } diff --git a/src/main/java/io/facturapi/models/complements/pago/PagoComplementData.java b/src/main/java/io/facturapi/models/complements/pago/PagoComplementData.java index 391e148..2f45647 100644 --- a/src/main/java/io/facturapi/models/complements/pago/PagoComplementData.java +++ b/src/main/java/io/facturapi/models/complements/pago/PagoComplementData.java @@ -2,6 +2,7 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; +import java.time.Instant; import java.util.ArrayList; import java.util.List; @@ -9,7 +10,7 @@ public class PagoComplementData { @JsonProperty("payment_form") private String paymentForm; - private String date; + private Instant date; @JsonProperty("related_documents") private List relatedDocuments = new ArrayList<>(); private String currency; @@ -27,8 +28,8 @@ public class PagoComplementData { public String getPaymentForm() { return paymentForm; } public void setPaymentForm(String paymentForm) { this.paymentForm = paymentForm; } - public String getDate() { return date; } - public void setDate(String date) { this.date = date; } + public Instant getDate() { return date; } + public void setDate(Instant date) { this.date = date; } public List getRelatedDocuments() { return relatedDocuments; } public void setRelatedDocuments(List relatedDocuments) { this.relatedDocuments = relatedDocuments; } public String getCurrency() { return currency; } diff --git a/src/test/java/io/facturapi/FacturapiResourcesTest.java b/src/test/java/io/facturapi/FacturapiResourcesTest.java index 82cf536..c220e88 100644 --- a/src/test/java/io/facturapi/FacturapiResourcesTest.java +++ b/src/test/java/io/facturapi/FacturapiResourcesTest.java @@ -5,6 +5,9 @@ import static org.junit.jupiter.api.Assertions.assertNotNull; import io.facturapi.http.FacturapiConfig; +import io.facturapi.models.Customer; +import java.time.Instant; +import java.time.LocalDate; import java.util.Map; import org.junit.jupiter.api.Test; @@ -29,6 +32,26 @@ void invoiceCreateUsesExpectedPath() { assertEquals("/v2/invoices?test=true", request.uri().getPath() + "?" + request.uri().getQuery()); } + @Test + void sdkExposesAccessorBasedSurface() { + Facturapi sdk = new Facturapi( + FacturapiConfig.builder("sk_test") + .httpClient(new StubHttpClient()) + .build() + ); + + assertNotNull(sdk.customers()); + assertNotNull(sdk.invoices()); + assertNotNull(sdk.receipts()); + assertNotNull(sdk.retentions()); + assertNotNull(sdk.webhooks()); + assertNotNull(sdk.organizations()); + assertNotNull(sdk.catalogs()); + assertNotNull(sdk.cartaPorteCatalogs()); + assertNotNull(sdk.comercioExteriorCatalogs()); + assertNotNull(sdk.tools()); + } + @Test void organizationListLiveApiKeysIsTyped() { StubHttpClient httpClient = new StubHttpClient(); @@ -53,9 +76,9 @@ void invoiceComplementsAreTypedForPagoNominaAndCustom() { StubHttpClient httpClient = new StubHttpClient(); httpClient.enqueueJson( 200, - "{\"id\":\"inv_1\",\"complements\":[" + - "{\"type\":\"pago\",\"data\":[{\"payment_form\":\"03\",\"date\":\"2026-04-07\",\"currency\":\"MXN\",\"exchange\":1,\"related_documents\":[{\"uuid\":\"f03d5c3f-a93b-443f-927f-e89db2f7f58a\",\"amount\":100,\"installment\":1,\"last_balance\":100,\"currency\":\"MXN\",\"exchange\":1,\"taxes\":[{\"base\":100,\"rate\":0.16,\"type\":\"IVA\",\"factor\":\"Tasa\",\"withholding\":false}]}]}]}," + - "{\"type\":\"nomina\",\"data\":{\"tipo_nomina\":\"O\",\"fecha_pago\":\"2026-04-01\",\"fecha_inicial_pago\":\"2026-03-16\",\"fecha_final_pago\":\"2026-03-31\",\"num_dias_pagados\":15,\"receptor\":{\"curp\":\"TEST900101HDFABC01\",\"tipo_contrato\":\"01\",\"tipo_regimen\":\"02\",\"num_empleado\":\"EMP-1\",\"periodicidad_pago\":\"04\",\"clave_ent_fed\":\"CMX\"},\"percepciones\":{\"percepcion\":[{\"tipo_percepcion\":\"001\",\"clave\":\"P001\",\"importe_gravado\":1000,\"importe_exento\":0}]},\"deducciones\":[{\"tipo_deduccion\":\"002\",\"clave\":\"D001\",\"importe\":100}]}}," + + "{\"id\":\"inv_1\",\"created_at\":\"2026-04-07T10:00:00Z\",\"date\":\"2026-04-07T12:30:00Z\",\"complements\":[" + + "{\"type\":\"pago\",\"data\":[{\"payment_form\":\"03\",\"date\":\"2026-04-07T13:45:00Z\",\"currency\":\"MXN\",\"exchange\":1,\"related_documents\":[{\"uuid\":\"f03d5c3f-a93b-443f-927f-e89db2f7f58a\",\"amount\":100,\"installment\":1,\"last_balance\":100,\"currency\":\"MXN\",\"exchange\":1,\"taxes\":[{\"base\":100,\"rate\":0.16,\"type\":\"IVA\",\"factor\":\"Tasa\",\"withholding\":false}]}]}]}," + + "{\"type\":\"nomina\",\"data\":{\"tipo_nomina\":\"O\",\"fecha_pago\":\"2026-04-01\",\"fecha_inicial_pago\":\"2026-03-16\",\"fecha_final_pago\":\"2026-03-31\",\"num_dias_pagados\":15,\"receptor\":{\"curp\":\"TEST900101HDFABC01\",\"tipo_contrato\":\"01\",\"tipo_regimen\":\"02\",\"num_empleado\":\"EMP-1\",\"periodicidad_pago\":\"04\",\"clave_ent_fed\":\"CMX\",\"fecha_inicio_rel_laboral\":\"2026-01-01\"},\"percepciones\":{\"percepcion\":[{\"tipo_percepcion\":\"001\",\"clave\":\"P001\",\"importe_gravado\":1000,\"importe_exento\":0}]},\"deducciones\":[{\"tipo_deduccion\":\"002\",\"clave\":\"D001\",\"importe\":100}]}}," + "{\"type\":\"custom\",\"data\":\"\"}," + "{\"type\":\"carta_porte\",\"data\":{\"IdCCP\":\"CPC2026040700001\",\"TranspInternac\":\"No\",\"TotalDistRec\":15.4,\"Ubicaciones\":[],\"Mercancias\":{\"Mercancia\":[]}}}," + "{\"type\":\"comercio_exterior\",\"data\":{\"Version\":\"2.0\",\"ClaveDePedimento\":\"A1\",\"CertificadoOrigen\":0,\"TipoCambioUSD\":16.9,\"TotalUSD\":100.5,\"Emisor\":true,\"Propietario\":[{\"id\":\"cus_owner_1\"}],\"Receptor\":{\"NumRegIdTrib\":\"EXT12345\"},\"Destinatario\":[{\"Nombre\":\"Receiver Inc\",\"Domicilio\":[{\"Calle\":\"Main\",\"Estado\":\"TX\",\"Pais\":\"USA\",\"CodigoPostal\":\"77001\"}]}],\"Mercancias\":{\"Mercancia\":[{\"NoIdentificacion\":\"SKU-1\",\"ValorDolares\":100.5}]}}}" + @@ -69,6 +92,8 @@ void invoiceComplementsAreTypedForPagoNominaAndCustom() { ); var invoice = sdk.invoices().retrieve("inv_1"); + assertEquals(Instant.parse("2026-04-07T10:00:00Z"), invoice.getCreatedAt()); + assertEquals(Instant.parse("2026-04-07T12:30:00Z"), invoice.getDate()); assertEquals(5, invoice.getComplements().size()); var pago = invoice.getComplements().get(0); @@ -76,6 +101,7 @@ void invoiceComplementsAreTypedForPagoNominaAndCustom() { assertNotNull(pago.getPagoData()); assertEquals(1, pago.getPagoData().size()); assertEquals("03", pago.getPagoData().get(0).getPaymentForm()); + assertEquals(Instant.parse("2026-04-07T13:45:00Z"), pago.getPagoData().get(0).getDate()); assertEquals("f03d5c3f-a93b-443f-927f-e89db2f7f58a", pago.getPagoData().get(0).getRelatedDocuments().get(0).getUuid()); assertInstanceOf(java.util.List.class, pago.getData()); @@ -84,6 +110,10 @@ void invoiceComplementsAreTypedForPagoNominaAndCustom() { assertNotNull(nomina.getNominaData()); assertEquals("O", nomina.getNominaData().getTipoNomina()); assertEquals("EMP-1", nomina.getNominaData().getReceptor().getNumEmpleado()); + assertEquals(LocalDate.parse("2026-01-01"), nomina.getNominaData().getReceptor().getFechaInicioRelLaboral()); + assertEquals(LocalDate.parse("2026-04-01"), nomina.getNominaData().getFechaPago()); + assertEquals(LocalDate.parse("2026-03-16"), nomina.getNominaData().getFechaInicialPago()); + assertEquals(LocalDate.parse("2026-03-31"), nomina.getNominaData().getFechaFinalPago()); assertEquals("001", nomina.getNominaData().getPercepciones().getPercepcion().get(0).getTipoPercepcion()); var custom = invoice.getComplements().get(2); @@ -109,4 +139,18 @@ void invoiceComplementsAreTypedForPagoNominaAndCustom() { assertEquals("cus_owner_1", comercioExterior.getComercioExteriorData().getPropietario().get(0).getId()); assertEquals("SKU-1", comercioExterior.getComercioExteriorData().getMercancias().getMercancia().get(0).getNoIdentificacion()); } + + @Test + void objectMapperDeserializesJavaTimeTypes() throws Exception { + var mapper = FacturapiConfig.builder("sk_test").build().getObjectMapper(); + + var customer = mapper.readValue( + "{\"created_at\":\"2026-04-07T10:11:12Z\",\"sat_validated_at\":\"2026-04-07T11:11:12Z\",\"edit_link_expires_at\":\"2026-04-08T00:00:00Z\"}", + Customer.class + ); + + assertEquals(Instant.parse("2026-04-07T10:11:12Z"), customer.getCreatedAt()); + assertEquals(Instant.parse("2026-04-07T11:11:12Z"), customer.getSatValidatedAt()); + assertEquals(Instant.parse("2026-04-08T00:00:00Z"), customer.getEditLinkExpiresAt()); + } } From 4b1afc0f7fcb8a825c0626674b1f9efc707b346f Mon Sep 17 00:00:00 2001 From: javorosas Date: Tue, 7 Apr 2026 12:40:19 +0200 Subject: [PATCH 05/22] refactor: type remaining code-like fields --- .../facturapi/enums/CancellationMotive.java | 14 +++++++ .../facturapi/enums/CancellationStatus.java | 23 ++++++++++ .../io/facturapi/enums/InvoiceStatus.java | 21 ++++++++++ .../java/io/facturapi/enums/InvoiceType.java | 14 +++++++ .../java/io/facturapi/enums/IssuingType.java | 19 +++++++++ .../java/io/facturapi/enums/PaymentForm.java | 30 +++++++++++++ .../io/facturapi/enums/PaymentMethod.java | 19 +++++++++ .../java/io/facturapi/enums/TaxFactor.java | 29 ++++++++++++- src/main/java/io/facturapi/enums/TaxType.java | 15 ++++++- .../java/io/facturapi/enums/Taxability.java | 36 ++++++++++++++++ .../java/io/facturapi/models/Invoice.java | 42 +++++++++++-------- .../facturapi/models/InvoiceCancellation.java | 14 ++++--- .../java/io/facturapi/models/LocalTax.java | 14 ++++--- .../java/io/facturapi/models/Payment.java | 7 ++-- .../java/io/facturapi/models/Product.java | 7 ++-- .../java/io/facturapi/models/ProductInfo.java | 7 ++-- .../java/io/facturapi/models/Receipt.java | 7 ++-- src/main/java/io/facturapi/models/Tax.java | 14 ++++--- .../complements/pago/PagoComplementData.java | 7 ++-- .../pago/PaymentRelatedDocument.java | 7 ++-- .../pago/PaymentRelatedDocumentTax.java | 14 ++++--- .../io/facturapi/FacturapiResourcesTest.java | 33 +++++++++++++-- 22 files changed, 327 insertions(+), 66 deletions(-) create mode 100644 src/main/java/io/facturapi/enums/CancellationStatus.java create mode 100644 src/main/java/io/facturapi/enums/InvoiceStatus.java create mode 100644 src/main/java/io/facturapi/enums/IssuingType.java create mode 100644 src/main/java/io/facturapi/enums/PaymentMethod.java create mode 100644 src/main/java/io/facturapi/enums/Taxability.java diff --git a/src/main/java/io/facturapi/enums/CancellationMotive.java b/src/main/java/io/facturapi/enums/CancellationMotive.java index 9f4a60a..12cc6b9 100644 --- a/src/main/java/io/facturapi/enums/CancellationMotive.java +++ b/src/main/java/io/facturapi/enums/CancellationMotive.java @@ -1,5 +1,8 @@ package io.facturapi.enums; +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonValue; + public enum CancellationMotive { ERRORES_CON_RELACION("01"), ERRORES_SIN_RELACION("02"), @@ -12,7 +15,18 @@ public enum CancellationMotive { this.value = value; } + @JsonValue public String value() { return value; } + + @JsonCreator + public static CancellationMotive fromValue(String value) { + for (CancellationMotive item : values()) { + if (item.value.equals(value)) { + return item; + } + } + throw new IllegalArgumentException("Unknown cancellation motive: " + value); + } } diff --git a/src/main/java/io/facturapi/enums/CancellationStatus.java b/src/main/java/io/facturapi/enums/CancellationStatus.java new file mode 100644 index 0000000..6899c83 --- /dev/null +++ b/src/main/java/io/facturapi/enums/CancellationStatus.java @@ -0,0 +1,23 @@ +package io.facturapi.enums; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonValue; + +public enum CancellationStatus { + NONE, + VERIFYING, + PENDING, + ACCEPTED, + REJECTED, + EXPIRED; + + @JsonValue + public String value() { + return name().toLowerCase(); + } + + @JsonCreator + public static CancellationStatus fromValue(String value) { + return CancellationStatus.valueOf(value.toUpperCase()); + } +} diff --git a/src/main/java/io/facturapi/enums/InvoiceStatus.java b/src/main/java/io/facturapi/enums/InvoiceStatus.java new file mode 100644 index 0000000..e2e63b9 --- /dev/null +++ b/src/main/java/io/facturapi/enums/InvoiceStatus.java @@ -0,0 +1,21 @@ +package io.facturapi.enums; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonValue; + +public enum InvoiceStatus { + PENDING, + VALID, + CANCELED, + DRAFT; + + @JsonValue + public String value() { + return name().toLowerCase(); + } + + @JsonCreator + public static InvoiceStatus fromValue(String value) { + return InvoiceStatus.valueOf(value.toUpperCase()); + } +} diff --git a/src/main/java/io/facturapi/enums/InvoiceType.java b/src/main/java/io/facturapi/enums/InvoiceType.java index bed4f8f..08c188b 100644 --- a/src/main/java/io/facturapi/enums/InvoiceType.java +++ b/src/main/java/io/facturapi/enums/InvoiceType.java @@ -1,5 +1,8 @@ package io.facturapi.enums; +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonValue; + public enum InvoiceType { INGRESO("I"), EGRESO("E"), @@ -13,7 +16,18 @@ public enum InvoiceType { this.value = value; } + @JsonValue public String value() { return value; } + + @JsonCreator + public static InvoiceType fromValue(String value) { + for (InvoiceType item : values()) { + if (item.value.equals(value)) { + return item; + } + } + throw new IllegalArgumentException("Unknown invoice type: " + value); + } } diff --git a/src/main/java/io/facturapi/enums/IssuingType.java b/src/main/java/io/facturapi/enums/IssuingType.java new file mode 100644 index 0000000..612b2d3 --- /dev/null +++ b/src/main/java/io/facturapi/enums/IssuingType.java @@ -0,0 +1,19 @@ +package io.facturapi.enums; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonValue; + +public enum IssuingType { + ISSUING, + RECEIVING; + + @JsonValue + public String value() { + return name().toLowerCase(); + } + + @JsonCreator + public static IssuingType fromValue(String value) { + return IssuingType.valueOf(value.toUpperCase()); + } +} diff --git a/src/main/java/io/facturapi/enums/PaymentForm.java b/src/main/java/io/facturapi/enums/PaymentForm.java index 76a036e..5e37bd0 100644 --- a/src/main/java/io/facturapi/enums/PaymentForm.java +++ b/src/main/java/io/facturapi/enums/PaymentForm.java @@ -1,11 +1,30 @@ package io.facturapi.enums; +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonValue; + public enum PaymentForm { EFECTIVO("01"), CHEQUE_NOMINATIVO("02"), TRANSFERENCIA_ELECTRONICA_DE_FONDOS("03"), TARJETA_DE_CREDITO("04"), + MONEDERO_ELECTRONICO("05"), + DINERO_ELECTRONICO("06"), + VALES_DE_DESPENSA("08"), + DACION_EN_PAGO("12"), + PAGO_POR_SUBROGACION("13"), + PAGO_POR_CONSIGNACION("14"), + CONDONACION("15"), + COMPENSACION("17"), + NOVACION("23"), + CONFUSION("24"), + REMISION_DE_DEUDA("25"), + PRESCRIPCION_O_CADUCIDAD("26"), + A_SATISFACCION_DEL_ACREEDOR("27"), TARJETA_DE_DEBITO("28"), + SERVICIO("29"), + APLICACION_DE_ANTICIPOS("30"), + INTERMEDIARIO_PAGOS("31"), POR_DEFINIR("99"); private final String value; @@ -14,7 +33,18 @@ public enum PaymentForm { this.value = value; } + @JsonValue public String value() { return value; } + + @JsonCreator + public static PaymentForm fromValue(String value) { + for (PaymentForm item : values()) { + if (item.value.equals(value)) { + return item; + } + } + throw new IllegalArgumentException("Unknown payment form: " + value); + } } diff --git a/src/main/java/io/facturapi/enums/PaymentMethod.java b/src/main/java/io/facturapi/enums/PaymentMethod.java new file mode 100644 index 0000000..973cbbc --- /dev/null +++ b/src/main/java/io/facturapi/enums/PaymentMethod.java @@ -0,0 +1,19 @@ +package io.facturapi.enums; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonValue; + +public enum PaymentMethod { + PUE, + PPD; + + @JsonValue + public String value() { + return name(); + } + + @JsonCreator + public static PaymentMethod fromValue(String value) { + return PaymentMethod.valueOf(value); + } +} diff --git a/src/main/java/io/facturapi/enums/TaxFactor.java b/src/main/java/io/facturapi/enums/TaxFactor.java index 416e3ae..dd66679 100644 --- a/src/main/java/io/facturapi/enums/TaxFactor.java +++ b/src/main/java/io/facturapi/enums/TaxFactor.java @@ -1,6 +1,31 @@ package io.facturapi.enums; +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonValue; + public enum TaxFactor { - Tasa, - Cuota + TASA("Tasa"), + CUOTA("Cuota"), + EXENTO("Exento"); + + private final String value; + + TaxFactor(String value) { + this.value = value; + } + + @JsonValue + public String value() { + return value; + } + + @JsonCreator + public static TaxFactor fromValue(String value) { + for (TaxFactor item : values()) { + if (item.value.equals(value)) { + return item; + } + } + throw new IllegalArgumentException("Unknown tax factor: " + value); + } } diff --git a/src/main/java/io/facturapi/enums/TaxType.java b/src/main/java/io/facturapi/enums/TaxType.java index cc9ca14..4a12100 100644 --- a/src/main/java/io/facturapi/enums/TaxType.java +++ b/src/main/java/io/facturapi/enums/TaxType.java @@ -1,7 +1,20 @@ package io.facturapi.enums; +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonValue; + public enum TaxType { IVA, IEPS, - ISR + ISR; + + @JsonValue + public String value() { + return name(); + } + + @JsonCreator + public static TaxType fromValue(String value) { + return TaxType.valueOf(value); + } } diff --git a/src/main/java/io/facturapi/enums/Taxability.java b/src/main/java/io/facturapi/enums/Taxability.java new file mode 100644 index 0000000..766db1e --- /dev/null +++ b/src/main/java/io/facturapi/enums/Taxability.java @@ -0,0 +1,36 @@ +package io.facturapi.enums; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonValue; + +public enum Taxability { + NOT_SUBJECT_TO_TAX("01"), + SUBJECT_TO_TAX("02"), + SUBJECT_TO_TAX_NOT_BREAKDOWN_REQUIRED("03"), + SUBJECT_TO_TAX_NO_TAX_CAUSED("04"), + SUBJECT_TO_TAX_VAT_CREDIT_PODEBI("05"), + SUBJECT_TO_TAX_IVA_NO_TRANSFERRED("06"), + NOT_SUBJECT_TO_TAX_IVA_BUT_IEPS_BREAKDOWN_REQUIRED("07"), + NOT_SUBJECT_TO_TAX_IVA_AND_IEPS_BREAKDOWN_NOT_REQUIRED("08"); + + private final String value; + + Taxability(String value) { + this.value = value; + } + + @JsonValue + public String value() { + return value; + } + + @JsonCreator + public static Taxability fromValue(String value) { + for (Taxability item : values()) { + if (item.value.equals(value)) { + return item; + } + } + throw new IllegalArgumentException("Unknown taxability: " + value); + } +} diff --git a/src/main/java/io/facturapi/models/Invoice.java b/src/main/java/io/facturapi/models/Invoice.java index 90076c5..e2bd751 100644 --- a/src/main/java/io/facturapi/models/Invoice.java +++ b/src/main/java/io/facturapi/models/Invoice.java @@ -2,6 +2,12 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; +import io.facturapi.enums.CancellationStatus; +import io.facturapi.enums.InvoiceStatus; +import io.facturapi.enums.InvoiceType; +import io.facturapi.enums.IssuingType; +import io.facturapi.enums.PaymentForm; +import io.facturapi.enums.PaymentMethod; import io.facturapi.models.complements.InvoiceComplement; import java.time.Instant; import java.util.ArrayList; @@ -16,17 +22,17 @@ public class Invoice { private Instant createdAt; private Instant date; @JsonProperty("issuer_type") - private String issuerType; - private String type; - private String status; + private IssuingType issuerType; + private InvoiceType type; + private InvoiceStatus status; @JsonProperty("cfdi_version") private Integer cfdiVersion; @JsonProperty("issuer_info") private CustomerInfo issuerInfo; @JsonProperty("payment_form") - private String paymentForm; + private PaymentForm paymentForm; @JsonProperty("payment_method") - private String paymentMethod; + private PaymentMethod paymentMethod; private String currency; private Double exchange; private String uuid; @@ -47,7 +53,7 @@ public class Invoice { @JsonProperty("verification_carta_porte") private String verificationCartaPorte; @JsonProperty("cancellation_status") - private String cancellationStatus; + private CancellationStatus cancellationStatus; @JsonProperty("external_id") private String externalId; @JsonProperty("idempotency_key") @@ -80,20 +86,20 @@ public class Invoice { public void setCreatedAt(Instant createdAt) { this.createdAt = createdAt; } public Instant getDate() { return date; } public void setDate(Instant date) { this.date = date; } - public String getIssuerType() { return issuerType; } - public void setIssuerType(String issuerType) { this.issuerType = issuerType; } - public String getType() { return type; } - public void setType(String type) { this.type = type; } - public String getStatus() { return status; } - public void setStatus(String status) { this.status = status; } + public IssuingType getIssuerType() { return issuerType; } + public void setIssuerType(IssuingType issuerType) { this.issuerType = issuerType; } + public InvoiceType getType() { return type; } + public void setType(InvoiceType type) { this.type = type; } + public InvoiceStatus getStatus() { return status; } + public void setStatus(InvoiceStatus status) { this.status = status; } public Integer getCfdiVersion() { return cfdiVersion; } public void setCfdiVersion(Integer cfdiVersion) { this.cfdiVersion = cfdiVersion; } public CustomerInfo getIssuerInfo() { return issuerInfo; } public void setIssuerInfo(CustomerInfo issuerInfo) { this.issuerInfo = issuerInfo; } - public String getPaymentForm() { return paymentForm; } - public void setPaymentForm(String paymentForm) { this.paymentForm = paymentForm; } - public String getPaymentMethod() { return paymentMethod; } - public void setPaymentMethod(String paymentMethod) { this.paymentMethod = paymentMethod; } + public PaymentForm getPaymentForm() { return paymentForm; } + public void setPaymentForm(PaymentForm paymentForm) { this.paymentForm = paymentForm; } + public PaymentMethod getPaymentMethod() { return paymentMethod; } + public void setPaymentMethod(PaymentMethod paymentMethod) { this.paymentMethod = paymentMethod; } public String getCurrency() { return currency; } public void setCurrency(String currency) { this.currency = currency; } public Double getExchange() { return exchange; } @@ -122,8 +128,8 @@ public class Invoice { public void setVerificationUrl(String verificationUrl) { this.verificationUrl = verificationUrl; } public String getVerificationCartaPorte() { return verificationCartaPorte; } public void setVerificationCartaPorte(String verificationCartaPorte) { this.verificationCartaPorte = verificationCartaPorte; } - public String getCancellationStatus() { return cancellationStatus; } - public void setCancellationStatus(String cancellationStatus) { this.cancellationStatus = cancellationStatus; } + public CancellationStatus getCancellationStatus() { return cancellationStatus; } + public void setCancellationStatus(CancellationStatus cancellationStatus) { this.cancellationStatus = cancellationStatus; } public String getExternalId() { return externalId; } public void setExternalId(String externalId) { this.externalId = externalId; } public String getIdempotencyKey() { return idempotencyKey; } diff --git a/src/main/java/io/facturapi/models/InvoiceCancellation.java b/src/main/java/io/facturapi/models/InvoiceCancellation.java index 5fd641f..c5bd51a 100644 --- a/src/main/java/io/facturapi/models/InvoiceCancellation.java +++ b/src/main/java/io/facturapi/models/InvoiceCancellation.java @@ -2,27 +2,29 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; +import io.facturapi.enums.CancellationMotive; +import io.facturapi.enums.CancellationStatus; import java.time.Instant; @JsonIgnoreProperties(ignoreUnknown = true) public class InvoiceCancellation { @JsonProperty("requested_at") private Instant requestedAt; - private String status; + private CancellationStatus status; @JsonProperty("last_checked") private Instant lastChecked; - private String motive; + private CancellationMotive motive; @JsonProperty("substitution_uuid") private String substitutionUuid; public Instant getRequestedAt() { return requestedAt; } public void setRequestedAt(Instant requestedAt) { this.requestedAt = requestedAt; } - public String getStatus() { return status; } - public void setStatus(String status) { this.status = status; } + public CancellationStatus getStatus() { return status; } + public void setStatus(CancellationStatus status) { this.status = status; } public Instant getLastChecked() { return lastChecked; } public void setLastChecked(Instant lastChecked) { this.lastChecked = lastChecked; } - public String getMotive() { return motive; } - public void setMotive(String motive) { this.motive = motive; } + public CancellationMotive getMotive() { return motive; } + public void setMotive(CancellationMotive motive) { this.motive = motive; } public String getSubstitutionUuid() { return substitutionUuid; } public void setSubstitutionUuid(String substitutionUuid) { this.substitutionUuid = substitutionUuid; } } diff --git a/src/main/java/io/facturapi/models/LocalTax.java b/src/main/java/io/facturapi/models/LocalTax.java index bee5119..88bdf9c 100644 --- a/src/main/java/io/facturapi/models/LocalTax.java +++ b/src/main/java/io/facturapi/models/LocalTax.java @@ -1,14 +1,16 @@ package io.facturapi.models; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import io.facturapi.enums.TaxFactor; +import io.facturapi.enums.TaxType; @JsonIgnoreProperties(ignoreUnknown = true) public class LocalTax { private Double base; private Double rate; - private String type; + private TaxType type; private Boolean withholding; - private String factor; + private TaxFactor factor; public Double getBase() { return base; @@ -26,11 +28,11 @@ public void setRate(Double rate) { this.rate = rate; } - public String getType() { + public TaxType getType() { return type; } - public void setType(String type) { + public void setType(TaxType type) { this.type = type; } @@ -42,11 +44,11 @@ public void setWithholding(Boolean withholding) { this.withholding = withholding; } - public String getFactor() { + public TaxFactor getFactor() { return factor; } - public void setFactor(String factor) { + public void setFactor(TaxFactor factor) { this.factor = factor; } } diff --git a/src/main/java/io/facturapi/models/Payment.java b/src/main/java/io/facturapi/models/Payment.java index 908a62c..43b38ce 100644 --- a/src/main/java/io/facturapi/models/Payment.java +++ b/src/main/java/io/facturapi/models/Payment.java @@ -2,6 +2,7 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; +import io.facturapi.enums.PaymentForm; import java.time.Instant; import java.util.ArrayList; import java.util.List; @@ -9,14 +10,14 @@ @JsonIgnoreProperties(ignoreUnknown = true) public class Payment { @JsonProperty("payment_form") - private String paymentForm; + private PaymentForm paymentForm; private String currency; private Double exchange; private Instant date; private List related = new ArrayList<>(); - public String getPaymentForm() { return paymentForm; } - public void setPaymentForm(String paymentForm) { this.paymentForm = paymentForm; } + public PaymentForm getPaymentForm() { return paymentForm; } + public void setPaymentForm(PaymentForm paymentForm) { this.paymentForm = paymentForm; } public String getCurrency() { return currency; } public void setCurrency(String currency) { this.currency = currency; } public Double getExchange() { return exchange; } diff --git a/src/main/java/io/facturapi/models/Product.java b/src/main/java/io/facturapi/models/Product.java index 207e3eb..dc6d3fc 100644 --- a/src/main/java/io/facturapi/models/Product.java +++ b/src/main/java/io/facturapi/models/Product.java @@ -2,6 +2,7 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; +import io.facturapi.enums.Taxability; import java.time.Instant; import java.util.ArrayList; import java.util.List; @@ -27,7 +28,7 @@ public class Product { @JsonProperty("unit_name") private String unitName; private String sku; - private String taxability; + private Taxability taxability; public String getId() { return id; } public void setId(String id) { this.id = id; } @@ -55,6 +56,6 @@ public class Product { public void setUnitName(String unitName) { this.unitName = unitName; } public String getSku() { return sku; } public void setSku(String sku) { this.sku = sku; } - public String getTaxability() { return taxability; } - public void setTaxability(String taxability) { this.taxability = taxability; } + public Taxability getTaxability() { return taxability; } + public void setTaxability(Taxability taxability) { this.taxability = taxability; } } diff --git a/src/main/java/io/facturapi/models/ProductInfo.java b/src/main/java/io/facturapi/models/ProductInfo.java index b73c139..5abdac5 100644 --- a/src/main/java/io/facturapi/models/ProductInfo.java +++ b/src/main/java/io/facturapi/models/ProductInfo.java @@ -2,6 +2,7 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; +import io.facturapi.enums.Taxability; import java.util.ArrayList; import java.util.List; @@ -16,7 +17,7 @@ public class ProductInfo { @JsonProperty("unit_name") private String unitName; private Double price; - private String taxability; + private Taxability taxability; @JsonProperty("tax_included") private Boolean taxIncluded; private List taxes = new ArrayList<>(); @@ -36,8 +37,8 @@ public class ProductInfo { public void setUnitName(String unitName) { this.unitName = unitName; } public Double getPrice() { return price; } public void setPrice(Double price) { this.price = price; } - public String getTaxability() { return taxability; } - public void setTaxability(String taxability) { this.taxability = taxability; } + public Taxability getTaxability() { return taxability; } + public void setTaxability(Taxability taxability) { this.taxability = taxability; } public Boolean getTaxIncluded() { return taxIncluded; } public void setTaxIncluded(Boolean taxIncluded) { this.taxIncluded = taxIncluded; } public List getTaxes() { return taxes; } diff --git a/src/main/java/io/facturapi/models/Receipt.java b/src/main/java/io/facturapi/models/Receipt.java index 50f87c8..f4b377c 100644 --- a/src/main/java/io/facturapi/models/Receipt.java +++ b/src/main/java/io/facturapi/models/Receipt.java @@ -2,6 +2,7 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; +import io.facturapi.enums.PaymentForm; import java.time.Instant; import java.util.ArrayList; import java.util.List; @@ -24,7 +25,7 @@ public class Receipt { private String idempotencyKey; private String branch; @JsonProperty("payment_form") - private String paymentForm; + private PaymentForm paymentForm; private List items = new ArrayList<>(); private String currency; private Double exchange; @@ -57,8 +58,8 @@ public class Receipt { public void setIdempotencyKey(String idempotencyKey) { this.idempotencyKey = idempotencyKey; } public String getBranch() { return branch; } public void setBranch(String branch) { this.branch = branch; } - public String getPaymentForm() { return paymentForm; } - public void setPaymentForm(String paymentForm) { this.paymentForm = paymentForm; } + public PaymentForm getPaymentForm() { return paymentForm; } + public void setPaymentForm(PaymentForm paymentForm) { this.paymentForm = paymentForm; } public List getItems() { return items; } public void setItems(List items) { this.items = items; } public String getCurrency() { return currency; } diff --git a/src/main/java/io/facturapi/models/Tax.java b/src/main/java/io/facturapi/models/Tax.java index 5ef0a41..155a15b 100644 --- a/src/main/java/io/facturapi/models/Tax.java +++ b/src/main/java/io/facturapi/models/Tax.java @@ -1,15 +1,17 @@ package io.facturapi.models; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import io.facturapi.enums.TaxFactor; +import io.facturapi.enums.TaxType; @JsonIgnoreProperties(ignoreUnknown = true) public class Tax { private Double base; private Double amount; private Double rate; - private String type; + private TaxType type; private Boolean withholding; - private String factor; + private TaxFactor factor; public Double getBase() { return base; @@ -35,11 +37,11 @@ public void setRate(Double rate) { this.rate = rate; } - public String getType() { + public TaxType getType() { return type; } - public void setType(String type) { + public void setType(TaxType type) { this.type = type; } @@ -51,11 +53,11 @@ public void setWithholding(Boolean withholding) { this.withholding = withholding; } - public String getFactor() { + public TaxFactor getFactor() { return factor; } - public void setFactor(String factor) { + public void setFactor(TaxFactor factor) { this.factor = factor; } } diff --git a/src/main/java/io/facturapi/models/complements/pago/PagoComplementData.java b/src/main/java/io/facturapi/models/complements/pago/PagoComplementData.java index 2f45647..ebe4896 100644 --- a/src/main/java/io/facturapi/models/complements/pago/PagoComplementData.java +++ b/src/main/java/io/facturapi/models/complements/pago/PagoComplementData.java @@ -2,6 +2,7 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; +import io.facturapi.enums.PaymentForm; import java.time.Instant; import java.util.ArrayList; import java.util.List; @@ -9,7 +10,7 @@ @JsonIgnoreProperties(ignoreUnknown = true) public class PagoComplementData { @JsonProperty("payment_form") - private String paymentForm; + private PaymentForm paymentForm; private Instant date; @JsonProperty("related_documents") private List relatedDocuments = new ArrayList<>(); @@ -26,8 +27,8 @@ public class PagoComplementData { private String cadPago; private String selloPago; - public String getPaymentForm() { return paymentForm; } - public void setPaymentForm(String paymentForm) { this.paymentForm = paymentForm; } + public PaymentForm getPaymentForm() { return paymentForm; } + public void setPaymentForm(PaymentForm paymentForm) { this.paymentForm = paymentForm; } public Instant getDate() { return date; } public void setDate(Instant date) { this.date = date; } public List getRelatedDocuments() { return relatedDocuments; } diff --git a/src/main/java/io/facturapi/models/complements/pago/PaymentRelatedDocument.java b/src/main/java/io/facturapi/models/complements/pago/PaymentRelatedDocument.java index 6b0d2be..3c38773 100644 --- a/src/main/java/io/facturapi/models/complements/pago/PaymentRelatedDocument.java +++ b/src/main/java/io/facturapi/models/complements/pago/PaymentRelatedDocument.java @@ -2,6 +2,7 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; +import io.facturapi.enums.Taxability; import java.util.ArrayList; import java.util.List; @@ -17,7 +18,7 @@ public class PaymentRelatedDocument { @JsonProperty("folio_number") private String folioNumber; private String series; - private String taxability; + private Taxability taxability; private List taxes = new ArrayList<>(); public String getUuid() { return uuid; } @@ -36,8 +37,8 @@ public class PaymentRelatedDocument { public void setFolioNumber(String folioNumber) { this.folioNumber = folioNumber; } public String getSeries() { return series; } public void setSeries(String series) { this.series = series; } - public String getTaxability() { return taxability; } - public void setTaxability(String taxability) { this.taxability = taxability; } + public Taxability getTaxability() { return taxability; } + public void setTaxability(Taxability taxability) { this.taxability = taxability; } public List getTaxes() { return taxes; } public void setTaxes(List taxes) { this.taxes = taxes; } } diff --git a/src/main/java/io/facturapi/models/complements/pago/PaymentRelatedDocumentTax.java b/src/main/java/io/facturapi/models/complements/pago/PaymentRelatedDocumentTax.java index 5c08d6e..0e9ac78 100644 --- a/src/main/java/io/facturapi/models/complements/pago/PaymentRelatedDocumentTax.java +++ b/src/main/java/io/facturapi/models/complements/pago/PaymentRelatedDocumentTax.java @@ -1,23 +1,25 @@ package io.facturapi.models.complements.pago; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import io.facturapi.enums.TaxFactor; +import io.facturapi.enums.TaxType; @JsonIgnoreProperties(ignoreUnknown = true) public class PaymentRelatedDocumentTax { private Double base; private Double rate; - private String type; - private String factor; + private TaxType type; + private TaxFactor factor; private Boolean withholding; public Double getBase() { return base; } public void setBase(Double base) { this.base = base; } public Double getRate() { return rate; } public void setRate(Double rate) { this.rate = rate; } - public String getType() { return type; } - public void setType(String type) { this.type = type; } - public String getFactor() { return factor; } - public void setFactor(String factor) { this.factor = factor; } + public TaxType getType() { return type; } + public void setType(TaxType type) { this.type = type; } + public TaxFactor getFactor() { return factor; } + public void setFactor(TaxFactor factor) { this.factor = factor; } public Boolean getWithholding() { return withholding; } public void setWithholding(Boolean withholding) { this.withholding = withholding; } } diff --git a/src/test/java/io/facturapi/FacturapiResourcesTest.java b/src/test/java/io/facturapi/FacturapiResourcesTest.java index c220e88..144853b 100644 --- a/src/test/java/io/facturapi/FacturapiResourcesTest.java +++ b/src/test/java/io/facturapi/FacturapiResourcesTest.java @@ -4,6 +4,15 @@ import static org.junit.jupiter.api.Assertions.assertInstanceOf; import static org.junit.jupiter.api.Assertions.assertNotNull; +import io.facturapi.enums.CancellationStatus; +import io.facturapi.enums.InvoiceStatus; +import io.facturapi.enums.InvoiceType; +import io.facturapi.enums.IssuingType; +import io.facturapi.enums.PaymentForm; +import io.facturapi.enums.PaymentMethod; +import io.facturapi.enums.TaxFactor; +import io.facturapi.enums.TaxType; +import io.facturapi.enums.Taxability; import io.facturapi.http.FacturapiConfig; import io.facturapi.models.Customer; import java.time.Instant; @@ -76,8 +85,8 @@ void invoiceComplementsAreTypedForPagoNominaAndCustom() { StubHttpClient httpClient = new StubHttpClient(); httpClient.enqueueJson( 200, - "{\"id\":\"inv_1\",\"created_at\":\"2026-04-07T10:00:00Z\",\"date\":\"2026-04-07T12:30:00Z\",\"complements\":[" + - "{\"type\":\"pago\",\"data\":[{\"payment_form\":\"03\",\"date\":\"2026-04-07T13:45:00Z\",\"currency\":\"MXN\",\"exchange\":1,\"related_documents\":[{\"uuid\":\"f03d5c3f-a93b-443f-927f-e89db2f7f58a\",\"amount\":100,\"installment\":1,\"last_balance\":100,\"currency\":\"MXN\",\"exchange\":1,\"taxes\":[{\"base\":100,\"rate\":0.16,\"type\":\"IVA\",\"factor\":\"Tasa\",\"withholding\":false}]}]}]}," + + "{\"id\":\"inv_1\",\"created_at\":\"2026-04-07T10:00:00Z\",\"date\":\"2026-04-07T12:30:00Z\",\"issuer_type\":\"issuing\",\"type\":\"P\",\"status\":\"valid\",\"payment_form\":\"03\",\"payment_method\":\"PUE\",\"cancellation_status\":\"none\",\"complements\":[" + + "{\"type\":\"pago\",\"data\":[{\"payment_form\":\"03\",\"date\":\"2026-04-07T13:45:00Z\",\"currency\":\"MXN\",\"exchange\":1,\"related_documents\":[{\"uuid\":\"f03d5c3f-a93b-443f-927f-e89db2f7f58a\",\"amount\":100,\"installment\":1,\"last_balance\":100,\"currency\":\"MXN\",\"exchange\":1,\"taxability\":\"02\",\"taxes\":[{\"base\":100,\"rate\":0.16,\"type\":\"IVA\",\"factor\":\"Tasa\",\"withholding\":false}]}]}]}," + "{\"type\":\"nomina\",\"data\":{\"tipo_nomina\":\"O\",\"fecha_pago\":\"2026-04-01\",\"fecha_inicial_pago\":\"2026-03-16\",\"fecha_final_pago\":\"2026-03-31\",\"num_dias_pagados\":15,\"receptor\":{\"curp\":\"TEST900101HDFABC01\",\"tipo_contrato\":\"01\",\"tipo_regimen\":\"02\",\"num_empleado\":\"EMP-1\",\"periodicidad_pago\":\"04\",\"clave_ent_fed\":\"CMX\",\"fecha_inicio_rel_laboral\":\"2026-01-01\"},\"percepciones\":{\"percepcion\":[{\"tipo_percepcion\":\"001\",\"clave\":\"P001\",\"importe_gravado\":1000,\"importe_exento\":0}]},\"deducciones\":[{\"tipo_deduccion\":\"002\",\"clave\":\"D001\",\"importe\":100}]}}," + "{\"type\":\"custom\",\"data\":\"\"}," + "{\"type\":\"carta_porte\",\"data\":{\"IdCCP\":\"CPC2026040700001\",\"TranspInternac\":\"No\",\"TotalDistRec\":15.4,\"Ubicaciones\":[],\"Mercancias\":{\"Mercancia\":[]}}}," + @@ -94,15 +103,24 @@ void invoiceComplementsAreTypedForPagoNominaAndCustom() { var invoice = sdk.invoices().retrieve("inv_1"); assertEquals(Instant.parse("2026-04-07T10:00:00Z"), invoice.getCreatedAt()); assertEquals(Instant.parse("2026-04-07T12:30:00Z"), invoice.getDate()); + assertEquals(IssuingType.ISSUING, invoice.getIssuerType()); + assertEquals(InvoiceType.PAGO, invoice.getType()); + assertEquals(InvoiceStatus.VALID, invoice.getStatus()); + assertEquals(PaymentForm.TRANSFERENCIA_ELECTRONICA_DE_FONDOS, invoice.getPaymentForm()); + assertEquals(PaymentMethod.PUE, invoice.getPaymentMethod()); + assertEquals(CancellationStatus.NONE, invoice.getCancellationStatus()); assertEquals(5, invoice.getComplements().size()); var pago = invoice.getComplements().get(0); assertEquals("pago", pago.getType()); assertNotNull(pago.getPagoData()); assertEquals(1, pago.getPagoData().size()); - assertEquals("03", pago.getPagoData().get(0).getPaymentForm()); + assertEquals(PaymentForm.TRANSFERENCIA_ELECTRONICA_DE_FONDOS, pago.getPagoData().get(0).getPaymentForm()); assertEquals(Instant.parse("2026-04-07T13:45:00Z"), pago.getPagoData().get(0).getDate()); assertEquals("f03d5c3f-a93b-443f-927f-e89db2f7f58a", pago.getPagoData().get(0).getRelatedDocuments().get(0).getUuid()); + assertEquals(Taxability.SUBJECT_TO_TAX, pago.getPagoData().get(0).getRelatedDocuments().get(0).getTaxability()); + assertEquals(TaxType.IVA, pago.getPagoData().get(0).getRelatedDocuments().get(0).getTaxes().get(0).getType()); + assertEquals(TaxFactor.TASA, pago.getPagoData().get(0).getRelatedDocuments().get(0).getTaxes().get(0).getFactor()); assertInstanceOf(java.util.List.class, pago.getData()); var nomina = invoice.getComplements().get(1); @@ -153,4 +171,13 @@ void objectMapperDeserializesJavaTimeTypes() throws Exception { assertEquals(Instant.parse("2026-04-07T11:11:12Z"), customer.getSatValidatedAt()); assertEquals(Instant.parse("2026-04-08T00:00:00Z"), customer.getEditLinkExpiresAt()); } + + @Test + void objectMapperDeserializesCodeEnums() throws Exception { + var mapper = FacturapiConfig.builder("sk_test").build().getObjectMapper(); + + var tax = mapper.readValue("{\"type\":\"IEPS\",\"factor\":\"Exento\"}", io.facturapi.models.Tax.class); + assertEquals(TaxType.IEPS, tax.getType()); + assertEquals(TaxFactor.EXENTO, tax.getFactor()); + } } From 5e9e2e01a7e9042be7a0570923732db439ba7fc8 Mon Sep 17 00:00:00 2001 From: javorosas Date: Tue, 7 Apr 2026 12:46:27 +0200 Subject: [PATCH 06/22] feat: add streaming download helpers --- .../facturapi/http/FacturapiHttpClient.java | 45 +++++++++++++++ .../facturapi/resources/InvoicesResource.java | 56 +++++++++++++++++++ .../facturapi/resources/ReceiptsResource.java | 12 ++++ .../resources/RetentionsResource.java | 34 +++++++++++ .../io/facturapi/FacturapiResourcesTest.java | 21 +++++++ .../java/io/facturapi/StubHttpClient.java | 50 ++++++++++++++++- 6 files changed, 217 insertions(+), 1 deletion(-) diff --git a/src/main/java/io/facturapi/http/FacturapiHttpClient.java b/src/main/java/io/facturapi/http/FacturapiHttpClient.java index b0754a7..6542f93 100644 --- a/src/main/java/io/facturapi/http/FacturapiHttpClient.java +++ b/src/main/java/io/facturapi/http/FacturapiHttpClient.java @@ -5,6 +5,7 @@ import com.fasterxml.jackson.databind.ObjectMapper; import io.facturapi.FacturapiException; import java.io.IOException; +import java.io.InputStream; import java.net.URI; import java.net.URLEncoder; import java.net.http.HttpClient; @@ -82,6 +83,14 @@ public byte[] postBytes(String path, Object body) { return requestBytes("POST", path, body); } + public InputStream getStream(String path) { + return requestStream("GET", path, null); + } + + public InputStream postStream(String path, Object body) { + return requestStream("POST", path, body); + } + private JsonNode requestJsonNode( String method, String path, @@ -126,6 +135,42 @@ private byte[] requestBytes(String method, String path, Object body) { } } + private InputStream requestStream(String method, String path, Object body) { + try { + HttpRequest request = buildRequest(method, path, null, body, null); + HttpResponse response = httpClient.send(request, HttpResponse.BodyHandlers.ofInputStream()); + int statusCode = response.statusCode(); + if (statusCode < 200 || statusCode >= 300) { + byte[] responseBytes; + try (InputStream errorStream = response.body()) { + responseBytes = errorStream == null ? new byte[0] : errorStream.readAllBytes(); + } + String bodyText = responseBytes.length == 0 ? "" : new String(responseBytes, StandardCharsets.UTF_8); + String message = "Request failed with status " + statusCode; + try { + JsonNode error = objectMapper.readTree(bodyText); + JsonNode messageNode = firstDefined(error, "message", "error", "detail"); + if (messageNode != null && messageNode.isTextual()) { + message = messageNode.asText(); + } else if (!bodyText.isEmpty()) { + message = bodyText; + } + } catch (Exception ignored) { + if (!bodyText.isEmpty()) { + message = bodyText; + } + } + throw new FacturapiException(message, statusCode, bodyText); + } + return response.body(); + } catch (IOException e) { + throw new FacturapiException("I/O error when calling Facturapi API", e); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new FacturapiException("Request interrupted", e); + } + } + private T convert(JsonNode node, Class type) { if (type == Void.class) { return null; diff --git a/src/main/java/io/facturapi/resources/InvoicesResource.java b/src/main/java/io/facturapi/resources/InvoicesResource.java index 9befb3a..f0d2911 100644 --- a/src/main/java/io/facturapi/resources/InvoicesResource.java +++ b/src/main/java/io/facturapi/resources/InvoicesResource.java @@ -5,6 +5,7 @@ import io.facturapi.models.GenericResponse; import io.facturapi.models.Invoice; import io.facturapi.models.SearchResult; +import java.io.InputStream; import java.util.Map; public class InvoicesResource extends BaseResource { @@ -86,6 +87,17 @@ public byte[] downloadPdf(String id) { return client.getBytes("/invoices/" + id + "/pdf"); } + /** + * Opens a streaming invoice PDF download. + * + * @param id Invoice id. + * @return PDF stream. Caller owns closing it. + * @see API reference + */ + public InputStream downloadPdfStream(String id) { + return client.getStream("/invoices/" + id + "/pdf"); + } + /** * Downloads an invoice XML file. * @@ -97,6 +109,17 @@ public byte[] downloadXml(String id) { return client.getBytes("/invoices/" + id + "/xml"); } + /** + * Opens a streaming invoice XML download. + * + * @param id Invoice id. + * @return XML stream. Caller owns closing it. + * @see API reference + */ + public InputStream downloadXmlStream(String id) { + return client.getStream("/invoices/" + id + "/xml"); + } + /** * Downloads an invoice ZIP package with PDF and XML. * @@ -108,6 +131,17 @@ public byte[] downloadZip(String id) { return client.getBytes("/invoices/" + id + "/zip"); } + /** + * Opens a streaming invoice ZIP download. + * + * @param id Invoice id. + * @return ZIP stream. Caller owns closing it. + * @see API reference + */ + public InputStream downloadZipStream(String id) { + return client.getStream("/invoices/" + id + "/zip"); + } + /** * Downloads the cancellation receipt XML file. * @@ -119,6 +153,17 @@ public byte[] downloadCancellationReceiptXml(String id) { return client.getBytes("/invoices/" + id + "/cancellation_receipt/xml"); } + /** + * Opens a streaming cancellation receipt XML download. + * + * @param id Invoice id. + * @return XML stream. Caller owns closing it. + * @see API reference + */ + public InputStream downloadCancellationReceiptXmlStream(String id) { + return client.getStream("/invoices/" + id + "/cancellation_receipt/xml"); + } + /** * Downloads the cancellation receipt PDF file. * @@ -130,6 +175,17 @@ public byte[] downloadCancellationReceiptPdf(String id) { return client.getBytes("/invoices/" + id + "/cancellation_receipt/pdf"); } + /** + * Opens a streaming cancellation receipt PDF download. + * + * @param id Invoice id. + * @return PDF stream. Caller owns closing it. + * @see API reference + */ + public InputStream downloadCancellationReceiptPdfStream(String id) { + return client.getStream("/invoices/" + id + "/cancellation_receipt/pdf"); + } + /** * Updates a draft invoice. * diff --git a/src/main/java/io/facturapi/resources/ReceiptsResource.java b/src/main/java/io/facturapi/resources/ReceiptsResource.java index 17d3357..faa6d4b 100644 --- a/src/main/java/io/facturapi/resources/ReceiptsResource.java +++ b/src/main/java/io/facturapi/resources/ReceiptsResource.java @@ -6,6 +6,7 @@ import io.facturapi.models.Invoice; import io.facturapi.models.Receipt; import io.facturapi.models.SearchResult; +import java.io.InputStream; import java.util.Map; public class ReceiptsResource extends BaseResource { @@ -107,4 +108,15 @@ public GenericResponse sendByEmail(String id, Map data) { public byte[] downloadPdf(String id) { return client.getBytes("/receipts/" + id + "/pdf"); } + + /** + * Opens a streaming receipt PDF download. + * + * @param id Receipt id. + * @return PDF stream. Caller owns closing it. + * @see API reference + */ + public InputStream downloadPdfStream(String id) { + return client.getStream("/receipts/" + id + "/pdf"); + } } diff --git a/src/main/java/io/facturapi/resources/RetentionsResource.java b/src/main/java/io/facturapi/resources/RetentionsResource.java index 64653f4..4fd50fc 100644 --- a/src/main/java/io/facturapi/resources/RetentionsResource.java +++ b/src/main/java/io/facturapi/resources/RetentionsResource.java @@ -5,6 +5,7 @@ import io.facturapi.models.GenericResponse; import io.facturapi.models.Retention; import io.facturapi.models.SearchResult; +import java.io.InputStream; import java.util.Map; public class RetentionsResource extends BaseResource { @@ -85,6 +86,17 @@ public byte[] downloadPdf(String id) { return client.getBytes("/retentions/" + id + "/pdf"); } + /** + * Opens a streaming retention PDF download. + * + * @param id Retention id. + * @return PDF stream. Caller owns closing it. + * @see API reference + */ + public InputStream downloadPdfStream(String id) { + return client.getStream("/retentions/" + id + "/pdf"); + } + /** * Downloads a retention XML file. * @@ -96,6 +108,17 @@ public byte[] downloadXml(String id) { return client.getBytes("/retentions/" + id + "/xml"); } + /** + * Opens a streaming retention XML download. + * + * @param id Retention id. + * @return XML stream. Caller owns closing it. + * @see API reference + */ + public InputStream downloadXmlStream(String id) { + return client.getStream("/retentions/" + id + "/xml"); + } + /** * Downloads a retention ZIP package with PDF and XML. * @@ -106,4 +129,15 @@ public byte[] downloadXml(String id) { public byte[] downloadZip(String id) { return client.getBytes("/retentions/" + id + "/zip"); } + + /** + * Opens a streaming retention ZIP download. + * + * @param id Retention id. + * @return ZIP stream. Caller owns closing it. + * @see API reference + */ + public InputStream downloadZipStream(String id) { + return client.getStream("/retentions/" + id + "/zip"); + } } diff --git a/src/test/java/io/facturapi/FacturapiResourcesTest.java b/src/test/java/io/facturapi/FacturapiResourcesTest.java index 144853b..12c87a2 100644 --- a/src/test/java/io/facturapi/FacturapiResourcesTest.java +++ b/src/test/java/io/facturapi/FacturapiResourcesTest.java @@ -15,6 +15,8 @@ import io.facturapi.enums.Taxability; import io.facturapi.http.FacturapiConfig; import io.facturapi.models.Customer; +import java.io.InputStream; +import java.nio.charset.StandardCharsets; import java.time.Instant; import java.time.LocalDate; import java.util.Map; @@ -41,6 +43,25 @@ void invoiceCreateUsesExpectedPath() { assertEquals("/v2/invoices?test=true", request.uri().getPath() + "?" + request.uri().getQuery()); } + @Test + void invoicePdfCanBeStreamed() throws Exception { + StubHttpClient httpClient = new StubHttpClient(); + httpClient.enqueueBinary(200, "PDF-CONTENT".getBytes(), "application/pdf"); + + Facturapi sdk = new Facturapi( + FacturapiConfig.builder("sk_test") + .httpClient(httpClient) + .build() + ); + + try (InputStream stream = sdk.invoices().downloadPdfStream("inv_1")) { + assertEquals("PDF-CONTENT", new String(stream.readAllBytes(), StandardCharsets.UTF_8)); + } + + var request = httpClient.requests().get(0); + assertEquals("/v2/invoices/inv_1/pdf", request.uri().getPath()); + } + @Test void sdkExposesAccessorBasedSurface() { Facturapi sdk = new Facturapi( diff --git a/src/test/java/io/facturapi/StubHttpClient.java b/src/test/java/io/facturapi/StubHttpClient.java index ce65d17..12d1502 100644 --- a/src/test/java/io/facturapi/StubHttpClient.java +++ b/src/test/java/io/facturapi/StubHttpClient.java @@ -1,6 +1,7 @@ package io.facturapi; import java.io.IOException; +import java.io.InputStream; import java.net.Authenticator; import java.net.CookieHandler; import java.net.ProxySelector; @@ -10,6 +11,7 @@ import java.net.http.HttpRequest; import java.net.http.HttpResponse; import java.time.Duration; +import java.nio.ByteBuffer; import java.util.ArrayDeque; import java.util.ArrayList; import java.util.Deque; @@ -17,6 +19,7 @@ import java.util.Map; import java.util.Optional; import java.util.concurrent.CompletableFuture; +import java.util.concurrent.Flow; import java.util.concurrent.Executor; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLParameters; @@ -108,7 +111,7 @@ public HttpResponse send(HttpRequest request, HttpResponse.BodyHandler throw new IOException("No queued response"); } @SuppressWarnings("unchecked") - T body = (T) queued.body; + T body = (T) buildBody(responseBodyHandler, queued.body, queued.statusCode, queued.headers); return new StubHttpResponse<>(request, queued.statusCode, body, queued.headers); } @@ -188,4 +191,49 @@ public Version version() { return Version.HTTP_1_1; } } + + private static T buildBody( + HttpResponse.BodyHandler responseBodyHandler, + byte[] body, + int statusCode, + Map> headers + ) { + HttpResponse.ResponseInfo responseInfo = new ResponseInfo(statusCode, headers); + HttpResponse.BodySubscriber subscriber = responseBodyHandler.apply(responseInfo); + subscriber.onSubscribe(new Flow.Subscription() { + @Override + public void request(long n) {} + + @Override + public void cancel() {} + }); + subscriber.onNext(List.of(ByteBuffer.wrap(body))); + subscriber.onComplete(); + return subscriber.getBody().toCompletableFuture().join(); + } + + private static final class ResponseInfo implements HttpResponse.ResponseInfo { + private final int statusCode; + private final HttpHeaders headers; + + ResponseInfo(int statusCode, Map> headers) { + this.statusCode = statusCode; + this.headers = HttpHeaders.of(headers, (k, v) -> true); + } + + @Override + public int statusCode() { + return statusCode; + } + + @Override + public HttpHeaders headers() { + return headers; + } + + @Override + public HttpClient.Version version() { + return HttpClient.Version.HTTP_1_1; + } + } } From 9e48d7074f9a4b19b51eaa30ee437f36303ff61d Mon Sep 17 00:00:00 2001 From: javorosas Date: Tue, 7 Apr 2026 12:48:43 +0200 Subject: [PATCH 07/22] refactor: switch organization uploads to file bytes --- .../resources/OrganizationsResource.java | 41 +++++++++++++++--- .../io/facturapi/FacturapiResourcesTest.java | 43 +++++++++++++++++++ 2 files changed, 77 insertions(+), 7 deletions(-) diff --git a/src/main/java/io/facturapi/resources/OrganizationsResource.java b/src/main/java/io/facturapi/resources/OrganizationsResource.java index 62aabab..b8a10fd 100644 --- a/src/main/java/io/facturapi/resources/OrganizationsResource.java +++ b/src/main/java/io/facturapi/resources/OrganizationsResource.java @@ -14,9 +14,9 @@ import io.facturapi.models.OrganizationUserAccess; import io.facturapi.models.SearchResult; import io.facturapi.models.Series; +import java.io.File; import java.io.IOException; import java.nio.file.Files; -import java.nio.file.Path; import java.util.List; import java.util.Map; @@ -89,10 +89,16 @@ public DomainAvailability checkDomainAvailability(Map query) { /** * Uploads organization logo file. */ - public Organization uploadLogo(String id, Path filePath) throws IOException { - byte[] fileBytes = Files.readAllBytes(filePath); + public Organization uploadLogo(String id, File file) throws IOException { + return uploadLogo(id, Files.readAllBytes(file.toPath()), file.getName()); + } + + /** + * Uploads organization logo file bytes. + */ + public Organization uploadLogo(String id, byte[] fileBytes, String fileName) { MultipartBody multipartBody = new MultipartBodyBuilder() - .addFile("file", filePath.getFileName().toString(), fileBytes, "application/octet-stream") + .addFile("file", fileName, fileBytes, "application/octet-stream") .build(); return client.putMultipart("/organizations/" + id + "/logo", multipartBody, Organization.class); } @@ -100,10 +106,31 @@ public Organization uploadLogo(String id, Path filePath) throws IOException { /** * Uploads organization CSD certificate files. */ - public Organization uploadCertificate(String id, Path cerFile, Path keyFile, String password) throws IOException { + public Organization uploadCertificate(String id, File cerFile, File keyFile, String password) throws IOException { + return uploadCertificate( + id, + Files.readAllBytes(cerFile.toPath()), + cerFile.getName(), + Files.readAllBytes(keyFile.toPath()), + keyFile.getName(), + password + ); + } + + /** + * Uploads organization CSD certificate file bytes. + */ + public Organization uploadCertificate( + String id, + byte[] cerFileBytes, + String cerFileName, + byte[] keyFileBytes, + String keyFileName, + String password + ) { MultipartBody multipartBody = new MultipartBodyBuilder() - .addFile("cer", cerFile.getFileName().toString(), Files.readAllBytes(cerFile), "application/octet-stream") - .addFile("key", keyFile.getFileName().toString(), Files.readAllBytes(keyFile), "application/octet-stream") + .addFile("cer", cerFileName, cerFileBytes, "application/octet-stream") + .addFile("key", keyFileName, keyFileBytes, "application/octet-stream") .addField("password", password) .build(); return client.putMultipart("/organizations/" + id + "/certificate", multipartBody, Organization.class); diff --git a/src/test/java/io/facturapi/FacturapiResourcesTest.java b/src/test/java/io/facturapi/FacturapiResourcesTest.java index 12c87a2..1eced89 100644 --- a/src/test/java/io/facturapi/FacturapiResourcesTest.java +++ b/src/test/java/io/facturapi/FacturapiResourcesTest.java @@ -62,6 +62,49 @@ void invoicePdfCanBeStreamed() throws Exception { assertEquals("/v2/invoices/inv_1/pdf", request.uri().getPath()); } + @Test + void organizationUploadsAcceptBytes() { + StubHttpClient httpClient = new StubHttpClient(); + httpClient.enqueueJson(200, "{\"id\":\"org_1\"}"); + + Facturapi sdk = new Facturapi( + FacturapiConfig.builder("sk_test") + .httpClient(httpClient) + .build() + ); + + var response = sdk.organizations().uploadLogo("org_1", "logo-bytes".getBytes(StandardCharsets.UTF_8), "logo.png"); + + assertEquals("org_1", response.getId()); + assertEquals("PUT", httpClient.requests().get(0).method()); + assertEquals("/v2/organizations/org_1/logo", httpClient.requests().get(0).uri().getPath()); + } + + @Test + void organizationCertificateUploadsAcceptBytes() { + StubHttpClient httpClient = new StubHttpClient(); + httpClient.enqueueJson(200, "{\"id\":\"org_1\"}"); + + Facturapi sdk = new Facturapi( + FacturapiConfig.builder("sk_test") + .httpClient(httpClient) + .build() + ); + + var response = sdk.organizations().uploadCertificate( + "org_1", + "cer-bytes".getBytes(StandardCharsets.UTF_8), + "certificate.cer", + "key-bytes".getBytes(StandardCharsets.UTF_8), + "certificate.key", + "secret" + ); + + assertEquals("org_1", response.getId()); + assertEquals("PUT", httpClient.requests().get(0).method()); + assertEquals("/v2/organizations/org_1/certificate", httpClient.requests().get(0).uri().getPath()); + } + @Test void sdkExposesAccessorBasedSurface() { Facturapi sdk = new Facturapi( From d3f067b95cbcf528b546c7de5e63cf11cd0d880f Mon Sep 17 00:00:00 2001 From: javorosas Date: Tue, 7 Apr 2026 12:56:47 +0200 Subject: [PATCH 08/22] refactor: simplify organization uploads --- README.md | 18 ++++++++++++++++ .../resources/OrganizationsResource.java | 21 ++++++------------- .../io/facturapi/FacturapiResourcesTest.java | 4 +--- 3 files changed, 25 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index 811caea..4ca1549 100644 --- a/README.md +++ b/README.md @@ -51,6 +51,24 @@ var invoice = facturapi.invoices().create(Map.of( System.out.println(invoice.getId()); ``` +## Uploads + +```java +import java.io.File; + +var organization = facturapi.organizations().uploadLogo( + "org_123", + new File("logo.png") +); + +var updated = facturapi.organizations().uploadCertificate( + "org_123", + new File("certificate.cer"), + new File("certificate.key"), + "secret" +); +``` + ## Design - Inputs use flexible JSON dictionaries (`Map`). diff --git a/src/main/java/io/facturapi/resources/OrganizationsResource.java b/src/main/java/io/facturapi/resources/OrganizationsResource.java index b8a10fd..b2011d4 100644 --- a/src/main/java/io/facturapi/resources/OrganizationsResource.java +++ b/src/main/java/io/facturapi/resources/OrganizationsResource.java @@ -90,15 +90,15 @@ public DomainAvailability checkDomainAvailability(Map query) { * Uploads organization logo file. */ public Organization uploadLogo(String id, File file) throws IOException { - return uploadLogo(id, Files.readAllBytes(file.toPath()), file.getName()); + return uploadLogo(id, Files.readAllBytes(file.toPath())); } /** * Uploads organization logo file bytes. */ - public Organization uploadLogo(String id, byte[] fileBytes, String fileName) { + public Organization uploadLogo(String id, byte[] fileBytes) { MultipartBody multipartBody = new MultipartBodyBuilder() - .addFile("file", fileName, fileBytes, "application/octet-stream") + .addFile("file", "logo.jpg", fileBytes, "application/octet-stream") .build(); return client.putMultipart("/organizations/" + id + "/logo", multipartBody, Organization.class); } @@ -110,9 +110,7 @@ public Organization uploadCertificate(String id, File cerFile, File keyFile, Str return uploadCertificate( id, Files.readAllBytes(cerFile.toPath()), - cerFile.getName(), Files.readAllBytes(keyFile.toPath()), - keyFile.getName(), password ); } @@ -120,17 +118,10 @@ public Organization uploadCertificate(String id, File cerFile, File keyFile, Str /** * Uploads organization CSD certificate file bytes. */ - public Organization uploadCertificate( - String id, - byte[] cerFileBytes, - String cerFileName, - byte[] keyFileBytes, - String keyFileName, - String password - ) { + public Organization uploadCertificate(String id, byte[] cerFileBytes, byte[] keyFileBytes, String password) { MultipartBody multipartBody = new MultipartBodyBuilder() - .addFile("cer", cerFileName, cerFileBytes, "application/octet-stream") - .addFile("key", keyFileName, keyFileBytes, "application/octet-stream") + .addFile("cer", "certificate.cer", cerFileBytes, "application/octet-stream") + .addFile("key", "certificate.key", keyFileBytes, "application/octet-stream") .addField("password", password) .build(); return client.putMultipart("/organizations/" + id + "/certificate", multipartBody, Organization.class); diff --git a/src/test/java/io/facturapi/FacturapiResourcesTest.java b/src/test/java/io/facturapi/FacturapiResourcesTest.java index 1eced89..5307298 100644 --- a/src/test/java/io/facturapi/FacturapiResourcesTest.java +++ b/src/test/java/io/facturapi/FacturapiResourcesTest.java @@ -73,7 +73,7 @@ void organizationUploadsAcceptBytes() { .build() ); - var response = sdk.organizations().uploadLogo("org_1", "logo-bytes".getBytes(StandardCharsets.UTF_8), "logo.png"); + var response = sdk.organizations().uploadLogo("org_1", "logo-bytes".getBytes(StandardCharsets.UTF_8)); assertEquals("org_1", response.getId()); assertEquals("PUT", httpClient.requests().get(0).method()); @@ -94,9 +94,7 @@ void organizationCertificateUploadsAcceptBytes() { var response = sdk.organizations().uploadCertificate( "org_1", "cer-bytes".getBytes(StandardCharsets.UTF_8), - "certificate.cer", "key-bytes".getBytes(StandardCharsets.UTF_8), - "certificate.key", "secret" ); From 0b5f40e0ac7038dd0be9ad157e2f7a4d38dffeb4 Mon Sep 17 00:00:00 2001 From: javorosas Date: Tue, 7 Apr 2026 13:12:11 +0200 Subject: [PATCH 09/22] fix: address copilot review comments --- .../models/complements/pago/PagoComplementData.java | 10 ++++++++++ src/test/java/io/facturapi/StubHttpClient.java | 5 ++++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/src/main/java/io/facturapi/models/complements/pago/PagoComplementData.java b/src/main/java/io/facturapi/models/complements/pago/PagoComplementData.java index ebe4896..7ab8e9b 100644 --- a/src/main/java/io/facturapi/models/complements/pago/PagoComplementData.java +++ b/src/main/java/io/facturapi/models/complements/pago/PagoComplementData.java @@ -16,15 +16,25 @@ public class PagoComplementData { private List relatedDocuments = new ArrayList<>(); private String currency; private Double exchange; + @JsonProperty("num_operacion") private String numOperacion; + @JsonProperty("rfc_emisor_cta_ord") private String rfcEmisorCtaOrd; + @JsonProperty("nom_banco_ord_ext") private String nomBancoOrdExt; + @JsonProperty("cta_ordenante") private String ctaOrdenante; + @JsonProperty("rfc_emisor_cta_ben") private String rfcEmisorCtaBen; + @JsonProperty("cta_beneficiario") private String ctaBeneficiario; + @JsonProperty("tipo_cad_pago") private String tipoCadPago; + @JsonProperty("cert_pago") private String certPago; + @JsonProperty("cad_pago") private String cadPago; + @JsonProperty("sello_pago") private String selloPago; public PaymentForm getPaymentForm() { return paymentForm; } diff --git a/src/test/java/io/facturapi/StubHttpClient.java b/src/test/java/io/facturapi/StubHttpClient.java index 12d1502..34c86c0 100644 --- a/src/test/java/io/facturapi/StubHttpClient.java +++ b/src/test/java/io/facturapi/StubHttpClient.java @@ -10,6 +10,7 @@ import java.net.http.HttpHeaders; import java.net.http.HttpRequest; import java.net.http.HttpResponse; +import java.nio.charset.StandardCharsets; import java.time.Duration; import java.nio.ByteBuffer; import java.util.ArrayDeque; @@ -42,7 +43,9 @@ static final class QueuedResponse { private final List requests = new ArrayList<>(); void enqueueJson(int statusCode, String json) { - queue.add(new QueuedResponse(statusCode, json.getBytes(), Map.of("Content-Type", List.of("application/json")))); + queue.add( + new QueuedResponse(statusCode, json.getBytes(StandardCharsets.UTF_8), Map.of("Content-Type", List.of("application/json"))) + ); } void enqueueBinary(int statusCode, byte[] bytes, String contentType) { From 205dc0441dd9bcbb856dd49a7c89aff0997f372c Mon Sep 17 00:00:00 2001 From: javorosas Date: Tue, 7 Apr 2026 13:24:24 +0200 Subject: [PATCH 10/22] refactor: use snake case object mappers --- src/main/java/io/facturapi/http/FacturapiConfig.java | 2 ++ .../java/io/facturapi/models/complements/InvoiceComplement.java | 2 ++ .../comercio_exterior/ComercioExteriorComplementData.java | 2 ++ 3 files changed, 6 insertions(+) diff --git a/src/main/java/io/facturapi/http/FacturapiConfig.java b/src/main/java/io/facturapi/http/FacturapiConfig.java index 09efecc..a8642d9 100644 --- a/src/main/java/io/facturapi/http/FacturapiConfig.java +++ b/src/main/java/io/facturapi/http/FacturapiConfig.java @@ -2,6 +2,7 @@ import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.PropertyNamingStrategies; import com.fasterxml.jackson.databind.SerializationFeature; import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; import io.facturapi.ApiVersion; @@ -108,6 +109,7 @@ public FacturapiConfig build() { ObjectMapper resolvedMapper = new ObjectMapper() .registerModule(new JavaTimeModule()) + .setPropertyNamingStrategy(PropertyNamingStrategies.SNAKE_CASE) .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false) .disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); diff --git a/src/main/java/io/facturapi/models/complements/InvoiceComplement.java b/src/main/java/io/facturapi/models/complements/InvoiceComplement.java index 21e7077..1cef460 100644 --- a/src/main/java/io/facturapi/models/complements/InvoiceComplement.java +++ b/src/main/java/io/facturapi/models/complements/InvoiceComplement.java @@ -8,6 +8,7 @@ import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.PropertyNamingStrategies; import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; import io.facturapi.models.complements.carta_porte.CartaPorteComplementData; import io.facturapi.models.complements.comercio_exterior.ComercioExteriorComplementData; @@ -19,6 +20,7 @@ public class InvoiceComplement { private static final ObjectMapper MAPPER = new ObjectMapper() .registerModule(new JavaTimeModule()) + .setPropertyNamingStrategy(PropertyNamingStrategies.SNAKE_CASE) .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); private String type; diff --git a/src/main/java/io/facturapi/models/complements/comercio_exterior/ComercioExteriorComplementData.java b/src/main/java/io/facturapi/models/complements/comercio_exterior/ComercioExteriorComplementData.java index eadae7b..1a1fba4 100644 --- a/src/main/java/io/facturapi/models/complements/comercio_exterior/ComercioExteriorComplementData.java +++ b/src/main/java/io/facturapi/models/complements/comercio_exterior/ComercioExteriorComplementData.java @@ -7,6 +7,7 @@ import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.PropertyNamingStrategies; import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; import java.util.ArrayList; import java.util.List; @@ -15,6 +16,7 @@ public class ComercioExteriorComplementData { private static final ObjectMapper MAPPER = new ObjectMapper() .registerModule(new JavaTimeModule()) + .setPropertyNamingStrategy(PropertyNamingStrategies.SNAKE_CASE) .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); @JsonProperty("Version") From 226d2e2751a425e48e76bb81c4f1498d54c221a0 Mon Sep 17 00:00:00 2001 From: javorosas Date: Tue, 7 Apr 2026 13:26:24 +0200 Subject: [PATCH 11/22] refactor: remove redundant json property mappings --- src/main/java/io/facturapi/models/ApiEvent.java | 1 - src/main/java/io/facturapi/models/ApiKey.java | 1 - .../java/io/facturapi/models/CatalogItem.java | 1 - .../java/io/facturapi/models/Certificate.java | 4 ---- src/main/java/io/facturapi/models/Customer.java | 9 --------- .../java/io/facturapi/models/CustomerInfo.java | 3 --- .../java/io/facturapi/models/Customization.java | 3 --- src/main/java/io/facturapi/models/Invoice.java | 17 ----------------- .../facturapi/models/InvoiceCancellation.java | 3 --- .../java/io/facturapi/models/InvoiceItem.java | 3 --- .../io/facturapi/models/InvoiceItemPart.java | 3 --- .../facturapi/models/InvoiceItemThirdParty.java | 3 --- src/main/java/io/facturapi/models/Legal.java | 4 ---- .../java/io/facturapi/models/Organization.java | 7 ------- .../io/facturapi/models/OrganizationInvite.java | 4 ---- .../facturapi/models/OrganizationTeamRole.java | 6 ------ .../models/OrganizationUserAccess.java | 4 ---- src/main/java/io/facturapi/models/Payment.java | 1 - .../io/facturapi/models/PaymentRelated.java | 2 -- src/main/java/io/facturapi/models/PdfExtra.java | 7 ------- .../io/facturapi/models/PendingPlanUpdate.java | 1 - src/main/java/io/facturapi/models/Product.java | 6 ------ .../java/io/facturapi/models/ProductInfo.java | 5 ----- src/main/java/io/facturapi/models/Receipt.java | 8 -------- .../io/facturapi/models/ReceiptSettings.java | 3 --- .../java/io/facturapi/models/Retention.java | 10 ---------- .../io/facturapi/models/RetentionPeriod.java | 2 -- .../facturapi/models/RetentionRetainedTax.java | 4 ---- .../io/facturapi/models/RetentionTotals.java | 5 ----- .../java/io/facturapi/models/SearchResult.java | 3 --- .../facturapi/models/SelfInvoiceSettings.java | 4 ---- src/main/java/io/facturapi/models/Series.java | 2 -- src/main/java/io/facturapi/models/Stamp.java | 4 ---- .../io/facturapi/models/TaxInfoValidation.java | 1 - src/main/java/io/facturapi/models/Webhook.java | 2 -- .../java/io/facturapi/models/XmlNamespace.java | 1 - .../complements/nomina/NominaAcciones.java | 2 -- .../complements/nomina/NominaCompensacion.java | 2 -- .../nomina/NominaComplementData.java | 6 ------ .../complements/nomina/NominaDeduccion.java | 1 - .../models/complements/nomina/NominaEmisor.java | 3 --- .../complements/nomina/NominaEntidadSncf.java | 2 -- .../complements/nomina/NominaHorasExtra.java | 3 --- .../complements/nomina/NominaIncapacidad.java | 3 --- .../complements/nomina/NominaJubilacion.java | 5 ----- .../complements/nomina/NominaOtroPago.java | 3 --- .../complements/nomina/NominaPercepcion.java | 5 ----- .../complements/nomina/NominaPercepciones.java | 3 --- .../complements/nomina/NominaReceptor.java | 14 -------------- .../complements/nomina/NominaSeparacion.java | 5 ----- .../nomina/NominaSubcontratacion.java | 2 -- .../complements/pago/PagoComplementData.java | 12 ------------ .../pago/PaymentRelatedDocument.java | 2 -- 53 files changed, 220 deletions(-) diff --git a/src/main/java/io/facturapi/models/ApiEvent.java b/src/main/java/io/facturapi/models/ApiEvent.java index dc9ead9..7ed3d6f 100644 --- a/src/main/java/io/facturapi/models/ApiEvent.java +++ b/src/main/java/io/facturapi/models/ApiEvent.java @@ -7,7 +7,6 @@ @JsonIgnoreProperties(ignoreUnknown = true) public class ApiEvent { - @JsonProperty("created_at") private Instant createdAt; private String organization; private Boolean livemode; diff --git a/src/main/java/io/facturapi/models/ApiKey.java b/src/main/java/io/facturapi/models/ApiKey.java index d8b16ab..f262e0c 100644 --- a/src/main/java/io/facturapi/models/ApiKey.java +++ b/src/main/java/io/facturapi/models/ApiKey.java @@ -10,7 +10,6 @@ public class ApiKey { private String id; @JsonProperty("first_12") private String first12; - @JsonProperty("created_at") private Instant createdAt; @JsonAlias({"key", "api_key", "token"}) private String key; diff --git a/src/main/java/io/facturapi/models/CatalogItem.java b/src/main/java/io/facturapi/models/CatalogItem.java index 078e20f..d3809a5 100644 --- a/src/main/java/io/facturapi/models/CatalogItem.java +++ b/src/main/java/io/facturapi/models/CatalogItem.java @@ -10,7 +10,6 @@ public class CatalogItem { private String code; @JsonAlias({"label", "description", "name"}) private String label; - @JsonProperty("score") private Double score; public String getCode() { diff --git a/src/main/java/io/facturapi/models/Certificate.java b/src/main/java/io/facturapi/models/Certificate.java index a15cf55..b387212 100644 --- a/src/main/java/io/facturapi/models/Certificate.java +++ b/src/main/java/io/facturapi/models/Certificate.java @@ -6,13 +6,9 @@ @JsonIgnoreProperties(ignoreUnknown = true) public class Certificate { - @JsonProperty("has_certificate") private Boolean hasCertificate; - @JsonProperty("updated_at") private Instant updatedAt; - @JsonProperty("expires_at") private Instant expiresAt; - @JsonProperty("serial_number") private String serialNumber; public Boolean getHasCertificate() { return hasCertificate; } diff --git a/src/main/java/io/facturapi/models/Customer.java b/src/main/java/io/facturapi/models/Customer.java index b1a8f55..f3885e4 100644 --- a/src/main/java/io/facturapi/models/Customer.java +++ b/src/main/java/io/facturapi/models/Customer.java @@ -9,27 +9,18 @@ public class Customer { private String id; private String organization; private Boolean livemode; - @JsonProperty("created_at") private Instant createdAt; - @JsonProperty("tax_id") private String taxId; - @JsonProperty("tax_system") private String taxSystem; - @JsonProperty("legal_name") private String legalName; private String email; private String phone; private String curp; private Address address; - @JsonProperty("external_id") private String externalId; - @JsonProperty("default_invoice_use") private String defaultInvoiceUse; - @JsonProperty("sat_validated_at") private Instant satValidatedAt; - @JsonProperty("edit_link") private String editLink; - @JsonProperty("edit_link_expires_at") private Instant editLinkExpiresAt; public String getId() { return id; } diff --git a/src/main/java/io/facturapi/models/CustomerInfo.java b/src/main/java/io/facturapi/models/CustomerInfo.java index 283dd58..3a19b8f 100644 --- a/src/main/java/io/facturapi/models/CustomerInfo.java +++ b/src/main/java/io/facturapi/models/CustomerInfo.java @@ -6,11 +6,8 @@ @JsonIgnoreProperties(ignoreUnknown = true) public class CustomerInfo { private String id; - @JsonProperty("legal_name") private String legalName; - @JsonProperty("tax_id") private String taxId; - @JsonProperty("tax_system") private String taxSystem; private Address address; diff --git a/src/main/java/io/facturapi/models/Customization.java b/src/main/java/io/facturapi/models/Customization.java index 869c205..2520323 100644 --- a/src/main/java/io/facturapi/models/Customization.java +++ b/src/main/java/io/facturapi/models/Customization.java @@ -8,11 +8,8 @@ @JsonIgnoreProperties(ignoreUnknown = true) public class Customization { private String color; - @JsonProperty("pdf_extra") private PdfExtra pdfExtra; - @JsonProperty("default_series") private Map defaultSeries = new HashMap<>(); - @JsonProperty("has_logo") private Boolean hasLogo; public String getColor() { return color; } diff --git a/src/main/java/io/facturapi/models/Invoice.java b/src/main/java/io/facturapi/models/Invoice.java index e2bd751..b662ea9 100644 --- a/src/main/java/io/facturapi/models/Invoice.java +++ b/src/main/java/io/facturapi/models/Invoice.java @@ -18,20 +18,14 @@ public class Invoice { private String id; private String organization; private Boolean livemode; - @JsonProperty("created_at") private Instant createdAt; private Instant date; - @JsonProperty("issuer_type") private IssuingType issuerType; private InvoiceType type; private InvoiceStatus status; - @JsonProperty("cfdi_version") private Integer cfdiVersion; - @JsonProperty("issuer_info") private CustomerInfo issuerInfo; - @JsonProperty("payment_form") private PaymentForm paymentForm; - @JsonProperty("payment_method") private PaymentMethod paymentMethod; private String currency; private Double exchange; @@ -39,41 +33,30 @@ public class Invoice { private CustomerInfo customer; private Double total; private String use; - @JsonProperty("folio_number") private String folioNumber; private String series; @JsonProperty("is_ready_to_stamp") private Boolean readyToStamp; private List items = new ArrayList<>(); private Address address; - @JsonProperty("amount_due") private Double amountDue; - @JsonProperty("verification_url") private String verificationUrl; - @JsonProperty("verification_carta_porte") private String verificationCartaPorte; - @JsonProperty("cancellation_status") private CancellationStatus cancellationStatus; - @JsonProperty("external_id") private String externalId; - @JsonProperty("idempotency_key") private String idempotencyKey; private Stamp stamp; private String addenda; private String conditions; - @JsonProperty("pdf_custom_section") private String pdfCustomSection; @JsonProperty("export") private String exportReference; private GlobalInfo global; private InvoiceCancellation cancellation; private List complements = new ArrayList<>(); - @JsonProperty("related_documents") private List relatedDocuments = new ArrayList<>(); private List namespaces = new ArrayList<>(); - @JsonProperty("received_payment_ids") private List receivedPaymentIds = new ArrayList<>(); - @JsonProperty("target_invoice_ids") private List targetInvoiceIds = new ArrayList<>(); public String getId() { return id; } diff --git a/src/main/java/io/facturapi/models/InvoiceCancellation.java b/src/main/java/io/facturapi/models/InvoiceCancellation.java index c5bd51a..99bd45e 100644 --- a/src/main/java/io/facturapi/models/InvoiceCancellation.java +++ b/src/main/java/io/facturapi/models/InvoiceCancellation.java @@ -8,13 +8,10 @@ @JsonIgnoreProperties(ignoreUnknown = true) public class InvoiceCancellation { - @JsonProperty("requested_at") private Instant requestedAt; private CancellationStatus status; - @JsonProperty("last_checked") private Instant lastChecked; private CancellationMotive motive; - @JsonProperty("substitution_uuid") private String substitutionUuid; public Instant getRequestedAt() { return requestedAt; } diff --git a/src/main/java/io/facturapi/models/InvoiceItem.java b/src/main/java/io/facturapi/models/InvoiceItem.java index 104ad21..adcb675 100644 --- a/src/main/java/io/facturapi/models/InvoiceItem.java +++ b/src/main/java/io/facturapi/models/InvoiceItem.java @@ -10,13 +10,10 @@ public class InvoiceItem { private Double quantity; private ProductInfo product; private Double discount; - @JsonProperty("customs_keys") private List customsKeys = new ArrayList<>(); - @JsonProperty("third_party") private InvoiceItemThirdParty thirdParty; private String complement; private List parts = new ArrayList<>(); - @JsonProperty("property_tax_account") private String propertyTaxAccount; public Double getQuantity() { return quantity; } diff --git a/src/main/java/io/facturapi/models/InvoiceItemPart.java b/src/main/java/io/facturapi/models/InvoiceItemPart.java index e73c7bd..599571f 100644 --- a/src/main/java/io/facturapi/models/InvoiceItemPart.java +++ b/src/main/java/io/facturapi/models/InvoiceItemPart.java @@ -6,13 +6,10 @@ @JsonIgnoreProperties(ignoreUnknown = true) public class InvoiceItemPart { private Double quantity; - @JsonProperty("product_key") private String productKey; private String description; - @JsonProperty("unit_name") private String unitName; private String sku; - @JsonProperty("unit_price") private Double unitPrice; public Double getQuantity() { return quantity; } diff --git a/src/main/java/io/facturapi/models/InvoiceItemThirdParty.java b/src/main/java/io/facturapi/models/InvoiceItemThirdParty.java index 3e33a2e..1cc080a 100644 --- a/src/main/java/io/facturapi/models/InvoiceItemThirdParty.java +++ b/src/main/java/io/facturapi/models/InvoiceItemThirdParty.java @@ -5,11 +5,8 @@ @JsonIgnoreProperties(ignoreUnknown = true) public class InvoiceItemThirdParty { - @JsonProperty("tax_id") private String taxId; - @JsonProperty("legal_name") private String legalName; - @JsonProperty("tax_system") private String taxSystem; private String zip; diff --git a/src/main/java/io/facturapi/models/Legal.java b/src/main/java/io/facturapi/models/Legal.java index 0c2c91c..90991da 100644 --- a/src/main/java/io/facturapi/models/Legal.java +++ b/src/main/java/io/facturapi/models/Legal.java @@ -6,16 +6,12 @@ @JsonIgnoreProperties(ignoreUnknown = true) public class Legal { private String name; - @JsonProperty("legal_name") private String legalName; - @JsonProperty("tax_id") private String taxId; - @JsonProperty("tax_system") private String taxSystem; private Address address; private String phone; private String website; - @JsonProperty("support_email") private String supportEmail; private String curp; diff --git a/src/main/java/io/facturapi/models/Organization.java b/src/main/java/io/facturapi/models/Organization.java index 0ae791f..c5b9dd7 100644 --- a/src/main/java/io/facturapi/models/Organization.java +++ b/src/main/java/io/facturapi/models/Organization.java @@ -9,19 +9,14 @@ @JsonIgnoreProperties(ignoreUnknown = true) public class Organization { private String id; - @JsonProperty("created_at") private Instant createdAt; private String plan; - @JsonProperty("add_ons") private List addOns = new ArrayList<>(); @JsonProperty("is_production_ready") private Boolean productionReady; - @JsonProperty("pending_steps") private List pendingSteps = new ArrayList<>(); - @JsonProperty("logo_url") private String logoUrl; private String domain; - @JsonProperty("custom_domain") private String customDomain; private String timezone; private Legal legal; @@ -29,9 +24,7 @@ public class Organization { private Certificate certificate; private Certificate fiel; private ReceiptSettings receipts; - @JsonProperty("self_invoice") private SelfInvoiceSettings selfInvoice; - @JsonProperty("pending_plan_update") private PendingPlanUpdate pendingPlanUpdate; public String getId() { return id; } diff --git a/src/main/java/io/facturapi/models/OrganizationInvite.java b/src/main/java/io/facturapi/models/OrganizationInvite.java index bad77f1..1ce533c 100644 --- a/src/main/java/io/facturapi/models/OrganizationInvite.java +++ b/src/main/java/io/facturapi/models/OrganizationInvite.java @@ -9,16 +9,12 @@ @JsonIgnoreProperties(ignoreUnknown = true) public class OrganizationInvite { private String id; - @JsonProperty("created_at") private Instant createdAt; private String email; - @JsonProperty("organization_name") private String organizationName; private String role; - @JsonProperty("role_name") private String roleName; private List roles = new ArrayList<>(); - @JsonProperty("expires_at") private Instant expiresAt; private String status; diff --git a/src/main/java/io/facturapi/models/OrganizationTeamRole.java b/src/main/java/io/facturapi/models/OrganizationTeamRole.java index 669e58d..59f5b9b 100644 --- a/src/main/java/io/facturapi/models/OrganizationTeamRole.java +++ b/src/main/java/io/facturapi/models/OrganizationTeamRole.java @@ -11,20 +11,14 @@ public class OrganizationTeamRole { private String id; private String name; - @JsonProperty("template_code") private String templateCode; private String scope; private String organization; private List operations = new ArrayList<>(); - @JsonProperty("used_by") private Integer usedBy; - @JsonProperty("created_at") private Instant createdAt; - @JsonProperty("updated_at") private Instant updatedAt; - @JsonProperty("created_by") private Map createdBy; - @JsonProperty("updated_by") private Map updatedBy; public String getId() { return id; } diff --git a/src/main/java/io/facturapi/models/OrganizationUserAccess.java b/src/main/java/io/facturapi/models/OrganizationUserAccess.java index ed11f05..921c60f 100644 --- a/src/main/java/io/facturapi/models/OrganizationUserAccess.java +++ b/src/main/java/io/facturapi/models/OrganizationUserAccess.java @@ -9,17 +9,13 @@ @JsonIgnoreProperties(ignoreUnknown = true) public class OrganizationUserAccess { private String id; - @JsonProperty("full_name") private String fullName; private String email; private String role; - @JsonProperty("role_name") private String roleName; private String organization; private List operations = new ArrayList<>(); - @JsonProperty("created_at") private Instant createdAt; - @JsonProperty("updated_at") private Instant updatedAt; public String getId() { return id; } diff --git a/src/main/java/io/facturapi/models/Payment.java b/src/main/java/io/facturapi/models/Payment.java index 43b38ce..411287c 100644 --- a/src/main/java/io/facturapi/models/Payment.java +++ b/src/main/java/io/facturapi/models/Payment.java @@ -9,7 +9,6 @@ @JsonIgnoreProperties(ignoreUnknown = true) public class Payment { - @JsonProperty("payment_form") private PaymentForm paymentForm; private String currency; private Double exchange; diff --git a/src/main/java/io/facturapi/models/PaymentRelated.java b/src/main/java/io/facturapi/models/PaymentRelated.java index c8cadd9..531e67d 100644 --- a/src/main/java/io/facturapi/models/PaymentRelated.java +++ b/src/main/java/io/facturapi/models/PaymentRelated.java @@ -4,9 +4,7 @@ public class PaymentRelated { private String uuid; - @JsonProperty("installment") private Integer installment; - @JsonProperty("last_balance") private Double lastBalance; private Double amount; private String currency; diff --git a/src/main/java/io/facturapi/models/PdfExtra.java b/src/main/java/io/facturapi/models/PdfExtra.java index ce5e1c3..c66655b 100644 --- a/src/main/java/io/facturapi/models/PdfExtra.java +++ b/src/main/java/io/facturapi/models/PdfExtra.java @@ -6,19 +6,12 @@ @JsonIgnoreProperties(ignoreUnknown = true) public class PdfExtra { private Boolean codes; - @JsonProperty("address_codes") private Boolean addressCodes; - @JsonProperty("product_key") private Boolean productKey; - @JsonProperty("round_unit_price") private Boolean roundUnitPrice; - @JsonProperty("tax_breakdown") private Boolean taxBreakdown; - @JsonProperty("ieps_breakdown") private Boolean iepsBreakdown; - @JsonProperty("render_carta_porte") private Boolean renderCartaPorte; - @JsonProperty("repeat_signature") private Boolean repeatSignature; public Boolean getCodes() { return codes; } diff --git a/src/main/java/io/facturapi/models/PendingPlanUpdate.java b/src/main/java/io/facturapi/models/PendingPlanUpdate.java index dffa847..9a02e49 100644 --- a/src/main/java/io/facturapi/models/PendingPlanUpdate.java +++ b/src/main/java/io/facturapi/models/PendingPlanUpdate.java @@ -7,7 +7,6 @@ @JsonIgnoreProperties(ignoreUnknown = true) public class PendingPlanUpdate { private String plan; - @JsonProperty("scheduled_for") private Instant scheduledFor; public String getPlan() { return plan; } diff --git a/src/main/java/io/facturapi/models/Product.java b/src/main/java/io/facturapi/models/Product.java index dc6d3fc..5b1311d 100644 --- a/src/main/java/io/facturapi/models/Product.java +++ b/src/main/java/io/facturapi/models/Product.java @@ -12,20 +12,14 @@ public class Product { private String id; private String organization; private Boolean livemode; - @JsonProperty("product_key") private String productKey; private String description; private Double price; - @JsonProperty("created_at") private Instant createdAt; - @JsonProperty("tax_included") private Boolean taxIncluded; private List taxes = new ArrayList<>(); - @JsonProperty("local_taxes") private List localTaxes = new ArrayList<>(); - @JsonProperty("unit_key") private String unitKey; - @JsonProperty("unit_name") private String unitName; private String sku; private Taxability taxability; diff --git a/src/main/java/io/facturapi/models/ProductInfo.java b/src/main/java/io/facturapi/models/ProductInfo.java index 5abdac5..22ebea8 100644 --- a/src/main/java/io/facturapi/models/ProductInfo.java +++ b/src/main/java/io/facturapi/models/ProductInfo.java @@ -9,19 +9,14 @@ @JsonIgnoreProperties(ignoreUnknown = true) public class ProductInfo { private String id; - @JsonProperty("product_key") private String productKey; private String description; - @JsonProperty("unit_key") private String unitKey; - @JsonProperty("unit_name") private String unitName; private Double price; private Taxability taxability; - @JsonProperty("tax_included") private Boolean taxIncluded; private List taxes = new ArrayList<>(); - @JsonProperty("local_taxes") private List localTaxes = new ArrayList<>(); private String sku; diff --git a/src/main/java/io/facturapi/models/Receipt.java b/src/main/java/io/facturapi/models/Receipt.java index f4b377c..c7cbf62 100644 --- a/src/main/java/io/facturapi/models/Receipt.java +++ b/src/main/java/io/facturapi/models/Receipt.java @@ -10,32 +10,24 @@ @JsonIgnoreProperties(ignoreUnknown = true) public class Receipt { private String id; - @JsonProperty("created_at") private Instant createdAt; private Instant date; - @JsonProperty("api_version") private Integer apiVersion; private Boolean livemode; private String organization; - @JsonProperty("folio_number") private Integer folioNumber; - @JsonProperty("external_id") private String externalId; - @JsonProperty("idempotency_key") private String idempotencyKey; private String branch; - @JsonProperty("payment_form") private PaymentForm paymentForm; private List items = new ArrayList<>(); private String currency; private Double exchange; private Double total; private String invoice; - @JsonProperty("expires_at") private Instant expiresAt; private String key; private String status; - @JsonProperty("self_invoice_url") private String selfInvoiceUrl; public String getId() { return id; } diff --git a/src/main/java/io/facturapi/models/ReceiptSettings.java b/src/main/java/io/facturapi/models/ReceiptSettings.java index 522b80d..508122b 100644 --- a/src/main/java/io/facturapi/models/ReceiptSettings.java +++ b/src/main/java/io/facturapi/models/ReceiptSettings.java @@ -6,11 +6,8 @@ @JsonIgnoreProperties(ignoreUnknown = true) public class ReceiptSettings { private String periodicity; - @JsonProperty("duration_days") private Integer durationDays; - @JsonProperty("next_folio_number") private Integer nextFolioNumber; - @JsonProperty("next_folio_number_test") private Integer nextFolioNumberTest; public String getPeriodicity() { return periodicity; } diff --git a/src/main/java/io/facturapi/models/Retention.java b/src/main/java/io/facturapi/models/Retention.java index 2c87685..efef076 100644 --- a/src/main/java/io/facturapi/models/Retention.java +++ b/src/main/java/io/facturapi/models/Retention.java @@ -9,36 +9,26 @@ @JsonIgnoreProperties(ignoreUnknown = true) public class Retention { private String id; - @JsonProperty("created_at") private Instant createdAt; private CustomerInfo customer; private String organization; private Boolean livemode; private String status; private String uuid; - @JsonProperty("external_id") private String externalId; - @JsonProperty("fecha_exp") private Instant fechaExp; - @JsonProperty("cve_retenc") private String cveRetenc; - @JsonProperty("folio_int") private String folioInt; - @JsonProperty("desc_retenc") private String descRetenc; private RetentionPeriod periodo; private RetentionTotals totales; private List namespaces = new ArrayList<>(); - @JsonProperty("related_documents") private List relatedDocuments = new ArrayList<>(); private List complements = new ArrayList<>(); private List addenda = new ArrayList<>(); - @JsonProperty("cancellation_receipt") private String cancellationReceipt; private Stamp stamp; - @JsonProperty("pdf_custom_section") private String pdfCustomSection; - @JsonProperty("verification_url") private String verificationUrl; public String getId() { return id; } diff --git a/src/main/java/io/facturapi/models/RetentionPeriod.java b/src/main/java/io/facturapi/models/RetentionPeriod.java index 0931f6b..5df92c5 100644 --- a/src/main/java/io/facturapi/models/RetentionPeriod.java +++ b/src/main/java/io/facturapi/models/RetentionPeriod.java @@ -5,9 +5,7 @@ @JsonIgnoreProperties(ignoreUnknown = true) public class RetentionPeriod { - @JsonProperty("mes_ini") private Integer mesIni; - @JsonProperty("mes_fin") private Integer mesFin; private Integer ejerc; diff --git a/src/main/java/io/facturapi/models/RetentionRetainedTax.java b/src/main/java/io/facturapi/models/RetentionRetainedTax.java index 8b046f8..4890e55 100644 --- a/src/main/java/io/facturapi/models/RetentionRetainedTax.java +++ b/src/main/java/io/facturapi/models/RetentionRetainedTax.java @@ -5,14 +5,10 @@ @JsonIgnoreProperties(ignoreUnknown = true) public class RetentionRetainedTax { - @JsonProperty("base_ret") private Double baseRet; private String impuesto; - @JsonProperty("tipo_pago_ret") private String tipoPagoRet; - @JsonProperty("monto_ret") private Double montoRet; - @JsonProperty("pago_provisional") private Boolean pagoProvisional; public Double getBaseRet() { return baseRet; } diff --git a/src/main/java/io/facturapi/models/RetentionTotals.java b/src/main/java/io/facturapi/models/RetentionTotals.java index dc7cd47..5968cc5 100644 --- a/src/main/java/io/facturapi/models/RetentionTotals.java +++ b/src/main/java/io/facturapi/models/RetentionTotals.java @@ -7,15 +7,10 @@ @JsonIgnoreProperties(ignoreUnknown = true) public class RetentionTotals { - @JsonProperty("monto_tot_grav") private Double montoTotGrav; - @JsonProperty("monto_tot_exent") private Double montoTotExent; - @JsonProperty("monto_tot_operacion") private Double montoTotOperacion; - @JsonProperty("monto_tot_ret") private Double montoTotRet; - @JsonProperty("imp_retenidos") private List impRetenidos = new ArrayList<>(); public Double getMontoTotGrav() { return montoTotGrav; } diff --git a/src/main/java/io/facturapi/models/SearchResult.java b/src/main/java/io/facturapi/models/SearchResult.java index e358e70..2701e72 100644 --- a/src/main/java/io/facturapi/models/SearchResult.java +++ b/src/main/java/io/facturapi/models/SearchResult.java @@ -9,12 +9,9 @@ @JsonIgnoreProperties(ignoreUnknown = true) public class SearchResult { private Integer page; - @JsonProperty("total_pages") private Integer totalPages; - @JsonProperty("total_results") @JsonAlias({"total"}) private Integer totalResults; - @JsonProperty("has_more") private Boolean hasMore; private List data = new ArrayList<>(); diff --git a/src/main/java/io/facturapi/models/SelfInvoiceSettings.java b/src/main/java/io/facturapi/models/SelfInvoiceSettings.java index dcb8e1a..ed2a0d6 100644 --- a/src/main/java/io/facturapi/models/SelfInvoiceSettings.java +++ b/src/main/java/io/facturapi/models/SelfInvoiceSettings.java @@ -7,13 +7,9 @@ @JsonIgnoreProperties(ignoreUnknown = true) public class SelfInvoiceSettings { - @JsonProperty("allowed_cfdi_uses") private List allowedCfdiUses = new ArrayList<>(); - @JsonProperty("apply_resico_isr") private Boolean applyResicoIsr; - @JsonProperty("support_email") private String supportEmail; - @JsonProperty("support_email_verified") private Boolean supportEmailVerified; public List getAllowedCfdiUses() { return allowedCfdiUses; } diff --git a/src/main/java/io/facturapi/models/Series.java b/src/main/java/io/facturapi/models/Series.java index 483e935..95f3640 100644 --- a/src/main/java/io/facturapi/models/Series.java +++ b/src/main/java/io/facturapi/models/Series.java @@ -8,9 +8,7 @@ public class Series { @JsonAlias({"series", "name"}) private String series; - @JsonProperty("next_folio") private Integer nextFolio; - @JsonProperty("next_folio_test") private Integer nextFolioTest; public String getSeries() { return series; } diff --git a/src/main/java/io/facturapi/models/Stamp.java b/src/main/java/io/facturapi/models/Stamp.java index 540e071..89cdc3d 100644 --- a/src/main/java/io/facturapi/models/Stamp.java +++ b/src/main/java/io/facturapi/models/Stamp.java @@ -7,14 +7,10 @@ @JsonIgnoreProperties(ignoreUnknown = true) public class Stamp { private Instant date; - @JsonProperty("sat_signature") private String satSignature; - @JsonProperty("sat_cert_number") private String satCertNumber; private String signature; - @JsonProperty("complement_string") private String complementString; - @JsonProperty("rfc_provider_cert") private String rfcProviderCert; public Instant getDate() { return date; } diff --git a/src/main/java/io/facturapi/models/TaxInfoValidation.java b/src/main/java/io/facturapi/models/TaxInfoValidation.java index 8a005db..9b9cd3d 100644 --- a/src/main/java/io/facturapi/models/TaxInfoValidation.java +++ b/src/main/java/io/facturapi/models/TaxInfoValidation.java @@ -8,7 +8,6 @@ @JsonIgnoreProperties(ignoreUnknown = true) public class TaxInfoValidation { - @JsonProperty("is_valid") @JsonAlias({"valid"}) private Boolean isValid; private List errors = new ArrayList<>(); diff --git a/src/main/java/io/facturapi/models/Webhook.java b/src/main/java/io/facturapi/models/Webhook.java index 5772dad..fd18da3 100644 --- a/src/main/java/io/facturapi/models/Webhook.java +++ b/src/main/java/io/facturapi/models/Webhook.java @@ -9,11 +9,9 @@ @JsonIgnoreProperties(ignoreUnknown = true) public class Webhook { private String id; - @JsonProperty("created_at") private Instant createdAt; private String organization; private Boolean livemode; - @JsonProperty("enabled_events") private List enabledEvents = new ArrayList<>(); private String description; private String url; diff --git a/src/main/java/io/facturapi/models/XmlNamespace.java b/src/main/java/io/facturapi/models/XmlNamespace.java index 64b68d7..022cb91 100644 --- a/src/main/java/io/facturapi/models/XmlNamespace.java +++ b/src/main/java/io/facturapi/models/XmlNamespace.java @@ -7,7 +7,6 @@ public class XmlNamespace { private String prefix; private String uri; - @JsonProperty("schema_location") private String schemaLocation; public String getPrefix() { return prefix; } diff --git a/src/main/java/io/facturapi/models/complements/nomina/NominaAcciones.java b/src/main/java/io/facturapi/models/complements/nomina/NominaAcciones.java index edbc619..d34626d 100644 --- a/src/main/java/io/facturapi/models/complements/nomina/NominaAcciones.java +++ b/src/main/java/io/facturapi/models/complements/nomina/NominaAcciones.java @@ -5,9 +5,7 @@ @JsonIgnoreProperties(ignoreUnknown = true) public class NominaAcciones { - @JsonProperty("valor_mercado") private Double valorMercado; - @JsonProperty("precio_al_otorgarse") private Double precioAlOtorgarse; public Double getValorMercado() { return valorMercado; } diff --git a/src/main/java/io/facturapi/models/complements/nomina/NominaCompensacion.java b/src/main/java/io/facturapi/models/complements/nomina/NominaCompensacion.java index 46b4a70..756d6fa 100644 --- a/src/main/java/io/facturapi/models/complements/nomina/NominaCompensacion.java +++ b/src/main/java/io/facturapi/models/complements/nomina/NominaCompensacion.java @@ -5,10 +5,8 @@ @JsonIgnoreProperties(ignoreUnknown = true) public class NominaCompensacion { - @JsonProperty("saldo_a_favor") private Double saldoAFavor; private Integer ano; - @JsonProperty("remanente_sal_fav") private Double remanenteSalFav; public Double getSaldoAFavor() { return saldoAFavor; } diff --git a/src/main/java/io/facturapi/models/complements/nomina/NominaComplementData.java b/src/main/java/io/facturapi/models/complements/nomina/NominaComplementData.java index 3a6efaf..5b603f1 100644 --- a/src/main/java/io/facturapi/models/complements/nomina/NominaComplementData.java +++ b/src/main/java/io/facturapi/models/complements/nomina/NominaComplementData.java @@ -8,22 +8,16 @@ @JsonIgnoreProperties(ignoreUnknown = true) public class NominaComplementData { - @JsonProperty("fecha_inicial_pago") private LocalDate fechaInicialPago; - @JsonProperty("fecha_final_pago") private LocalDate fechaFinalPago; private NominaPercepciones percepciones; private List deducciones = new ArrayList<>(); - @JsonProperty("otros_pagos") private List otrosPagos = new ArrayList<>(); private List incapacidades = new ArrayList<>(); private NominaEmisor emisor; private NominaReceptor receptor; - @JsonProperty("tipo_nomina") private String tipoNomina; - @JsonProperty("fecha_pago") private LocalDate fechaPago; - @JsonProperty("num_dias_pagados") private Double numDiasPagados; public LocalDate getFechaInicialPago() { return fechaInicialPago; } diff --git a/src/main/java/io/facturapi/models/complements/nomina/NominaDeduccion.java b/src/main/java/io/facturapi/models/complements/nomina/NominaDeduccion.java index c5213dc..9663eab 100644 --- a/src/main/java/io/facturapi/models/complements/nomina/NominaDeduccion.java +++ b/src/main/java/io/facturapi/models/complements/nomina/NominaDeduccion.java @@ -5,7 +5,6 @@ @JsonIgnoreProperties(ignoreUnknown = true) public class NominaDeduccion { - @JsonProperty("tipo_deduccion") private String tipoDeduccion; private String concepto; private String clave; diff --git a/src/main/java/io/facturapi/models/complements/nomina/NominaEmisor.java b/src/main/java/io/facturapi/models/complements/nomina/NominaEmisor.java index 2534e19..a136dac 100644 --- a/src/main/java/io/facturapi/models/complements/nomina/NominaEmisor.java +++ b/src/main/java/io/facturapi/models/complements/nomina/NominaEmisor.java @@ -6,11 +6,8 @@ @JsonIgnoreProperties(ignoreUnknown = true) public class NominaEmisor { private String curp; - @JsonProperty("registro_patronal") private String registroPatronal; - @JsonProperty("rfc_patron_origen") private String rfcPatronOrigen; - @JsonProperty("entidad_sncf") private NominaEntidadSncf entidadSncf; public String getCurp() { return curp; } diff --git a/src/main/java/io/facturapi/models/complements/nomina/NominaEntidadSncf.java b/src/main/java/io/facturapi/models/complements/nomina/NominaEntidadSncf.java index 1dd44e9..ebd08ce 100644 --- a/src/main/java/io/facturapi/models/complements/nomina/NominaEntidadSncf.java +++ b/src/main/java/io/facturapi/models/complements/nomina/NominaEntidadSncf.java @@ -5,9 +5,7 @@ @JsonIgnoreProperties(ignoreUnknown = true) public class NominaEntidadSncf { - @JsonProperty("origen_recurso") private String origenRecurso; - @JsonProperty("monto_recurso_propio") private Double montoRecursoPropio; public String getOrigenRecurso() { return origenRecurso; } diff --git a/src/main/java/io/facturapi/models/complements/nomina/NominaHorasExtra.java b/src/main/java/io/facturapi/models/complements/nomina/NominaHorasExtra.java index cbed048..8b22751 100644 --- a/src/main/java/io/facturapi/models/complements/nomina/NominaHorasExtra.java +++ b/src/main/java/io/facturapi/models/complements/nomina/NominaHorasExtra.java @@ -6,11 +6,8 @@ @JsonIgnoreProperties(ignoreUnknown = true) public class NominaHorasExtra { private Integer dias; - @JsonProperty("tipo_horas") private String tipoHoras; - @JsonProperty("horas_extra") private Integer horasExtra; - @JsonProperty("importe_pagado") private Double importePagado; public Integer getDias() { return dias; } diff --git a/src/main/java/io/facturapi/models/complements/nomina/NominaIncapacidad.java b/src/main/java/io/facturapi/models/complements/nomina/NominaIncapacidad.java index a9ae1d2..1123717 100644 --- a/src/main/java/io/facturapi/models/complements/nomina/NominaIncapacidad.java +++ b/src/main/java/io/facturapi/models/complements/nomina/NominaIncapacidad.java @@ -5,11 +5,8 @@ @JsonIgnoreProperties(ignoreUnknown = true) public class NominaIncapacidad { - @JsonProperty("dias_incapacidad") private Integer diasIncapacidad; - @JsonProperty("tipo_incapacidad") private String tipoIncapacidad; - @JsonProperty("importe_monetario") private Double importeMonetario; public Integer getDiasIncapacidad() { return diasIncapacidad; } diff --git a/src/main/java/io/facturapi/models/complements/nomina/NominaJubilacion.java b/src/main/java/io/facturapi/models/complements/nomina/NominaJubilacion.java index 303a9b0..b11f1a8 100644 --- a/src/main/java/io/facturapi/models/complements/nomina/NominaJubilacion.java +++ b/src/main/java/io/facturapi/models/complements/nomina/NominaJubilacion.java @@ -5,15 +5,10 @@ @JsonIgnoreProperties(ignoreUnknown = true) public class NominaJubilacion { - @JsonProperty("total_una_exhibicion") private Double totalUnaExhibicion; - @JsonProperty("total_parcialidad") private Double totalParcialidad; - @JsonProperty("monto_diario") private Double montoDiario; - @JsonProperty("ingreso_acumulable") private Double ingresoAcumulable; - @JsonProperty("ingreso_no_acumulable") private Double ingresoNoAcumulable; public Double getTotalUnaExhibicion() { return totalUnaExhibicion; } diff --git a/src/main/java/io/facturapi/models/complements/nomina/NominaOtroPago.java b/src/main/java/io/facturapi/models/complements/nomina/NominaOtroPago.java index 7f48634..919c9f3 100644 --- a/src/main/java/io/facturapi/models/complements/nomina/NominaOtroPago.java +++ b/src/main/java/io/facturapi/models/complements/nomina/NominaOtroPago.java @@ -5,14 +5,11 @@ @JsonIgnoreProperties(ignoreUnknown = true) public class NominaOtroPago { - @JsonProperty("tipo_otro_pago") private String tipoOtroPago; private String clave; private String concepto; private Double importe; - @JsonProperty("subsidio_causado") private Double subsidioCausado; - @JsonProperty("compensacion_saldos_a_favor") private NominaCompensacion compensacionSaldosAFavor; public String getTipoOtroPago() { return tipoOtroPago; } diff --git a/src/main/java/io/facturapi/models/complements/nomina/NominaPercepcion.java b/src/main/java/io/facturapi/models/complements/nomina/NominaPercepcion.java index a9ee609..485bdf9 100644 --- a/src/main/java/io/facturapi/models/complements/nomina/NominaPercepcion.java +++ b/src/main/java/io/facturapi/models/complements/nomina/NominaPercepcion.java @@ -7,17 +7,12 @@ @JsonIgnoreProperties(ignoreUnknown = true) public class NominaPercepcion { - @JsonProperty("tipo_percepcion") private String tipoPercepcion; private String concepto; private String clave; - @JsonProperty("importe_gravado") private Double importeGravado; - @JsonProperty("importe_exento") private Double importeExento; - @JsonProperty("acciones_o_titulos") private NominaAcciones accionesOTitulos; - @JsonProperty("horas_extra") private List horasExtra = new ArrayList<>(); public String getTipoPercepcion() { return tipoPercepcion; } diff --git a/src/main/java/io/facturapi/models/complements/nomina/NominaPercepciones.java b/src/main/java/io/facturapi/models/complements/nomina/NominaPercepciones.java index b506699..3abb0e5 100644 --- a/src/main/java/io/facturapi/models/complements/nomina/NominaPercepciones.java +++ b/src/main/java/io/facturapi/models/complements/nomina/NominaPercepciones.java @@ -7,11 +7,8 @@ @JsonIgnoreProperties(ignoreUnknown = true) public class NominaPercepciones { - @JsonProperty("percepcion") private List percepcion = new ArrayList<>(); - @JsonProperty("jubilacion_pension_retiro") private NominaJubilacion jubilacionPensionRetiro; - @JsonProperty("separacion_indemnizacion") private NominaSeparacion separacionIndemnizacion; public List getPercepcion() { return percepcion; } diff --git a/src/main/java/io/facturapi/models/complements/nomina/NominaReceptor.java b/src/main/java/io/facturapi/models/complements/nomina/NominaReceptor.java index 6379d83..3721531 100644 --- a/src/main/java/io/facturapi/models/complements/nomina/NominaReceptor.java +++ b/src/main/java/io/facturapi/models/complements/nomina/NominaReceptor.java @@ -9,38 +9,24 @@ @JsonIgnoreProperties(ignoreUnknown = true) public class NominaReceptor { private String curp; - @JsonProperty("num_seguridad_social") private String numSeguridadSocial; - @JsonProperty("fecha_inicio_rel_laboral") private LocalDate fechaInicioRelLaboral; private Object antiguedad; - @JsonProperty("tipo_contrato") private String tipoContrato; private Boolean sindicalizado; - @JsonProperty("tipo_jornada") private String tipoJornada; - @JsonProperty("tipo_regimen") private String tipoRegimen; - @JsonProperty("num_empleado") private String numEmpleado; private String departamento; private String puesto; - @JsonProperty("riesgo_puesto") private String riesgoPuesto; - @JsonProperty("periodicidad_pago") private String periodicidadPago; private String banco; - @JsonProperty("nombre_banco") private String nombreBanco; - @JsonProperty("cuenta_bancaria") private String cuentaBancaria; - @JsonProperty("salario_base_cot_apor") private Double salarioBaseCotApor; - @JsonProperty("salario_diario_integrado") private Double salarioDiarioIntegrado; - @JsonProperty("clave_ent_fed") private String claveEntFed; - @JsonProperty("sub_contratacion") private List subContratacion = new ArrayList<>(); public String getCurp() { return curp; } diff --git a/src/main/java/io/facturapi/models/complements/nomina/NominaSeparacion.java b/src/main/java/io/facturapi/models/complements/nomina/NominaSeparacion.java index eb0d1c2..082a598 100644 --- a/src/main/java/io/facturapi/models/complements/nomina/NominaSeparacion.java +++ b/src/main/java/io/facturapi/models/complements/nomina/NominaSeparacion.java @@ -5,15 +5,10 @@ @JsonIgnoreProperties(ignoreUnknown = true) public class NominaSeparacion { - @JsonProperty("total_pagado") private Double totalPagado; - @JsonProperty("num_anos_servicio") private Integer numAnosServicio; - @JsonProperty("ultimo_sueldo_mens_ord") private Double ultimoSueldoMensOrd; - @JsonProperty("ingreso_acumulable") private Double ingresoAcumulable; - @JsonProperty("ingreso_no_acumulable") private Double ingresoNoAcumulable; public Double getTotalPagado() { return totalPagado; } diff --git a/src/main/java/io/facturapi/models/complements/nomina/NominaSubcontratacion.java b/src/main/java/io/facturapi/models/complements/nomina/NominaSubcontratacion.java index b6aa13e..6e7d787 100644 --- a/src/main/java/io/facturapi/models/complements/nomina/NominaSubcontratacion.java +++ b/src/main/java/io/facturapi/models/complements/nomina/NominaSubcontratacion.java @@ -5,9 +5,7 @@ @JsonIgnoreProperties(ignoreUnknown = true) public class NominaSubcontratacion { - @JsonProperty("rfc_labora") private String rfcLabora; - @JsonProperty("porcentaje_tiempo") private Double porcentajeTiempo; public String getRfcLabora() { return rfcLabora; } diff --git a/src/main/java/io/facturapi/models/complements/pago/PagoComplementData.java b/src/main/java/io/facturapi/models/complements/pago/PagoComplementData.java index 7ab8e9b..624ed97 100644 --- a/src/main/java/io/facturapi/models/complements/pago/PagoComplementData.java +++ b/src/main/java/io/facturapi/models/complements/pago/PagoComplementData.java @@ -9,32 +9,20 @@ @JsonIgnoreProperties(ignoreUnknown = true) public class PagoComplementData { - @JsonProperty("payment_form") private PaymentForm paymentForm; private Instant date; - @JsonProperty("related_documents") private List relatedDocuments = new ArrayList<>(); private String currency; private Double exchange; - @JsonProperty("num_operacion") private String numOperacion; - @JsonProperty("rfc_emisor_cta_ord") private String rfcEmisorCtaOrd; - @JsonProperty("nom_banco_ord_ext") private String nomBancoOrdExt; - @JsonProperty("cta_ordenante") private String ctaOrdenante; - @JsonProperty("rfc_emisor_cta_ben") private String rfcEmisorCtaBen; - @JsonProperty("cta_beneficiario") private String ctaBeneficiario; - @JsonProperty("tipo_cad_pago") private String tipoCadPago; - @JsonProperty("cert_pago") private String certPago; - @JsonProperty("cad_pago") private String cadPago; - @JsonProperty("sello_pago") private String selloPago; public PaymentForm getPaymentForm() { return paymentForm; } diff --git a/src/main/java/io/facturapi/models/complements/pago/PaymentRelatedDocument.java b/src/main/java/io/facturapi/models/complements/pago/PaymentRelatedDocument.java index 3c38773..6e65897 100644 --- a/src/main/java/io/facturapi/models/complements/pago/PaymentRelatedDocument.java +++ b/src/main/java/io/facturapi/models/complements/pago/PaymentRelatedDocument.java @@ -11,11 +11,9 @@ public class PaymentRelatedDocument { private String uuid; private Double amount; private Integer installment; - @JsonProperty("last_balance") private Double lastBalance; private String currency; private Double exchange; - @JsonProperty("folio_number") private String folioNumber; private String series; private Taxability taxability; From 2a9fa534cd8b78baca5c1facfa2827e309b755cd Mon Sep 17 00:00:00 2001 From: javorosas Date: Tue, 7 Apr 2026 15:47:02 +0200 Subject: [PATCH 12/22] refactor: drop redundant complement annotation --- .../java/io/facturapi/models/complements/InvoiceComplement.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/io/facturapi/models/complements/InvoiceComplement.java b/src/main/java/io/facturapi/models/complements/InvoiceComplement.java index 1cef460..6424cee 100644 --- a/src/main/java/io/facturapi/models/complements/InvoiceComplement.java +++ b/src/main/java/io/facturapi/models/complements/InvoiceComplement.java @@ -52,7 +52,6 @@ private void setRawData(JsonNode rawData) { parseRawData(); } - @JsonProperty("data") public Object getData() { if ("pago".equals(type)) { return pagoData; From b5a7b109b08f114988c9d6e57bd76088371a2889 Mon Sep 17 00:00:00 2001 From: javorosas Date: Tue, 7 Apr 2026 16:01:07 +0200 Subject: [PATCH 13/22] feat: expose typed api error --- .../java/io/facturapi/FacturapiException.java | 23 +++++ .../facturapi/http/FacturapiHttpClient.java | 93 +++++++++++++------ .../java/io/facturapi/models/ApiError.java | 90 ++++++++++++++++++ .../io/facturapi/FacturapiHttpClientTest.java | 10 +- 4 files changed, 185 insertions(+), 31 deletions(-) create mode 100644 src/main/java/io/facturapi/models/ApiError.java diff --git a/src/main/java/io/facturapi/FacturapiException.java b/src/main/java/io/facturapi/FacturapiException.java index e9f3030..b2ce484 100644 --- a/src/main/java/io/facturapi/FacturapiException.java +++ b/src/main/java/io/facturapi/FacturapiException.java @@ -1,27 +1,42 @@ package io.facturapi; +import io.facturapi.models.ApiError; + public class FacturapiException extends RuntimeException { + private final ApiError apiError; private final int statusCode; private final String responseBody; public FacturapiException(String message) { super(message); + this.apiError = null; this.statusCode = -1; this.responseBody = null; } public FacturapiException(String message, Throwable cause) { super(message, cause); + this.apiError = null; this.statusCode = -1; this.responseBody = null; } public FacturapiException(String message, int statusCode, String responseBody) { super(message); + this.apiError = null; this.statusCode = statusCode; this.responseBody = responseBody; } + public FacturapiException(ApiError apiError, String responseBody) { + super(apiError != null && apiError.getMessage() != null && !apiError.getMessage().isBlank() + ? apiError.getMessage() + : "An error occurred"); + this.apiError = apiError; + this.statusCode = apiError != null && apiError.getStatus() != null ? apiError.getStatus() : -1; + this.responseBody = responseBody; + } + public int getStatusCode() { return statusCode; } @@ -29,4 +44,12 @@ public int getStatusCode() { public String getResponseBody() { return responseBody; } + + public ApiError getApiError() { + return apiError; + } + + public ApiError getError() { + return apiError; + } } diff --git a/src/main/java/io/facturapi/http/FacturapiHttpClient.java b/src/main/java/io/facturapi/http/FacturapiHttpClient.java index 6542f93..0399a60 100644 --- a/src/main/java/io/facturapi/http/FacturapiHttpClient.java +++ b/src/main/java/io/facturapi/http/FacturapiHttpClient.java @@ -4,6 +4,7 @@ import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import io.facturapi.FacturapiException; +import io.facturapi.models.ApiError; import java.io.IOException; import java.io.InputStream; import java.net.URI; @@ -146,21 +147,7 @@ private InputStream requestStream(String method, String path, Object body) { responseBytes = errorStream == null ? new byte[0] : errorStream.readAllBytes(); } String bodyText = responseBytes.length == 0 ? "" : new String(responseBytes, StandardCharsets.UTF_8); - String message = "Request failed with status " + statusCode; - try { - JsonNode error = objectMapper.readTree(bodyText); - JsonNode messageNode = firstDefined(error, "message", "error", "detail"); - if (messageNode != null && messageNode.isTextual()) { - message = messageNode.asText(); - } else if (!bodyText.isEmpty()) { - message = bodyText; - } - } catch (Exception ignored) { - if (!bodyText.isEmpty()) { - message = bodyText; - } - } - throw new FacturapiException(message, statusCode, bodyText); + throw new FacturapiException(parseApiError(bodyText, statusCode), bodyText); } return response.body(); } catch (IOException e) { @@ -215,6 +202,66 @@ private static JsonNode firstDefined(JsonNode node, String... keys) { return null; } + private ApiError parseApiError(String bodyText, int statusCode) { + ApiError apiError = null; + if (bodyText != null && !bodyText.isBlank()) { + try { + apiError = objectMapper.readValue(bodyText, ApiError.class); + } catch (Exception ignored) { + try { + JsonNode error = objectMapper.readTree(bodyText); + apiError = new ApiError(); + + JsonNode messageNode = firstDefined(error, "message", "error", "detail"); + if (messageNode != null && messageNode.isTextual()) { + apiError.setMessage(messageNode.asText()); + } else { + apiError.setMessage(bodyText); + } + + JsonNode statusNode = firstDefined(error, "status"); + if (statusNode != null) { + apiError.setStatus(statusNode); + } + + JsonNode codeNode = firstDefined(error, "code"); + if (codeNode != null) { + apiError.setCode(codeNode); + } + + JsonNode pathNode = firstDefined(error, "path"); + if (pathNode != null && pathNode.isTextual()) { + apiError.setPath(pathNode.asText()); + } + + JsonNode okNode = firstDefined(error, "ok"); + if (okNode != null && okNode.isBoolean()) { + apiError.setOk(okNode.asBoolean()); + } + } catch (Exception secondaryIgnored) { + apiError = new ApiError(); + apiError.setMessage(bodyText.isBlank() ? "Request failed with status " + statusCode : bodyText); + } + } + } + + if (apiError == null) { + apiError = new ApiError(); + apiError.setMessage("Request failed with status " + statusCode); + } + + if (apiError.getMessage() == null || apiError.getMessage().isBlank()) { + apiError.setMessage("Request failed with status " + statusCode); + } + if (apiError.getStatus() == null) { + apiError.setStatus(statusCode); + } + if (!apiError.isOk()) { + apiError.setOk(false); + } + return apiError; + } + private HttpRequest buildRequest( String method, String path, @@ -248,21 +295,7 @@ private void validateResponse(HttpResponse response) { int statusCode = response.statusCode(); if (statusCode < 200 || statusCode >= 300) { String bodyText = response.body() == null ? "" : new String(response.body(), StandardCharsets.UTF_8); - String message = "Request failed with status " + statusCode; - try { - JsonNode error = objectMapper.readTree(bodyText); - JsonNode messageNode = firstDefined(error, "message", "error", "detail"); - if (messageNode != null && messageNode.isTextual()) { - message = messageNode.asText(); - } else if (!bodyText.isEmpty()) { - message = bodyText; - } - } catch (Exception ignored) { - if (!bodyText.isEmpty()) { - message = bodyText; - } - } - throw new FacturapiException(message, statusCode, bodyText); + throw new FacturapiException(parseApiError(bodyText, statusCode), bodyText); } } diff --git a/src/main/java/io/facturapi/models/ApiError.java b/src/main/java/io/facturapi/models/ApiError.java new file mode 100644 index 0000000..8fad6a4 --- /dev/null +++ b/src/main/java/io/facturapi/models/ApiError.java @@ -0,0 +1,90 @@ +package io.facturapi.models; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonSetter; +import com.fasterxml.jackson.databind.JsonNode; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class ApiError { + private String message; + private Integer status; + private boolean ok; + private Object code; + private String path; + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + public Integer getStatus() { + return status; + } + + public void setStatus(Integer status) { + this.status = status; + } + + @JsonSetter("status") + public void setStatus(JsonNode status) { + if (status == null || status.isNull()) { + this.status = null; + return; + } + if (status.isIntegralNumber()) { + this.status = status.intValue(); + return; + } + if (status.isNumber()) { + this.status = (int) Math.round(status.asDouble()); + return; + } + if (status.isTextual()) { + try { + this.status = Integer.parseInt(status.asText()); + } catch (NumberFormatException ignored) { + this.status = null; + } + } + } + + public boolean isOk() { + return ok; + } + + public void setOk(boolean ok) { + this.ok = ok; + } + + public Object getCode() { + return code; + } + + @JsonSetter("code") + public void setCode(JsonNode code) { + if (code == null || code.isNull()) { + this.code = null; + } else if (code.isTextual()) { + this.code = code.asText(); + } else if (code.isIntegralNumber()) { + this.code = code.intValue(); + } else if (code.isNumber()) { + this.code = code.numberValue(); + } else if (code.isBoolean()) { + this.code = code.asBoolean(); + } else { + this.code = code.toString(); + } + } + + public String getPath() { + return path; + } + + public void setPath(String path) { + this.path = path; + } +} diff --git a/src/test/java/io/facturapi/FacturapiHttpClientTest.java b/src/test/java/io/facturapi/FacturapiHttpClientTest.java index 853b602..54145c4 100644 --- a/src/test/java/io/facturapi/FacturapiHttpClientTest.java +++ b/src/test/java/io/facturapi/FacturapiHttpClientTest.java @@ -2,6 +2,8 @@ import static org.junit.jupiter.api.Assertions.assertArrayEquals; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -50,7 +52,7 @@ void returnsBinaryBytesForPdf() { @Test void throwsFacturapiExceptionWithApiMessage() { StubHttpClient httpClient = new StubHttpClient(); - httpClient.enqueueJson(400, "{\"message\":\"Invalid customer\"}"); + httpClient.enqueueJson(400, "{\"message\":\"Invalid customer\",\"status\":\"400\",\"ok\":false,\"code\":\"validation_error\",\"path\":\"customer.tax_id\"}"); FacturapiHttpClient client = new FacturapiHttpClient( FacturapiConfig.builder("sk_test_123") @@ -65,5 +67,11 @@ void throwsFacturapiExceptionWithApiMessage() { assertEquals(400, ex.getStatusCode()); assertTrue(ex.getMessage().contains("Invalid customer")); + assertNotNull(ex.getApiError()); + assertEquals("Invalid customer", ex.getApiError().getMessage()); + assertEquals(400, ex.getApiError().getStatus()); + assertFalse(ex.getApiError().isOk()); + assertEquals("validation_error", ex.getApiError().getCode()); + assertEquals("customer.tax_id", ex.getApiError().getPath()); } } From 84546f3274b9dfe44d401468f58a79f187cf7649 Mon Sep 17 00:00:00 2001 From: javorosas Date: Tue, 7 Apr 2026 16:03:40 +0200 Subject: [PATCH 14/22] docs: add api error example --- README.md | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/README.md b/README.md index 4ca1549..35e0eb8 100644 --- a/README.md +++ b/README.md @@ -69,10 +69,30 @@ var updated = facturapi.organizations().uploadCertificate( ); ``` +## Errors + +```java +import io.facturapi.FacturapiException; + +try { + facturapi.customers().retrieve("cus_123"); +} catch (FacturapiException e) { + System.out.println(e.getMessage()); + + var apiError = e.getApiError(); + if (apiError != null) { + System.out.println(apiError.getStatus()); + System.out.println(apiError.getCode()); + System.out.println(apiError.getPath()); + } +} +``` + ## Design - Inputs use flexible JSON dictionaries (`Map`). - Outputs are typed Java models (`Invoice`, `Customer`, `SearchResult`, etc.). +- Errors expose the API error payload when the response body is JSON. - Auth uses `Authorization: Bearer `. ## Configuration From d63af00ff6cc844e9c29312ee8b1dfc39630cc73 Mon Sep 17 00:00:00 2001 From: javorosas Date: Tue, 7 Apr 2026 16:10:21 +0200 Subject: [PATCH 15/22] refactor: simplify error surface --- README.md | 12 +-- .../java/io/facturapi/FacturapiException.java | 42 +++------ .../facturapi/http/FacturapiHttpClient.java | 88 +++++++++--------- .../java/io/facturapi/models/ApiError.java | 90 ------------------- .../io/facturapi/FacturapiHttpClientTest.java | 12 +-- 5 files changed, 64 insertions(+), 180 deletions(-) delete mode 100644 src/main/java/io/facturapi/models/ApiError.java diff --git a/README.md b/README.md index 35e0eb8..12cd018 100644 --- a/README.md +++ b/README.md @@ -78,13 +78,9 @@ try { facturapi.customers().retrieve("cus_123"); } catch (FacturapiException e) { System.out.println(e.getMessage()); - - var apiError = e.getApiError(); - if (apiError != null) { - System.out.println(apiError.getStatus()); - System.out.println(apiError.getCode()); - System.out.println(apiError.getPath()); - } + System.out.println(e.getStatusCode()); + System.out.println(e.getErrorCode()); + System.out.println(e.getErrorPath()); } ``` @@ -92,7 +88,7 @@ try { - Inputs use flexible JSON dictionaries (`Map`). - Outputs are typed Java models (`Invoice`, `Customer`, `SearchResult`, etc.). -- Errors expose the API error payload when the response body is JSON. +- Errors expose the useful API error fields directly on `FacturapiException`. - Auth uses `Authorization: Bearer `. ## Configuration diff --git a/src/main/java/io/facturapi/FacturapiException.java b/src/main/java/io/facturapi/FacturapiException.java index b2ce484..ec6b9d9 100644 --- a/src/main/java/io/facturapi/FacturapiException.java +++ b/src/main/java/io/facturapi/FacturapiException.java @@ -1,55 +1,37 @@ package io.facturapi; -import io.facturapi.models.ApiError; - public class FacturapiException extends RuntimeException { - private final ApiError apiError; private final int statusCode; - private final String responseBody; + private final Object errorCode; + private final String errorPath; public FacturapiException(String message) { - super(message); - this.apiError = null; - this.statusCode = -1; - this.responseBody = null; + this(message, -1, null, null); } public FacturapiException(String message, Throwable cause) { super(message, cause); - this.apiError = null; this.statusCode = -1; - this.responseBody = null; + this.errorCode = null; + this.errorPath = null; } - public FacturapiException(String message, int statusCode, String responseBody) { + public FacturapiException(String message, int statusCode, Object errorCode, String errorPath) { super(message); - this.apiError = null; this.statusCode = statusCode; - this.responseBody = responseBody; - } - - public FacturapiException(ApiError apiError, String responseBody) { - super(apiError != null && apiError.getMessage() != null && !apiError.getMessage().isBlank() - ? apiError.getMessage() - : "An error occurred"); - this.apiError = apiError; - this.statusCode = apiError != null && apiError.getStatus() != null ? apiError.getStatus() : -1; - this.responseBody = responseBody; + this.errorCode = errorCode; + this.errorPath = errorPath; } public int getStatusCode() { return statusCode; } - public String getResponseBody() { - return responseBody; - } - - public ApiError getApiError() { - return apiError; + public Object getErrorCode() { + return errorCode; } - public ApiError getError() { - return apiError; + public String getErrorPath() { + return errorPath; } } diff --git a/src/main/java/io/facturapi/http/FacturapiHttpClient.java b/src/main/java/io/facturapi/http/FacturapiHttpClient.java index 0399a60..c03478a 100644 --- a/src/main/java/io/facturapi/http/FacturapiHttpClient.java +++ b/src/main/java/io/facturapi/http/FacturapiHttpClient.java @@ -4,7 +4,6 @@ import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import io.facturapi.FacturapiException; -import io.facturapi.models.ApiError; import java.io.IOException; import java.io.InputStream; import java.net.URI; @@ -147,7 +146,7 @@ private InputStream requestStream(String method, String path, Object body) { responseBytes = errorStream == null ? new byte[0] : errorStream.readAllBytes(); } String bodyText = responseBytes.length == 0 ? "" : new String(responseBytes, StandardCharsets.UTF_8); - throw new FacturapiException(parseApiError(bodyText, statusCode), bodyText); + throw buildApiException(bodyText, statusCode); } return response.body(); } catch (IOException e) { @@ -202,64 +201,67 @@ private static JsonNode firstDefined(JsonNode node, String... keys) { return null; } - private ApiError parseApiError(String bodyText, int statusCode) { - ApiError apiError = null; + private FacturapiException buildApiException(String bodyText, int statusCode) { + int resolvedStatus = statusCode; + Object errorCode = null; + String errorPath = null; + String message = "Request failed with status " + statusCode; + if (bodyText != null && !bodyText.isBlank()) { try { - apiError = objectMapper.readValue(bodyText, ApiError.class); - } catch (Exception ignored) { - try { - JsonNode error = objectMapper.readTree(bodyText); - apiError = new ApiError(); - - JsonNode messageNode = firstDefined(error, "message", "error", "detail"); + JsonNode root = objectMapper.readTree(bodyText); + if (root != null) { + JsonNode messageNode = firstDefined(root, "message", "error", "detail"); if (messageNode != null && messageNode.isTextual()) { - apiError.setMessage(messageNode.asText()); + message = messageNode.asText(); + } else if (root.isTextual()) { + message = root.asText(); } else { - apiError.setMessage(bodyText); + message = bodyText; } - JsonNode statusNode = firstDefined(error, "status"); + JsonNode statusNode = firstDefined(root, "status"); if (statusNode != null) { - apiError.setStatus(statusNode); + if (statusNode.isIntegralNumber()) { + resolvedStatus = statusNode.intValue(); + } else if (statusNode.isNumber()) { + resolvedStatus = (int) Math.round(statusNode.asDouble()); + } else if (statusNode.isTextual()) { + try { + resolvedStatus = Integer.parseInt(statusNode.asText()); + } catch (NumberFormatException ignored) { + resolvedStatus = statusCode; + } + } } - JsonNode codeNode = firstDefined(error, "code"); - if (codeNode != null) { - apiError.setCode(codeNode); + JsonNode codeNode = firstDefined(root, "code"); + if (codeNode != null && !codeNode.isNull()) { + if (codeNode.isTextual()) { + errorCode = codeNode.asText(); + } else if (codeNode.isIntegralNumber()) { + errorCode = codeNode.intValue(); + } else if (codeNode.isNumber()) { + errorCode = codeNode.numberValue(); + } else if (codeNode.isBoolean()) { + errorCode = codeNode.asBoolean(); + } else { + errorCode = codeNode.toString(); + } } - JsonNode pathNode = firstDefined(error, "path"); + JsonNode pathNode = firstDefined(root, "path"); if (pathNode != null && pathNode.isTextual()) { - apiError.setPath(pathNode.asText()); + errorPath = pathNode.asText(); } - JsonNode okNode = firstDefined(error, "ok"); - if (okNode != null && okNode.isBoolean()) { - apiError.setOk(okNode.asBoolean()); - } - } catch (Exception secondaryIgnored) { - apiError = new ApiError(); - apiError.setMessage(bodyText.isBlank() ? "Request failed with status " + statusCode : bodyText); } + } catch (Exception ignored) { + message = bodyText.isBlank() ? message : bodyText; } } - if (apiError == null) { - apiError = new ApiError(); - apiError.setMessage("Request failed with status " + statusCode); - } - - if (apiError.getMessage() == null || apiError.getMessage().isBlank()) { - apiError.setMessage("Request failed with status " + statusCode); - } - if (apiError.getStatus() == null) { - apiError.setStatus(statusCode); - } - if (!apiError.isOk()) { - apiError.setOk(false); - } - return apiError; + return new FacturapiException(message, resolvedStatus, errorCode, errorPath); } private HttpRequest buildRequest( @@ -295,7 +297,7 @@ private void validateResponse(HttpResponse response) { int statusCode = response.statusCode(); if (statusCode < 200 || statusCode >= 300) { String bodyText = response.body() == null ? "" : new String(response.body(), StandardCharsets.UTF_8); - throw new FacturapiException(parseApiError(bodyText, statusCode), bodyText); + throw buildApiException(bodyText, statusCode); } } diff --git a/src/main/java/io/facturapi/models/ApiError.java b/src/main/java/io/facturapi/models/ApiError.java deleted file mode 100644 index 8fad6a4..0000000 --- a/src/main/java/io/facturapi/models/ApiError.java +++ /dev/null @@ -1,90 +0,0 @@ -package io.facturapi.models; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonSetter; -import com.fasterxml.jackson.databind.JsonNode; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class ApiError { - private String message; - private Integer status; - private boolean ok; - private Object code; - private String path; - - public String getMessage() { - return message; - } - - public void setMessage(String message) { - this.message = message; - } - - public Integer getStatus() { - return status; - } - - public void setStatus(Integer status) { - this.status = status; - } - - @JsonSetter("status") - public void setStatus(JsonNode status) { - if (status == null || status.isNull()) { - this.status = null; - return; - } - if (status.isIntegralNumber()) { - this.status = status.intValue(); - return; - } - if (status.isNumber()) { - this.status = (int) Math.round(status.asDouble()); - return; - } - if (status.isTextual()) { - try { - this.status = Integer.parseInt(status.asText()); - } catch (NumberFormatException ignored) { - this.status = null; - } - } - } - - public boolean isOk() { - return ok; - } - - public void setOk(boolean ok) { - this.ok = ok; - } - - public Object getCode() { - return code; - } - - @JsonSetter("code") - public void setCode(JsonNode code) { - if (code == null || code.isNull()) { - this.code = null; - } else if (code.isTextual()) { - this.code = code.asText(); - } else if (code.isIntegralNumber()) { - this.code = code.intValue(); - } else if (code.isNumber()) { - this.code = code.numberValue(); - } else if (code.isBoolean()) { - this.code = code.asBoolean(); - } else { - this.code = code.toString(); - } - } - - public String getPath() { - return path; - } - - public void setPath(String path) { - this.path = path; - } -} diff --git a/src/test/java/io/facturapi/FacturapiHttpClientTest.java b/src/test/java/io/facturapi/FacturapiHttpClientTest.java index 54145c4..56e4800 100644 --- a/src/test/java/io/facturapi/FacturapiHttpClientTest.java +++ b/src/test/java/io/facturapi/FacturapiHttpClientTest.java @@ -2,8 +2,6 @@ import static org.junit.jupiter.api.Assertions.assertArrayEquals; import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -52,7 +50,7 @@ void returnsBinaryBytesForPdf() { @Test void throwsFacturapiExceptionWithApiMessage() { StubHttpClient httpClient = new StubHttpClient(); - httpClient.enqueueJson(400, "{\"message\":\"Invalid customer\",\"status\":\"400\",\"ok\":false,\"code\":\"validation_error\",\"path\":\"customer.tax_id\"}"); + httpClient.enqueueJson(400, "{\"message\":\"Invalid customer\",\"status\":\"400\",\"code\":\"validation_error\",\"path\":\"customer.tax_id\"}"); FacturapiHttpClient client = new FacturapiHttpClient( FacturapiConfig.builder("sk_test_123") @@ -67,11 +65,7 @@ void throwsFacturapiExceptionWithApiMessage() { assertEquals(400, ex.getStatusCode()); assertTrue(ex.getMessage().contains("Invalid customer")); - assertNotNull(ex.getApiError()); - assertEquals("Invalid customer", ex.getApiError().getMessage()); - assertEquals(400, ex.getApiError().getStatus()); - assertFalse(ex.getApiError().isOk()); - assertEquals("validation_error", ex.getApiError().getCode()); - assertEquals("customer.tax_id", ex.getApiError().getPath()); + assertEquals("validation_error", ex.getErrorCode()); + assertEquals("customer.tax_id", ex.getErrorPath()); } } From 8fc2de3c6eaa7d74a425980743c9e88f7bf27a23 Mon Sep 17 00:00:00 2001 From: javorosas Date: Tue, 7 Apr 2026 16:32:51 +0200 Subject: [PATCH 16/22] ci: add java 25 to test matrix --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a9e68d5..909c0eb 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -8,12 +8,12 @@ on: jobs: test: - name: Test (Java 11, 17, 21) + name: Test (Java 11, 17, 21, 25) runs-on: ubuntu-latest strategy: fail-fast: false matrix: - java: [11, 17, 21] + java: [11, 17, 21, 25] steps: - name: Checkout From 4f30d1b6b297e90ecf9063cee1a6667619870f34 Mon Sep 17 00:00:00 2001 From: javorosas Date: Tue, 7 Apr 2026 16:42:01 +0200 Subject: [PATCH 17/22] ci: add maven central publish workflow --- .github/workflows/publish.yml | 104 ++++++++++++++++++++++++++++++++++ pom.xml | 89 +++++++++++++++++++++++++++++ 2 files changed, 193 insertions(+) create mode 100644 .github/workflows/publish.yml diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml new file mode 100644 index 0000000..6893cd4 --- /dev/null +++ b/.github/workflows/publish.yml @@ -0,0 +1,104 @@ +name: Publish Java SDK + +on: + push: + branches: + - main + +permissions: + contents: read + +jobs: + publish: + name: Publish to Maven Central + runs-on: ubuntu-latest + env: + CENTRAL_USERNAME: ${{ secrets.CENTRAL_USERNAME }} + CENTRAL_PASSWORD: ${{ secrets.CENTRAL_PASSWORD }} + GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }} + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup Java + uses: actions/setup-java@v4 + with: + distribution: temurin + java-version: 25 + cache: maven + server-id: central + server-username: CENTRAL_USERNAME + server-password: CENTRAL_PASSWORD + gpg-private-key: ${{ secrets.GPG_PRIVATE_KEY }} + gpg-passphrase: GPG_PASSPHRASE + + - name: Check release gate + id: gate + shell: bash + run: | + set -euo pipefail + + python3 <<'PY' >> "$GITHUB_OUTPUT" + import sys + import urllib.request + import xml.etree.ElementTree as ET + + ns = {"m": "http://maven.apache.org/POM/4.0.0"} + pom = ET.parse("pom.xml").getroot() + version = pom.findtext("m:version", namespaces=ns) + if version is None: + print("publish=false") + print("reason=missing version") + sys.exit(0) + + if version.endswith("-SNAPSHOT"): + print("publish=false") + print(f"current_version={version}") + print("reason=snapshot version") + sys.exit(0) + + metadata_url = "https://repo.maven.apache.org/maven2/io/facturapi/facturapi-java/maven-metadata.xml" + latest = "0.0.0" + try: + with urllib.request.urlopen(metadata_url, timeout=20) as response: + metadata = ET.fromstring(response.read()) + latest = metadata.findtext("./versioning/release") or metadata.findtext("./versioning/latest") or latest + except Exception: + latest = "0.0.0" + + def parse_semver(value: str): + core = value.split("+", 1)[0] + main, _, prerelease = core.partition("-") + major, minor, patch = (int(part) for part in main.split(".")[:3]) + return major, minor, patch, prerelease + + def is_greater(left: str, right: str) -> bool: + left_parts = parse_semver(left) + right_parts = parse_semver(right) + if left_parts[:3] != right_parts[:3]: + return left_parts[:3] > right_parts[:3] + left_pre = left_parts[3] + right_pre = right_parts[3] + if left_pre == right_pre: + return False + if not left_pre: + return True + if not right_pre: + return False + return left_pre > right_pre + + publish = is_greater(version, latest) + print(f"current_version={version}") + print(f"latest_version={latest}") + print(f"publish={'true' if publish else 'false'}") + print(f"reason={'current version is newer than published version' if publish else 'published version is current or newer'}") + PY + + - name: Publish + if: steps.gate.outputs.publish == 'true' + run: mvn -B -ntp -DskipTests -DpublishRelease=true deploy + + - name: Skip publish + if: steps.gate.outputs.publish != 'true' + run: | + echo "Skipping publish: ${{ steps.gate.outputs.reason }} (${{ steps.gate.outputs.current_version }} vs ${{ steps.gate.outputs.latest_version }})" diff --git a/pom.xml b/pom.xml index 3afce5a..7d796f1 100644 --- a/pom.xml +++ b/pom.xml @@ -10,6 +10,25 @@ Official Java SDK for Facturapi https://github.com/facturapi/facturapi-java + + FacturAPI + https://facturapi.io + + + + scm:git:git://github.com/facturapi/facturapi-java.git + scm:git:ssh://git@github.com/facturapi/facturapi-java.git + https://github.com/facturapi/facturapi-java + + + + + FacturAPI + FacturAPI + https://facturapi.io + + + MIT License @@ -57,4 +76,74 @@ + + + + release + + + publishRelease + true + + + + + + org.sonatype.central + central-publishing-maven-plugin + 0.9.0 + true + + central + true + published + + + + org.apache.maven.plugins + maven-source-plugin + 3.4.0 + + + attach-sources + + jar-no-fork + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + 3.12.0 + + none + + + + attach-javadocs + + jar + + + + + + org.apache.maven.plugins + maven-gpg-plugin + 3.2.8 + + + sign-artifacts + verify + + sign + + + + + + + + From 42354010b9e020a3c51ea370f8623cc2ca0ec358 Mon Sep 17 00:00:00 2001 From: javorosas Date: Tue, 7 Apr 2026 16:55:25 +0200 Subject: [PATCH 18/22] refactor: use okhttp for all transports --- pom.xml | 14 + .../io/facturapi/http/FacturapiConfig.java | 17 +- .../facturapi/http/FacturapiHttpClient.java | 170 ++++++---- .../java/io/facturapi/http/MultipartBody.java | 12 +- .../facturapi/http/MultipartBodyBuilder.java | 37 +-- .../io/facturapi/FacturapiHttpClientTest.java | 6 +- .../io/facturapi/FacturapiResourcesTest.java | 15 +- .../java/io/facturapi/StubHttpClient.java | 292 ++++++------------ 8 files changed, 260 insertions(+), 303 deletions(-) diff --git a/pom.xml b/pom.xml index 7d796f1..05068b6 100644 --- a/pom.xml +++ b/pom.xml @@ -41,6 +41,7 @@ UTF-8 2.17.2 5.11.0 + 4.12.0 @@ -56,12 +57,25 @@ ${jackson.version} + + com.squareup.okhttp3 + okhttp + ${okhttp.version} + + org.junit.jupiter junit-jupiter ${junit.version} test + + + com.squareup.okhttp3 + mockwebserver + ${okhttp.version} + test + diff --git a/src/main/java/io/facturapi/http/FacturapiConfig.java b/src/main/java/io/facturapi/http/FacturapiConfig.java index a8642d9..04f5761 100644 --- a/src/main/java/io/facturapi/http/FacturapiConfig.java +++ b/src/main/java/io/facturapi/http/FacturapiConfig.java @@ -7,9 +7,9 @@ import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; import io.facturapi.ApiVersion; import io.facturapi.constants.FacturapiConstants; -import java.net.http.HttpClient; import java.time.Duration; import java.util.Objects; +import okhttp3.OkHttpClient; public final class FacturapiConfig { private final String apiKey; @@ -17,7 +17,7 @@ public final class FacturapiConfig { private final String baseUrl; private final Duration timeout; private final String userAgent; - private final HttpClient httpClient; + private final OkHttpClient httpClient; private final ObjectMapper objectMapper; private FacturapiConfig(Builder builder) { @@ -50,7 +50,7 @@ public String getUserAgent() { return userAgent; } - public HttpClient getHttpClient() { + public OkHttpClient getHttpClient() { return httpClient; } @@ -68,7 +68,7 @@ public static final class Builder { private String baseUrl; private Duration timeout = Duration.ofSeconds(30); private final String userAgent = "facturapi-java/0.1.x"; - private HttpClient httpClient; + private OkHttpClient httpClient; private ObjectMapper objectMapper; private Builder(String apiKey) { @@ -93,7 +93,7 @@ public Builder timeout(Duration timeout) { return this; } - public Builder httpClient(HttpClient httpClient) { + public Builder httpClient(OkHttpClient httpClient) { this.httpClient = Objects.requireNonNull(httpClient, "httpClient is required"); return this; } @@ -103,8 +103,11 @@ public FacturapiConfig build() { ? FacturapiConstants.BASE_URL_V1 : FacturapiConstants.BASE_URL_V2; - HttpClient resolvedClient = this.httpClient == null - ? HttpClient.newBuilder().connectTimeout(timeout).build() + OkHttpClient resolvedClient = this.httpClient == null + ? new OkHttpClient.Builder() + .connectTimeout(timeout) + .callTimeout(timeout) + .build() : this.httpClient; ObjectMapper resolvedMapper = new ObjectMapper() diff --git a/src/main/java/io/facturapi/http/FacturapiHttpClient.java b/src/main/java/io/facturapi/http/FacturapiHttpClient.java index c03478a..18578d5 100644 --- a/src/main/java/io/facturapi/http/FacturapiHttpClient.java +++ b/src/main/java/io/facturapi/http/FacturapiHttpClient.java @@ -4,24 +4,28 @@ import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import io.facturapi.FacturapiException; +import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; -import java.net.URI; +import java.io.UncheckedIOException; import java.net.URLEncoder; -import java.net.http.HttpClient; -import java.net.http.HttpRequest; -import java.net.http.HttpResponse; import java.nio.charset.StandardCharsets; -import java.time.Duration; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Objects; +import okhttp3.MediaType; +import okhttp3.OkHttpClient; +import okhttp3.Request; +import okhttp3.RequestBody; +import okhttp3.Response; +import okhttp3.ResponseBody; public final class FacturapiHttpClient { - private final HttpClient httpClient; + private static final MediaType JSON_MEDIA_TYPE = MediaType.get("application/json; charset=utf-8"); + + private final OkHttpClient httpClient; private final ObjectMapper objectMapper; - private final Duration timeout; private final String baseUrl; private final String apiKey; private final String userAgent; @@ -29,7 +33,6 @@ public final class FacturapiHttpClient { public FacturapiHttpClient(FacturapiConfig config) { this.httpClient = config.getHttpClient(); this.objectMapper = config.getObjectMapper(); - this.timeout = config.getTimeout(); this.baseUrl = config.getBaseUrl(); this.apiKey = config.getApiKey(); this.userAgent = config.getUserAgent(); @@ -98,62 +101,65 @@ private JsonNode requestJsonNode( Object body, MultipartBody multipartBody ) { - try { - HttpRequest request = buildRequest(method, path, queryParams, body, multipartBody); - HttpResponse response = httpClient.send(request, HttpResponse.BodyHandlers.ofByteArray()); - validateResponse(response); + Request request = buildRequest(method, path, queryParams, body, multipartBody); + try (Response response = httpClient.newCall(request).execute()) { + if (!response.isSuccessful()) { + throw buildApiException(readBodyText(response), response.code()); + } - byte[] responseBytes = response.body(); - if (responseBytes == null || responseBytes.length == 0) { + ResponseBody responseBody = response.body(); + if (responseBody == null) { return objectMapper.nullNode(); } - String contentType = response.headers().firstValue("Content-Type").orElse(""); + byte[] responseBytes = responseBody.bytes(); + if (responseBytes.length == 0) { + return objectMapper.nullNode(); + } + + String contentType = responseBody.contentType() == null ? "" : responseBody.contentType().toString(); if (!contentType.contains("application/json")) { return objectMapper.valueToTree(new String(responseBytes, StandardCharsets.UTF_8)); } return objectMapper.readTree(responseBytes); } catch (IOException e) { throw new FacturapiException("I/O error when calling Facturapi API", e); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - throw new FacturapiException("Request interrupted", e); } } private byte[] requestBytes(String method, String path, Object body) { - try { - HttpRequest request = buildRequest(method, path, null, body, null); - HttpResponse response = httpClient.send(request, HttpResponse.BodyHandlers.ofByteArray()); - validateResponse(response); - return response.body(); + Request request = buildRequest(method, path, null, body, null); + try (Response response = httpClient.newCall(request).execute()) { + if (!response.isSuccessful()) { + throw buildApiException(readBodyText(response), response.code()); + } + ResponseBody responseBody = response.body(); + return responseBody == null ? new byte[0] : responseBody.bytes(); } catch (IOException e) { throw new FacturapiException("I/O error when calling Facturapi API", e); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - throw new FacturapiException("Request interrupted", e); } } private InputStream requestStream(String method, String path, Object body) { + Request request = buildRequest(method, path, null, body, null); try { - HttpRequest request = buildRequest(method, path, null, body, null); - HttpResponse response = httpClient.send(request, HttpResponse.BodyHandlers.ofInputStream()); - int statusCode = response.statusCode(); - if (statusCode < 200 || statusCode >= 300) { - byte[] responseBytes; - try (InputStream errorStream = response.body()) { - responseBytes = errorStream == null ? new byte[0] : errorStream.readAllBytes(); + Response response = httpClient.newCall(request).execute(); + if (!response.isSuccessful()) { + try { + throw buildApiException(readBodyText(response), response.code()); + } finally { + response.close(); } - String bodyText = responseBytes.length == 0 ? "" : new String(responseBytes, StandardCharsets.UTF_8); - throw buildApiException(bodyText, statusCode); } - return response.body(); + + ResponseBody responseBody = response.body(); + if (responseBody == null) { + response.close(); + return new ByteArrayInputStream(new byte[0]); + } + return new ResponseInputStream(response, responseBody); } catch (IOException e) { throw new FacturapiException("I/O error when calling Facturapi API", e); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - throw new FacturapiException("Request interrupted", e); } } @@ -255,6 +261,9 @@ private FacturapiException buildApiException(String bodyText, int statusCode) { errorPath = pathNode.asText(); } + if (firstDefined(root, "message", "error", "detail") == null) { + message = bodyText; + } } } catch (Exception ignored) { message = bodyText.isBlank() ? message : bodyText; @@ -264,41 +273,50 @@ private FacturapiException buildApiException(String bodyText, int statusCode) { return new FacturapiException(message, resolvedStatus, errorCode, errorPath); } - private HttpRequest buildRequest( + private static String readBodyText(Response response) throws IOException { + ResponseBody responseBody = response.body(); + if (responseBody == null) { + return ""; + } + return responseBody.string(); + } + + private Request buildRequest( String method, String path, Map queryParams, Object body, MultipartBody multipartBody - ) throws IOException { - URI uri = URI.create(baseUrl + normalizePath(path) + buildQuery(queryParams)); - HttpRequest.Builder requestBuilder = HttpRequest.newBuilder() - .uri(uri) - .timeout(timeout) + ) { + String url = baseUrl + normalizePath(path) + buildQuery(queryParams); + Request.Builder builder = new Request.Builder() + .url(url) .header("Authorization", "Bearer " + apiKey) .header("Accept", "application/json") .header("User-Agent", userAgent); - HttpRequest.BodyPublisher publisher = HttpRequest.BodyPublishers.noBody(); + RequestBody requestBody = null; if (multipartBody != null) { - publisher = multipartBody.getPublisher(); - requestBuilder.header("Content-Type", multipartBody.getContentType()); + requestBody = multipartBody.getBody(); } else if (body != null) { - byte[] json = objectMapper.writeValueAsBytes(body); - publisher = HttpRequest.BodyPublishers.ofByteArray(json); - requestBuilder.header("Content-Type", "application/json"); + try { + byte[] json = objectMapper.writeValueAsBytes(body); + requestBody = RequestBody.create(json, JSON_MEDIA_TYPE); + } catch (IOException e) { + throw new UncheckedIOException("Could not serialize request body", e); + } } - requestBuilder.method(method, publisher); - return requestBuilder.build(); - } - - private void validateResponse(HttpResponse response) { - int statusCode = response.statusCode(); - if (statusCode < 200 || statusCode >= 300) { - String bodyText = response.body() == null ? "" : new String(response.body(), StandardCharsets.UTF_8); - throw buildApiException(bodyText, statusCode); + if (requestBody == null) { + if ("GET".equals(method) || "HEAD".equals(method)) { + builder.method(method, null); + } else { + builder.method(method, RequestBody.create(new byte[0], null)); + } + } else { + builder.method(method, requestBody); } + return builder.build(); } private static String normalizePath(String path) { @@ -345,4 +363,36 @@ private static void appendQueryPart(List parts, String key, Object value String encodedValue = URLEncoder.encode(Objects.toString(value), StandardCharsets.UTF_8); parts.add(encodedKey + "=" + encodedValue); } + + private static final class ResponseInputStream extends InputStream { + private final Response response; + private final ResponseBody responseBody; + private final InputStream delegate; + + private ResponseInputStream(Response response, ResponseBody responseBody) { + this.response = response; + this.responseBody = responseBody; + this.delegate = responseBody.byteStream(); + } + + @Override + public int read() throws IOException { + return delegate.read(); + } + + @Override + public int read(byte[] b, int off, int len) throws IOException { + return delegate.read(b, off, len); + } + + @Override + public void close() throws IOException { + try { + delegate.close(); + } finally { + responseBody.close(); + response.close(); + } + } + } } diff --git a/src/main/java/io/facturapi/http/MultipartBody.java b/src/main/java/io/facturapi/http/MultipartBody.java index 314c18f..06e5f31 100644 --- a/src/main/java/io/facturapi/http/MultipartBody.java +++ b/src/main/java/io/facturapi/http/MultipartBody.java @@ -1,18 +1,18 @@ package io.facturapi.http; -import java.net.http.HttpRequest; +import okhttp3.RequestBody; public final class MultipartBody { - private final HttpRequest.BodyPublisher publisher; + private final RequestBody body; private final String contentType; - public MultipartBody(HttpRequest.BodyPublisher publisher, String contentType) { - this.publisher = publisher; + public MultipartBody(RequestBody body, String contentType) { + this.body = body; this.contentType = contentType; } - public HttpRequest.BodyPublisher getPublisher() { - return publisher; + public RequestBody getBody() { + return body; } public String getContentType() { diff --git a/src/main/java/io/facturapi/http/MultipartBodyBuilder.java b/src/main/java/io/facturapi/http/MultipartBodyBuilder.java index 8829318..0d7d3ec 100644 --- a/src/main/java/io/facturapi/http/MultipartBodyBuilder.java +++ b/src/main/java/io/facturapi/http/MultipartBodyBuilder.java @@ -1,43 +1,26 @@ package io.facturapi.http; -import java.net.http.HttpRequest; -import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.List; -import java.util.UUID; +import okhttp3.MediaType; +import okhttp3.RequestBody; public final class MultipartBodyBuilder { - private static final String CRLF = "\r\n"; - private final String boundary = "----FacturapiJava" + UUID.randomUUID(); - private final List parts = new ArrayList<>(); + private static final MediaType OCTET_STREAM = MediaType.get("application/octet-stream"); + private final okhttp3.MultipartBody.Builder builder = new okhttp3.MultipartBody.Builder() + .setType(okhttp3.MultipartBody.FORM); public MultipartBodyBuilder addField(String name, String value) { - StringBuilder builder = new StringBuilder(); - builder.append("--").append(boundary).append(CRLF); - builder.append("Content-Disposition: form-data; name=\"").append(name).append("\"").append(CRLF); - builder.append(CRLF); - builder.append(value == null ? "" : value).append(CRLF); - parts.add(builder.toString().getBytes(StandardCharsets.UTF_8)); + builder.addFormDataPart(name, value == null ? "" : value); return this; } public MultipartBodyBuilder addFile(String fieldName, String fileName, byte[] content, String contentType) { - StringBuilder builder = new StringBuilder(); - builder.append("--").append(boundary).append(CRLF); - builder.append("Content-Disposition: form-data; name=\"").append(fieldName) - .append("\"; filename=\"").append(fileName).append("\"").append(CRLF); - builder.append("Content-Type: ").append(contentType).append(CRLF); - builder.append(CRLF); - parts.add(builder.toString().getBytes(StandardCharsets.UTF_8)); - parts.add(content); - parts.add(CRLF.getBytes(StandardCharsets.UTF_8)); + MediaType mediaType = contentType == null ? OCTET_STREAM : MediaType.get(contentType); + builder.addFormDataPart(fieldName, fileName, RequestBody.create(content, mediaType)); return this; } public MultipartBody build() { - String ending = "--" + boundary + "--" + CRLF; - parts.add(ending.getBytes(StandardCharsets.UTF_8)); - HttpRequest.BodyPublisher publisher = HttpRequest.BodyPublishers.ofByteArrays(parts); - return new MultipartBody(publisher, "multipart/form-data; boundary=" + boundary); + okhttp3.MultipartBody multipartBody = builder.build(); + return new MultipartBody(multipartBody, multipartBody.contentType().toString()); } } diff --git a/src/test/java/io/facturapi/FacturapiHttpClientTest.java b/src/test/java/io/facturapi/FacturapiHttpClientTest.java index 56e4800..dc1d41b 100644 --- a/src/test/java/io/facturapi/FacturapiHttpClientTest.java +++ b/src/test/java/io/facturapi/FacturapiHttpClientTest.java @@ -19,7 +19,7 @@ void sendsBearerAuthAndParsesTypedJson() throws Exception { FacturapiHttpClient client = new FacturapiHttpClient( FacturapiConfig.builder("sk_test_123") - .httpClient(httpClient) + .httpClient(httpClient.client()) .build() ); @@ -40,7 +40,7 @@ void returnsBinaryBytesForPdf() { FacturapiHttpClient client = new FacturapiHttpClient( FacturapiConfig.builder("sk_test_123") - .httpClient(httpClient) + .httpClient(httpClient.client()) .build() ); @@ -54,7 +54,7 @@ void throwsFacturapiExceptionWithApiMessage() { FacturapiHttpClient client = new FacturapiHttpClient( FacturapiConfig.builder("sk_test_123") - .httpClient(httpClient) + .httpClient(httpClient.client()) .build() ); diff --git a/src/test/java/io/facturapi/FacturapiResourcesTest.java b/src/test/java/io/facturapi/FacturapiResourcesTest.java index 5307298..e4bbbec 100644 --- a/src/test/java/io/facturapi/FacturapiResourcesTest.java +++ b/src/test/java/io/facturapi/FacturapiResourcesTest.java @@ -30,7 +30,7 @@ void invoiceCreateUsesExpectedPath() { Facturapi sdk = new Facturapi( FacturapiConfig.builder("sk_test") - .httpClient(httpClient) + .httpClient(httpClient.client()) .build() ); @@ -50,7 +50,7 @@ void invoicePdfCanBeStreamed() throws Exception { Facturapi sdk = new Facturapi( FacturapiConfig.builder("sk_test") - .httpClient(httpClient) + .httpClient(httpClient.client()) .build() ); @@ -69,7 +69,7 @@ void organizationUploadsAcceptBytes() { Facturapi sdk = new Facturapi( FacturapiConfig.builder("sk_test") - .httpClient(httpClient) + .httpClient(httpClient.client()) .build() ); @@ -87,7 +87,7 @@ void organizationCertificateUploadsAcceptBytes() { Facturapi sdk = new Facturapi( FacturapiConfig.builder("sk_test") - .httpClient(httpClient) + .httpClient(httpClient.client()) .build() ); @@ -105,9 +105,10 @@ void organizationCertificateUploadsAcceptBytes() { @Test void sdkExposesAccessorBasedSurface() { + StubHttpClient httpClient = new StubHttpClient(); Facturapi sdk = new Facturapi( FacturapiConfig.builder("sk_test") - .httpClient(new StubHttpClient()) + .httpClient(httpClient.client()) .build() ); @@ -130,7 +131,7 @@ void organizationListLiveApiKeysIsTyped() { Facturapi sdk = new Facturapi( FacturapiConfig.builder("sk_test") - .httpClient(httpClient) + .httpClient(httpClient.client()) .build() ); @@ -158,7 +159,7 @@ void invoiceComplementsAreTypedForPagoNominaAndCustom() { Facturapi sdk = new Facturapi( FacturapiConfig.builder("sk_test") - .httpClient(httpClient) + .httpClient(httpClient.client()) .build() ); diff --git a/src/test/java/io/facturapi/StubHttpClient.java b/src/test/java/io/facturapi/StubHttpClient.java index 34c86c0..a247f82 100644 --- a/src/test/java/io/facturapi/StubHttpClient.java +++ b/src/test/java/io/facturapi/StubHttpClient.java @@ -1,32 +1,26 @@ package io.facturapi; import java.io.IOException; -import java.io.InputStream; -import java.net.Authenticator; -import java.net.CookieHandler; -import java.net.ProxySelector; import java.net.URI; -import java.net.http.HttpClient; -import java.net.http.HttpHeaders; -import java.net.http.HttpRequest; -import java.net.http.HttpResponse; import java.nio.charset.StandardCharsets; -import java.time.Duration; -import java.nio.ByteBuffer; import java.util.ArrayDeque; import java.util.ArrayList; import java.util.Deque; import java.util.List; import java.util.Map; import java.util.Optional; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.Flow; -import java.util.concurrent.Executor; -import javax.net.ssl.SSLContext; -import javax.net.ssl.SSLParameters; -import javax.net.ssl.SSLSession; - -final class StubHttpClient extends HttpClient { +import okhttp3.Headers; +import okhttp3.Interceptor; +import okhttp3.MediaType; +import okhttp3.OkHttpClient; +import okhttp3.Protocol; +import okhttp3.Request; +import okhttp3.RequestBody; +import okhttp3.Response; +import okhttp3.ResponseBody; +import okio.Buffer; + +final class StubHttpClient { static final class QueuedResponse { final int statusCode; final byte[] body; @@ -39,204 +33,116 @@ static final class QueuedResponse { } } - private final Deque queue = new ArrayDeque<>(); - private final List requests = new ArrayList<>(); - - void enqueueJson(int statusCode, String json) { - queue.add( - new QueuedResponse(statusCode, json.getBytes(StandardCharsets.UTF_8), Map.of("Content-Type", List.of("application/json"))) - ); - } - - void enqueueBinary(int statusCode, byte[] bytes, String contentType) { - queue.add(new QueuedResponse(statusCode, bytes, Map.of("Content-Type", List.of(contentType)))); - } - - List requests() { - return requests; - } - - @Override - public Optional cookieHandler() { - return Optional.empty(); - } - - @Override - public Optional connectTimeout() { - return Optional.empty(); - } - - @Override - public Redirect followRedirects() { - return Redirect.NEVER; - } - - @Override - public Optional proxy() { - return Optional.empty(); - } - - @Override - public SSLContext sslContext() { - try { - return SSLContext.getDefault(); - } catch (Exception e) { - throw new RuntimeException(e); - } - } - - @Override - public SSLParameters sslParameters() { - return new SSLParameters(); - } - - @Override - public Optional authenticator() { - return Optional.empty(); - } - - @Override - public Version version() { - return Version.HTTP_1_1; - } - - @Override - public Optional executor() { - return Optional.empty(); - } + static final class RecordedHeaders { + private final Headers headers; - @Override - public HttpResponse send(HttpRequest request, HttpResponse.BodyHandler responseBodyHandler) - throws IOException, InterruptedException { - requests.add(request); - QueuedResponse queued = queue.poll(); - if (queued == null) { - throw new IOException("No queued response"); + RecordedHeaders(Headers headers) { + this.headers = headers; } - @SuppressWarnings("unchecked") - T body = (T) buildBody(responseBodyHandler, queued.body, queued.statusCode, queued.headers); - return new StubHttpResponse<>(request, queued.statusCode, body, queued.headers); - } - @Override - public CompletableFuture> sendAsync( - HttpRequest request, - HttpResponse.BodyHandler responseBodyHandler - ) { - try { - return CompletableFuture.completedFuture(send(request, responseBodyHandler)); - } catch (IOException | InterruptedException e) { - CompletableFuture> future = new CompletableFuture<>(); - future.completeExceptionally(e); - return future; + Optional firstValue(String name) { + return Optional.ofNullable(headers.values(name).stream().findFirst().orElse(null)); } } - @Override - public CompletableFuture> sendAsync( - HttpRequest request, - HttpResponse.BodyHandler responseBodyHandler, - HttpResponse.PushPromiseHandler pushPromiseHandler - ) { - return sendAsync(request, responseBodyHandler); - } - - private static final class StubHttpResponse implements HttpResponse { - private final HttpRequest request; - private final int statusCode; - private final T body; - private final HttpHeaders headers; + static final class RecordedRequest { + private final Request request; - StubHttpResponse(HttpRequest request, int statusCode, T body, Map> headers) { + RecordedRequest(Request request) { this.request = request; - this.statusCode = statusCode; - this.body = body; - this.headers = HttpHeaders.of(headers, (k, v) -> true); - } - - @Override - public int statusCode() { - return statusCode; - } - - @Override - public HttpRequest request() { - return request; - } - - @Override - public Optional> previousResponse() { - return Optional.empty(); - } - - @Override - public HttpHeaders headers() { - return headers; } - @Override - public T body() { - return body; + String method() { + return request.method(); } - @Override - public Optional sslSession() { - return Optional.empty(); + URI uri() { + return request.url().uri(); } - @Override - public URI uri() { - return request.uri(); + RecordedHeaders headers() { + return new RecordedHeaders(request.headers()); } - @Override - public Version version() { - return Version.HTTP_1_1; + String bodyUtf8() { + RequestBody body = request.body(); + if (body == null) { + return ""; + } + Buffer buffer = new Buffer(); + try { + body.writeTo(buffer); + } catch (IOException e) { + throw new RuntimeException(e); + } + return buffer.readString(StandardCharsets.UTF_8); } } - private static T buildBody( - HttpResponse.BodyHandler responseBodyHandler, - byte[] body, - int statusCode, - Map> headers - ) { - HttpResponse.ResponseInfo responseInfo = new ResponseInfo(statusCode, headers); - HttpResponse.BodySubscriber subscriber = responseBodyHandler.apply(responseInfo); - subscriber.onSubscribe(new Flow.Subscription() { - @Override - public void request(long n) {} - - @Override - public void cancel() {} - }); - subscriber.onNext(List.of(ByteBuffer.wrap(body))); - subscriber.onComplete(); - return subscriber.getBody().toCompletableFuture().join(); + private final Deque queue = new ArrayDeque<>(); + private final List requests = new ArrayList<>(); + private final OkHttpClient client; + + StubHttpClient() { + this.client = new OkHttpClient.Builder() + .addInterceptor(new Interceptor() { + @Override + public Response intercept(Chain chain) throws IOException { + Request request = chain.request(); + requests.add(new RecordedRequest(request)); + QueuedResponse queued = queue.poll(); + if (queued == null) { + throw new IOException("No queued response"); + } + return buildResponse(request, queued); + } + }) + .build(); + } + + OkHttpClient client() { + return client; } - private static final class ResponseInfo implements HttpResponse.ResponseInfo { - private final int statusCode; - private final HttpHeaders headers; - - ResponseInfo(int statusCode, Map> headers) { - this.statusCode = statusCode; - this.headers = HttpHeaders.of(headers, (k, v) -> true); - } + void enqueueJson(int statusCode, String json) { + queue.add( + new QueuedResponse( + statusCode, + json.getBytes(StandardCharsets.UTF_8), + Map.of("Content-Type", List.of("application/json")) + ) + ); + } - @Override - public int statusCode() { - return statusCode; - } + void enqueueBinary(int statusCode, byte[] bytes, String contentType) { + queue.add(new QueuedResponse(statusCode, bytes, Map.of("Content-Type", List.of(contentType)))); + } - @Override - public HttpHeaders headers() { - return headers; - } + List requests() { + return requests; + } - @Override - public HttpClient.Version version() { - return HttpClient.Version.HTTP_1_1; - } + private static Response buildResponse(Request request, QueuedResponse queued) { + Headers headers = toHeaders(queued.headers); + MediaType mediaType = headers.get("Content-Type") == null ? null : MediaType.get(headers.get("Content-Type")); + ResponseBody body = ResponseBody.create(queued.body, mediaType); + return new Response.Builder() + .request(request) + .protocol(Protocol.HTTP_1_1) + .code(queued.statusCode) + .message(queued.statusCode >= 200 && queued.statusCode < 300 ? "OK" : "ERROR") + .headers(headers) + .body(body) + .build(); + } + + private static Headers toHeaders(Map> headers) { + Headers.Builder builder = new Headers.Builder(); + for (Map.Entry> entry : headers.entrySet()) { + for (String value : entry.getValue()) { + builder.add(entry.getKey(), value); + } + } + return builder.build(); } } From 0d4b0185b2e5492411bafc631ee6272349151d6a Mon Sep 17 00:00:00 2001 From: javorosas Date: Tue, 7 Apr 2026 17:09:36 +0200 Subject: [PATCH 19/22] docs: clarify sdk compatibility --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index 12cd018..e4911ab 100644 --- a/README.md +++ b/README.md @@ -9,6 +9,9 @@ Official Java SDK for [Facturapi](https://www.facturapi.io). ## Requirements - Java 11+ +- Kotlin/JVM +- Android 8.0 (API level 26) o superior +- Spring Boot, Jakarta EE, Quarkus, Micronaut, and other JVM server apps ## Installation From a0c3eaaf1e6a347032b47c16afa488674194a37c Mon Sep 17 00:00:00 2001 From: javorosas Date: Tue, 7 Apr 2026 17:14:33 +0200 Subject: [PATCH 20/22] docs: add spanish readme --- README.es.md | 106 +++++++++++++++++++++++++++++++++++++++++++++++++++ README.md | 2 + 2 files changed, 108 insertions(+) create mode 100644 README.es.md diff --git a/README.es.md b/README.es.md new file mode 100644 index 0000000..d5c2f48 --- /dev/null +++ b/README.es.md @@ -0,0 +1,106 @@ +# facturapi-java + +SDK oficial de Java para [Facturapi](https://www.facturapi.io). + +English: [README.md](README.md) + +[![CI](https://img.shields.io/github/actions/workflow/status/facturapi/facturapi-java/ci.yml?branch=main&style=for-the-badge&label=CI)](https://github.com/facturapi/facturapi-java/actions/workflows/ci.yml) +[![Maven Central](https://img.shields.io/maven-central/v/io.facturapi/facturapi-java?style=for-the-badge&label=Maven%20Central)](https://central.sonatype.com/artifact/io.facturapi/facturapi-java) +[![Java](https://img.shields.io/badge/Java-11%2B-ED8B00?style=for-the-badge&logo=openjdk&logoColor=white)](https://openjdk.org/) + +## Requisitos + +- Java 11+ +- Kotlin/JVM +- Android 8.0 (API level 26) o superior +- Spring Boot, Jakarta EE, Quarkus, Micronaut y otras apps JVM de servidor + +## Instalación + +Maven: + +```xml + + io.facturapi + facturapi-java + 0.1.0 + +``` + +Gradle: + +```gradle +implementation("io.facturapi:facturapi-java:0.1.0") +``` + +## Inicio rápido + +```java +import io.facturapi.Facturapi; +import java.util.Map; + +Facturapi facturapi = new Facturapi("sk_test_..."); + +var customer = facturapi.customers().create(Map.of( + "legal_name", "Mi Empresa SA de CV", + "tax_id", "XAXX010101000", + "tax_system", "601", + "email", "cliente@example.com" +), null); + +var invoice = facturapi.invoices().create(Map.of( + "customer", customer.getId(), + "items", java.util.List.of(Map.of("quantity", 1, "product", "prod_123")) +), null); + +System.out.println(invoice.getId()); +``` + +## Subidas + +```java +import java.io.File; + +var organization = facturapi.organizations().uploadLogo( + "org_123", + new File("logo.png") +); + +var updated = facturapi.organizations().uploadCertificate( + "org_123", + new File("certificate.cer"), + new File("certificate.key"), + "secret" +); +``` + +## Errores + +```java +import io.facturapi.FacturapiException; + +try { + facturapi.customers().retrieve("cus_123"); +} catch (FacturapiException e) { + System.out.println(e.getMessage()); + System.out.println(e.getStatusCode()); + System.out.println(e.getErrorCode()); + System.out.println(e.getErrorPath()); +} +``` + +## Diseño + +- Las entradas usan diccionarios JSON flexibles (`Map`). +- Las salidas son modelos Java tipados (`Invoice`, `Customer`, `SearchResult`, etc.). +- Los errores exponen directamente los campos útiles del error del API en `FacturapiException`. +- La autenticación usa `Authorization: Bearer `. + +## Configuración + +```java +Facturapi facturapi = Facturapi.builder("sk_test_...") + .apiVersion("v2") + .timeout(java.time.Duration.ofSeconds(20)) + .build(); +``` diff --git a/README.md b/README.md index e4911ab..16d63ab 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,8 @@ Official Java SDK for [Facturapi](https://www.facturapi.io). +Español: [README.es.md](README.es.md) + [![CI](https://img.shields.io/github/actions/workflow/status/facturapi/facturapi-java/ci.yml?branch=main&style=for-the-badge&label=CI)](https://github.com/facturapi/facturapi-java/actions/workflows/ci.yml) [![Maven Central](https://img.shields.io/maven-central/v/io.facturapi/facturapi-java?style=for-the-badge&label=Maven%20Central)](https://central.sonatype.com/artifact/io.facturapi/facturapi-java) [![Java](https://img.shields.io/badge/Java-11%2B-ED8B00?style=for-the-badge&logo=openjdk&logoColor=white)](https://openjdk.org/) From be2e5ca38afae51c63191cd7eb4eb502a18393ef Mon Sep 17 00:00:00 2001 From: javorosas Date: Tue, 7 Apr 2026 17:22:13 +0200 Subject: [PATCH 21/22] release: set version to 1.0.0 --- README.es.md | 4 ++-- README.md | 4 ++-- pom.xml | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/README.es.md b/README.es.md index d5c2f48..f99683d 100644 --- a/README.es.md +++ b/README.es.md @@ -23,14 +23,14 @@ Maven: io.facturapi facturapi-java - 0.1.0 + 1.0.0 ``` Gradle: ```gradle -implementation("io.facturapi:facturapi-java:0.1.0") +implementation("io.facturapi:facturapi-java:1.0.0") ``` ## Inicio rápido diff --git a/README.md b/README.md index 16d63ab..e7dc65f 100644 --- a/README.md +++ b/README.md @@ -23,14 +23,14 @@ Maven: io.facturapi facturapi-java - 0.1.0 + 1.0.0 ``` Gradle: ```gradle -implementation("io.facturapi:facturapi-java:0.1.0") +implementation("io.facturapi:facturapi-java:1.0.0") ``` ## Quickstart diff --git a/pom.xml b/pom.xml index 05068b6..bdaf13e 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ io.facturapi facturapi-java - 0.1.0-SNAPSHOT + 1.0.0 facturapi-java Official Java SDK for Facturapi https://github.com/facturapi/facturapi-java From f80a6f5417db496dc9ed1fc4ca1858ec08f29159 Mon Sep 17 00:00:00 2001 From: javorosas Date: Tue, 7 Apr 2026 17:25:47 +0200 Subject: [PATCH 22/22] docs: rename requirements to compatibility --- README.es.md | 2 +- README.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.es.md b/README.es.md index f99683d..5cc9c1a 100644 --- a/README.es.md +++ b/README.es.md @@ -8,7 +8,7 @@ English: [README.md](README.md) [![Maven Central](https://img.shields.io/maven-central/v/io.facturapi/facturapi-java?style=for-the-badge&label=Maven%20Central)](https://central.sonatype.com/artifact/io.facturapi/facturapi-java) [![Java](https://img.shields.io/badge/Java-11%2B-ED8B00?style=for-the-badge&logo=openjdk&logoColor=white)](https://openjdk.org/) -## Requisitos +## Compatibilidad - Java 11+ - Kotlin/JVM diff --git a/README.md b/README.md index e7dc65f..7f3b383 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ Español: [README.es.md](README.es.md) [![Maven Central](https://img.shields.io/maven-central/v/io.facturapi/facturapi-java?style=for-the-badge&label=Maven%20Central)](https://central.sonatype.com/artifact/io.facturapi/facturapi-java) [![Java](https://img.shields.io/badge/Java-11%2B-ED8B00?style=for-the-badge&logo=openjdk&logoColor=white)](https://openjdk.org/) -## Requirements +## Compatibility - Java 11+ - Kotlin/JVM