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 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/.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.es.md b/README.es.md new file mode 100644 index 0000000..5cc9c1a --- /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/) + +## Compatibilidad + +- 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 + 1.0.0 + +``` + +Gradle: + +```gradle +implementation("io.facturapi:facturapi-java:1.0.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 38690cb..7f3b383 100644 --- a/README.md +++ b/README.md @@ -2,13 +2,23 @@ Official Java SDK for [Facturapi](https://www.facturapi.io). -## Requirements +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/) + +## Compatibility - Java 11+ -- Maven 3.8+ +- Kotlin/JVM +- Android 8.0 (API level 26) o superior +- Spring Boot, Jakarta EE, Quarkus, Micronaut, and other JVM server apps ## Installation +Maven: + ```xml io.facturapi @@ -17,27 +27,75 @@ Official Java SDK for [Facturapi](https://www.facturapi.io). ``` +Gradle: + +```gradle +implementation("io.facturapi:facturapi-java:1.0.0") +``` + ## Quickstart ```java -import com.facturapi.Facturapi; +import io.facturapi.Facturapi; 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( - "customer", customer.get("id").asText(), +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()); +``` + +## 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" +); ``` +## Errors + +```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()); +} +``` + +## Design + +- Inputs use flexible JSON dictionaries (`Map`). +- Outputs are typed Java models (`Invoice`, `Customer`, `SearchResult`, etc.). +- Errors expose the useful API error fields directly on `FacturapiException`. +- Auth uses `Authorization: Bearer `. + ## Configuration ```java @@ -46,9 +104,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..bdaf13e 100644 --- a/pom.xml +++ b/pom.xml @@ -5,11 +5,30 @@ io.facturapi facturapi-java - 1.0.0-SNAPSHOT + 1.0.0 facturapi-java 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 @@ -32,12 +51,25 @@ ${jackson.version} + + com.fasterxml.jackson.datatype + jackson-datatype-jsr310 + ${jackson.version} + + + + com.squareup.okhttp3 + okhttp + ${okhttp.version} + + org.junit.jupiter junit-jupiter ${junit.version} test + com.squareup.okhttp3 mockwebserver @@ -58,4 +90,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 + + + + + + + + diff --git a/src/main/java/com/facturapi/Facturapi.java b/src/main/java/com/facturapi/Facturapi.java deleted file mode 100644 index 5a0f7b2..0000000 --- a/src/main/java/com/facturapi/Facturapi.java +++ /dev/null @@ -1,124 +0,0 @@ -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; -import java.time.Duration; - -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; - - public Facturapi(String apiKey) { - this(FacturapiConfig.builder(apiKey).build()); - } - - // Backward-compatible constructor - public Facturapi(String apiKey, String apiVersion) { - this(FacturapiConfig.builder(apiKey).apiVersion(apiVersion).build()); - } - - public Facturapi(FacturapiConfig config) { - this.httpClient = new FacturapiHttpClient(config); - this.customers = new CustomersResource(httpClient); - this.products = new ProductsResource(httpClient); - this.invoices = new InvoicesResource(httpClient); - this.organizations = new OrganizationsResource(httpClient); - this.receipts = new ReceiptsResource(httpClient); - this.retentions = new RetentionsResource(httpClient); - this.webhooks = new WebhooksResource(httpClient); - - this.catalogs = new CatalogsTool(httpClient); - this.cartaPorteCatalogs = new CartaPorteCatalogsTool(httpClient); - this.comercioExteriorCatalogs = new ComercioExteriorCatalogsTool(httpClient); - this.tools = new ToolsResource(httpClient); - } - - public static Builder builder(String apiKey) { - return new Builder(apiKey); - } - - public static final class Builder { - private final FacturapiConfig.Builder configBuilder; - - private Builder(String apiKey) { - this.configBuilder = FacturapiConfig.builder(apiKey); - } - - public Builder apiVersion(ApiVersion apiVersion) { - this.configBuilder.apiVersion(apiVersion); - return this; - } - - public Builder apiVersion(String apiVersion) { - this.configBuilder.apiVersion(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()); - } - } - - public static Class PaymentForm() { - return PaymentForm.class; - } - - public static Class TaxType() { - return TaxType.class; - } - - public static Class TaxFactor() { - return TaxFactor.class; - } - - public static Class InvoiceType() { - return InvoiceType.class; - } - - public static Class CancellationMotive() { - return CancellationMotive.class; - } -} diff --git a/src/main/java/com/facturapi/FacturapiException.java b/src/main/java/com/facturapi/FacturapiException.java deleted file mode 100644 index b56c4c5..0000000 --- a/src/main/java/com/facturapi/FacturapiException.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.facturapi; - -public class FacturapiException extends RuntimeException { - private final int statusCode; - private final String responseBody; - - public FacturapiException(String message) { - super(message); - this.statusCode = -1; - this.responseBody = null; - } - - public FacturapiException(String message, Throwable cause) { - super(message, cause); - this.statusCode = -1; - this.responseBody = null; - } - - public FacturapiException(String message, int statusCode, String responseBody) { - super(message); - this.statusCode = statusCode; - this.responseBody = responseBody; - } - - public int getStatusCode() { - return statusCode; - } - - public String getResponseBody() { - return responseBody; - } -} diff --git a/src/main/java/com/facturapi/enums/CancellationMotive.java b/src/main/java/com/facturapi/enums/CancellationMotive.java deleted file mode 100644 index 61f0362..0000000 --- a/src/main/java/com/facturapi/enums/CancellationMotive.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.facturapi.enums; - -public enum CancellationMotive { - ERRORES_CON_RELACION("01"), - ERRORES_SIN_RELACION("02"), - NO_SE_CONCRETO("03"), - FACTURA_GLOBAL("04"); - - private final String value; - - CancellationMotive(String value) { - this.value = value; - } - - public String value() { - return value; - } -} diff --git a/src/main/java/com/facturapi/enums/InvoiceType.java b/src/main/java/com/facturapi/enums/InvoiceType.java deleted file mode 100644 index 0487742..0000000 --- a/src/main/java/com/facturapi/enums/InvoiceType.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.facturapi.enums; - -public enum InvoiceType { - INGRESO("I"), - EGRESO("E"), - TRASLADO("T"), - NOMINA("N"), - PAGO("P"); - - private final String value; - - InvoiceType(String value) { - this.value = value; - } - - public String value() { - return value; - } -} diff --git a/src/main/java/com/facturapi/enums/PaymentForm.java b/src/main/java/com/facturapi/enums/PaymentForm.java deleted file mode 100644 index e67fc1e..0000000 --- a/src/main/java/com/facturapi/enums/PaymentForm.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.facturapi.enums; - -public enum PaymentForm { - EFECTIVO("01"), - CHEQUE_NOMINATIVO("02"), - TRANSFERENCIA_ELECTRONICA_DE_FONDOS("03"), - TARJETA_DE_CREDITO("04"), - TARJETA_DE_DEBITO("28"), - POR_DEFINIR("99"); - - private final String value; - - PaymentForm(String value) { - this.value = value; - } - - public String value() { - return value; - } -} diff --git a/src/main/java/com/facturapi/enums/TaxFactor.java b/src/main/java/com/facturapi/enums/TaxFactor.java deleted file mode 100644 index 2898cf5..0000000 --- a/src/main/java/com/facturapi/enums/TaxFactor.java +++ /dev/null @@ -1,6 +0,0 @@ -package com.facturapi.enums; - -public enum TaxFactor { - Tasa, - Cuota -} diff --git a/src/main/java/com/facturapi/enums/TaxType.java b/src/main/java/com/facturapi/enums/TaxType.java deleted file mode 100644 index a56c26c..0000000 --- a/src/main/java/com/facturapi/enums/TaxType.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.facturapi.enums; - -public enum TaxType { - IVA, - IEPS, - ISR -} diff --git a/src/main/java/com/facturapi/http/FacturapiHttpClient.java b/src/main/java/com/facturapi/http/FacturapiHttpClient.java deleted file mode 100644 index 7f483a7..0000000 --- a/src/main/java/com/facturapi/http/FacturapiHttpClient.java +++ /dev/null @@ -1,204 +0,0 @@ -package com.facturapi.http; - -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.facturapi.FacturapiException; -import java.io.IOException; -import java.net.URI; -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; - -public final class FacturapiHttpClient { - private final HttpClient httpClient; - private final ObjectMapper objectMapper; - private final Duration timeout; - private final String baseUrl; - private final String apiKey; - private final String userAgent; - - 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(); - } - - public JsonNode getJson(String path, Map queryParams) { - return requestJson("GET", path, queryParams, null, null); - } - - public JsonNode postJson(String path, Object body, Map queryParams) { - return requestJson("POST", path, queryParams, body, null); - } - - public JsonNode putJson(String path, Object body, Map queryParams) { - return requestJson("PUT", path, queryParams, body, null); - } - - public JsonNode deleteJson(String path, Map queryParams) { - return requestJson("DELETE", path, queryParams, null, null); - } - - public JsonNode putMultipart(String path, MultipartBody multipartBody) { - return requestJson("PUT", path, null, null, multipartBody); - } - - public JsonNode postMultipart(String path, MultipartBody multipartBody) { - return requestJson("POST", path, null, null, multipartBody); - } - - public byte[] getBytes(String path) { - return requestBytes("GET", path, null); - } - - public byte[] postBytes(String path, Object body) { - return requestBytes("POST", path, body); - } - - private JsonNode requestJson( - String method, - String path, - Map queryParams, - Object body, - MultipartBody multipartBody - ) { - try { - 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(); - } - 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.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(); - } 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 HttpRequest 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) - .header("Authorization", "Bearer " + apiKey) - .header("Accept", "application/json") - .header("User-Agent", userAgent); - - HttpRequest.BodyPublisher publisher = HttpRequest.BodyPublishers.noBody(); - if (multipartBody != null) { - publisher = multipartBody.getPublisher(); - requestBuilder.header("Content-Type", multipartBody.getContentType()); - } else if (body != null) { - byte[] json = objectMapper.writeValueAsBytes(body); - publisher = HttpRequest.BodyPublishers.ofByteArray(json); - requestBuilder.header("Content-Type", "application/json"); - } - - 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); - String message = statusCode + " " + response.headers().firstValue(":status").orElse("Request failed"); - try { - JsonNode error = objectMapper.readTree(bodyText); - if (error.has("message") && error.get("message").isTextual()) { - message = error.get("message").asText(); - } else if (!bodyText.isEmpty()) { - message = bodyText; - } - } catch (Exception ignored) { - if (!bodyText.isEmpty()) { - message = bodyText; - } - } - throw new FacturapiException(message, statusCode, bodyText); - } - } - - private static String normalizePath(String path) { - if (path == null || path.isEmpty()) { - return ""; - } - return path.startsWith("/") ? path : "/" + path; - } - - private static String buildQuery(Map queryParams) { - if (queryParams == null || queryParams.isEmpty()) { - return ""; - } - - List parts = new ArrayList<>(); - for (Map.Entry entry : queryParams.entrySet()) { - String key = entry.getKey(); - Object value = entry.getValue(); - if (value == null) { - continue; - } - if (value instanceof Iterable) { - for (Object v : (Iterable) value) { - appendQueryPart(parts, key, v); - } - } else if (value.getClass().isArray()) { - int length = java.lang.reflect.Array.getLength(value); - for (int i = 0; i < length; i++) { - appendQueryPart(parts, key, java.lang.reflect.Array.get(value, i)); - } - } else { - appendQueryPart(parts, key, value); - } - } - - return parts.isEmpty() ? "" : "?" + String.join("&", parts); - } - - private static void appendQueryPart(List parts, String key, Object value) { - if (value == null) { - return; - } - String encodedKey = URLEncoder.encode(Objects.toString(key), StandardCharsets.UTF_8); - String encodedValue = URLEncoder.encode(Objects.toString(value), StandardCharsets.UTF_8); - parts.add(encodedKey + "=" + encodedValue); - } -} diff --git a/src/main/java/com/facturapi/http/MultipartBody.java b/src/main/java/com/facturapi/http/MultipartBody.java deleted file mode 100644 index 288997c..0000000 --- a/src/main/java/com/facturapi/http/MultipartBody.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.facturapi.http; - -import java.net.http.HttpRequest; - -public final class MultipartBody { - private final HttpRequest.BodyPublisher publisher; - private final String contentType; - - public MultipartBody(HttpRequest.BodyPublisher publisher, String contentType) { - this.publisher = publisher; - this.contentType = contentType; - } - - public HttpRequest.BodyPublisher getPublisher() { - return publisher; - } - - public String getContentType() { - return contentType; - } -} diff --git a/src/main/java/com/facturapi/http/MultipartBodyBuilder.java b/src/main/java/com/facturapi/http/MultipartBodyBuilder.java deleted file mode 100644 index f139a38..0000000 --- a/src/main/java/com/facturapi/http/MultipartBodyBuilder.java +++ /dev/null @@ -1,43 +0,0 @@ -package com.facturapi.http; - -import java.net.http.HttpRequest; -import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.List; -import java.util.UUID; - -public final class MultipartBodyBuilder { - private static final String CRLF = "\r\n"; - private final String boundary = "----FacturapiJava" + UUID.randomUUID(); - private final List parts = new ArrayList<>(); - - 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)); - 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)); - 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); - } -} 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/io/facturapi/Facturapi.java b/src/main/java/io/facturapi/Facturapi.java new file mode 100644 index 0000000..13403cf --- /dev/null +++ b/src/main/java/io/facturapi/Facturapi.java @@ -0,0 +1,179 @@ +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 { + private final FacturapiHttpClient httpClient; + + 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. + * + * @param apiKey Facturapi API key. + */ + public Facturapi(String apiKey) { + this(FacturapiConfig.builder(apiKey).build()); + } + + /** + * 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); + this.products = new ProductsResource(httpClient); + this.invoices = new InvoicesResource(httpClient); + this.organizations = new OrganizationsResource(httpClient); + this.receipts = new ReceiptsResource(httpClient); + this.retentions = new RetentionsResource(httpClient); + this.webhooks = new WebhooksResource(httpClient); + + this.catalogs = new CatalogsTool(httpClient); + this.cartaPorteCatalogs = new CartaPorteCatalogsTool(httpClient); + this.comercioExteriorCatalogs = new ComercioExteriorCatalogsTool(httpClient); + 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); + } + + 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; + + private Builder(String apiKey) { + this.configBuilder = FacturapiConfig.builder(apiKey); + } + + public Builder apiVersion(ApiVersion apiVersion) { + this.configBuilder.apiVersion(apiVersion); + return this; + } + + public Builder apiVersion(String apiVersion) { + this.configBuilder.apiVersion(apiVersion); + return this; + } + + public Builder timeout(Duration timeout) { + this.configBuilder.timeout(timeout); + return this; + } + + public Facturapi build() { + return new Facturapi(configBuilder.build()); + } + } + + public static Class PaymentForm() { + return PaymentForm.class; + } + + public static Class TaxType() { + return TaxType.class; + } + + public static Class TaxFactor() { + return TaxFactor.class; + } + + public static Class InvoiceType() { + return InvoiceType.class; + } + + public static Class CancellationMotive() { + return CancellationMotive.class; + } +} diff --git a/src/main/java/io/facturapi/FacturapiException.java b/src/main/java/io/facturapi/FacturapiException.java new file mode 100644 index 0000000..ec6b9d9 --- /dev/null +++ b/src/main/java/io/facturapi/FacturapiException.java @@ -0,0 +1,37 @@ +package io.facturapi; + +public class FacturapiException extends RuntimeException { + private final int statusCode; + private final Object errorCode; + private final String errorPath; + + public FacturapiException(String message) { + this(message, -1, null, null); + } + + public FacturapiException(String message, Throwable cause) { + super(message, cause); + this.statusCode = -1; + this.errorCode = null; + this.errorPath = null; + } + + public FacturapiException(String message, int statusCode, Object errorCode, String errorPath) { + super(message); + this.statusCode = statusCode; + this.errorCode = errorCode; + this.errorPath = errorPath; + } + + public int getStatusCode() { + return statusCode; + } + + public Object getErrorCode() { + return errorCode; + } + + public String getErrorPath() { + return errorPath; + } +} 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/io/facturapi/enums/CancellationMotive.java b/src/main/java/io/facturapi/enums/CancellationMotive.java new file mode 100644 index 0000000..12cc6b9 --- /dev/null +++ b/src/main/java/io/facturapi/enums/CancellationMotive.java @@ -0,0 +1,32 @@ +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"), + NO_SE_CONCRETO("03"), + FACTURA_GLOBAL("04"); + + private final String value; + + CancellationMotive(String value) { + 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 new file mode 100644 index 0000000..08c188b --- /dev/null +++ b/src/main/java/io/facturapi/enums/InvoiceType.java @@ -0,0 +1,33 @@ +package io.facturapi.enums; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonValue; + +public enum InvoiceType { + INGRESO("I"), + EGRESO("E"), + TRASLADO("T"), + NOMINA("N"), + PAGO("P"); + + private final String value; + + InvoiceType(String value) { + 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 new file mode 100644 index 0000000..5e37bd0 --- /dev/null +++ b/src/main/java/io/facturapi/enums/PaymentForm.java @@ -0,0 +1,50 @@ +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; + + PaymentForm(String value) { + 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 new file mode 100644 index 0000000..dd66679 --- /dev/null +++ b/src/main/java/io/facturapi/enums/TaxFactor.java @@ -0,0 +1,31 @@ +package io.facturapi.enums; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonValue; + +public enum TaxFactor { + 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 new file mode 100644 index 0000000..4a12100 --- /dev/null +++ b/src/main/java/io/facturapi/enums/TaxType.java @@ -0,0 +1,20 @@ +package io.facturapi.enums; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonValue; + +public enum TaxType { + IVA, + IEPS, + 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/com/facturapi/http/FacturapiConfig.java b/src/main/java/io/facturapi/http/FacturapiConfig.java similarity index 58% rename from src/main/java/com/facturapi/http/FacturapiConfig.java rename to src/main/java/io/facturapi/http/FacturapiConfig.java index 9f3d7d3..04f5761 100644 --- a/src/main/java/com/facturapi/http/FacturapiConfig.java +++ b/src/main/java/io/facturapi/http/FacturapiConfig.java @@ -1,11 +1,15 @@ -package com.facturapi.http; +package io.facturapi.http; +import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; -import com.facturapi.ApiVersion; -import com.facturapi.constants.FacturapiConstants; -import java.net.http.HttpClient; +import com.fasterxml.jackson.databind.PropertyNamingStrategies; +import com.fasterxml.jackson.databind.SerializationFeature; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +import io.facturapi.ApiVersion; +import io.facturapi.constants.FacturapiConstants; import java.time.Duration; import java.util.Objects; +import okhttp3.OkHttpClient; public final class FacturapiConfig { private final String apiKey; @@ -13,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) { @@ -46,7 +50,7 @@ public String getUserAgent() { return userAgent; } - public HttpClient getHttpClient() { + public OkHttpClient getHttpClient() { return httpClient; } @@ -63,8 +67,8 @@ 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 HttpClient httpClient; + private final String userAgent = "facturapi-java/0.1.x"; + private OkHttpClient httpClient; private ObjectMapper objectMapper; private Builder(String apiKey) { @@ -84,53 +88,38 @@ 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) { + public Builder httpClient(OkHttpClient 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() + String resolvedBaseUrl = apiVersion == ApiVersion.V1 + ? FacturapiConstants.BASE_URL_V1 + : FacturapiConstants.BASE_URL_V2; + + OkHttpClient resolvedClient = this.httpClient == null + ? new OkHttpClient.Builder() .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) - ); + .callTimeout(timeout) + .build() + : this.httpClient; + + ObjectMapper resolvedMapper = new ObjectMapper() + .registerModule(new JavaTimeModule()) + .setPropertyNamingStrategy(PropertyNamingStrategies.SNAKE_CASE) + .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false) + .disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); + + this.baseUrl = resolvedBaseUrl; + this.httpClient = resolvedClient; + this.objectMapper = resolvedMapper; + return new FacturapiConfig(this); } } } diff --git a/src/main/java/io/facturapi/http/FacturapiHttpClient.java b/src/main/java/io/facturapi/http/FacturapiHttpClient.java new file mode 100644 index 0000000..18578d5 --- /dev/null +++ b/src/main/java/io/facturapi/http/FacturapiHttpClient.java @@ -0,0 +1,398 @@ +package io.facturapi.http; + +import com.fasterxml.jackson.core.type.TypeReference; +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.io.UncheckedIOException; +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; +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 static final MediaType JSON_MEDIA_TYPE = MediaType.get("application/json; charset=utf-8"); + + private final OkHttpClient httpClient; + private final ObjectMapper objectMapper; + private final String baseUrl; + private final String apiKey; + private final String userAgent; + + public FacturapiHttpClient(FacturapiConfig config) { + this.httpClient = config.getHttpClient(); + this.objectMapper = config.getObjectMapper(); + this.baseUrl = config.getBaseUrl(); + this.apiKey = config.getApiKey(); + this.userAgent = config.getUserAgent(); + } + + public ObjectMapper getObjectMapper() { + return objectMapper; + } + + public T get(String path, Map queryParams, Class responseType) { + return convert(requestJsonNode("GET", path, queryParams, null, null), responseType); + } + + public T get(String path, Map queryParams, TypeReference typeReference) { + return convert(requestJsonNode("GET", path, queryParams, null, null), typeReference); + } + + public T post(String path, Object body, Map queryParams, Class responseType) { + return convert(requestJsonNode("POST", path, queryParams, body, null), responseType); + } + + public T post(String path, Object body, Map queryParams, TypeReference typeReference) { + return convert(requestJsonNode("POST", path, queryParams, body, null), typeReference); + } + + 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) { + return requestBytes("GET", path, null); + } + + 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, + Map queryParams, + Object body, + MultipartBody multipartBody + ) { + Request request = buildRequest(method, path, queryParams, body, multipartBody); + try (Response response = httpClient.newCall(request).execute()) { + if (!response.isSuccessful()) { + throw buildApiException(readBodyText(response), response.code()); + } + + ResponseBody responseBody = response.body(); + if (responseBody == null) { + return objectMapper.nullNode(); + } + + 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); + } + } + + private byte[] requestBytes(String method, String path, Object 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); + } + } + + private InputStream requestStream(String method, String path, Object body) { + Request request = buildRequest(method, path, null, body, null); + try { + Response response = httpClient.newCall(request).execute(); + if (!response.isSuccessful()) { + try { + throw buildApiException(readBodyText(response), response.code()); + } finally { + response.close(); + } + } + + 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); + } + } + + 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 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 { + JsonNode root = objectMapper.readTree(bodyText); + if (root != null) { + JsonNode messageNode = firstDefined(root, "message", "error", "detail"); + if (messageNode != null && messageNode.isTextual()) { + message = messageNode.asText(); + } else if (root.isTextual()) { + message = root.asText(); + } else { + message = bodyText; + } + + JsonNode statusNode = firstDefined(root, "status"); + if (statusNode != null) { + 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(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(root, "path"); + if (pathNode != null && pathNode.isTextual()) { + errorPath = pathNode.asText(); + } + + if (firstDefined(root, "message", "error", "detail") == null) { + message = bodyText; + } + } + } catch (Exception ignored) { + message = bodyText.isBlank() ? message : bodyText; + } + } + + return new FacturapiException(message, resolvedStatus, errorCode, errorPath); + } + + 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 + ) { + 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); + + RequestBody requestBody = null; + if (multipartBody != null) { + requestBody = multipartBody.getBody(); + } else if (body != null) { + 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); + } + } + + 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) { + if (path == null || path.isEmpty()) { + return ""; + } + return path.startsWith("/") ? path : "/" + path; + } + + private static String buildQuery(Map queryParams) { + if (queryParams == null || queryParams.isEmpty()) { + return ""; + } + + List parts = new ArrayList<>(); + for (Map.Entry entry : queryParams.entrySet()) { + String key = entry.getKey(); + Object value = entry.getValue(); + if (value == null) { + continue; + } + if (value instanceof Iterable) { + for (Object v : (Iterable) value) { + appendQueryPart(parts, key, v); + } + } else if (value.getClass().isArray()) { + int length = java.lang.reflect.Array.getLength(value); + for (int i = 0; i < length; i++) { + appendQueryPart(parts, key, java.lang.reflect.Array.get(value, i)); + } + } else { + appendQueryPart(parts, key, value); + } + } + + return parts.isEmpty() ? "" : "?" + String.join("&", parts); + } + + private static void appendQueryPart(List parts, String key, Object value) { + if (value == null) { + return; + } + String encodedKey = URLEncoder.encode(Objects.toString(key), StandardCharsets.UTF_8); + 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 new file mode 100644 index 0000000..06e5f31 --- /dev/null +++ b/src/main/java/io/facturapi/http/MultipartBody.java @@ -0,0 +1,21 @@ +package io.facturapi.http; + +import okhttp3.RequestBody; + +public final class MultipartBody { + private final RequestBody body; + private final String contentType; + + public MultipartBody(RequestBody body, String contentType) { + this.body = body; + this.contentType = contentType; + } + + public RequestBody getBody() { + return body; + } + + public String getContentType() { + return contentType; + } +} diff --git a/src/main/java/io/facturapi/http/MultipartBodyBuilder.java b/src/main/java/io/facturapi/http/MultipartBodyBuilder.java new file mode 100644 index 0000000..0d7d3ec --- /dev/null +++ b/src/main/java/io/facturapi/http/MultipartBodyBuilder.java @@ -0,0 +1,26 @@ +package io.facturapi.http; + +import okhttp3.MediaType; +import okhttp3.RequestBody; + +public final class MultipartBodyBuilder { + 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) { + builder.addFormDataPart(name, value == null ? "" : value); + return this; + } + + public MultipartBodyBuilder addFile(String fieldName, String fileName, byte[] content, String contentType) { + MediaType mediaType = contentType == null ? OCTET_STREAM : MediaType.get(contentType); + builder.addFormDataPart(fieldName, fileName, RequestBody.create(content, mediaType)); + return this; + } + + public MultipartBody build() { + okhttp3.MultipartBody multipartBody = builder.build(); + return new MultipartBody(multipartBody, multipartBody.contentType().toString()); + } +} 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..7ed3d6f --- /dev/null +++ b/src/main/java/io/facturapi/models/ApiEvent.java @@ -0,0 +1,26 @@ +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 { + private Instant createdAt; + private String organization; + private Boolean livemode; + private String type; + private ApiEventData data; + + 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; } + 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..f262e0c --- /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; +import java.time.Instant; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class ApiKey { + private String id; + @JsonProperty("first_12") + private String first12; + private Instant 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 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/CatalogItem.java b/src/main/java/io/facturapi/models/CatalogItem.java new file mode 100644 index 0000000..d3809a5 --- /dev/null +++ b/src/main/java/io/facturapi/models/CatalogItem.java @@ -0,0 +1,38 @@ +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; + 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..b387212 --- /dev/null +++ b/src/main/java/io/facturapi/models/Certificate.java @@ -0,0 +1,22 @@ +package io.facturapi.models; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import java.time.Instant; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class Certificate { + private Boolean hasCertificate; + private Instant updatedAt; + private Instant expiresAt; + private String serialNumber; + + public Boolean getHasCertificate() { return hasCertificate; } + public void setHasCertificate(Boolean hasCertificate) { this.hasCertificate = hasCertificate; } + 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/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..f3885e4 --- /dev/null +++ b/src/main/java/io/facturapi/models/Customer.java @@ -0,0 +1,58 @@ +package io.facturapi.models; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import java.time.Instant; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class Customer { + private String id; + private String organization; + private Boolean livemode; + private Instant createdAt; + private String taxId; + private String taxSystem; + private String legalName; + private String email; + private String phone; + private String curp; + private Address address; + private String externalId; + private String defaultInvoiceUse; + private Instant satValidatedAt; + private String editLink; + private Instant 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 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; } + 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 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 Instant getEditLinkExpiresAt() { return editLinkExpiresAt; } + public void setEditLinkExpiresAt(Instant 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..3a19b8f --- /dev/null +++ b/src/main/java/io/facturapi/models/CustomerInfo.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 CustomerInfo { + private String id; + private String legalName; + private String taxId; + 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..2520323 --- /dev/null +++ b/src/main/java/io/facturapi/models/Customization.java @@ -0,0 +1,23 @@ +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; + private PdfExtra pdfExtra; + private Map defaultSeries = new HashMap<>(); + 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..b662ea9 --- /dev/null +++ b/src/main/java/io/facturapi/models/Invoice.java @@ -0,0 +1,144 @@ +package io.facturapi.models; + +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; +import java.util.List; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class Invoice { + private String id; + private String organization; + private Boolean livemode; + private Instant createdAt; + private Instant date; + private IssuingType issuerType; + private InvoiceType type; + private InvoiceStatus status; + private Integer cfdiVersion; + private CustomerInfo issuerInfo; + private PaymentForm paymentForm; + private PaymentMethod paymentMethod; + private String currency; + private Double exchange; + private String uuid; + private CustomerInfo customer; + private Double total; + private String use; + private String folioNumber; + private String series; + @JsonProperty("is_ready_to_stamp") + private Boolean readyToStamp; + private List items = new ArrayList<>(); + private Address address; + private Double amountDue; + private String verificationUrl; + private String verificationCartaPorte; + private CancellationStatus cancellationStatus; + private String externalId; + private String idempotencyKey; + private Stamp stamp; + private String addenda; + private String conditions; + private String pdfCustomSection; + @JsonProperty("export") + private String exportReference; + private GlobalInfo global; + private InvoiceCancellation cancellation; + private List complements = new ArrayList<>(); + private List relatedDocuments = new ArrayList<>(); + private List namespaces = new ArrayList<>(); + private List receivedPaymentIds = new ArrayList<>(); + 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 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 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 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; } + 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 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; } + 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..99bd45e --- /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; +import io.facturapi.enums.CancellationMotive; +import io.facturapi.enums.CancellationStatus; +import java.time.Instant; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class InvoiceCancellation { + private Instant requestedAt; + private CancellationStatus status; + private Instant lastChecked; + private CancellationMotive motive; + private String substitutionUuid; + + public Instant getRequestedAt() { return requestedAt; } + public void setRequestedAt(Instant requestedAt) { this.requestedAt = requestedAt; } + 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 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/InvoiceItem.java b/src/main/java/io/facturapi/models/InvoiceItem.java new file mode 100644 index 0000000..adcb675 --- /dev/null +++ b/src/main/java/io/facturapi/models/InvoiceItem.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 InvoiceItem { + private Double quantity; + private ProductInfo product; + private Double discount; + private List customsKeys = new ArrayList<>(); + private InvoiceItemThirdParty thirdParty; + private String complement; + private List parts = new ArrayList<>(); + 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..599571f --- /dev/null +++ b/src/main/java/io/facturapi/models/InvoiceItemPart.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 InvoiceItemPart { + private Double quantity; + private String productKey; + private String description; + private String unitName; + private String sku; + 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..1cc080a --- /dev/null +++ b/src/main/java/io/facturapi/models/InvoiceItemThirdParty.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 InvoiceItemThirdParty { + private String taxId; + private String legalName; + 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..90991da --- /dev/null +++ b/src/main/java/io/facturapi/models/Legal.java @@ -0,0 +1,36 @@ +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; + private String legalName; + private String taxId; + private String taxSystem; + private Address address; + private String phone; + private String website; + 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..88bdf9c --- /dev/null +++ b/src/main/java/io/facturapi/models/LocalTax.java @@ -0,0 +1,54 @@ +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 TaxType type; + private Boolean withholding; + private TaxFactor 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 TaxType getType() { + return type; + } + + public void setType(TaxType type) { + this.type = type; + } + + public Boolean getWithholding() { + return withholding; + } + + public void setWithholding(Boolean withholding) { + this.withholding = withholding; + } + + public TaxFactor getFactor() { + return factor; + } + + public void setFactor(TaxFactor factor) { + this.factor = factor; + } +} 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..c5b9dd7 --- /dev/null +++ b/src/main/java/io/facturapi/models/Organization.java @@ -0,0 +1,64 @@ +package io.facturapi.models; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import java.time.Instant; +import java.util.ArrayList; +import java.util.List; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class Organization { + private String id; + private Instant createdAt; + private String plan; + private List addOns = new ArrayList<>(); + @JsonProperty("is_production_ready") + private Boolean productionReady; + private List pendingSteps = new ArrayList<>(); + private String logoUrl; + private String domain; + private String customDomain; + private String timezone; + private Legal legal; + private Customization customization; + private Certificate certificate; + private Certificate fiel; + private ReceiptSettings receipts; + private SelfInvoiceSettings selfInvoice; + private PendingPlanUpdate pendingPlanUpdate; + + public String getId() { return id; } + public void setId(String id) { this.id = id; } + 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; } + 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..1ce533c --- /dev/null +++ b/src/main/java/io/facturapi/models/OrganizationInvite.java @@ -0,0 +1,39 @@ +package io.facturapi.models; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import java.time.Instant; +import java.util.ArrayList; +import java.util.List; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class OrganizationInvite { + private String id; + private Instant createdAt; + private String email; + private String organizationName; + private String role; + private String roleName; + private List roles = new ArrayList<>(); + private Instant expiresAt; + private String status; + + public String getId() { return id; } + public void setId(String id) { this.id = id; } + 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; } + 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 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 new file mode 100644 index 0000000..59f5b9b --- /dev/null +++ b/src/main/java/io/facturapi/models/OrganizationTeamRole.java @@ -0,0 +1,46 @@ +package io.facturapi.models; + +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; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class OrganizationTeamRole { + private String id; + private String name; + private String templateCode; + private String scope; + private String organization; + private List operations = new ArrayList<>(); + private Integer usedBy; + private Instant createdAt; + private Instant updatedAt; + private Map createdBy; + 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 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; } + 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..921c60f --- /dev/null +++ b/src/main/java/io/facturapi/models/OrganizationUserAccess.java @@ -0,0 +1,39 @@ +package io.facturapi.models; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import java.time.Instant; +import java.util.ArrayList; +import java.util.List; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class OrganizationUserAccess { + private String id; + private String fullName; + private String email; + private String role; + private String roleName; + private String organization; + private List operations = new ArrayList<>(); + private Instant createdAt; + private Instant 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 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 new file mode 100644 index 0000000..411287c --- /dev/null +++ b/src/main/java/io/facturapi/models/Payment.java @@ -0,0 +1,28 @@ +package io.facturapi.models; + +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; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class Payment { + private PaymentForm paymentForm; + private String currency; + private Double exchange; + private Instant date; + private List related = new ArrayList<>(); + + 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; } + public void setExchange(Double exchange) { this.exchange = exchange; } + 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/PaymentRelated.java b/src/main/java/io/facturapi/models/PaymentRelated.java new file mode 100644 index 0000000..531e67d --- /dev/null +++ b/src/main/java/io/facturapi/models/PaymentRelated.java @@ -0,0 +1,25 @@ +package io.facturapi.models; + +import com.fasterxml.jackson.annotation.JsonProperty; + +public class PaymentRelated { + private String uuid; + private Integer installment; + 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/PdfExtra.java b/src/main/java/io/facturapi/models/PdfExtra.java new file mode 100644 index 0000000..c66655b --- /dev/null +++ b/src/main/java/io/facturapi/models/PdfExtra.java @@ -0,0 +1,33 @@ +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; + private Boolean addressCodes; + private Boolean productKey; + private Boolean roundUnitPrice; + private Boolean taxBreakdown; + private Boolean iepsBreakdown; + private Boolean renderCartaPorte; + 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..9a02e49 --- /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; +import java.time.Instant; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class PendingPlanUpdate { + private String plan; + private Instant scheduledFor; + + public String getPlan() { return plan; } + public void setPlan(String plan) { this.plan = plan; } + 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 new file mode 100644 index 0000000..5b1311d --- /dev/null +++ b/src/main/java/io/facturapi/models/Product.java @@ -0,0 +1,55 @@ +package io.facturapi.models; + +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; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class Product { + private String id; + private String organization; + private Boolean livemode; + private String productKey; + private String description; + private Double price; + private Instant createdAt; + private Boolean taxIncluded; + private List taxes = new ArrayList<>(); + private List localTaxes = new ArrayList<>(); + private String unitKey; + private String unitName; + private String sku; + private Taxability 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 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; } + 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 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 new file mode 100644 index 0000000..22ebea8 --- /dev/null +++ b/src/main/java/io/facturapi/models/ProductInfo.java @@ -0,0 +1,45 @@ +package io.facturapi.models; + +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; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class ProductInfo { + private String id; + private String productKey; + private String description; + private String unitKey; + private String unitName; + private Double price; + private Taxability taxability; + private Boolean taxIncluded; + private List taxes = new ArrayList<>(); + 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 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; } + 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..c7cbf62 --- /dev/null +++ b/src/main/java/io/facturapi/models/Receipt.java @@ -0,0 +1,73 @@ +package io.facturapi.models; + +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; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class Receipt { + private String id; + private Instant createdAt; + private Instant date; + private Integer apiVersion; + private Boolean livemode; + private String organization; + private Integer folioNumber; + private String externalId; + private String idempotencyKey; + private String branch; + private PaymentForm paymentForm; + private List items = new ArrayList<>(); + private String currency; + private Double exchange; + private Double total; + private String invoice; + private Instant expiresAt; + private String key; + private String status; + private String selfInvoiceUrl; + + public String getId() { return id; } + public void setId(String id) { this.id = id; } + 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; } + 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 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; } + 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 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; } + 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..508122b --- /dev/null +++ b/src/main/java/io/facturapi/models/ReceiptSettings.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 ReceiptSettings { + private String periodicity; + private Integer durationDays; + private Integer nextFolioNumber; + 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..efef076 --- /dev/null +++ b/src/main/java/io/facturapi/models/Retention.java @@ -0,0 +1,78 @@ +package io.facturapi.models; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import java.time.Instant; +import java.util.ArrayList; +import java.util.List; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class Retention { + private String id; + private Instant createdAt; + private CustomerInfo customer; + private String organization; + private Boolean livemode; + private String status; + private String uuid; + private String externalId; + private Instant fechaExp; + private String cveRetenc; + private String folioInt; + private String descRetenc; + private RetentionPeriod periodo; + private RetentionTotals totales; + private List namespaces = new ArrayList<>(); + private List relatedDocuments = new ArrayList<>(); + private List complements = new ArrayList<>(); + private List addenda = new ArrayList<>(); + private String cancellationReceipt; + private Stamp stamp; + private String pdfCustomSection; + private String verificationUrl; + + public String getId() { return id; } + public void setId(String id) { this.id = id; } + 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; } + 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 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; } + 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..5df92c5 --- /dev/null +++ b/src/main/java/io/facturapi/models/RetentionPeriod.java @@ -0,0 +1,18 @@ +package io.facturapi.models; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class RetentionPeriod { + private Integer mesIni; + 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..4890e55 --- /dev/null +++ b/src/main/java/io/facturapi/models/RetentionRetainedTax.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 RetentionRetainedTax { + private Double baseRet; + private String impuesto; + private String tipoPagoRet; + private Double montoRet; + 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..5968cc5 --- /dev/null +++ b/src/main/java/io/facturapi/models/RetentionTotals.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 RetentionTotals { + private Double montoTotGrav; + private Double montoTotExent; + private Double montoTotOperacion; + private Double montoTotRet; + 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..2701e72 --- /dev/null +++ b/src/main/java/io/facturapi/models/SearchResult.java @@ -0,0 +1,57 @@ +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; + private Integer totalPages; + @JsonAlias({"total"}) + private Integer totalResults; + 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..ed2a0d6 --- /dev/null +++ b/src/main/java/io/facturapi/models/SelfInvoiceSettings.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 SelfInvoiceSettings { + private List allowedCfdiUses = new ArrayList<>(); + private Boolean applyResicoIsr; + private String supportEmail; + 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..95f3640 --- /dev/null +++ b/src/main/java/io/facturapi/models/Series.java @@ -0,0 +1,20 @@ +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; + private Integer nextFolio; + 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..89cdc3d --- /dev/null +++ b/src/main/java/io/facturapi/models/Stamp.java @@ -0,0 +1,28 @@ +package io.facturapi.models; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import java.time.Instant; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class Stamp { + private Instant date; + private String satSignature; + private String satCertNumber; + private String signature; + private String complementString; + private String rfcProviderCert; + + 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; } + 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..155a15b --- /dev/null +++ b/src/main/java/io/facturapi/models/Tax.java @@ -0,0 +1,63 @@ +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 TaxType type; + private Boolean withholding; + private TaxFactor 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 TaxType getType() { + return type; + } + + public void setType(TaxType type) { + this.type = type; + } + + public Boolean getWithholding() { + return withholding; + } + + public void setWithholding(Boolean withholding) { + this.withholding = withholding; + } + + public TaxFactor getFactor() { + return factor; + } + + public void setFactor(TaxFactor 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..9b9cd3d --- /dev/null +++ b/src/main/java/io/facturapi/models/TaxInfoValidation.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; +import java.util.ArrayList; +import java.util.List; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class TaxInfoValidation { + @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..fd18da3 --- /dev/null +++ b/src/main/java/io/facturapi/models/Webhook.java @@ -0,0 +1,39 @@ +package io.facturapi.models; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import java.time.Instant; +import java.util.ArrayList; +import java.util.List; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class Webhook { + private String id; + private Instant createdAt; + private String organization; + private Boolean livemode; + 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 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; } + 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..022cb91 --- /dev/null +++ b/src/main/java/io/facturapi/models/XmlNamespace.java @@ -0,0 +1,18 @@ +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; + 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/models/complements/InvoiceComplement.java b/src/main/java/io/facturapi/models/complements/InvoiceComplement.java new file mode 100644 index 0000000..6424cee --- /dev/null +++ b/src/main/java/io/facturapi/models/complements/InvoiceComplement.java @@ -0,0 +1,156 @@ +package io.facturapi.models.complements; + +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 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; +import io.facturapi.models.complements.nomina.NominaComplementData; +import io.facturapi.models.complements.pago.PagoComplementData; +import java.util.List; + +@JsonIgnoreProperties(ignoreUnknown = true) +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; + @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(); + } + + 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/complements/carta_porte/CartaPorteAutotransporte.java b/src/main/java/io/facturapi/models/complements/carta_porte/CartaPorteAutotransporte.java new file mode 100644 index 0000000..7bbe218 --- /dev/null +++ b/src/main/java/io/facturapi/models/complements/carta_porte/CartaPorteAutotransporte.java @@ -0,0 +1,31 @@ +package io.facturapi.models.complements.carta_porte; + +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/complements/carta_porte/CartaPorteCantidadTransporta.java b/src/main/java/io/facturapi/models/complements/carta_porte/CartaPorteCantidadTransporta.java new file mode 100644 index 0000000..155fb36 --- /dev/null +++ b/src/main/java/io/facturapi/models/complements/carta_porte/CartaPorteCantidadTransporta.java @@ -0,0 +1,25 @@ +package io.facturapi.models.complements.carta_porte; + +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/complements/carta_porte/CartaPorteCarroFerroviario.java b/src/main/java/io/facturapi/models/complements/carta_porte/CartaPorteCarroFerroviario.java new file mode 100644 index 0000000..55ec2ae --- /dev/null +++ b/src/main/java/io/facturapi/models/complements/carta_porte/CartaPorteCarroFerroviario.java @@ -0,0 +1,31 @@ +package io.facturapi.models.complements.carta_porte; + +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/complements/carta_porte/CartaPorteComplementData.java b/src/main/java/io/facturapi/models/complements/carta_porte/CartaPorteComplementData.java new file mode 100644 index 0000000..f210991 --- /dev/null +++ b/src/main/java/io/facturapi/models/complements/carta_porte/CartaPorteComplementData.java @@ -0,0 +1,65 @@ +package io.facturapi.models.complements.carta_porte; + +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/complements/carta_porte/CartaPorteContenedorFerroviario.java b/src/main/java/io/facturapi/models/complements/carta_porte/CartaPorteContenedorFerroviario.java new file mode 100644 index 0000000..247b384 --- /dev/null +++ b/src/main/java/io/facturapi/models/complements/carta_porte/CartaPorteContenedorFerroviario.java @@ -0,0 +1,21 @@ +package io.facturapi.models.complements.carta_porte; + +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/complements/carta_porte/CartaPorteContenedorMaritimo.java b/src/main/java/io/facturapi/models/complements/carta_porte/CartaPorteContenedorMaritimo.java new file mode 100644 index 0000000..90bbaa2 --- /dev/null +++ b/src/main/java/io/facturapi/models/complements/carta_porte/CartaPorteContenedorMaritimo.java @@ -0,0 +1,39 @@ +package io.facturapi.models.complements.carta_porte; + +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/complements/carta_porte/CartaPorteDerechosDePaso.java b/src/main/java/io/facturapi/models/complements/carta_porte/CartaPorteDerechosDePaso.java new file mode 100644 index 0000000..66f64e5 --- /dev/null +++ b/src/main/java/io/facturapi/models/complements/carta_porte/CartaPorteDerechosDePaso.java @@ -0,0 +1,17 @@ +package io.facturapi.models.complements.carta_porte; + +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/complements/carta_porte/CartaPorteDetalleMercancia.java b/src/main/java/io/facturapi/models/complements/carta_porte/CartaPorteDetalleMercancia.java new file mode 100644 index 0000000..d5854dc --- /dev/null +++ b/src/main/java/io/facturapi/models/complements/carta_porte/CartaPorteDetalleMercancia.java @@ -0,0 +1,29 @@ +package io.facturapi.models.complements.carta_porte; + +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/complements/carta_porte/CartaPorteDocumentacionAduanera.java b/src/main/java/io/facturapi/models/complements/carta_porte/CartaPorteDocumentacionAduanera.java new file mode 100644 index 0000000..677878f --- /dev/null +++ b/src/main/java/io/facturapi/models/complements/carta_porte/CartaPorteDocumentacionAduanera.java @@ -0,0 +1,25 @@ +package io.facturapi.models.complements.carta_porte; + +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/complements/carta_porte/CartaPorteDomicilio.java b/src/main/java/io/facturapi/models/complements/carta_porte/CartaPorteDomicilio.java new file mode 100644 index 0000000..3eda958 --- /dev/null +++ b/src/main/java/io/facturapi/models/complements/carta_porte/CartaPorteDomicilio.java @@ -0,0 +1,49 @@ +package io.facturapi.models.complements.carta_porte; + +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/complements/carta_porte/CartaPorteFiguraTransporte.java b/src/main/java/io/facturapi/models/complements/carta_porte/CartaPorteFiguraTransporte.java new file mode 100644 index 0000000..f2f57cd --- /dev/null +++ b/src/main/java/io/facturapi/models/complements/carta_porte/CartaPorteFiguraTransporte.java @@ -0,0 +1,43 @@ +package io.facturapi.models.complements.carta_porte; + +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/complements/carta_porte/CartaPorteGuiaIdentificacion.java b/src/main/java/io/facturapi/models/complements/carta_porte/CartaPorteGuiaIdentificacion.java new file mode 100644 index 0000000..41f4b84 --- /dev/null +++ b/src/main/java/io/facturapi/models/complements/carta_porte/CartaPorteGuiaIdentificacion.java @@ -0,0 +1,21 @@ +package io.facturapi.models.complements.carta_porte; + +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/complements/carta_porte/CartaPorteIdentificacionVehicular.java b/src/main/java/io/facturapi/models/complements/carta_porte/CartaPorteIdentificacionVehicular.java new file mode 100644 index 0000000..d63c2a0 --- /dev/null +++ b/src/main/java/io/facturapi/models/complements/carta_porte/CartaPorteIdentificacionVehicular.java @@ -0,0 +1,25 @@ +package io.facturapi.models.complements.carta_porte; + +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/complements/carta_porte/CartaPorteMercancia.java b/src/main/java/io/facturapi/models/complements/carta_porte/CartaPorteMercancia.java new file mode 100644 index 0000000..a57146d --- /dev/null +++ b/src/main/java/io/facturapi/models/complements/carta_porte/CartaPorteMercancia.java @@ -0,0 +1,179 @@ +package io.facturapi.models.complements.carta_porte; + +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/complements/carta_porte/CartaPorteMercancias.java b/src/main/java/io/facturapi/models/complements/carta_porte/CartaPorteMercancias.java new file mode 100644 index 0000000..52e8edd --- /dev/null +++ b/src/main/java/io/facturapi/models/complements/carta_porte/CartaPorteMercancias.java @@ -0,0 +1,55 @@ +package io.facturapi.models.complements.carta_porte; + +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/complements/carta_porte/CartaPorteParteTransporte.java b/src/main/java/io/facturapi/models/complements/carta_porte/CartaPorteParteTransporte.java new file mode 100644 index 0000000..e8cd4a9 --- /dev/null +++ b/src/main/java/io/facturapi/models/complements/carta_porte/CartaPorteParteTransporte.java @@ -0,0 +1,13 @@ +package io.facturapi.models.complements.carta_porte; + +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/complements/carta_porte/CartaPorteRemolque.java b/src/main/java/io/facturapi/models/complements/carta_porte/CartaPorteRemolque.java new file mode 100644 index 0000000..3808bd9 --- /dev/null +++ b/src/main/java/io/facturapi/models/complements/carta_porte/CartaPorteRemolque.java @@ -0,0 +1,17 @@ +package io.facturapi.models.complements.carta_porte; + +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/complements/carta_porte/CartaPorteRemolqueCcp.java b/src/main/java/io/facturapi/models/complements/carta_porte/CartaPorteRemolqueCcp.java new file mode 100644 index 0000000..1d4edc6 --- /dev/null +++ b/src/main/java/io/facturapi/models/complements/carta_porte/CartaPorteRemolqueCcp.java @@ -0,0 +1,17 @@ +package io.facturapi.models.complements.carta_porte; + +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/complements/carta_porte/CartaPorteSeguros.java b/src/main/java/io/facturapi/models/complements/carta_porte/CartaPorteSeguros.java new file mode 100644 index 0000000..300229d --- /dev/null +++ b/src/main/java/io/facturapi/models/complements/carta_porte/CartaPorteSeguros.java @@ -0,0 +1,37 @@ +package io.facturapi.models.complements.carta_porte; + +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/complements/carta_porte/CartaPorteTransporteAereo.java b/src/main/java/io/facturapi/models/complements/carta_porte/CartaPorteTransporteAereo.java new file mode 100644 index 0000000..0a9652e --- /dev/null +++ b/src/main/java/io/facturapi/models/complements/carta_porte/CartaPorteTransporteAereo.java @@ -0,0 +1,57 @@ +package io.facturapi.models.complements.carta_porte; + +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/complements/carta_porte/CartaPorteTransporteFerroviario.java b/src/main/java/io/facturapi/models/complements/carta_porte/CartaPorteTransporteFerroviario.java new file mode 100644 index 0000000..c18af94 --- /dev/null +++ b/src/main/java/io/facturapi/models/complements/carta_porte/CartaPorteTransporteFerroviario.java @@ -0,0 +1,35 @@ +package io.facturapi.models.complements.carta_porte; + +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/complements/carta_porte/CartaPorteTransporteMaritimo.java b/src/main/java/io/facturapi/models/complements/carta_porte/CartaPorteTransporteMaritimo.java new file mode 100644 index 0000000..7b19239 --- /dev/null +++ b/src/main/java/io/facturapi/models/complements/carta_porte/CartaPorteTransporteMaritimo.java @@ -0,0 +1,103 @@ +package io.facturapi.models.complements.carta_porte; + +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/complements/carta_porte/CartaPorteUbicacion.java b/src/main/java/io/facturapi/models/complements/carta_porte/CartaPorteUbicacion.java new file mode 100644 index 0000000..d6cc039 --- /dev/null +++ b/src/main/java/io/facturapi/models/complements/carta_porte/CartaPorteUbicacion.java @@ -0,0 +1,61 @@ +package io.facturapi.models.complements.carta_porte; + +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/complements/comercio_exterior/ComercioExteriorComplementData.java b/src/main/java/io/facturapi/models/complements/comercio_exterior/ComercioExteriorComplementData.java new file mode 100644 index 0000000..1a1fba4 --- /dev/null +++ b/src/main/java/io/facturapi/models/complements/comercio_exterior/ComercioExteriorComplementData.java @@ -0,0 +1,110 @@ +package io.facturapi.models.complements.comercio_exterior; + +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 com.fasterxml.jackson.databind.PropertyNamingStrategies; +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()) + .setPropertyNamingStrategy(PropertyNamingStrategies.SNAKE_CASE) + .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/complements/comercio_exterior/ComercioExteriorDescripcionesEspecificas.java b/src/main/java/io/facturapi/models/complements/comercio_exterior/ComercioExteriorDescripcionesEspecificas.java new file mode 100644 index 0000000..7344d39 --- /dev/null +++ b/src/main/java/io/facturapi/models/complements/comercio_exterior/ComercioExteriorDescripcionesEspecificas.java @@ -0,0 +1,25 @@ +package io.facturapi.models.complements.comercio_exterior; + +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/complements/comercio_exterior/ComercioExteriorDestinatarioRef.java b/src/main/java/io/facturapi/models/complements/comercio_exterior/ComercioExteriorDestinatarioRef.java new file mode 100644 index 0000000..a6e5c44 --- /dev/null +++ b/src/main/java/io/facturapi/models/complements/comercio_exterior/ComercioExteriorDestinatarioRef.java @@ -0,0 +1,26 @@ +package io.facturapi.models.complements.comercio_exterior; + +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/complements/comercio_exterior/ComercioExteriorDomicilio.java b/src/main/java/io/facturapi/models/complements/comercio_exterior/ComercioExteriorDomicilio.java new file mode 100644 index 0000000..556e75c --- /dev/null +++ b/src/main/java/io/facturapi/models/complements/comercio_exterior/ComercioExteriorDomicilio.java @@ -0,0 +1,49 @@ +package io.facturapi.models.complements.comercio_exterior; + +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/complements/comercio_exterior/ComercioExteriorEmisor.java b/src/main/java/io/facturapi/models/complements/comercio_exterior/ComercioExteriorEmisor.java new file mode 100644 index 0000000..65c4355 --- /dev/null +++ b/src/main/java/io/facturapi/models/complements/comercio_exterior/ComercioExteriorEmisor.java @@ -0,0 +1,17 @@ +package io.facturapi.models.complements.comercio_exterior; + +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/complements/comercio_exterior/ComercioExteriorMercancia.java b/src/main/java/io/facturapi/models/complements/comercio_exterior/ComercioExteriorMercancia.java new file mode 100644 index 0000000..6123e19 --- /dev/null +++ b/src/main/java/io/facturapi/models/complements/comercio_exterior/ComercioExteriorMercancia.java @@ -0,0 +1,39 @@ +package io.facturapi.models.complements.comercio_exterior; + +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/complements/comercio_exterior/ComercioExteriorMercancias.java b/src/main/java/io/facturapi/models/complements/comercio_exterior/ComercioExteriorMercancias.java new file mode 100644 index 0000000..6797dd2 --- /dev/null +++ b/src/main/java/io/facturapi/models/complements/comercio_exterior/ComercioExteriorMercancias.java @@ -0,0 +1,15 @@ +package io.facturapi.models.complements.comercio_exterior; + +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/complements/comercio_exterior/ComercioExteriorPartyRef.java b/src/main/java/io/facturapi/models/complements/comercio_exterior/ComercioExteriorPartyRef.java new file mode 100644 index 0000000..ad6b49a --- /dev/null +++ b/src/main/java/io/facturapi/models/complements/comercio_exterior/ComercioExteriorPartyRef.java @@ -0,0 +1,20 @@ +package io.facturapi.models.complements.comercio_exterior; + +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/complements/comercio_exterior/ComercioExteriorReceptorRef.java b/src/main/java/io/facturapi/models/complements/comercio_exterior/ComercioExteriorReceptorRef.java new file mode 100644 index 0000000..0142345 --- /dev/null +++ b/src/main/java/io/facturapi/models/complements/comercio_exterior/ComercioExteriorReceptorRef.java @@ -0,0 +1,20 @@ +package io.facturapi.models.complements.comercio_exterior; + +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/complements/nomina/NominaAcciones.java b/src/main/java/io/facturapi/models/complements/nomina/NominaAcciones.java new file mode 100644 index 0000000..d34626d --- /dev/null +++ b/src/main/java/io/facturapi/models/complements/nomina/NominaAcciones.java @@ -0,0 +1,15 @@ +package io.facturapi.models.complements.nomina; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class NominaAcciones { + private Double valorMercado; + 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/complements/nomina/NominaCompensacion.java b/src/main/java/io/facturapi/models/complements/nomina/NominaCompensacion.java new file mode 100644 index 0000000..756d6fa --- /dev/null +++ b/src/main/java/io/facturapi/models/complements/nomina/NominaCompensacion.java @@ -0,0 +1,18 @@ +package io.facturapi.models.complements.nomina; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class NominaCompensacion { + private Double saldoAFavor; + private Integer ano; + 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/complements/nomina/NominaComplementData.java b/src/main/java/io/facturapi/models/complements/nomina/NominaComplementData.java new file mode 100644 index 0000000..5b603f1 --- /dev/null +++ b/src/main/java/io/facturapi/models/complements/nomina/NominaComplementData.java @@ -0,0 +1,45 @@ +package io.facturapi.models.complements.nomina; + +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 { + private LocalDate fechaInicialPago; + private LocalDate fechaFinalPago; + private NominaPercepciones percepciones; + private List deducciones = new ArrayList<>(); + private List otrosPagos = new ArrayList<>(); + private List incapacidades = new ArrayList<>(); + private NominaEmisor emisor; + private NominaReceptor receptor; + private String tipoNomina; + private LocalDate fechaPago; + private Double numDiasPagados; + + 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; } + 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 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/NominaDeduccion.java b/src/main/java/io/facturapi/models/complements/nomina/NominaDeduccion.java new file mode 100644 index 0000000..9663eab --- /dev/null +++ b/src/main/java/io/facturapi/models/complements/nomina/NominaDeduccion.java @@ -0,0 +1,21 @@ +package io.facturapi.models.complements.nomina; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class NominaDeduccion { + 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/complements/nomina/NominaEmisor.java b/src/main/java/io/facturapi/models/complements/nomina/NominaEmisor.java new file mode 100644 index 0000000..a136dac --- /dev/null +++ b/src/main/java/io/facturapi/models/complements/nomina/NominaEmisor.java @@ -0,0 +1,21 @@ +package io.facturapi.models.complements.nomina; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class NominaEmisor { + private String curp; + private String registroPatronal; + private String rfcPatronOrigen; + 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/complements/nomina/NominaEntidadSncf.java b/src/main/java/io/facturapi/models/complements/nomina/NominaEntidadSncf.java new file mode 100644 index 0000000..ebd08ce --- /dev/null +++ b/src/main/java/io/facturapi/models/complements/nomina/NominaEntidadSncf.java @@ -0,0 +1,15 @@ +package io.facturapi.models.complements.nomina; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class NominaEntidadSncf { + private String origenRecurso; + 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/complements/nomina/NominaHorasExtra.java b/src/main/java/io/facturapi/models/complements/nomina/NominaHorasExtra.java new file mode 100644 index 0000000..8b22751 --- /dev/null +++ b/src/main/java/io/facturapi/models/complements/nomina/NominaHorasExtra.java @@ -0,0 +1,21 @@ +package io.facturapi.models.complements.nomina; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class NominaHorasExtra { + private Integer dias; + private String tipoHoras; + private Integer horasExtra; + 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/complements/nomina/NominaIncapacidad.java b/src/main/java/io/facturapi/models/complements/nomina/NominaIncapacidad.java new file mode 100644 index 0000000..1123717 --- /dev/null +++ b/src/main/java/io/facturapi/models/complements/nomina/NominaIncapacidad.java @@ -0,0 +1,18 @@ +package io.facturapi.models.complements.nomina; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class NominaIncapacidad { + private Integer diasIncapacidad; + private String tipoIncapacidad; + 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/complements/nomina/NominaJubilacion.java b/src/main/java/io/facturapi/models/complements/nomina/NominaJubilacion.java new file mode 100644 index 0000000..b11f1a8 --- /dev/null +++ b/src/main/java/io/facturapi/models/complements/nomina/NominaJubilacion.java @@ -0,0 +1,24 @@ +package io.facturapi.models.complements.nomina; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class NominaJubilacion { + private Double totalUnaExhibicion; + private Double totalParcialidad; + private Double montoDiario; + private Double ingresoAcumulable; + 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/complements/nomina/NominaOtroPago.java b/src/main/java/io/facturapi/models/complements/nomina/NominaOtroPago.java new file mode 100644 index 0000000..919c9f3 --- /dev/null +++ b/src/main/java/io/facturapi/models/complements/nomina/NominaOtroPago.java @@ -0,0 +1,27 @@ +package io.facturapi.models.complements.nomina; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class NominaOtroPago { + private String tipoOtroPago; + private String clave; + private String concepto; + private Double importe; + private Double subsidioCausado; + 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/complements/nomina/NominaPercepcion.java b/src/main/java/io/facturapi/models/complements/nomina/NominaPercepcion.java new file mode 100644 index 0000000..485bdf9 --- /dev/null +++ b/src/main/java/io/facturapi/models/complements/nomina/NominaPercepcion.java @@ -0,0 +1,32 @@ +package io.facturapi.models.complements.nomina; + +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 { + private String tipoPercepcion; + private String concepto; + private String clave; + private Double importeGravado; + private Double importeExento; + private NominaAcciones accionesOTitulos; + 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/complements/nomina/NominaPercepciones.java b/src/main/java/io/facturapi/models/complements/nomina/NominaPercepciones.java new file mode 100644 index 0000000..3abb0e5 --- /dev/null +++ b/src/main/java/io/facturapi/models/complements/nomina/NominaPercepciones.java @@ -0,0 +1,20 @@ +package io.facturapi.models.complements.nomina; + +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 { + private List percepcion = new ArrayList<>(); + private NominaJubilacion jubilacionPensionRetiro; + 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/complements/nomina/NominaReceptor.java b/src/main/java/io/facturapi/models/complements/nomina/NominaReceptor.java new file mode 100644 index 0000000..3721531 --- /dev/null +++ b/src/main/java/io/facturapi/models/complements/nomina/NominaReceptor.java @@ -0,0 +1,72 @@ +package io.facturapi.models.complements.nomina; + +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 NominaReceptor { + private String curp; + private String numSeguridadSocial; + private LocalDate fechaInicioRelLaboral; + private Object antiguedad; + private String tipoContrato; + private Boolean sindicalizado; + private String tipoJornada; + private String tipoRegimen; + private String numEmpleado; + private String departamento; + private String puesto; + private String riesgoPuesto; + private String periodicidadPago; + private String banco; + private String nombreBanco; + private String cuentaBancaria; + private Double salarioBaseCotApor; + private Double salarioDiarioIntegrado; + private String claveEntFed; + 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 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; } + 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/complements/nomina/NominaSeparacion.java b/src/main/java/io/facturapi/models/complements/nomina/NominaSeparacion.java new file mode 100644 index 0000000..082a598 --- /dev/null +++ b/src/main/java/io/facturapi/models/complements/nomina/NominaSeparacion.java @@ -0,0 +1,24 @@ +package io.facturapi.models.complements.nomina; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class NominaSeparacion { + private Double totalPagado; + private Integer numAnosServicio; + private Double ultimoSueldoMensOrd; + private Double ingresoAcumulable; + 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/complements/nomina/NominaSubcontratacion.java b/src/main/java/io/facturapi/models/complements/nomina/NominaSubcontratacion.java new file mode 100644 index 0000000..6e7d787 --- /dev/null +++ b/src/main/java/io/facturapi/models/complements/nomina/NominaSubcontratacion.java @@ -0,0 +1,15 @@ +package io.facturapi.models.complements.nomina; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class NominaSubcontratacion { + private String rfcLabora; + 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/complements/pago/PagoComplementData.java b/src/main/java/io/facturapi/models/complements/pago/PagoComplementData.java new file mode 100644 index 0000000..624ed97 --- /dev/null +++ b/src/main/java/io/facturapi/models/complements/pago/PagoComplementData.java @@ -0,0 +1,58 @@ +package io.facturapi.models.complements.pago; + +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; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class PagoComplementData { + private PaymentForm paymentForm; + private Instant date; + 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 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; } + 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/complements/pago/PaymentRelatedDocument.java b/src/main/java/io/facturapi/models/complements/pago/PaymentRelatedDocument.java new file mode 100644 index 0000000..6e65897 --- /dev/null +++ b/src/main/java/io/facturapi/models/complements/pago/PaymentRelatedDocument.java @@ -0,0 +1,42 @@ +package io.facturapi.models.complements.pago; + +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; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class PaymentRelatedDocument { + private String uuid; + private Double amount; + private Integer installment; + private Double lastBalance; + private String currency; + private Double exchange; + private String folioNumber; + private String series; + private Taxability 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 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 new file mode 100644 index 0000000..0e9ac78 --- /dev/null +++ b/src/main/java/io/facturapi/models/complements/pago/PaymentRelatedDocumentTax.java @@ -0,0 +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 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 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/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..f0d2911 --- /dev/null +++ b/src/main/java/io/facturapi/resources/InvoicesResource.java @@ -0,0 +1,245 @@ +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.io.InputStream; +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"); + } + + /** + * 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. + * + * @param id Invoice id. + * @return XML bytes. + * @see API reference + */ + 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. + * + * @param id Invoice id. + * @return ZIP bytes. + * @see API reference + */ + 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. + * + * @param id Invoice id. + * @return XML bytes. + * @see API reference + */ + 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. + * + * @param id Invoice id. + * @return PDF bytes. + * @see API reference + */ + 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. + * + * @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..b2011d4 --- /dev/null +++ b/src/main/java/io/facturapi/resources/OrganizationsResource.java @@ -0,0 +1,349 @@ +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.File; +import java.io.IOException; +import java.nio.file.Files; +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, File file) throws IOException { + return uploadLogo(id, Files.readAllBytes(file.toPath())); + } + + /** + * Uploads organization logo file bytes. + */ + public Organization uploadLogo(String id, byte[] fileBytes) { + MultipartBody multipartBody = new MultipartBodyBuilder() + .addFile("file", "logo.jpg", fileBytes, "application/octet-stream") + .build(); + return client.putMultipart("/organizations/" + id + "/logo", multipartBody, Organization.class); + } + + /** + * Uploads organization CSD certificate files. + */ + public Organization uploadCertificate(String id, File cerFile, File keyFile, String password) throws IOException { + return uploadCertificate( + id, + Files.readAllBytes(cerFile.toPath()), + Files.readAllBytes(keyFile.toPath()), + password + ); + } + + /** + * Uploads organization CSD certificate file bytes. + */ + public Organization uploadCertificate(String id, byte[] cerFileBytes, byte[] keyFileBytes, String password) { + MultipartBody multipartBody = new MultipartBodyBuilder() + .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); + } + + /** + * 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..faa6d4b --- /dev/null +++ b/src/main/java/io/facturapi/resources/ReceiptsResource.java @@ -0,0 +1,122 @@ +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.io.InputStream; +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"); + } + + /** + * 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 new file mode 100644 index 0000000..4fd50fc --- /dev/null +++ b/src/main/java/io/facturapi/resources/RetentionsResource.java @@ -0,0 +1,143 @@ +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.io.InputStream; +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"); + } + + /** + * 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. + * + * @param id Retention id. + * @return XML bytes. + * @see API reference + */ + 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. + * + * @param id Retention id. + * @return ZIP bytes. + * @see API reference + */ + 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/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..dc1d41b --- /dev/null +++ b/src/test/java/io/facturapi/FacturapiHttpClientTest.java @@ -0,0 +1,71 @@ +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.client()) + .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.client()) + .build() + ); + + assertArrayEquals(payload, client.getBytes("/invoices/inv_1/pdf")); + } + + @Test + void throwsFacturapiExceptionWithApiMessage() { + StubHttpClient httpClient = new StubHttpClient(); + httpClient.enqueueJson(400, "{\"message\":\"Invalid customer\",\"status\":\"400\",\"code\":\"validation_error\",\"path\":\"customer.tax_id\"}"); + + FacturapiHttpClient client = new FacturapiHttpClient( + FacturapiConfig.builder("sk_test_123") + .httpClient(httpClient.client()) + .build() + ); + + FacturapiException ex = assertThrows( + FacturapiException.class, + () -> client.get("/customers/cus_1", null, GenericResponse.class) + ); + + assertEquals(400, ex.getStatusCode()); + assertTrue(ex.getMessage().contains("Invalid customer")); + assertEquals("validation_error", ex.getErrorCode()); + assertEquals("customer.tax_id", ex.getErrorPath()); + } +} diff --git a/src/test/java/io/facturapi/FacturapiResourcesTest.java b/src/test/java/io/facturapi/FacturapiResourcesTest.java new file mode 100644 index 0000000..e4bbbec --- /dev/null +++ b/src/test/java/io/facturapi/FacturapiResourcesTest.java @@ -0,0 +1,246 @@ +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.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.io.InputStream; +import java.nio.charset.StandardCharsets; +import java.time.Instant; +import java.time.LocalDate; +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.client()) + .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 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.client()) + .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 organizationUploadsAcceptBytes() { + StubHttpClient httpClient = new StubHttpClient(); + httpClient.enqueueJson(200, "{\"id\":\"org_1\"}"); + + Facturapi sdk = new Facturapi( + FacturapiConfig.builder("sk_test") + .httpClient(httpClient.client()) + .build() + ); + + 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()); + 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.client()) + .build() + ); + + var response = sdk.organizations().uploadCertificate( + "org_1", + "cer-bytes".getBytes(StandardCharsets.UTF_8), + "key-bytes".getBytes(StandardCharsets.UTF_8), + "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() { + StubHttpClient httpClient = new StubHttpClient(); + Facturapi sdk = new Facturapi( + FacturapiConfig.builder("sk_test") + .httpClient(httpClient.client()) + .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(); + httpClient.enqueueJson(200, "[{\"id\":\"live_1\",\"key\":\"sk_live_x\"}]"); + + Facturapi sdk = new Facturapi( + FacturapiConfig.builder("sk_test") + .httpClient(httpClient.client()) + .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\",\"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\":[]}}}," + + "{\"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.client()) + .build() + ); + + 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(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); + assertEquals("nomina", nomina.getType()); + 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); + 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()); + } + + @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()); + } + + @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()); + } +} diff --git a/src/test/java/io/facturapi/StubHttpClient.java b/src/test/java/io/facturapi/StubHttpClient.java new file mode 100644 index 0000000..a247f82 --- /dev/null +++ b/src/test/java/io/facturapi/StubHttpClient.java @@ -0,0 +1,148 @@ +package io.facturapi; + +import java.io.IOException; +import java.net.URI; +import java.nio.charset.StandardCharsets; +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 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; + final Map> headers; + + QueuedResponse(int statusCode, byte[] body, Map> headers) { + this.statusCode = statusCode; + this.body = body; + this.headers = headers; + } + } + + static final class RecordedHeaders { + private final Headers headers; + + RecordedHeaders(Headers headers) { + this.headers = headers; + } + + Optional firstValue(String name) { + return Optional.ofNullable(headers.values(name).stream().findFirst().orElse(null)); + } + } + + static final class RecordedRequest { + private final Request request; + + RecordedRequest(Request request) { + this.request = request; + } + + String method() { + return request.method(); + } + + URI uri() { + return request.url().uri(); + } + + RecordedHeaders headers() { + return new RecordedHeaders(request.headers()); + } + + 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 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; + } + + 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; + } + + 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(); + } +} 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(