diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b2cacc9..cc9f68a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -20,10 +20,10 @@ jobs: if: github.event_name == 'push' || github.event.pull_request.head.repo.fork steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - name: Set up Java - uses: actions/setup-java@v4 + uses: actions/setup-java@v5 with: distribution: temurin java-version: | @@ -40,14 +40,17 @@ jobs: build: timeout-minutes: 15 name: build + permissions: + contents: read + id-token: write runs-on: ${{ github.repository == 'stainless-sdks/e-invoice-api-java' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }} if: github.event_name == 'push' || github.event.pull_request.head.repo.fork steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - name: Set up Java - uses: actions/setup-java@v4 + uses: actions/setup-java@v5 with: distribution: temurin java-version: | @@ -61,16 +64,31 @@ jobs: - name: Build SDK run: ./scripts/build + - name: Get GitHub OIDC Token + if: github.repository == 'stainless-sdks/e-invoice-api-java' + id: github-oidc + uses: actions/github-script@v8 + with: + script: core.setOutput('github_token', await core.getIDToken()); + + - name: Build and upload Maven artifacts + if: github.repository == 'stainless-sdks/e-invoice-api-java' + env: + URL: https://pkg.stainless.com/s + AUTH: ${{ steps.github-oidc.outputs.github_token }} + SHA: ${{ github.sha }} + PROJECT: e-invoice-api-java + run: ./scripts/upload-artifacts test: timeout-minutes: 15 name: test runs-on: ${{ github.repository == 'stainless-sdks/e-invoice-api-java' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }} if: github.event_name == 'push' || github.event.pull_request.head.repo.fork steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - name: Set up Java - uses: actions/setup-java@v4 + uses: actions/setup-java@v5 with: distribution: temurin java-version: | diff --git a/.github/workflows/publish-sonatype.yml b/.github/workflows/publish-sonatype.yml index c498ce6..8e5483e 100644 --- a/.github/workflows/publish-sonatype.yml +++ b/.github/workflows/publish-sonatype.yml @@ -14,10 +14,10 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - name: Set up Java - uses: actions/setup-java@v4 + uses: actions/setup-java@v5 with: distribution: temurin java-version: | diff --git a/.github/workflows/release-doctor.yml b/.github/workflows/release-doctor.yml index 4c260b7..6a059b2 100644 --- a/.github/workflows/release-doctor.yml +++ b/.github/workflows/release-doctor.yml @@ -12,7 +12,7 @@ jobs: if: github.repository == 'e-invoice-be/e-invoice-java' && (github.event_name == 'push' || github.event_name == 'workflow_dispatch' || startsWith(github.head_ref, 'release-please') || github.head_ref == 'next') steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - name: Check release environment run: | diff --git a/.release-please-manifest.json b/.release-please-manifest.json index fd0ccba..000572e 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.1.0-alpha.12" + ".": "0.1.0-alpha.13" } \ No newline at end of file diff --git a/.stats.yml b/.stats.yml index 5507ef0..6da94ee 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 24 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/e-invoice-be%2Fe-invoice-api-6bf85ca7bc7eac16815d912ab0720537e72e39e6234b030c9c3644b3df327788.yml -openapi_spec_hash: f9ac6f267c1fde475250d7893cf966c7 -config_hash: d627f345d2cab6590eeea9820301272e +configured_endpoints: 28 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/e-invoice-be%2Fe-invoice-api-456484895d394520a1179d60cd2df0b377207849fa84562e406d66886bf8244f.yml +openapi_spec_hash: b51d0365469bbe89d7e1e8c13983475d +config_hash: 852a0117abb3db077933876ad1185f41 diff --git a/CHANGELOG.md b/CHANGELOG.md index 851053c..d948f44 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,61 @@ # Changelog +## 0.1.0-alpha.13 (2026-02-09) + +Full Changelog: [v0.1.0-alpha.12...v0.1.0-alpha.13](https://github.com/e-invoice-be/e-invoice-java/compare/v0.1.0-alpha.12...v0.1.0-alpha.13) + +### Features + +* **api:** api update ([60dbcea](https://github.com/e-invoice-be/e-invoice-java/commit/60dbcea186a99adbde90154602023e831daf3632)) +* **api:** api update ([c634578](https://github.com/e-invoice-be/e-invoice-java/commit/c63457882b2760456275e531d05f289c716e5934)) +* **api:** api update ([8af9305](https://github.com/e-invoice-be/e-invoice-java/commit/8af9305dcb70550adbd23bc6b31119eaa5aaf23c)) +* **api:** api update ([2b90fa4](https://github.com/e-invoice-be/e-invoice-java/commit/2b90fa4367258ccc96cdf4fe039efeede2a7048e)) +* **api:** api update ([74c4c9e](https://github.com/e-invoice-be/e-invoice-java/commit/74c4c9e381b260df4545a7180365cf517a65b26f)) +* **api:** api update ([5c08714](https://github.com/e-invoice-be/e-invoice-java/commit/5c0871400561a727de59401802a44d4722e6a09a)) +* **api:** api update ([3ef5ab9](https://github.com/e-invoice-be/e-invoice-java/commit/3ef5ab9f1fd50c8dc83094c6d58212e350e1000e)) +* **api:** api update ([4a468b2](https://github.com/e-invoice-be/e-invoice-java/commit/4a468b27a6b2a2c8e748131b3d4f35176a4e3d98)) +* **api:** api update ([d42fb14](https://github.com/e-invoice-be/e-invoice-java/commit/d42fb14927fcae080a39896743dade19a3f23c81)) +* **api:** api update ([3bc4883](https://github.com/e-invoice-be/e-invoice-java/commit/3bc4883a59e0cc7352dfa41a3c6f67f4efc8ba19)) +* **api:** api update ([010d7f1](https://github.com/e-invoice-be/e-invoice-java/commit/010d7f1fc776ed37da2fb55f96ade8267e184cee)) +* **api:** api update ([02308b8](https://github.com/e-invoice-be/e-invoice-java/commit/02308b86f70414c3008b61e1776f17f1fa8d38f0)) +* **api:** api update ([50eb173](https://github.com/e-invoice-be/e-invoice-java/commit/50eb173e52614313f0474c525571300d31f47003)) +* **api:** api update ([88a2388](https://github.com/e-invoice-be/e-invoice-java/commit/88a2388ce1f68f3ad01ac7ae30aa6fd25c1daa15)) +* **api:** api update ([5b447b4](https://github.com/e-invoice-be/e-invoice-java/commit/5b447b4473189cf6675d79480758e989808dab38)) +* **api:** api update ([7c8d5d6](https://github.com/e-invoice-be/e-invoice-java/commit/7c8d5d6baaf53b8fa24983e413280c44ef6783bb)) +* **api:** api update ([16e58bd](https://github.com/e-invoice-be/e-invoice-java/commit/16e58bd343a028e65724cd766aaea0c96b8a01aa)) +* **api:** manual updates ([4f7dc90](https://github.com/e-invoice-be/e-invoice-java/commit/4f7dc90de5d979ea18f9650a25a4b747e28ce5af)) +* **client:** send `X-Stainless-Kotlin-Version` header ([310f45e](https://github.com/e-invoice-be/e-invoice-java/commit/310f45e949318fdc406d157cebe1525e048e1f7c)) + + +### Bug Fixes + +* **client:** cancel okhttp call when future cancelled ([f34d373](https://github.com/e-invoice-be/e-invoice-java/commit/f34d373cab9477deb15c0c5670166984fe83c850)) +* **client:** multi-value header serialization ([57c75d9](https://github.com/e-invoice-be/e-invoice-java/commit/57c75d98fc1b53bdc1d1544476c6a31cec525601)) +* **client:** preserve time zone in lenient date-time parsing ([2bc9f75](https://github.com/e-invoice-be/e-invoice-java/commit/2bc9f757bcc64596e9db1b2fab3bdeb504e92534)) +* **tests:** add missing query/header params ([a1039c6](https://github.com/e-invoice-be/e-invoice-java/commit/a1039c67421588b13f9a5d522b5baa7c1b150931)) + + +### Chores + +* **internal:** codegen related update ([0bd96de](https://github.com/e-invoice-be/e-invoice-java/commit/0bd96de349c640f0757190242e91a9e315c133e1)) +* **internal:** codegen related update ([20dd5a8](https://github.com/e-invoice-be/e-invoice-java/commit/20dd5a8e841a3649ffe0f76098e1046e1d8f00e9)) +* **internal:** codegen related update ([04ffe93](https://github.com/e-invoice-be/e-invoice-java/commit/04ffe93692ea6714f8825df585864c39b84a2663)) +* **internal:** codegen related update ([eb5c7e5](https://github.com/e-invoice-be/e-invoice-java/commit/eb5c7e54df6ca465861af705907ed654e844d5a5)) +* **internal:** codegen related update ([34d3b25](https://github.com/e-invoice-be/e-invoice-java/commit/34d3b2519e014679f33b0e66e807b13134c12741)) +* **internal:** codegen related update ([6c5b431](https://github.com/e-invoice-be/e-invoice-java/commit/6c5b4313f318f8c7e7a99cade9644bbb2103be72)) +* **internal:** codegen related update ([0059a2f](https://github.com/e-invoice-be/e-invoice-java/commit/0059a2f619a5e17c3bc9f17e7f684e4af983fe60)) +* **internal:** codegen related update ([ee9459a](https://github.com/e-invoice-be/e-invoice-java/commit/ee9459ac80af991d3a9d719f46d28bee16ac1d49)) +* **internal:** codegen related update ([52e1ebb](https://github.com/e-invoice-be/e-invoice-java/commit/52e1ebbb83280db67feb3581a08d3f7241a500f0)) +* **internal:** codegen related update ([b3aad10](https://github.com/e-invoice-be/e-invoice-java/commit/b3aad10fd43571a39c18361ddf3597d68a643531)) +* **internal:** codegen related update ([b5a6a0f](https://github.com/e-invoice-be/e-invoice-java/commit/b5a6a0f7aa5ed8d9a44f27f818da15da3ff30d3f)) +* **internal:** correct cache invalidation for `SKIP_MOCK_TESTS` ([524c037](https://github.com/e-invoice-be/e-invoice-java/commit/524c0373a029f9e0ac7429d05d0e9869dca8a723)) +* **internal:** update maven repo doc to include authentication ([9e69b7f](https://github.com/e-invoice-be/e-invoice-java/commit/9e69b7ff607be2392d5ab6e9796518e129c46fcc)) + + +### Documentation + +* remove `$` for better copy-pasteabality ([4b1c946](https://github.com/e-invoice-be/e-invoice-java/commit/4b1c946cf5e6403194165bf0c92f5160a5e95e32)) + ## 0.1.0-alpha.12 (2025-09-26) Full Changelog: [v0.1.0-alpha.11...v0.1.0-alpha.12](https://github.com/e-invoice-be/e-invoice-java/compare/v0.1.0-alpha.11...v0.1.0-alpha.12) diff --git a/LICENSE b/LICENSE index 735c9bb..05f8e0b 100644 --- a/LICENSE +++ b/LICENSE @@ -186,7 +186,7 @@ same "printed page" as the copyright notice for easier identification within third-party archives. - Copyright 2025 E Invoice + Copyright 2026 E Invoice Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/README.md b/README.md index af73d52..3b9ed83 100644 --- a/README.md +++ b/README.md @@ -2,16 +2,25 @@ -[![Maven Central](https://img.shields.io/maven-central/v/com.e_invoice.api/e-invoice-java)](https://central.sonatype.com/artifact/com.e_invoice.api/e-invoice-java/0.1.0-alpha.12) -[![javadoc](https://javadoc.io/badge2/com.e_invoice.api/e-invoice-java/0.1.0-alpha.12/javadoc.svg)](https://javadoc.io/doc/com.e_invoice.api/e-invoice-java/0.1.0-alpha.12) +[![Maven Central](https://img.shields.io/maven-central/v/com.e_invoice.api/e-invoice-java)](https://central.sonatype.com/artifact/com.e_invoice.api/e-invoice-java/0.1.0-alpha.13) +[![javadoc](https://javadoc.io/badge2/com.e_invoice.api/e-invoice-java/0.1.0-alpha.13/javadoc.svg)](https://javadoc.io/doc/com.e_invoice.api/e-invoice-java/0.1.0-alpha.13) The e-invoice.be Peppol SDK provides convenient access to the [e-invoice.be REST API](https://api.e-invoice.be) from applications written in Java. +## MCP Server + +Use the E Invoice MCP Server to enable AI assistants to interact with this API, allowing them to explore endpoints, make test requests, and use documentation to help integrate this SDK into your application. + +[![Add to Cursor](https://cursor.com/deeplink/mcp-install-dark.svg)](https://cursor.com/en-US/install-mcp?name=e-invoice-api-mcp&config=eyJjb21tYW5kIjoibnB4IiwiYXJncyI6WyIteSIsImUtaW52b2ljZS1hcGktbWNwIl0sImVudiI6eyJFX0lOVk9JQ0VfQVBJX0tFWSI6Ik15IEFQSSBLZXkifX0) +[![Install in VS Code](https://img.shields.io/badge/_-Add_to_VS_Code-blue?style=for-the-badge&logo=data:image/svg%2bxml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGZpbGw9Im5vbmUiIHZpZXdCb3g9IjAgMCA0MCA0MCI+PHBhdGggZmlsbD0iI0VFRSIgZmlsbC1ydWxlPSJldmVub2RkIiBkPSJNMzAuMjM1IDM5Ljg4NGEyLjQ5MSAyLjQ5MSAwIDAgMS0xLjc4MS0uNzNMMTIuNyAyNC43OGwtMy40NiAyLjYyNC0zLjQwNiAyLjU4MmExLjY2NSAxLjY2NSAwIDAgMS0xLjA4Mi4zMzggMS42NjQgMS42NjQgMCAwIDEtMS4wNDYtLjQzMWwtMi4yLTJhMS42NjYgMS42NjYgMCAwIDEgMC0yLjQ2M0w3LjQ1OCAyMCA0LjY3IDE3LjQ1MyAxLjUwNyAxNC41N2ExLjY2NSAxLjY2NSAwIDAgMSAwLTIuNDYzbDIuMi0yYTEuNjY1IDEuNjY1IDAgMCAxIDIuMTMtLjA5N2w2Ljg2MyA1LjIwOUwyOC40NTIuODQ0YTIuNDg4IDIuNDg4IDAgMCAxIDEuODQxLS43MjljLjM1MS4wMDkuNjk5LjA5MSAxLjAxOS4yNDVsOC4yMzYgMy45NjFhMi41IDIuNSAwIDAgMSAxLjQxNSAyLjI1M3YuMDk5LS4wNDVWMzMuMzd2LS4wNDUuMDk1YTIuNTAxIDIuNTAxIDAgMCAxLTEuNDE2IDIuMjU3bC04LjIzNSAzLjk2MWEyLjQ5MiAyLjQ5MiAwIDAgMS0xLjA3Ny4yNDZabS43MTYtMjguOTQ3LTExLjk0OCA5LjA2MiAxMS45NTIgOS4wNjUtLjAwNC0xOC4xMjdaIi8+PC9zdmc+)](https://vscode.stainless.com/mcp/%7B%22name%22%3A%22e-invoice-api-mcp%22%2C%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22-y%22%2C%22e-invoice-api-mcp%22%5D%2C%22env%22%3A%7B%22E_INVOICE_API_KEY%22%3A%22My%20API%20Key%22%7D%7D) + +> Note: You may need to set environment variables in your MCP client. + -The REST API documentation can be found on [api.e-invoice.be](https://api.e-invoice.be). Javadocs are available on [javadoc.io](https://javadoc.io/doc/com.e_invoice.api/e-invoice-java/0.1.0-alpha.12). +The REST API documentation can be found on [api.e-invoice.be](https://api.e-invoice.be). Javadocs are available on [javadoc.io](https://javadoc.io/doc/com.e_invoice.api/e-invoice-java/0.1.0-alpha.13). @@ -22,7 +31,7 @@ The REST API documentation can be found on [api.e-invoice.be](https://api.e-invo ### Gradle ```kotlin -implementation("com.e_invoice.api:e-invoice-java:0.1.0-alpha.12") +implementation("com.e_invoice.api:e-invoice-java:0.1.0-alpha.13") ``` ### Maven @@ -31,7 +40,7 @@ implementation("com.e_invoice.api:e-invoice-java:0.1.0-alpha.12") com.e_invoice.api e-invoice-java - 0.1.0-alpha.12 + 0.1.0-alpha.13 ``` @@ -185,61 +194,57 @@ The SDK defines methods that accept files. To upload a file, pass a [`Path`](https://docs.oracle.com/javase/8/docs/api/java/nio/file/Path.html): ```java -import com.e_invoice.api.models.documents.attachments.AttachmentAddParams; -import com.e_invoice.api.models.documents.attachments.DocumentAttachment; +import com.e_invoice.api.models.documents.DocumentCreateFromPdfParams; +import com.e_invoice.api.models.documents.DocumentCreateFromPdfResponse; import java.nio.file.Paths; -AttachmentAddParams params = AttachmentAddParams.builder() - .documentId("document_id") +DocumentCreateFromPdfParams params = DocumentCreateFromPdfParams.builder() .file(Paths.get("/path/to/file")) .build(); -DocumentAttachment documentAttachment = client.documents().attachments().add(params); +DocumentCreateFromPdfResponse response = client.documents().createFromPdf(params); ``` Or an arbitrary [`InputStream`](https://docs.oracle.com/javase/8/docs/api/java/io/InputStream.html): ```java -import com.e_invoice.api.models.documents.attachments.AttachmentAddParams; -import com.e_invoice.api.models.documents.attachments.DocumentAttachment; +import com.e_invoice.api.models.documents.DocumentCreateFromPdfParams; +import com.e_invoice.api.models.documents.DocumentCreateFromPdfResponse; import java.net.URL; -AttachmentAddParams params = AttachmentAddParams.builder() - .documentId("document_id") +DocumentCreateFromPdfParams params = DocumentCreateFromPdfParams.builder() .file(new URL("https://example.com//path/to/file").openStream()) .build(); -DocumentAttachment documentAttachment = client.documents().attachments().add(params); +DocumentCreateFromPdfResponse response = client.documents().createFromPdf(params); ``` Or a `byte[]` array: ```java -import com.e_invoice.api.models.documents.attachments.AttachmentAddParams; -import com.e_invoice.api.models.documents.attachments.DocumentAttachment; +import com.e_invoice.api.models.documents.DocumentCreateFromPdfParams; +import com.e_invoice.api.models.documents.DocumentCreateFromPdfResponse; -AttachmentAddParams params = AttachmentAddParams.builder() - .documentId("document_id") +DocumentCreateFromPdfParams params = DocumentCreateFromPdfParams.builder() .file("content".getBytes()) .build(); -DocumentAttachment documentAttachment = client.documents().attachments().add(params); +DocumentCreateFromPdfResponse response = client.documents().createFromPdf(params); ``` Note that when passing a non-`Path` its filename is unknown so it will not be included in the request. To manually set a filename, pass a [`MultipartField`](e-invoice-java-core/src/main/kotlin/com/e_invoice/api/core/Values.kt): ```java import com.e_invoice.api.core.MultipartField; -import com.e_invoice.api.models.documents.attachments.AttachmentAddParams; -import com.e_invoice.api.models.documents.attachments.DocumentAttachment; +import com.e_invoice.api.models.documents.DocumentCreateFromPdfParams; +import com.e_invoice.api.models.documents.DocumentCreateFromPdfResponse; import java.io.InputStream; import java.net.URL; -AttachmentAddParams params = AttachmentAddParams.builder() - .documentId("document_id") +DocumentCreateFromPdfParams params = DocumentCreateFromPdfParams.builder() .file(MultipartField.builder() .value(new URL("https://example.com//path/to/file").openStream()) .filename("/path/to/file") .build()) .build(); -DocumentAttachment documentAttachment = client.documents().attachments().add(params); +DocumentCreateFromPdfResponse response = client.documents().createFromPdf(params); ``` ## Raw responses @@ -402,13 +407,13 @@ The SDK uses the standard [OkHttp logging interceptor](https://github.com/square Enable logging by setting the `E_INVOICE_LOG` environment variable to `info`: ```sh -$ export E_INVOICE_LOG=info +export E_INVOICE_LOG=info ``` Or to `debug` for more verbose logging: ```sh -$ export E_INVOICE_LOG=debug +export E_INVOICE_LOG=debug ``` ## ProGuard and R8 @@ -428,6 +433,8 @@ If the SDK threw an exception, but you're _certain_ the version is compatible, t > [!CAUTION] > We make no guarantee that the SDK works correctly when the Jackson version check is disabled. +Also note that there are bugs in older Jackson versions that can affect the SDK. We don't work around all Jackson bugs ([example](https://github.com/FasterXML/jackson-databind/issues/3240)) and expect users to upgrade Jackson for those instead. + ## Network options ### Retries diff --git a/build.gradle.kts b/build.gradle.kts index c57fa31..a545472 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -9,7 +9,7 @@ repositories { allprojects { group = "com.e_invoice.api" - version = "0.1.0-alpha.12" // x-release-please-version + version = "0.1.0-alpha.13" // x-release-please-version } subprojects { diff --git a/buildSrc/src/main/kotlin/e-invoice.kotlin.gradle.kts b/buildSrc/src/main/kotlin/e-invoice.kotlin.gradle.kts index 8541ea6..16c0db2 100644 --- a/buildSrc/src/main/kotlin/e-invoice.kotlin.gradle.kts +++ b/buildSrc/src/main/kotlin/e-invoice.kotlin.gradle.kts @@ -33,6 +33,9 @@ kotlin { tasks.withType().configureEach { systemProperty("junit.jupiter.execution.parallel.enabled", true) systemProperty("junit.jupiter.execution.parallel.mode.default", "concurrent") + + // `SKIP_MOCK_TESTS` affects which tests run so it must be added as input for proper cache invalidation. + inputs.property("skipMockTests", System.getenv("SKIP_MOCK_TESTS")).optional(true) } val ktfmt by configurations.creating diff --git a/buildSrc/src/main/kotlin/e-invoice.publish.gradle.kts b/buildSrc/src/main/kotlin/e-invoice.publish.gradle.kts index dc41057..078189f 100644 --- a/buildSrc/src/main/kotlin/e-invoice.publish.gradle.kts +++ b/buildSrc/src/main/kotlin/e-invoice.publish.gradle.kts @@ -40,6 +40,14 @@ configure { } } } + repositories { + if (project.hasProperty("publishLocal")) { + maven { + name = "LocalFileSystem" + url = uri("${rootProject.layout.buildDirectory.get()}/local-maven-repo") + } + } + } } signing { diff --git a/e-invoice-java-client-okhttp/build.gradle.kts b/e-invoice-java-client-okhttp/build.gradle.kts index 83540c1..20efb7d 100644 --- a/e-invoice-java-client-okhttp/build.gradle.kts +++ b/e-invoice-java-client-okhttp/build.gradle.kts @@ -10,5 +10,6 @@ dependencies { implementation("com.squareup.okhttp3:logging-interceptor:4.12.0") testImplementation(kotlin("test")) - testImplementation("org.assertj:assertj-core:3.25.3") + testImplementation("org.assertj:assertj-core:3.27.7") + testImplementation("com.github.tomakehurst:wiremock-jre8:2.35.2") } diff --git a/e-invoice-java-client-okhttp/src/main/kotlin/com/e_invoice/api/client/okhttp/EInvoiceOkHttpClient.kt b/e-invoice-java-client-okhttp/src/main/kotlin/com/e_invoice/api/client/okhttp/EInvoiceOkHttpClient.kt index f723839..4dbfcfc 100644 --- a/e-invoice-java-client-okhttp/src/main/kotlin/com/e_invoice/api/client/okhttp/EInvoiceOkHttpClient.kt +++ b/e-invoice-java-client-okhttp/src/main/kotlin/com/e_invoice/api/client/okhttp/EInvoiceOkHttpClient.kt @@ -18,6 +18,7 @@ import java.time.Clock import java.time.Duration import java.util.Optional import java.util.concurrent.Executor +import java.util.concurrent.ExecutorService import javax.net.ssl.HostnameVerifier import javax.net.ssl.SSLSocketFactory import javax.net.ssl.X509TrustManager @@ -46,11 +47,31 @@ class EInvoiceOkHttpClient private constructor() { class Builder internal constructor() { private var clientOptions: ClientOptions.Builder = ClientOptions.builder() + private var dispatcherExecutorService: ExecutorService? = null private var proxy: Proxy? = null private var sslSocketFactory: SSLSocketFactory? = null private var trustManager: X509TrustManager? = null private var hostnameVerifier: HostnameVerifier? = null + /** + * The executor service to use for running HTTP requests. + * + * Defaults to OkHttp's + * [default executor service](https://github.com/square/okhttp/blob/ace792f443b2ffb17974f5c0d1cecdf589309f26/okhttp/src/commonJvmAndroid/kotlin/okhttp3/Dispatcher.kt#L98-L104). + * + * This class takes ownership of the executor service and shuts it down when closed. + */ + fun dispatcherExecutorService(dispatcherExecutorService: ExecutorService?) = apply { + this.dispatcherExecutorService = dispatcherExecutorService + } + + /** + * Alias for calling [Builder.dispatcherExecutorService] with + * `dispatcherExecutorService.orElse(null)`. + */ + fun dispatcherExecutorService(dispatcherExecutorService: Optional) = + dispatcherExecutorService(dispatcherExecutorService.getOrNull()) + fun proxy(proxy: Proxy?) = apply { this.proxy = proxy } /** Alias for calling [Builder.proxy] with `proxy.orElse(null)`. */ @@ -309,6 +330,7 @@ class EInvoiceOkHttpClient private constructor() { OkHttpClient.builder() .timeout(clientOptions.timeout()) .proxy(proxy) + .dispatcherExecutorService(dispatcherExecutorService) .sslSocketFactory(sslSocketFactory) .trustManager(trustManager) .hostnameVerifier(hostnameVerifier) diff --git a/e-invoice-java-client-okhttp/src/main/kotlin/com/e_invoice/api/client/okhttp/EInvoiceOkHttpClientAsync.kt b/e-invoice-java-client-okhttp/src/main/kotlin/com/e_invoice/api/client/okhttp/EInvoiceOkHttpClientAsync.kt index 225db7f..2f4d1e2 100644 --- a/e-invoice-java-client-okhttp/src/main/kotlin/com/e_invoice/api/client/okhttp/EInvoiceOkHttpClientAsync.kt +++ b/e-invoice-java-client-okhttp/src/main/kotlin/com/e_invoice/api/client/okhttp/EInvoiceOkHttpClientAsync.kt @@ -18,6 +18,7 @@ import java.time.Clock import java.time.Duration import java.util.Optional import java.util.concurrent.Executor +import java.util.concurrent.ExecutorService import javax.net.ssl.HostnameVerifier import javax.net.ssl.SSLSocketFactory import javax.net.ssl.X509TrustManager @@ -46,11 +47,31 @@ class EInvoiceOkHttpClientAsync private constructor() { class Builder internal constructor() { private var clientOptions: ClientOptions.Builder = ClientOptions.builder() + private var dispatcherExecutorService: ExecutorService? = null private var proxy: Proxy? = null private var sslSocketFactory: SSLSocketFactory? = null private var trustManager: X509TrustManager? = null private var hostnameVerifier: HostnameVerifier? = null + /** + * The executor service to use for running HTTP requests. + * + * Defaults to OkHttp's + * [default executor service](https://github.com/square/okhttp/blob/ace792f443b2ffb17974f5c0d1cecdf589309f26/okhttp/src/commonJvmAndroid/kotlin/okhttp3/Dispatcher.kt#L98-L104). + * + * This class takes ownership of the executor service and shuts it down when closed. + */ + fun dispatcherExecutorService(dispatcherExecutorService: ExecutorService?) = apply { + this.dispatcherExecutorService = dispatcherExecutorService + } + + /** + * Alias for calling [Builder.dispatcherExecutorService] with + * `dispatcherExecutorService.orElse(null)`. + */ + fun dispatcherExecutorService(dispatcherExecutorService: Optional) = + dispatcherExecutorService(dispatcherExecutorService.getOrNull()) + fun proxy(proxy: Proxy?) = apply { this.proxy = proxy } /** Alias for calling [Builder.proxy] with `proxy.orElse(null)`. */ @@ -309,6 +330,7 @@ class EInvoiceOkHttpClientAsync private constructor() { OkHttpClient.builder() .timeout(clientOptions.timeout()) .proxy(proxy) + .dispatcherExecutorService(dispatcherExecutorService) .sslSocketFactory(sslSocketFactory) .trustManager(trustManager) .hostnameVerifier(hostnameVerifier) diff --git a/e-invoice-java-client-okhttp/src/main/kotlin/com/e_invoice/api/client/okhttp/OkHttpClient.kt b/e-invoice-java-client-okhttp/src/main/kotlin/com/e_invoice/api/client/okhttp/OkHttpClient.kt index f3c8245..9d16508 100644 --- a/e-invoice-java-client-okhttp/src/main/kotlin/com/e_invoice/api/client/okhttp/OkHttpClient.kt +++ b/e-invoice-java-client-okhttp/src/main/kotlin/com/e_invoice/api/client/okhttp/OkHttpClient.kt @@ -13,12 +13,15 @@ import java.io.IOException import java.io.InputStream import java.net.Proxy import java.time.Duration +import java.util.concurrent.CancellationException import java.util.concurrent.CompletableFuture +import java.util.concurrent.ExecutorService import javax.net.ssl.HostnameVerifier import javax.net.ssl.SSLSocketFactory import javax.net.ssl.X509TrustManager import okhttp3.Call import okhttp3.Callback +import okhttp3.Dispatcher import okhttp3.HttpUrl.Companion.toHttpUrl import okhttp3.MediaType import okhttp3.MediaType.Companion.toMediaType @@ -29,8 +32,8 @@ import okhttp3.Response import okhttp3.logging.HttpLoggingInterceptor import okio.BufferedSink -class OkHttpClient private constructor(private val okHttpClient: okhttp3.OkHttpClient) : - HttpClient { +class OkHttpClient +private constructor(@JvmSynthetic internal val okHttpClient: okhttp3.OkHttpClient) : HttpClient { override fun execute(request: HttpRequest, requestOptions: RequestOptions): HttpResponse { val call = newCall(request, requestOptions) @@ -50,20 +53,25 @@ class OkHttpClient private constructor(private val okHttpClient: okhttp3.OkHttpC ): CompletableFuture { val future = CompletableFuture() - request.body?.run { future.whenComplete { _, _ -> close() } } - - newCall(request, requestOptions) - .enqueue( - object : Callback { - override fun onResponse(call: Call, response: Response) { - future.complete(response.toResponse()) - } + val call = newCall(request, requestOptions) + call.enqueue( + object : Callback { + override fun onResponse(call: Call, response: Response) { + future.complete(response.toResponse()) + } - override fun onFailure(call: Call, e: IOException) { - future.completeExceptionally(EInvoiceIoException("Request failed", e)) - } + override fun onFailure(call: Call, e: IOException) { + future.completeExceptionally(EInvoiceIoException("Request failed", e)) } - ) + } + ) + + future.whenComplete { _, e -> + if (e is CancellationException) { + call.cancel() + } + request.body?.close() + } return future } @@ -109,19 +117,19 @@ class OkHttpClient private constructor(private val okHttpClient: okhttp3.OkHttpC val builder = Request.Builder().url(toUrl()).method(method.name, body) headers.names().forEach { name -> - headers.values(name).forEach { builder.header(name, it) } + headers.values(name).forEach { builder.addHeader(name, it) } } if ( !headers.names().contains("X-Stainless-Read-Timeout") && client.readTimeoutMillis != 0 ) { - builder.header( + builder.addHeader( "X-Stainless-Read-Timeout", Duration.ofMillis(client.readTimeoutMillis.toLong()).seconds.toString(), ) } if (!headers.names().contains("X-Stainless-Timeout") && client.callTimeoutMillis != 0) { - builder.header( + builder.addHeader( "X-Stainless-Timeout", Duration.ofMillis(client.callTimeoutMillis.toLong()).seconds.toString(), ) @@ -192,6 +200,7 @@ class OkHttpClient private constructor(private val okHttpClient: okhttp3.OkHttpC private var timeout: Timeout = Timeout.default() private var proxy: Proxy? = null + private var dispatcherExecutorService: ExecutorService? = null private var sslSocketFactory: SSLSocketFactory? = null private var trustManager: X509TrustManager? = null private var hostnameVerifier: HostnameVerifier? = null @@ -202,6 +211,10 @@ class OkHttpClient private constructor(private val okHttpClient: okhttp3.OkHttpC fun proxy(proxy: Proxy?) = apply { this.proxy = proxy } + fun dispatcherExecutorService(dispatcherExecutorService: ExecutorService?) = apply { + this.dispatcherExecutorService = dispatcherExecutorService + } + fun sslSocketFactory(sslSocketFactory: SSLSocketFactory?) = apply { this.sslSocketFactory = sslSocketFactory } @@ -217,12 +230,16 @@ class OkHttpClient private constructor(private val okHttpClient: okhttp3.OkHttpC fun build(): OkHttpClient = OkHttpClient( okhttp3.OkHttpClient.Builder() + // `RetryingHttpClient` handles retries if the user enabled them. + .retryOnConnectionFailure(false) .connectTimeout(timeout.connect()) .readTimeout(timeout.read()) .writeTimeout(timeout.write()) .callTimeout(timeout.request()) .proxy(proxy) .apply { + dispatcherExecutorService?.let { dispatcher(Dispatcher(it)) } + val sslSocketFactory = sslSocketFactory val trustManager = trustManager if (sslSocketFactory != null && trustManager != null) { diff --git a/e-invoice-java-client-okhttp/src/test/kotlin/com/e_invoice/api/client/okhttp/OkHttpClientTest.kt b/e-invoice-java-client-okhttp/src/test/kotlin/com/e_invoice/api/client/okhttp/OkHttpClientTest.kt new file mode 100644 index 0000000..faec5b4 --- /dev/null +++ b/e-invoice-java-client-okhttp/src/test/kotlin/com/e_invoice/api/client/okhttp/OkHttpClientTest.kt @@ -0,0 +1,44 @@ +package com.e_invoice.api.client.okhttp + +import com.e_invoice.api.core.http.HttpMethod +import com.e_invoice.api.core.http.HttpRequest +import com.github.tomakehurst.wiremock.client.WireMock.* +import com.github.tomakehurst.wiremock.junit5.WireMockRuntimeInfo +import com.github.tomakehurst.wiremock.junit5.WireMockTest +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.parallel.ResourceLock + +@WireMockTest +@ResourceLock("https://github.com/wiremock/wiremock/issues/169") +internal class OkHttpClientTest { + + private lateinit var baseUrl: String + private lateinit var httpClient: OkHttpClient + + @BeforeEach + fun beforeEach(wmRuntimeInfo: WireMockRuntimeInfo) { + baseUrl = wmRuntimeInfo.httpBaseUrl + httpClient = OkHttpClient.builder().build() + } + + @Test + fun executeAsync_whenFutureCancelled_cancelsUnderlyingCall() { + stubFor(post(urlPathEqualTo("/something")).willReturn(ok())) + val responseFuture = + httpClient.executeAsync( + HttpRequest.builder() + .method(HttpMethod.POST) + .baseUrl(baseUrl) + .addPathSegment("something") + .build() + ) + val call = httpClient.okHttpClient.dispatcher.runningCalls().single() + + responseFuture.cancel(false) + + // Should have cancelled the underlying call + assertThat(call.isCanceled()).isTrue() + } +} diff --git a/e-invoice-java-core/build.gradle.kts b/e-invoice-java-core/build.gradle.kts index 50c3534..0465618 100644 --- a/e-invoice-java-core/build.gradle.kts +++ b/e-invoice-java-core/build.gradle.kts @@ -5,14 +5,16 @@ plugins { configurations.all { resolutionStrategy { - // Compile and test against a lower Jackson version to ensure we're compatible with it. - // We publish with a higher version (see below) to ensure users depend on a secure version by default. - force("com.fasterxml.jackson.core:jackson-core:2.13.4") - force("com.fasterxml.jackson.core:jackson-databind:2.13.4") - force("com.fasterxml.jackson.core:jackson-annotations:2.13.4") - force("com.fasterxml.jackson.datatype:jackson-datatype-jdk8:2.13.4") - force("com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.13.4") - force("com.fasterxml.jackson.module:jackson-module-kotlin:2.13.4") + // Compile and test against a lower Jackson version to ensure we're compatible with it. Note that + // we generally support 2.13.4, but test against 2.14.0 because 2.13.4 has some annoying (but + // niche) bugs (users should upgrade if they encounter them). We publish with a higher version + // (see below) to ensure users depend on a secure version by default. + force("com.fasterxml.jackson.core:jackson-core:2.14.0") + force("com.fasterxml.jackson.core:jackson-databind:2.14.0") + force("com.fasterxml.jackson.core:jackson-annotations:2.14.0") + force("com.fasterxml.jackson.datatype:jackson-datatype-jdk8:2.14.0") + force("com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.14.0") + force("com.fasterxml.jackson.module:jackson-module-kotlin:2.14.0") } } @@ -31,7 +33,7 @@ dependencies { testImplementation(kotlin("test")) testImplementation(project(":e-invoice-java-client-okhttp")) testImplementation("com.github.tomakehurst:wiremock-jre8:2.35.2") - testImplementation("org.assertj:assertj-core:3.25.3") + testImplementation("org.assertj:assertj-core:3.27.7") testImplementation("org.junit.jupiter:junit-jupiter-api:5.9.3") testImplementation("org.junit.jupiter:junit-jupiter-params:5.9.3") testImplementation("org.junit-pioneer:junit-pioneer:1.9.1") diff --git a/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/client/EInvoiceClient.kt b/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/client/EInvoiceClient.kt index bdb63cf..a542ec7 100644 --- a/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/client/EInvoiceClient.kt +++ b/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/client/EInvoiceClient.kt @@ -6,6 +6,7 @@ import com.e_invoice.api.core.ClientOptions import com.e_invoice.api.services.blocking.DocumentService import com.e_invoice.api.services.blocking.InboxService import com.e_invoice.api.services.blocking.LookupService +import com.e_invoice.api.services.blocking.MeService import com.e_invoice.api.services.blocking.OutboxService import com.e_invoice.api.services.blocking.ValidateService import com.e_invoice.api.services.blocking.WebhookService @@ -57,6 +58,8 @@ interface EInvoiceClient { fun lookup(): LookupService + fun me(): MeService + fun webhooks(): WebhookService /** @@ -92,6 +95,8 @@ interface EInvoiceClient { fun lookup(): LookupService.WithRawResponse + fun me(): MeService.WithRawResponse + fun webhooks(): WebhookService.WithRawResponse } } diff --git a/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/client/EInvoiceClientAsync.kt b/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/client/EInvoiceClientAsync.kt index 41b20ab..5fed5d0 100644 --- a/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/client/EInvoiceClientAsync.kt +++ b/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/client/EInvoiceClientAsync.kt @@ -6,6 +6,7 @@ import com.e_invoice.api.core.ClientOptions import com.e_invoice.api.services.async.DocumentServiceAsync import com.e_invoice.api.services.async.InboxServiceAsync import com.e_invoice.api.services.async.LookupServiceAsync +import com.e_invoice.api.services.async.MeServiceAsync import com.e_invoice.api.services.async.OutboxServiceAsync import com.e_invoice.api.services.async.ValidateServiceAsync import com.e_invoice.api.services.async.WebhookServiceAsync @@ -57,6 +58,8 @@ interface EInvoiceClientAsync { fun lookup(): LookupServiceAsync + fun me(): MeServiceAsync + fun webhooks(): WebhookServiceAsync /** @@ -96,6 +99,8 @@ interface EInvoiceClientAsync { fun lookup(): LookupServiceAsync.WithRawResponse + fun me(): MeServiceAsync.WithRawResponse + fun webhooks(): WebhookServiceAsync.WithRawResponse } } diff --git a/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/client/EInvoiceClientAsyncImpl.kt b/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/client/EInvoiceClientAsyncImpl.kt index 68f8a26..4c1c28a 100644 --- a/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/client/EInvoiceClientAsyncImpl.kt +++ b/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/client/EInvoiceClientAsyncImpl.kt @@ -10,6 +10,8 @@ import com.e_invoice.api.services.async.InboxServiceAsync import com.e_invoice.api.services.async.InboxServiceAsyncImpl import com.e_invoice.api.services.async.LookupServiceAsync import com.e_invoice.api.services.async.LookupServiceAsyncImpl +import com.e_invoice.api.services.async.MeServiceAsync +import com.e_invoice.api.services.async.MeServiceAsyncImpl import com.e_invoice.api.services.async.OutboxServiceAsync import com.e_invoice.api.services.async.OutboxServiceAsyncImpl import com.e_invoice.api.services.async.ValidateServiceAsync @@ -55,6 +57,8 @@ class EInvoiceClientAsyncImpl(private val clientOptions: ClientOptions) : EInvoi LookupServiceAsyncImpl(clientOptionsWithUserAgent) } + private val me: MeServiceAsync by lazy { MeServiceAsyncImpl(clientOptionsWithUserAgent) } + private val webhooks: WebhookServiceAsync by lazy { WebhookServiceAsyncImpl(clientOptionsWithUserAgent) } @@ -76,6 +80,8 @@ class EInvoiceClientAsyncImpl(private val clientOptions: ClientOptions) : EInvoi override fun lookup(): LookupServiceAsync = lookup + override fun me(): MeServiceAsync = me + override fun webhooks(): WebhookServiceAsync = webhooks override fun close() = clientOptions.close() @@ -103,6 +109,10 @@ class EInvoiceClientAsyncImpl(private val clientOptions: ClientOptions) : EInvoi LookupServiceAsyncImpl.WithRawResponseImpl(clientOptions) } + private val me: MeServiceAsync.WithRawResponse by lazy { + MeServiceAsyncImpl.WithRawResponseImpl(clientOptions) + } + private val webhooks: WebhookServiceAsync.WithRawResponse by lazy { WebhookServiceAsyncImpl.WithRawResponseImpl(clientOptions) } @@ -124,6 +134,8 @@ class EInvoiceClientAsyncImpl(private val clientOptions: ClientOptions) : EInvoi override fun lookup(): LookupServiceAsync.WithRawResponse = lookup + override fun me(): MeServiceAsync.WithRawResponse = me + override fun webhooks(): WebhookServiceAsync.WithRawResponse = webhooks } } diff --git a/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/client/EInvoiceClientImpl.kt b/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/client/EInvoiceClientImpl.kt index ecf0dc0..ff71e20 100644 --- a/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/client/EInvoiceClientImpl.kt +++ b/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/client/EInvoiceClientImpl.kt @@ -10,6 +10,8 @@ import com.e_invoice.api.services.blocking.InboxService import com.e_invoice.api.services.blocking.InboxServiceImpl import com.e_invoice.api.services.blocking.LookupService import com.e_invoice.api.services.blocking.LookupServiceImpl +import com.e_invoice.api.services.blocking.MeService +import com.e_invoice.api.services.blocking.MeServiceImpl import com.e_invoice.api.services.blocking.OutboxService import com.e_invoice.api.services.blocking.OutboxServiceImpl import com.e_invoice.api.services.blocking.ValidateService @@ -49,6 +51,8 @@ class EInvoiceClientImpl(private val clientOptions: ClientOptions) : EInvoiceCli private val lookup: LookupService by lazy { LookupServiceImpl(clientOptionsWithUserAgent) } + private val me: MeService by lazy { MeServiceImpl(clientOptionsWithUserAgent) } + private val webhooks: WebhookService by lazy { WebhookServiceImpl(clientOptionsWithUserAgent) } override fun async(): EInvoiceClientAsync = async @@ -68,6 +72,8 @@ class EInvoiceClientImpl(private val clientOptions: ClientOptions) : EInvoiceCli override fun lookup(): LookupService = lookup + override fun me(): MeService = me + override fun webhooks(): WebhookService = webhooks override fun close() = clientOptions.close() @@ -95,6 +101,10 @@ class EInvoiceClientImpl(private val clientOptions: ClientOptions) : EInvoiceCli LookupServiceImpl.WithRawResponseImpl(clientOptions) } + private val me: MeService.WithRawResponse by lazy { + MeServiceImpl.WithRawResponseImpl(clientOptions) + } + private val webhooks: WebhookService.WithRawResponse by lazy { WebhookServiceImpl.WithRawResponseImpl(clientOptions) } @@ -116,6 +126,8 @@ class EInvoiceClientImpl(private val clientOptions: ClientOptions) : EInvoiceCli override fun lookup(): LookupService.WithRawResponse = lookup + override fun me(): MeService.WithRawResponse = me + override fun webhooks(): WebhookService.WithRawResponse = webhooks } } diff --git a/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/core/ClientOptions.kt b/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/core/ClientOptions.kt index 2586a9d..a29ecb3 100644 --- a/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/core/ClientOptions.kt +++ b/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/core/ClientOptions.kt @@ -450,6 +450,7 @@ private constructor( headers.put("X-Stainless-Package-Version", getPackageVersion()) headers.put("X-Stainless-Runtime", "JRE") headers.put("X-Stainless-Runtime-Version", getJavaVersion()) + headers.put("X-Stainless-Kotlin-Version", KotlinVersion.CURRENT.toString()) apiKey.let { if (!it.isEmpty()) { headers.put("Authorization", "Bearer $it") diff --git a/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/core/ObjectMappers.kt b/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/core/ObjectMappers.kt index 50e9584..54ad6ad 100644 --- a/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/core/ObjectMappers.kt +++ b/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/core/ObjectMappers.kt @@ -24,7 +24,8 @@ import java.io.InputStream import java.time.DateTimeException import java.time.LocalDate import java.time.LocalDateTime -import java.time.ZonedDateTime +import java.time.OffsetDateTime +import java.time.ZoneId import java.time.format.DateTimeFormatter import java.time.temporal.ChronoField @@ -36,7 +37,7 @@ fun jsonMapper(): JsonMapper = .addModule( SimpleModule() .addSerializer(InputStreamSerializer) - .addDeserializer(LocalDateTime::class.java, LenientLocalDateTimeDeserializer()) + .addDeserializer(OffsetDateTime::class.java, LenientOffsetDateTimeDeserializer()) ) .withCoercionConfig(LogicalType.Boolean) { it.setCoercion(CoercionInputShape.Integer, CoercionAction.Fail) @@ -47,6 +48,7 @@ fun jsonMapper(): JsonMapper = } .withCoercionConfig(LogicalType.Integer) { it.setCoercion(CoercionInputShape.Boolean, CoercionAction.Fail) + .setCoercion(CoercionInputShape.Float, CoercionAction.Fail) .setCoercion(CoercionInputShape.String, CoercionAction.Fail) .setCoercion(CoercionInputShape.Array, CoercionAction.Fail) .setCoercion(CoercionInputShape.Object, CoercionAction.Fail) @@ -64,6 +66,12 @@ fun jsonMapper(): JsonMapper = .setCoercion(CoercionInputShape.Array, CoercionAction.Fail) .setCoercion(CoercionInputShape.Object, CoercionAction.Fail) } + .withCoercionConfig(LogicalType.DateTime) { + it.setCoercion(CoercionInputShape.Integer, CoercionAction.Fail) + .setCoercion(CoercionInputShape.Float, CoercionAction.Fail) + .setCoercion(CoercionInputShape.Array, CoercionAction.Fail) + .setCoercion(CoercionInputShape.Object, CoercionAction.Fail) + } .withCoercionConfig(LogicalType.Array) { it.setCoercion(CoercionInputShape.Boolean, CoercionAction.Fail) .setCoercion(CoercionInputShape.Integer, CoercionAction.Fail) @@ -124,10 +132,10 @@ private object InputStreamSerializer : BaseSerializer(InputStream:: } /** - * A deserializer that can deserialize [LocalDateTime] from datetimes, dates, and zoned datetimes. + * A deserializer that can deserialize [OffsetDateTime] from datetimes, dates, and zoned datetimes. */ -private class LenientLocalDateTimeDeserializer : - StdDeserializer(LocalDateTime::class.java) { +private class LenientOffsetDateTimeDeserializer : + StdDeserializer(OffsetDateTime::class.java) { companion object { @@ -141,7 +149,7 @@ private class LenientLocalDateTimeDeserializer : override fun logicalType(): LogicalType = LogicalType.DateTime - override fun deserialize(p: JsonParser, context: DeserializationContext?): LocalDateTime { + override fun deserialize(p: JsonParser, context: DeserializationContext): OffsetDateTime { val exceptions = mutableListOf() for (formatter in DATE_TIME_FORMATTERS) { @@ -150,17 +158,20 @@ private class LenientLocalDateTimeDeserializer : return when { !temporal.isSupported(ChronoField.HOUR_OF_DAY) -> - LocalDate.from(temporal).atStartOfDay() + LocalDate.from(temporal) + .atStartOfDay() + .atZone(ZoneId.of("UTC")) + .toOffsetDateTime() !temporal.isSupported(ChronoField.OFFSET_SECONDS) -> - LocalDateTime.from(temporal) - else -> ZonedDateTime.from(temporal).toLocalDateTime() + LocalDateTime.from(temporal).atZone(ZoneId.of("UTC")).toOffsetDateTime() + else -> OffsetDateTime.from(temporal) } } catch (e: DateTimeException) { exceptions.add(e) } } - throw JsonParseException(p, "Cannot parse `LocalDateTime` from value: ${p.text}").apply { + throw JsonParseException(p, "Cannot parse `OffsetDateTime` from value: ${p.text}").apply { exceptions.forEach { addSuppressed(it) } } } diff --git a/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/core/http/HttpRequest.kt b/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/core/http/HttpRequest.kt index 9a52e88..9a0db4d 100644 --- a/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/core/http/HttpRequest.kt +++ b/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/core/http/HttpRequest.kt @@ -2,6 +2,7 @@ package com.e_invoice.api.core.http import com.e_invoice.api.core.checkRequired import com.e_invoice.api.core.toImmutable +import java.net.URLEncoder class HttpRequest private constructor( @@ -13,6 +14,35 @@ private constructor( @get:JvmName("body") val body: HttpRequestBody?, ) { + fun url(): String = buildString { + append(baseUrl) + + pathSegments.forEach { segment -> + if (!endsWith("/")) { + append("/") + } + append(URLEncoder.encode(segment, "UTF-8")) + } + + if (queryParams.isEmpty()) { + return@buildString + } + + append("?") + var isFirst = true + queryParams.keys().forEach { key -> + queryParams.values(key).forEach { value -> + if (!isFirst) { + append("&") + } + append(URLEncoder.encode(key, "UTF-8")) + append("=") + append(URLEncoder.encode(value, "UTF-8")) + isFirst = false + } + } + } + fun toBuilder(): Builder = Builder().from(this) override fun toString(): String = diff --git a/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/core/http/RetryingHttpClient.kt b/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/core/http/RetryingHttpClient.kt index be62ba9..db2fef5 100644 --- a/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/core/http/RetryingHttpClient.kt +++ b/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/core/http/RetryingHttpClient.kt @@ -31,10 +31,6 @@ private constructor( ) : HttpClient { override fun execute(request: HttpRequest, requestOptions: RequestOptions): HttpResponse { - if (!isRetryable(request) || maxRetries <= 0) { - return httpClient.execute(request, requestOptions) - } - var modifiedRequest = maybeAddIdempotencyHeader(request) // Don't send the current retry count in the headers if the caller set their own value. @@ -48,6 +44,10 @@ private constructor( modifiedRequest = setRetryCountHeader(modifiedRequest, retries) } + if (!isRetryable(modifiedRequest)) { + return httpClient.execute(modifiedRequest, requestOptions) + } + val response = try { val response = httpClient.execute(modifiedRequest, requestOptions) @@ -75,10 +75,6 @@ private constructor( request: HttpRequest, requestOptions: RequestOptions, ): CompletableFuture { - if (!isRetryable(request) || maxRetries <= 0) { - return httpClient.executeAsync(request, requestOptions) - } - val modifiedRequest = maybeAddIdempotencyHeader(request) // Don't send the current retry count in the headers if the caller set their own value. @@ -94,8 +90,12 @@ private constructor( val requestWithRetryCount = if (shouldSendRetryCount) setRetryCountHeader(request, retries) else request - return httpClient - .executeAsync(requestWithRetryCount, requestOptions) + val responseFuture = httpClient.executeAsync(requestWithRetryCount, requestOptions) + if (!isRetryable(requestWithRetryCount)) { + return responseFuture + } + + return responseFuture .handleAsync( fun( response: HttpResponse?, diff --git a/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/models/documents/Allowance.kt b/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/models/documents/Allowance.kt new file mode 100644 index 0000000..0351698 --- /dev/null +++ b/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/models/documents/Allowance.kt @@ -0,0 +1,845 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.e_invoice.api.models.documents + +import com.e_invoice.api.core.Enum +import com.e_invoice.api.core.ExcludeMissing +import com.e_invoice.api.core.JsonField +import com.e_invoice.api.core.JsonMissing +import com.e_invoice.api.core.JsonValue +import com.e_invoice.api.errors.EInvoiceInvalidDataException +import com.fasterxml.jackson.annotation.JsonAnyGetter +import com.fasterxml.jackson.annotation.JsonAnySetter +import com.fasterxml.jackson.annotation.JsonCreator +import com.fasterxml.jackson.annotation.JsonProperty +import java.util.Collections +import java.util.Objects +import java.util.Optional +import kotlin.jvm.optionals.getOrNull + +/** An allowance is a discount for example for early payment, volume discount, etc. */ +class Allowance +@JsonCreator(mode = JsonCreator.Mode.DISABLED) +private constructor( + private val amount: JsonField, + private val baseAmount: JsonField, + private val multiplierFactor: JsonField, + private val reason: JsonField, + private val reasonCode: JsonField, + private val taxCode: JsonField, + private val taxRate: JsonField, + private val additionalProperties: MutableMap, +) { + + @JsonCreator + private constructor( + @JsonProperty("amount") @ExcludeMissing amount: JsonField = JsonMissing.of(), + @JsonProperty("base_amount") + @ExcludeMissing + baseAmount: JsonField = JsonMissing.of(), + @JsonProperty("multiplier_factor") + @ExcludeMissing + multiplierFactor: JsonField = JsonMissing.of(), + @JsonProperty("reason") @ExcludeMissing reason: JsonField = JsonMissing.of(), + @JsonProperty("reason_code") + @ExcludeMissing + reasonCode: JsonField = JsonMissing.of(), + @JsonProperty("tax_code") @ExcludeMissing taxCode: JsonField = JsonMissing.of(), + @JsonProperty("tax_rate") @ExcludeMissing taxRate: JsonField = JsonMissing.of(), + ) : this( + amount, + baseAmount, + multiplierFactor, + reason, + reasonCode, + taxCode, + taxRate, + mutableMapOf(), + ) + + /** + * The allowance amount, without VAT. Must be rounded to maximum 2 decimals + * + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun amount(): Optional = amount.getOptional("amount") + + /** + * The base amount that may be used, in conjunction with the allowance percentage, to calculate + * the allowance amount. Must be rounded to maximum 2 decimals + * + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun baseAmount(): Optional = baseAmount.getOptional("base_amount") + + /** + * The percentage that may be used, in conjunction with the allowance base amount, to calculate + * the allowance amount. To state 20%, use value 20. Must be rounded to maximum 2 decimals + * + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun multiplierFactor(): Optional = multiplierFactor.getOptional("multiplier_factor") + + /** + * The reason for the allowance + * + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun reason(): Optional = reason.getOptional("reason") + + /** + * Allowance reason codes for invoice discounts and charges + * + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun reasonCode(): Optional = reasonCode.getOptional("reason_code") + + /** + * The VAT category code that applies to the allowance + * + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun taxCode(): Optional = taxCode.getOptional("tax_code") + + /** + * The VAT rate, represented as percentage that applies to the allowance. Must be rounded to + * maximum 2 decimals + * + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun taxRate(): Optional = taxRate.getOptional("tax_rate") + + /** + * Returns the raw JSON value of [amount]. + * + * Unlike [amount], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("amount") @ExcludeMissing fun _amount(): JsonField = amount + + /** + * Returns the raw JSON value of [baseAmount]. + * + * Unlike [baseAmount], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("base_amount") @ExcludeMissing fun _baseAmount(): JsonField = baseAmount + + /** + * Returns the raw JSON value of [multiplierFactor]. + * + * Unlike [multiplierFactor], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("multiplier_factor") + @ExcludeMissing + fun _multiplierFactor(): JsonField = multiplierFactor + + /** + * Returns the raw JSON value of [reason]. + * + * Unlike [reason], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("reason") @ExcludeMissing fun _reason(): JsonField = reason + + /** + * Returns the raw JSON value of [reasonCode]. + * + * Unlike [reasonCode], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("reason_code") + @ExcludeMissing + fun _reasonCode(): JsonField = reasonCode + + /** + * Returns the raw JSON value of [taxCode]. + * + * Unlike [taxCode], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("tax_code") @ExcludeMissing fun _taxCode(): JsonField = taxCode + + /** + * Returns the raw JSON value of [taxRate]. + * + * Unlike [taxRate], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("tax_rate") @ExcludeMissing fun _taxRate(): JsonField = taxRate + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** Returns a mutable builder for constructing an instance of [Allowance]. */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [Allowance]. */ + class Builder internal constructor() { + + private var amount: JsonField = JsonMissing.of() + private var baseAmount: JsonField = JsonMissing.of() + private var multiplierFactor: JsonField = JsonMissing.of() + private var reason: JsonField = JsonMissing.of() + private var reasonCode: JsonField = JsonMissing.of() + private var taxCode: JsonField = JsonMissing.of() + private var taxRate: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(allowance: Allowance) = apply { + amount = allowance.amount + baseAmount = allowance.baseAmount + multiplierFactor = allowance.multiplierFactor + reason = allowance.reason + reasonCode = allowance.reasonCode + taxCode = allowance.taxCode + taxRate = allowance.taxRate + additionalProperties = allowance.additionalProperties.toMutableMap() + } + + /** The allowance amount, without VAT. Must be rounded to maximum 2 decimals */ + fun amount(amount: String?) = amount(JsonField.ofNullable(amount)) + + /** Alias for calling [Builder.amount] with `amount.orElse(null)`. */ + fun amount(amount: Optional) = amount(amount.getOrNull()) + + /** + * Sets [Builder.amount] to an arbitrary JSON value. + * + * You should usually call [Builder.amount] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun amount(amount: JsonField) = apply { this.amount = amount } + + /** + * The base amount that may be used, in conjunction with the allowance percentage, to + * calculate the allowance amount. Must be rounded to maximum 2 decimals + */ + fun baseAmount(baseAmount: String?) = baseAmount(JsonField.ofNullable(baseAmount)) + + /** Alias for calling [Builder.baseAmount] with `baseAmount.orElse(null)`. */ + fun baseAmount(baseAmount: Optional) = baseAmount(baseAmount.getOrNull()) + + /** + * Sets [Builder.baseAmount] to an arbitrary JSON value. + * + * You should usually call [Builder.baseAmount] with a well-typed [String] value instead. + * This method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun baseAmount(baseAmount: JsonField) = apply { this.baseAmount = baseAmount } + + /** + * The percentage that may be used, in conjunction with the allowance base amount, to + * calculate the allowance amount. To state 20%, use value 20. Must be rounded to maximum 2 + * decimals + */ + fun multiplierFactor(multiplierFactor: String?) = + multiplierFactor(JsonField.ofNullable(multiplierFactor)) + + /** Alias for calling [Builder.multiplierFactor] with `multiplierFactor.orElse(null)`. */ + fun multiplierFactor(multiplierFactor: Optional) = + multiplierFactor(multiplierFactor.getOrNull()) + + /** + * Sets [Builder.multiplierFactor] to an arbitrary JSON value. + * + * You should usually call [Builder.multiplierFactor] with a well-typed [String] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun multiplierFactor(multiplierFactor: JsonField) = apply { + this.multiplierFactor = multiplierFactor + } + + /** The reason for the allowance */ + fun reason(reason: String?) = reason(JsonField.ofNullable(reason)) + + /** Alias for calling [Builder.reason] with `reason.orElse(null)`. */ + fun reason(reason: Optional) = reason(reason.getOrNull()) + + /** + * Sets [Builder.reason] to an arbitrary JSON value. + * + * You should usually call [Builder.reason] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun reason(reason: JsonField) = apply { this.reason = reason } + + /** Allowance reason codes for invoice discounts and charges */ + fun reasonCode(reasonCode: ReasonCode?) = reasonCode(JsonField.ofNullable(reasonCode)) + + /** Alias for calling [Builder.reasonCode] with `reasonCode.orElse(null)`. */ + fun reasonCode(reasonCode: Optional) = reasonCode(reasonCode.getOrNull()) + + /** + * Sets [Builder.reasonCode] to an arbitrary JSON value. + * + * You should usually call [Builder.reasonCode] with a well-typed [ReasonCode] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun reasonCode(reasonCode: JsonField) = apply { this.reasonCode = reasonCode } + + /** The VAT category code that applies to the allowance */ + fun taxCode(taxCode: TaxCode) = taxCode(JsonField.of(taxCode)) + + /** + * Sets [Builder.taxCode] to an arbitrary JSON value. + * + * You should usually call [Builder.taxCode] with a well-typed [TaxCode] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun taxCode(taxCode: JsonField) = apply { this.taxCode = taxCode } + + /** + * The VAT rate, represented as percentage that applies to the allowance. Must be rounded to + * maximum 2 decimals + */ + fun taxRate(taxRate: String?) = taxRate(JsonField.ofNullable(taxRate)) + + /** Alias for calling [Builder.taxRate] with `taxRate.orElse(null)`. */ + fun taxRate(taxRate: Optional) = taxRate(taxRate.getOrNull()) + + /** + * Sets [Builder.taxRate] to an arbitrary JSON value. + * + * You should usually call [Builder.taxRate] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun taxRate(taxRate: JsonField) = apply { this.taxRate = taxRate } + + fun additionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.clear() + putAllAdditionalProperties(additionalProperties) + } + + fun putAdditionalProperty(key: String, value: JsonValue) = apply { + additionalProperties.put(key, value) + } + + fun putAllAdditionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.putAll(additionalProperties) + } + + fun removeAdditionalProperty(key: String) = apply { additionalProperties.remove(key) } + + fun removeAllAdditionalProperties(keys: Set) = apply { + keys.forEach(::removeAdditionalProperty) + } + + /** + * Returns an immutable instance of [Allowance]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): Allowance = + Allowance( + amount, + baseAmount, + multiplierFactor, + reason, + reasonCode, + taxCode, + taxRate, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + fun validate(): Allowance = apply { + if (validated) { + return@apply + } + + amount() + baseAmount() + multiplierFactor() + reason() + reasonCode().ifPresent { it.validate() } + taxCode().ifPresent { it.validate() } + taxRate() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: EInvoiceInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic + internal fun validity(): Int = + (if (amount.asKnown().isPresent) 1 else 0) + + (if (baseAmount.asKnown().isPresent) 1 else 0) + + (if (multiplierFactor.asKnown().isPresent) 1 else 0) + + (if (reason.asKnown().isPresent) 1 else 0) + + (reasonCode.asKnown().getOrNull()?.validity() ?: 0) + + (taxCode.asKnown().getOrNull()?.validity() ?: 0) + + (if (taxRate.asKnown().isPresent) 1 else 0) + + /** Allowance reason codes for invoice discounts and charges */ + class ReasonCode @JsonCreator private constructor(private val value: JsonField) : Enum { + + /** + * Returns this class instance's raw value. + * + * This is usually only useful if this instance was deserialized from data that doesn't + * match any known member, and you want to know that value. For example, if the SDK is on an + * older version than the API, then the API may respond with new members that the SDK is + * unaware of. + */ + @com.fasterxml.jackson.annotation.JsonValue fun _value(): JsonField = value + + companion object { + + @JvmField val _41 = of("41") + + @JvmField val _42 = of("42") + + @JvmField val _60 = of("60") + + @JvmField val _62 = of("62") + + @JvmField val _63 = of("63") + + @JvmField val _64 = of("64") + + @JvmField val _65 = of("65") + + @JvmField val _66 = of("66") + + @JvmField val _67 = of("67") + + @JvmField val _68 = of("68") + + @JvmField val _70 = of("70") + + @JvmField val _71 = of("71") + + @JvmField val _88 = of("88") + + @JvmField val _95 = of("95") + + @JvmField val _100 = of("100") + + @JvmField val _102 = of("102") + + @JvmField val _103 = of("103") + + @JvmField val _104 = of("104") + + @JvmField val _105 = of("105") + + @JvmStatic fun of(value: String) = ReasonCode(JsonField.of(value)) + } + + /** An enum containing [ReasonCode]'s known values. */ + enum class Known { + _41, + _42, + _60, + _62, + _63, + _64, + _65, + _66, + _67, + _68, + _70, + _71, + _88, + _95, + _100, + _102, + _103, + _104, + _105, + } + + /** + * An enum containing [ReasonCode]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [ReasonCode] can contain an unknown value in a couple of cases: + * - It was deserialized from data that doesn't match any known member. For example, if the + * SDK is on an older version than the API, then the API may respond with new members that + * the SDK is unaware of. + * - It was constructed with an arbitrary value using the [of] method. + */ + enum class Value { + _41, + _42, + _60, + _62, + _63, + _64, + _65, + _66, + _67, + _68, + _70, + _71, + _88, + _95, + _100, + _102, + _103, + _104, + _105, + /** + * An enum member indicating that [ReasonCode] was instantiated with an unknown value. + */ + _UNKNOWN, + } + + /** + * Returns an enum member corresponding to this class instance's value, or [Value._UNKNOWN] + * if the class was instantiated with an unknown value. + * + * Use the [known] method instead if you're certain the value is always known or if you want + * to throw for the unknown case. + */ + fun value(): Value = + when (this) { + _41 -> Value._41 + _42 -> Value._42 + _60 -> Value._60 + _62 -> Value._62 + _63 -> Value._63 + _64 -> Value._64 + _65 -> Value._65 + _66 -> Value._66 + _67 -> Value._67 + _68 -> Value._68 + _70 -> Value._70 + _71 -> Value._71 + _88 -> Value._88 + _95 -> Value._95 + _100 -> Value._100 + _102 -> Value._102 + _103 -> Value._103 + _104 -> Value._104 + _105 -> Value._105 + else -> Value._UNKNOWN + } + + /** + * Returns an enum member corresponding to this class instance's value. + * + * Use the [value] method instead if you're uncertain the value is always known and don't + * want to throw for the unknown case. + * + * @throws EInvoiceInvalidDataException if this class instance's value is a not a known + * member. + */ + fun known(): Known = + when (this) { + _41 -> Known._41 + _42 -> Known._42 + _60 -> Known._60 + _62 -> Known._62 + _63 -> Known._63 + _64 -> Known._64 + _65 -> Known._65 + _66 -> Known._66 + _67 -> Known._67 + _68 -> Known._68 + _70 -> Known._70 + _71 -> Known._71 + _88 -> Known._88 + _95 -> Known._95 + _100 -> Known._100 + _102 -> Known._102 + _103 -> Known._103 + _104 -> Known._104 + _105 -> Known._105 + else -> throw EInvoiceInvalidDataException("Unknown ReasonCode: $value") + } + + /** + * Returns this class instance's primitive wire representation. + * + * This differs from the [toString] method because that method is primarily for debugging + * and generally doesn't throw. + * + * @throws EInvoiceInvalidDataException if this class instance's value does not have the + * expected primitive type. + */ + fun asString(): String = + _value().asString().orElseThrow { + EInvoiceInvalidDataException("Value is not a String") + } + + private var validated: Boolean = false + + fun validate(): ReasonCode = apply { + if (validated) { + return@apply + } + + known() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: EInvoiceInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic internal fun validity(): Int = if (value() == Value._UNKNOWN) 0 else 1 + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is ReasonCode && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + /** The VAT category code that applies to the allowance */ + class TaxCode @JsonCreator private constructor(private val value: JsonField) : Enum { + + /** + * Returns this class instance's raw value. + * + * This is usually only useful if this instance was deserialized from data that doesn't + * match any known member, and you want to know that value. For example, if the SDK is on an + * older version than the API, then the API may respond with new members that the SDK is + * unaware of. + */ + @com.fasterxml.jackson.annotation.JsonValue fun _value(): JsonField = value + + companion object { + + @JvmField val AE = of("AE") + + @JvmField val E = of("E") + + @JvmField val S = of("S") + + @JvmField val Z = of("Z") + + @JvmField val G = of("G") + + @JvmField val O = of("O") + + @JvmField val K = of("K") + + @JvmField val L = of("L") + + @JvmField val M = of("M") + + @JvmField val B = of("B") + + @JvmStatic fun of(value: String) = TaxCode(JsonField.of(value)) + } + + /** An enum containing [TaxCode]'s known values. */ + enum class Known { + AE, + E, + S, + Z, + G, + O, + K, + L, + M, + B, + } + + /** + * An enum containing [TaxCode]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [TaxCode] can contain an unknown value in a couple of cases: + * - It was deserialized from data that doesn't match any known member. For example, if the + * SDK is on an older version than the API, then the API may respond with new members that + * the SDK is unaware of. + * - It was constructed with an arbitrary value using the [of] method. + */ + enum class Value { + AE, + E, + S, + Z, + G, + O, + K, + L, + M, + B, + /** An enum member indicating that [TaxCode] was instantiated with an unknown value. */ + _UNKNOWN, + } + + /** + * Returns an enum member corresponding to this class instance's value, or [Value._UNKNOWN] + * if the class was instantiated with an unknown value. + * + * Use the [known] method instead if you're certain the value is always known or if you want + * to throw for the unknown case. + */ + fun value(): Value = + when (this) { + AE -> Value.AE + E -> Value.E + S -> Value.S + Z -> Value.Z + G -> Value.G + O -> Value.O + K -> Value.K + L -> Value.L + M -> Value.M + B -> Value.B + else -> Value._UNKNOWN + } + + /** + * Returns an enum member corresponding to this class instance's value. + * + * Use the [value] method instead if you're uncertain the value is always known and don't + * want to throw for the unknown case. + * + * @throws EInvoiceInvalidDataException if this class instance's value is a not a known + * member. + */ + fun known(): Known = + when (this) { + AE -> Known.AE + E -> Known.E + S -> Known.S + Z -> Known.Z + G -> Known.G + O -> Known.O + K -> Known.K + L -> Known.L + M -> Known.M + B -> Known.B + else -> throw EInvoiceInvalidDataException("Unknown TaxCode: $value") + } + + /** + * Returns this class instance's primitive wire representation. + * + * This differs from the [toString] method because that method is primarily for debugging + * and generally doesn't throw. + * + * @throws EInvoiceInvalidDataException if this class instance's value does not have the + * expected primitive type. + */ + fun asString(): String = + _value().asString().orElseThrow { + EInvoiceInvalidDataException("Value is not a String") + } + + private var validated: Boolean = false + + fun validate(): TaxCode = apply { + if (validated) { + return@apply + } + + known() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: EInvoiceInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic internal fun validity(): Int = if (value() == Value._UNKNOWN) 0 else 1 + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is TaxCode && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Allowance && + amount == other.amount && + baseAmount == other.baseAmount && + multiplierFactor == other.multiplierFactor && + reason == other.reason && + reasonCode == other.reasonCode && + taxCode == other.taxCode && + taxRate == other.taxRate && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash( + amount, + baseAmount, + multiplierFactor, + reason, + reasonCode, + taxCode, + taxRate, + additionalProperties, + ) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "Allowance{amount=$amount, baseAmount=$baseAmount, multiplierFactor=$multiplierFactor, reason=$reason, reasonCode=$reasonCode, taxCode=$taxCode, taxRate=$taxRate, additionalProperties=$additionalProperties}" +} diff --git a/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/models/documents/Charge.kt b/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/models/documents/Charge.kt new file mode 100644 index 0000000..45e1ce7 --- /dev/null +++ b/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/models/documents/Charge.kt @@ -0,0 +1,1807 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.e_invoice.api.models.documents + +import com.e_invoice.api.core.Enum +import com.e_invoice.api.core.ExcludeMissing +import com.e_invoice.api.core.JsonField +import com.e_invoice.api.core.JsonMissing +import com.e_invoice.api.core.JsonValue +import com.e_invoice.api.errors.EInvoiceInvalidDataException +import com.fasterxml.jackson.annotation.JsonAnyGetter +import com.fasterxml.jackson.annotation.JsonAnySetter +import com.fasterxml.jackson.annotation.JsonCreator +import com.fasterxml.jackson.annotation.JsonProperty +import java.util.Collections +import java.util.Objects +import java.util.Optional +import kotlin.jvm.optionals.getOrNull + +/** A charge is an additional fee for example for late payment, late delivery, etc. */ +class Charge +@JsonCreator(mode = JsonCreator.Mode.DISABLED) +private constructor( + private val amount: JsonField, + private val baseAmount: JsonField, + private val multiplierFactor: JsonField, + private val reason: JsonField, + private val reasonCode: JsonField, + private val taxCode: JsonField, + private val taxRate: JsonField, + private val additionalProperties: MutableMap, +) { + + @JsonCreator + private constructor( + @JsonProperty("amount") @ExcludeMissing amount: JsonField = JsonMissing.of(), + @JsonProperty("base_amount") + @ExcludeMissing + baseAmount: JsonField = JsonMissing.of(), + @JsonProperty("multiplier_factor") + @ExcludeMissing + multiplierFactor: JsonField = JsonMissing.of(), + @JsonProperty("reason") @ExcludeMissing reason: JsonField = JsonMissing.of(), + @JsonProperty("reason_code") + @ExcludeMissing + reasonCode: JsonField = JsonMissing.of(), + @JsonProperty("tax_code") @ExcludeMissing taxCode: JsonField = JsonMissing.of(), + @JsonProperty("tax_rate") @ExcludeMissing taxRate: JsonField = JsonMissing.of(), + ) : this( + amount, + baseAmount, + multiplierFactor, + reason, + reasonCode, + taxCode, + taxRate, + mutableMapOf(), + ) + + /** + * The charge amount, without VAT. Must be rounded to maximum 2 decimals + * + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun amount(): Optional = amount.getOptional("amount") + + /** + * The base amount that may be used, in conjunction with the charge percentage, to calculate the + * charge amount. Must be rounded to maximum 2 decimals + * + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun baseAmount(): Optional = baseAmount.getOptional("base_amount") + + /** + * The percentage that may be used, in conjunction with the charge base amount, to calculate the + * charge amount. To state 20%, use value 20 + * + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun multiplierFactor(): Optional = multiplierFactor.getOptional("multiplier_factor") + + /** + * The reason for the charge + * + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun reason(): Optional = reason.getOptional("reason") + + /** + * Charge reason codes for invoice charges and fees + * + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun reasonCode(): Optional = reasonCode.getOptional("reason_code") + + /** + * Duty or tax or fee category codes (Subset of UNCL5305) + * + * Agency: UN/CEFACT Version: D.16B Subset: OpenPEPPOL + * + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun taxCode(): Optional = taxCode.getOptional("tax_code") + + /** + * The VAT rate, represented as percentage that applies to the charge + * + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun taxRate(): Optional = taxRate.getOptional("tax_rate") + + /** + * Returns the raw JSON value of [amount]. + * + * Unlike [amount], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("amount") @ExcludeMissing fun _amount(): JsonField = amount + + /** + * Returns the raw JSON value of [baseAmount]. + * + * Unlike [baseAmount], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("base_amount") @ExcludeMissing fun _baseAmount(): JsonField = baseAmount + + /** + * Returns the raw JSON value of [multiplierFactor]. + * + * Unlike [multiplierFactor], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("multiplier_factor") + @ExcludeMissing + fun _multiplierFactor(): JsonField = multiplierFactor + + /** + * Returns the raw JSON value of [reason]. + * + * Unlike [reason], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("reason") @ExcludeMissing fun _reason(): JsonField = reason + + /** + * Returns the raw JSON value of [reasonCode]. + * + * Unlike [reasonCode], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("reason_code") + @ExcludeMissing + fun _reasonCode(): JsonField = reasonCode + + /** + * Returns the raw JSON value of [taxCode]. + * + * Unlike [taxCode], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("tax_code") @ExcludeMissing fun _taxCode(): JsonField = taxCode + + /** + * Returns the raw JSON value of [taxRate]. + * + * Unlike [taxRate], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("tax_rate") @ExcludeMissing fun _taxRate(): JsonField = taxRate + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** Returns a mutable builder for constructing an instance of [Charge]. */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [Charge]. */ + class Builder internal constructor() { + + private var amount: JsonField = JsonMissing.of() + private var baseAmount: JsonField = JsonMissing.of() + private var multiplierFactor: JsonField = JsonMissing.of() + private var reason: JsonField = JsonMissing.of() + private var reasonCode: JsonField = JsonMissing.of() + private var taxCode: JsonField = JsonMissing.of() + private var taxRate: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(charge: Charge) = apply { + amount = charge.amount + baseAmount = charge.baseAmount + multiplierFactor = charge.multiplierFactor + reason = charge.reason + reasonCode = charge.reasonCode + taxCode = charge.taxCode + taxRate = charge.taxRate + additionalProperties = charge.additionalProperties.toMutableMap() + } + + /** The charge amount, without VAT. Must be rounded to maximum 2 decimals */ + fun amount(amount: String?) = amount(JsonField.ofNullable(amount)) + + /** Alias for calling [Builder.amount] with `amount.orElse(null)`. */ + fun amount(amount: Optional) = amount(amount.getOrNull()) + + /** + * Sets [Builder.amount] to an arbitrary JSON value. + * + * You should usually call [Builder.amount] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun amount(amount: JsonField) = apply { this.amount = amount } + + /** + * The base amount that may be used, in conjunction with the charge percentage, to calculate + * the charge amount. Must be rounded to maximum 2 decimals + */ + fun baseAmount(baseAmount: String?) = baseAmount(JsonField.ofNullable(baseAmount)) + + /** Alias for calling [Builder.baseAmount] with `baseAmount.orElse(null)`. */ + fun baseAmount(baseAmount: Optional) = baseAmount(baseAmount.getOrNull()) + + /** + * Sets [Builder.baseAmount] to an arbitrary JSON value. + * + * You should usually call [Builder.baseAmount] with a well-typed [String] value instead. + * This method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun baseAmount(baseAmount: JsonField) = apply { this.baseAmount = baseAmount } + + /** + * The percentage that may be used, in conjunction with the charge base amount, to calculate + * the charge amount. To state 20%, use value 20 + */ + fun multiplierFactor(multiplierFactor: String?) = + multiplierFactor(JsonField.ofNullable(multiplierFactor)) + + /** Alias for calling [Builder.multiplierFactor] with `multiplierFactor.orElse(null)`. */ + fun multiplierFactor(multiplierFactor: Optional) = + multiplierFactor(multiplierFactor.getOrNull()) + + /** + * Sets [Builder.multiplierFactor] to an arbitrary JSON value. + * + * You should usually call [Builder.multiplierFactor] with a well-typed [String] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun multiplierFactor(multiplierFactor: JsonField) = apply { + this.multiplierFactor = multiplierFactor + } + + /** The reason for the charge */ + fun reason(reason: String?) = reason(JsonField.ofNullable(reason)) + + /** Alias for calling [Builder.reason] with `reason.orElse(null)`. */ + fun reason(reason: Optional) = reason(reason.getOrNull()) + + /** + * Sets [Builder.reason] to an arbitrary JSON value. + * + * You should usually call [Builder.reason] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun reason(reason: JsonField) = apply { this.reason = reason } + + /** Charge reason codes for invoice charges and fees */ + fun reasonCode(reasonCode: ReasonCode?) = reasonCode(JsonField.ofNullable(reasonCode)) + + /** Alias for calling [Builder.reasonCode] with `reasonCode.orElse(null)`. */ + fun reasonCode(reasonCode: Optional) = reasonCode(reasonCode.getOrNull()) + + /** + * Sets [Builder.reasonCode] to an arbitrary JSON value. + * + * You should usually call [Builder.reasonCode] with a well-typed [ReasonCode] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun reasonCode(reasonCode: JsonField) = apply { this.reasonCode = reasonCode } + + /** + * Duty or tax or fee category codes (Subset of UNCL5305) + * + * Agency: UN/CEFACT Version: D.16B Subset: OpenPEPPOL + */ + fun taxCode(taxCode: TaxCode?) = taxCode(JsonField.ofNullable(taxCode)) + + /** Alias for calling [Builder.taxCode] with `taxCode.orElse(null)`. */ + fun taxCode(taxCode: Optional) = taxCode(taxCode.getOrNull()) + + /** + * Sets [Builder.taxCode] to an arbitrary JSON value. + * + * You should usually call [Builder.taxCode] with a well-typed [TaxCode] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun taxCode(taxCode: JsonField) = apply { this.taxCode = taxCode } + + /** The VAT rate, represented as percentage that applies to the charge */ + fun taxRate(taxRate: String?) = taxRate(JsonField.ofNullable(taxRate)) + + /** Alias for calling [Builder.taxRate] with `taxRate.orElse(null)`. */ + fun taxRate(taxRate: Optional) = taxRate(taxRate.getOrNull()) + + /** + * Sets [Builder.taxRate] to an arbitrary JSON value. + * + * You should usually call [Builder.taxRate] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun taxRate(taxRate: JsonField) = apply { this.taxRate = taxRate } + + fun additionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.clear() + putAllAdditionalProperties(additionalProperties) + } + + fun putAdditionalProperty(key: String, value: JsonValue) = apply { + additionalProperties.put(key, value) + } + + fun putAllAdditionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.putAll(additionalProperties) + } + + fun removeAdditionalProperty(key: String) = apply { additionalProperties.remove(key) } + + fun removeAllAdditionalProperties(keys: Set) = apply { + keys.forEach(::removeAdditionalProperty) + } + + /** + * Returns an immutable instance of [Charge]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): Charge = + Charge( + amount, + baseAmount, + multiplierFactor, + reason, + reasonCode, + taxCode, + taxRate, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + fun validate(): Charge = apply { + if (validated) { + return@apply + } + + amount() + baseAmount() + multiplierFactor() + reason() + reasonCode().ifPresent { it.validate() } + taxCode().ifPresent { it.validate() } + taxRate() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: EInvoiceInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic + internal fun validity(): Int = + (if (amount.asKnown().isPresent) 1 else 0) + + (if (baseAmount.asKnown().isPresent) 1 else 0) + + (if (multiplierFactor.asKnown().isPresent) 1 else 0) + + (if (reason.asKnown().isPresent) 1 else 0) + + (reasonCode.asKnown().getOrNull()?.validity() ?: 0) + + (taxCode.asKnown().getOrNull()?.validity() ?: 0) + + (if (taxRate.asKnown().isPresent) 1 else 0) + + /** Charge reason codes for invoice charges and fees */ + class ReasonCode @JsonCreator private constructor(private val value: JsonField) : Enum { + + /** + * Returns this class instance's raw value. + * + * This is usually only useful if this instance was deserialized from data that doesn't + * match any known member, and you want to know that value. For example, if the SDK is on an + * older version than the API, then the API may respond with new members that the SDK is + * unaware of. + */ + @com.fasterxml.jackson.annotation.JsonValue fun _value(): JsonField = value + + companion object { + + @JvmField val AA = of("AA") + + @JvmField val AAA = of("AAA") + + @JvmField val AAC = of("AAC") + + @JvmField val AAD = of("AAD") + + @JvmField val AAE = of("AAE") + + @JvmField val AAF = of("AAF") + + @JvmField val AAH = of("AAH") + + @JvmField val AAI = of("AAI") + + @JvmField val AAS = of("AAS") + + @JvmField val AAT = of("AAT") + + @JvmField val AAV = of("AAV") + + @JvmField val AAY = of("AAY") + + @JvmField val AAZ = of("AAZ") + + @JvmField val ABA = of("ABA") + + @JvmField val ABB = of("ABB") + + @JvmField val ABC = of("ABC") + + @JvmField val ABD = of("ABD") + + @JvmField val ABF = of("ABF") + + @JvmField val ABK = of("ABK") + + @JvmField val ABL = of("ABL") + + @JvmField val ABN = of("ABN") + + @JvmField val ABR = of("ABR") + + @JvmField val ABS = of("ABS") + + @JvmField val ABT = of("ABT") + + @JvmField val ABU = of("ABU") + + @JvmField val ACF = of("ACF") + + @JvmField val ACG = of("ACG") + + @JvmField val ACH = of("ACH") + + @JvmField val ACI = of("ACI") + + @JvmField val ACJ = of("ACJ") + + @JvmField val ACK = of("ACK") + + @JvmField val ACL = of("ACL") + + @JvmField val ACM = of("ACM") + + @JvmField val ACS = of("ACS") + + @JvmField val ADC = of("ADC") + + @JvmField val ADE = of("ADE") + + @JvmField val ADJ = of("ADJ") + + @JvmField val ADK = of("ADK") + + @JvmField val ADL = of("ADL") + + @JvmField val ADM = of("ADM") + + @JvmField val ADN = of("ADN") + + @JvmField val ADO = of("ADO") + + @JvmField val ADP = of("ADP") + + @JvmField val ADQ = of("ADQ") + + @JvmField val ADR = of("ADR") + + @JvmField val ADT = of("ADT") + + @JvmField val ADW = of("ADW") + + @JvmField val ADY = of("ADY") + + @JvmField val ADZ = of("ADZ") + + @JvmField val AEA = of("AEA") + + @JvmField val AEB = of("AEB") + + @JvmField val AEC = of("AEC") + + @JvmField val AED = of("AED") + + @JvmField val AEF = of("AEF") + + @JvmField val AEH = of("AEH") + + @JvmField val AEI = of("AEI") + + @JvmField val AEJ = of("AEJ") + + @JvmField val AEK = of("AEK") + + @JvmField val AEL = of("AEL") + + @JvmField val AEM = of("AEM") + + @JvmField val AEN = of("AEN") + + @JvmField val AEO = of("AEO") + + @JvmField val AEP = of("AEP") + + @JvmField val AES = of("AES") + + @JvmField val AET = of("AET") + + @JvmField val AEU = of("AEU") + + @JvmField val AEV = of("AEV") + + @JvmField val AEW = of("AEW") + + @JvmField val AEX = of("AEX") + + @JvmField val AEY = of("AEY") + + @JvmField val AEZ = of("AEZ") + + @JvmField val AJ = of("AJ") + + @JvmField val AU = of("AU") + + @JvmField val CA = of("CA") + + @JvmField val CAB = of("CAB") + + @JvmField val CAD = of("CAD") + + @JvmField val CAE = of("CAE") + + @JvmField val CAF = of("CAF") + + @JvmField val CAI = of("CAI") + + @JvmField val CAJ = of("CAJ") + + @JvmField val CAK = of("CAK") + + @JvmField val CAL = of("CAL") + + @JvmField val CAM = of("CAM") + + @JvmField val CAN = of("CAN") + + @JvmField val CAO = of("CAO") + + @JvmField val CAP = of("CAP") + + @JvmField val CAQ = of("CAQ") + + @JvmField val CAR = of("CAR") + + @JvmField val CAS = of("CAS") + + @JvmField val CAT = of("CAT") + + @JvmField val CAU = of("CAU") + + @JvmField val CAV = of("CAV") + + @JvmField val CAW = of("CAW") + + @JvmField val CAX = of("CAX") + + @JvmField val CAY = of("CAY") + + @JvmField val CAZ = of("CAZ") + + @JvmField val CD = of("CD") + + @JvmField val CG = of("CG") + + @JvmField val CS = of("CS") + + @JvmField val CT = of("CT") + + @JvmField val DAB = of("DAB") + + @JvmField val DAC = of("DAC") + + @JvmField val DAD = of("DAD") + + @JvmField val DAF = of("DAF") + + @JvmField val DAG = of("DAG") + + @JvmField val DAH = of("DAH") + + @JvmField val DAI = of("DAI") + + @JvmField val DAJ = of("DAJ") + + @JvmField val DAK = of("DAK") + + @JvmField val DAL = of("DAL") + + @JvmField val DAM = of("DAM") + + @JvmField val DAN = of("DAN") + + @JvmField val DAO = of("DAO") + + @JvmField val DAP = of("DAP") + + @JvmField val DAQ = of("DAQ") + + @JvmField val DL = of("DL") + + @JvmField val EG = of("EG") + + @JvmField val EP = of("EP") + + @JvmField val ER = of("ER") + + @JvmField val FAA = of("FAA") + + @JvmField val FAB = of("FAB") + + @JvmField val FAC = of("FAC") + + @JvmField val FC = of("FC") + + @JvmField val FH = of("FH") + + @JvmField val FI = of("FI") + + @JvmField val GAA = of("GAA") + + @JvmField val HAA = of("HAA") + + @JvmField val HD = of("HD") + + @JvmField val HH = of("HH") + + @JvmField val IAA = of("IAA") + + @JvmField val IAB = of("IAB") + + @JvmField val ID = of("ID") + + @JvmField val IF = of("IF") + + @JvmField val IR = of("IR") + + @JvmField val IS = of("IS") + + @JvmField val KO = of("KO") + + @JvmField val L1 = of("L1") + + @JvmField val LA = of("LA") + + @JvmField val LAA = of("LAA") + + @JvmField val LAB = of("LAB") + + @JvmField val LF = of("LF") + + @JvmField val MAE = of("MAE") + + @JvmField val MI = of("MI") + + @JvmField val ML = of("ML") + + @JvmField val NAA = of("NAA") + + @JvmField val OA = of("OA") + + @JvmField val PA = of("PA") + + @JvmField val PAA = of("PAA") + + @JvmField val PC = of("PC") + + @JvmField val PL = of("PL") + + @JvmField val PRV = of("PRV") + + @JvmField val RAB = of("RAB") + + @JvmField val RAC = of("RAC") + + @JvmField val RAD = of("RAD") + + @JvmField val RAF = of("RAF") + + @JvmField val RE = of("RE") + + @JvmField val RF = of("RF") + + @JvmField val RH = of("RH") + + @JvmField val RV = of("RV") + + @JvmField val SA = of("SA") + + @JvmField val SAA = of("SAA") + + @JvmField val SAD = of("SAD") + + @JvmField val SAE = of("SAE") + + @JvmField val SAI = of("SAI") + + @JvmField val SG = of("SG") + + @JvmField val SH = of("SH") + + @JvmField val SM = of("SM") + + @JvmField val SU = of("SU") + + @JvmField val TAB = of("TAB") + + @JvmField val TAC = of("TAC") + + @JvmField val TT = of("TT") + + @JvmField val TV = of("TV") + + @JvmField val V1 = of("V1") + + @JvmField val V2 = of("V2") + + @JvmField val WH = of("WH") + + @JvmField val XAA = of("XAA") + + @JvmField val YY = of("YY") + + @JvmField val ZZZ = of("ZZZ") + + @JvmStatic fun of(value: String) = ReasonCode(JsonField.of(value)) + } + + /** An enum containing [ReasonCode]'s known values. */ + enum class Known { + AA, + AAA, + AAC, + AAD, + AAE, + AAF, + AAH, + AAI, + AAS, + AAT, + AAV, + AAY, + AAZ, + ABA, + ABB, + ABC, + ABD, + ABF, + ABK, + ABL, + ABN, + ABR, + ABS, + ABT, + ABU, + ACF, + ACG, + ACH, + ACI, + ACJ, + ACK, + ACL, + ACM, + ACS, + ADC, + ADE, + ADJ, + ADK, + ADL, + ADM, + ADN, + ADO, + ADP, + ADQ, + ADR, + ADT, + ADW, + ADY, + ADZ, + AEA, + AEB, + AEC, + AED, + AEF, + AEH, + AEI, + AEJ, + AEK, + AEL, + AEM, + AEN, + AEO, + AEP, + AES, + AET, + AEU, + AEV, + AEW, + AEX, + AEY, + AEZ, + AJ, + AU, + CA, + CAB, + CAD, + CAE, + CAF, + CAI, + CAJ, + CAK, + CAL, + CAM, + CAN, + CAO, + CAP, + CAQ, + CAR, + CAS, + CAT, + CAU, + CAV, + CAW, + CAX, + CAY, + CAZ, + CD, + CG, + CS, + CT, + DAB, + DAC, + DAD, + DAF, + DAG, + DAH, + DAI, + DAJ, + DAK, + DAL, + DAM, + DAN, + DAO, + DAP, + DAQ, + DL, + EG, + EP, + ER, + FAA, + FAB, + FAC, + FC, + FH, + FI, + GAA, + HAA, + HD, + HH, + IAA, + IAB, + ID, + IF, + IR, + IS, + KO, + L1, + LA, + LAA, + LAB, + LF, + MAE, + MI, + ML, + NAA, + OA, + PA, + PAA, + PC, + PL, + PRV, + RAB, + RAC, + RAD, + RAF, + RE, + RF, + RH, + RV, + SA, + SAA, + SAD, + SAE, + SAI, + SG, + SH, + SM, + SU, + TAB, + TAC, + TT, + TV, + V1, + V2, + WH, + XAA, + YY, + ZZZ, + } + + /** + * An enum containing [ReasonCode]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [ReasonCode] can contain an unknown value in a couple of cases: + * - It was deserialized from data that doesn't match any known member. For example, if the + * SDK is on an older version than the API, then the API may respond with new members that + * the SDK is unaware of. + * - It was constructed with an arbitrary value using the [of] method. + */ + enum class Value { + AA, + AAA, + AAC, + AAD, + AAE, + AAF, + AAH, + AAI, + AAS, + AAT, + AAV, + AAY, + AAZ, + ABA, + ABB, + ABC, + ABD, + ABF, + ABK, + ABL, + ABN, + ABR, + ABS, + ABT, + ABU, + ACF, + ACG, + ACH, + ACI, + ACJ, + ACK, + ACL, + ACM, + ACS, + ADC, + ADE, + ADJ, + ADK, + ADL, + ADM, + ADN, + ADO, + ADP, + ADQ, + ADR, + ADT, + ADW, + ADY, + ADZ, + AEA, + AEB, + AEC, + AED, + AEF, + AEH, + AEI, + AEJ, + AEK, + AEL, + AEM, + AEN, + AEO, + AEP, + AES, + AET, + AEU, + AEV, + AEW, + AEX, + AEY, + AEZ, + AJ, + AU, + CA, + CAB, + CAD, + CAE, + CAF, + CAI, + CAJ, + CAK, + CAL, + CAM, + CAN, + CAO, + CAP, + CAQ, + CAR, + CAS, + CAT, + CAU, + CAV, + CAW, + CAX, + CAY, + CAZ, + CD, + CG, + CS, + CT, + DAB, + DAC, + DAD, + DAF, + DAG, + DAH, + DAI, + DAJ, + DAK, + DAL, + DAM, + DAN, + DAO, + DAP, + DAQ, + DL, + EG, + EP, + ER, + FAA, + FAB, + FAC, + FC, + FH, + FI, + GAA, + HAA, + HD, + HH, + IAA, + IAB, + ID, + IF, + IR, + IS, + KO, + L1, + LA, + LAA, + LAB, + LF, + MAE, + MI, + ML, + NAA, + OA, + PA, + PAA, + PC, + PL, + PRV, + RAB, + RAC, + RAD, + RAF, + RE, + RF, + RH, + RV, + SA, + SAA, + SAD, + SAE, + SAI, + SG, + SH, + SM, + SU, + TAB, + TAC, + TT, + TV, + V1, + V2, + WH, + XAA, + YY, + ZZZ, + /** + * An enum member indicating that [ReasonCode] was instantiated with an unknown value. + */ + _UNKNOWN, + } + + /** + * Returns an enum member corresponding to this class instance's value, or [Value._UNKNOWN] + * if the class was instantiated with an unknown value. + * + * Use the [known] method instead if you're certain the value is always known or if you want + * to throw for the unknown case. + */ + fun value(): Value = + when (this) { + AA -> Value.AA + AAA -> Value.AAA + AAC -> Value.AAC + AAD -> Value.AAD + AAE -> Value.AAE + AAF -> Value.AAF + AAH -> Value.AAH + AAI -> Value.AAI + AAS -> Value.AAS + AAT -> Value.AAT + AAV -> Value.AAV + AAY -> Value.AAY + AAZ -> Value.AAZ + ABA -> Value.ABA + ABB -> Value.ABB + ABC -> Value.ABC + ABD -> Value.ABD + ABF -> Value.ABF + ABK -> Value.ABK + ABL -> Value.ABL + ABN -> Value.ABN + ABR -> Value.ABR + ABS -> Value.ABS + ABT -> Value.ABT + ABU -> Value.ABU + ACF -> Value.ACF + ACG -> Value.ACG + ACH -> Value.ACH + ACI -> Value.ACI + ACJ -> Value.ACJ + ACK -> Value.ACK + ACL -> Value.ACL + ACM -> Value.ACM + ACS -> Value.ACS + ADC -> Value.ADC + ADE -> Value.ADE + ADJ -> Value.ADJ + ADK -> Value.ADK + ADL -> Value.ADL + ADM -> Value.ADM + ADN -> Value.ADN + ADO -> Value.ADO + ADP -> Value.ADP + ADQ -> Value.ADQ + ADR -> Value.ADR + ADT -> Value.ADT + ADW -> Value.ADW + ADY -> Value.ADY + ADZ -> Value.ADZ + AEA -> Value.AEA + AEB -> Value.AEB + AEC -> Value.AEC + AED -> Value.AED + AEF -> Value.AEF + AEH -> Value.AEH + AEI -> Value.AEI + AEJ -> Value.AEJ + AEK -> Value.AEK + AEL -> Value.AEL + AEM -> Value.AEM + AEN -> Value.AEN + AEO -> Value.AEO + AEP -> Value.AEP + AES -> Value.AES + AET -> Value.AET + AEU -> Value.AEU + AEV -> Value.AEV + AEW -> Value.AEW + AEX -> Value.AEX + AEY -> Value.AEY + AEZ -> Value.AEZ + AJ -> Value.AJ + AU -> Value.AU + CA -> Value.CA + CAB -> Value.CAB + CAD -> Value.CAD + CAE -> Value.CAE + CAF -> Value.CAF + CAI -> Value.CAI + CAJ -> Value.CAJ + CAK -> Value.CAK + CAL -> Value.CAL + CAM -> Value.CAM + CAN -> Value.CAN + CAO -> Value.CAO + CAP -> Value.CAP + CAQ -> Value.CAQ + CAR -> Value.CAR + CAS -> Value.CAS + CAT -> Value.CAT + CAU -> Value.CAU + CAV -> Value.CAV + CAW -> Value.CAW + CAX -> Value.CAX + CAY -> Value.CAY + CAZ -> Value.CAZ + CD -> Value.CD + CG -> Value.CG + CS -> Value.CS + CT -> Value.CT + DAB -> Value.DAB + DAC -> Value.DAC + DAD -> Value.DAD + DAF -> Value.DAF + DAG -> Value.DAG + DAH -> Value.DAH + DAI -> Value.DAI + DAJ -> Value.DAJ + DAK -> Value.DAK + DAL -> Value.DAL + DAM -> Value.DAM + DAN -> Value.DAN + DAO -> Value.DAO + DAP -> Value.DAP + DAQ -> Value.DAQ + DL -> Value.DL + EG -> Value.EG + EP -> Value.EP + ER -> Value.ER + FAA -> Value.FAA + FAB -> Value.FAB + FAC -> Value.FAC + FC -> Value.FC + FH -> Value.FH + FI -> Value.FI + GAA -> Value.GAA + HAA -> Value.HAA + HD -> Value.HD + HH -> Value.HH + IAA -> Value.IAA + IAB -> Value.IAB + ID -> Value.ID + IF -> Value.IF + IR -> Value.IR + IS -> Value.IS + KO -> Value.KO + L1 -> Value.L1 + LA -> Value.LA + LAA -> Value.LAA + LAB -> Value.LAB + LF -> Value.LF + MAE -> Value.MAE + MI -> Value.MI + ML -> Value.ML + NAA -> Value.NAA + OA -> Value.OA + PA -> Value.PA + PAA -> Value.PAA + PC -> Value.PC + PL -> Value.PL + PRV -> Value.PRV + RAB -> Value.RAB + RAC -> Value.RAC + RAD -> Value.RAD + RAF -> Value.RAF + RE -> Value.RE + RF -> Value.RF + RH -> Value.RH + RV -> Value.RV + SA -> Value.SA + SAA -> Value.SAA + SAD -> Value.SAD + SAE -> Value.SAE + SAI -> Value.SAI + SG -> Value.SG + SH -> Value.SH + SM -> Value.SM + SU -> Value.SU + TAB -> Value.TAB + TAC -> Value.TAC + TT -> Value.TT + TV -> Value.TV + V1 -> Value.V1 + V2 -> Value.V2 + WH -> Value.WH + XAA -> Value.XAA + YY -> Value.YY + ZZZ -> Value.ZZZ + else -> Value._UNKNOWN + } + + /** + * Returns an enum member corresponding to this class instance's value. + * + * Use the [value] method instead if you're uncertain the value is always known and don't + * want to throw for the unknown case. + * + * @throws EInvoiceInvalidDataException if this class instance's value is a not a known + * member. + */ + fun known(): Known = + when (this) { + AA -> Known.AA + AAA -> Known.AAA + AAC -> Known.AAC + AAD -> Known.AAD + AAE -> Known.AAE + AAF -> Known.AAF + AAH -> Known.AAH + AAI -> Known.AAI + AAS -> Known.AAS + AAT -> Known.AAT + AAV -> Known.AAV + AAY -> Known.AAY + AAZ -> Known.AAZ + ABA -> Known.ABA + ABB -> Known.ABB + ABC -> Known.ABC + ABD -> Known.ABD + ABF -> Known.ABF + ABK -> Known.ABK + ABL -> Known.ABL + ABN -> Known.ABN + ABR -> Known.ABR + ABS -> Known.ABS + ABT -> Known.ABT + ABU -> Known.ABU + ACF -> Known.ACF + ACG -> Known.ACG + ACH -> Known.ACH + ACI -> Known.ACI + ACJ -> Known.ACJ + ACK -> Known.ACK + ACL -> Known.ACL + ACM -> Known.ACM + ACS -> Known.ACS + ADC -> Known.ADC + ADE -> Known.ADE + ADJ -> Known.ADJ + ADK -> Known.ADK + ADL -> Known.ADL + ADM -> Known.ADM + ADN -> Known.ADN + ADO -> Known.ADO + ADP -> Known.ADP + ADQ -> Known.ADQ + ADR -> Known.ADR + ADT -> Known.ADT + ADW -> Known.ADW + ADY -> Known.ADY + ADZ -> Known.ADZ + AEA -> Known.AEA + AEB -> Known.AEB + AEC -> Known.AEC + AED -> Known.AED + AEF -> Known.AEF + AEH -> Known.AEH + AEI -> Known.AEI + AEJ -> Known.AEJ + AEK -> Known.AEK + AEL -> Known.AEL + AEM -> Known.AEM + AEN -> Known.AEN + AEO -> Known.AEO + AEP -> Known.AEP + AES -> Known.AES + AET -> Known.AET + AEU -> Known.AEU + AEV -> Known.AEV + AEW -> Known.AEW + AEX -> Known.AEX + AEY -> Known.AEY + AEZ -> Known.AEZ + AJ -> Known.AJ + AU -> Known.AU + CA -> Known.CA + CAB -> Known.CAB + CAD -> Known.CAD + CAE -> Known.CAE + CAF -> Known.CAF + CAI -> Known.CAI + CAJ -> Known.CAJ + CAK -> Known.CAK + CAL -> Known.CAL + CAM -> Known.CAM + CAN -> Known.CAN + CAO -> Known.CAO + CAP -> Known.CAP + CAQ -> Known.CAQ + CAR -> Known.CAR + CAS -> Known.CAS + CAT -> Known.CAT + CAU -> Known.CAU + CAV -> Known.CAV + CAW -> Known.CAW + CAX -> Known.CAX + CAY -> Known.CAY + CAZ -> Known.CAZ + CD -> Known.CD + CG -> Known.CG + CS -> Known.CS + CT -> Known.CT + DAB -> Known.DAB + DAC -> Known.DAC + DAD -> Known.DAD + DAF -> Known.DAF + DAG -> Known.DAG + DAH -> Known.DAH + DAI -> Known.DAI + DAJ -> Known.DAJ + DAK -> Known.DAK + DAL -> Known.DAL + DAM -> Known.DAM + DAN -> Known.DAN + DAO -> Known.DAO + DAP -> Known.DAP + DAQ -> Known.DAQ + DL -> Known.DL + EG -> Known.EG + EP -> Known.EP + ER -> Known.ER + FAA -> Known.FAA + FAB -> Known.FAB + FAC -> Known.FAC + FC -> Known.FC + FH -> Known.FH + FI -> Known.FI + GAA -> Known.GAA + HAA -> Known.HAA + HD -> Known.HD + HH -> Known.HH + IAA -> Known.IAA + IAB -> Known.IAB + ID -> Known.ID + IF -> Known.IF + IR -> Known.IR + IS -> Known.IS + KO -> Known.KO + L1 -> Known.L1 + LA -> Known.LA + LAA -> Known.LAA + LAB -> Known.LAB + LF -> Known.LF + MAE -> Known.MAE + MI -> Known.MI + ML -> Known.ML + NAA -> Known.NAA + OA -> Known.OA + PA -> Known.PA + PAA -> Known.PAA + PC -> Known.PC + PL -> Known.PL + PRV -> Known.PRV + RAB -> Known.RAB + RAC -> Known.RAC + RAD -> Known.RAD + RAF -> Known.RAF + RE -> Known.RE + RF -> Known.RF + RH -> Known.RH + RV -> Known.RV + SA -> Known.SA + SAA -> Known.SAA + SAD -> Known.SAD + SAE -> Known.SAE + SAI -> Known.SAI + SG -> Known.SG + SH -> Known.SH + SM -> Known.SM + SU -> Known.SU + TAB -> Known.TAB + TAC -> Known.TAC + TT -> Known.TT + TV -> Known.TV + V1 -> Known.V1 + V2 -> Known.V2 + WH -> Known.WH + XAA -> Known.XAA + YY -> Known.YY + ZZZ -> Known.ZZZ + else -> throw EInvoiceInvalidDataException("Unknown ReasonCode: $value") + } + + /** + * Returns this class instance's primitive wire representation. + * + * This differs from the [toString] method because that method is primarily for debugging + * and generally doesn't throw. + * + * @throws EInvoiceInvalidDataException if this class instance's value does not have the + * expected primitive type. + */ + fun asString(): String = + _value().asString().orElseThrow { + EInvoiceInvalidDataException("Value is not a String") + } + + private var validated: Boolean = false + + fun validate(): ReasonCode = apply { + if (validated) { + return@apply + } + + known() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: EInvoiceInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic internal fun validity(): Int = if (value() == Value._UNKNOWN) 0 else 1 + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is ReasonCode && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + /** + * Duty or tax or fee category codes (Subset of UNCL5305) + * + * Agency: UN/CEFACT Version: D.16B Subset: OpenPEPPOL + */ + class TaxCode @JsonCreator private constructor(private val value: JsonField) : Enum { + + /** + * Returns this class instance's raw value. + * + * This is usually only useful if this instance was deserialized from data that doesn't + * match any known member, and you want to know that value. For example, if the SDK is on an + * older version than the API, then the API may respond with new members that the SDK is + * unaware of. + */ + @com.fasterxml.jackson.annotation.JsonValue fun _value(): JsonField = value + + companion object { + + @JvmField val AE = of("AE") + + @JvmField val E = of("E") + + @JvmField val S = of("S") + + @JvmField val Z = of("Z") + + @JvmField val G = of("G") + + @JvmField val O = of("O") + + @JvmField val K = of("K") + + @JvmField val L = of("L") + + @JvmField val M = of("M") + + @JvmField val B = of("B") + + @JvmStatic fun of(value: String) = TaxCode(JsonField.of(value)) + } + + /** An enum containing [TaxCode]'s known values. */ + enum class Known { + AE, + E, + S, + Z, + G, + O, + K, + L, + M, + B, + } + + /** + * An enum containing [TaxCode]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [TaxCode] can contain an unknown value in a couple of cases: + * - It was deserialized from data that doesn't match any known member. For example, if the + * SDK is on an older version than the API, then the API may respond with new members that + * the SDK is unaware of. + * - It was constructed with an arbitrary value using the [of] method. + */ + enum class Value { + AE, + E, + S, + Z, + G, + O, + K, + L, + M, + B, + /** An enum member indicating that [TaxCode] was instantiated with an unknown value. */ + _UNKNOWN, + } + + /** + * Returns an enum member corresponding to this class instance's value, or [Value._UNKNOWN] + * if the class was instantiated with an unknown value. + * + * Use the [known] method instead if you're certain the value is always known or if you want + * to throw for the unknown case. + */ + fun value(): Value = + when (this) { + AE -> Value.AE + E -> Value.E + S -> Value.S + Z -> Value.Z + G -> Value.G + O -> Value.O + K -> Value.K + L -> Value.L + M -> Value.M + B -> Value.B + else -> Value._UNKNOWN + } + + /** + * Returns an enum member corresponding to this class instance's value. + * + * Use the [value] method instead if you're uncertain the value is always known and don't + * want to throw for the unknown case. + * + * @throws EInvoiceInvalidDataException if this class instance's value is a not a known + * member. + */ + fun known(): Known = + when (this) { + AE -> Known.AE + E -> Known.E + S -> Known.S + Z -> Known.Z + G -> Known.G + O -> Known.O + K -> Known.K + L -> Known.L + M -> Known.M + B -> Known.B + else -> throw EInvoiceInvalidDataException("Unknown TaxCode: $value") + } + + /** + * Returns this class instance's primitive wire representation. + * + * This differs from the [toString] method because that method is primarily for debugging + * and generally doesn't throw. + * + * @throws EInvoiceInvalidDataException if this class instance's value does not have the + * expected primitive type. + */ + fun asString(): String = + _value().asString().orElseThrow { + EInvoiceInvalidDataException("Value is not a String") + } + + private var validated: Boolean = false + + fun validate(): TaxCode = apply { + if (validated) { + return@apply + } + + known() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: EInvoiceInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic internal fun validity(): Int = if (value() == Value._UNKNOWN) 0 else 1 + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is TaxCode && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Charge && + amount == other.amount && + baseAmount == other.baseAmount && + multiplierFactor == other.multiplierFactor && + reason == other.reason && + reasonCode == other.reasonCode && + taxCode == other.taxCode && + taxRate == other.taxRate && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash( + amount, + baseAmount, + multiplierFactor, + reason, + reasonCode, + taxCode, + taxRate, + additionalProperties, + ) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "Charge{amount=$amount, baseAmount=$baseAmount, multiplierFactor=$multiplierFactor, reason=$reason, reasonCode=$reasonCode, taxCode=$taxCode, taxRate=$taxRate, additionalProperties=$additionalProperties}" +} diff --git a/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/models/documents/DocumentCreate.kt b/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/models/documents/DocumentCreate.kt index 0c51e23..a713762 100644 --- a/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/models/documents/DocumentCreate.kt +++ b/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/models/documents/DocumentCreate.kt @@ -4,6 +4,7 @@ package com.e_invoice.api.models.documents import com.e_invoice.api.core.BaseDeserializer import com.e_invoice.api.core.BaseSerializer +import com.e_invoice.api.core.Enum import com.e_invoice.api.core.ExcludeMissing import com.e_invoice.api.core.JsonField import com.e_invoice.api.core.JsonMissing @@ -34,13 +35,16 @@ import kotlin.jvm.optionals.getOrNull class DocumentCreate @JsonCreator(mode = JsonCreator.Mode.DISABLED) private constructor( + private val allowances: JsonField>, private val amountDue: JsonField, private val attachments: JsonField>, private val billingAddress: JsonField, private val billingAddressRecipient: JsonField, + private val charges: JsonField>, private val currency: JsonField, private val customerAddress: JsonField, private val customerAddressRecipient: JsonField, + private val customerCompanyId: JsonField, private val customerEmail: JsonField, private val customerId: JsonField, private val customerName: JsonField, @@ -67,11 +71,15 @@ private constructor( private val shippingAddressRecipient: JsonField, private val state: JsonField, private val subtotal: JsonField, + private val taxCode: JsonField, private val taxDetails: JsonField>, private val totalDiscount: JsonField, private val totalTax: JsonField, + private val vatex: JsonField, + private val vatexNote: JsonField, private val vendorAddress: JsonField, private val vendorAddressRecipient: JsonField, + private val vendorCompanyId: JsonField, private val vendorEmail: JsonField, private val vendorName: JsonField, private val vendorTaxId: JsonField, @@ -80,6 +88,9 @@ private constructor( @JsonCreator private constructor( + @JsonProperty("allowances") + @ExcludeMissing + allowances: JsonField> = JsonMissing.of(), @JsonProperty("amount_due") @ExcludeMissing amountDue: JsonField = JsonMissing.of(), @@ -92,6 +103,9 @@ private constructor( @JsonProperty("billing_address_recipient") @ExcludeMissing billingAddressRecipient: JsonField = JsonMissing.of(), + @JsonProperty("charges") + @ExcludeMissing + charges: JsonField> = JsonMissing.of(), @JsonProperty("currency") @ExcludeMissing currency: JsonField = JsonMissing.of(), @@ -101,6 +115,9 @@ private constructor( @JsonProperty("customer_address_recipient") @ExcludeMissing customerAddressRecipient: JsonField = JsonMissing.of(), + @JsonProperty("customer_company_id") + @ExcludeMissing + customerCompanyId: JsonField = JsonMissing.of(), @JsonProperty("customer_email") @ExcludeMissing customerEmail: JsonField = JsonMissing.of(), @@ -167,6 +184,7 @@ private constructor( shippingAddressRecipient: JsonField = JsonMissing.of(), @JsonProperty("state") @ExcludeMissing state: JsonField = JsonMissing.of(), @JsonProperty("subtotal") @ExcludeMissing subtotal: JsonField = JsonMissing.of(), + @JsonProperty("tax_code") @ExcludeMissing taxCode: JsonField = JsonMissing.of(), @JsonProperty("tax_details") @ExcludeMissing taxDetails: JsonField> = JsonMissing.of(), @@ -174,12 +192,17 @@ private constructor( @ExcludeMissing totalDiscount: JsonField = JsonMissing.of(), @JsonProperty("total_tax") @ExcludeMissing totalTax: JsonField = JsonMissing.of(), + @JsonProperty("vatex") @ExcludeMissing vatex: JsonField = JsonMissing.of(), + @JsonProperty("vatex_note") @ExcludeMissing vatexNote: JsonField = JsonMissing.of(), @JsonProperty("vendor_address") @ExcludeMissing vendorAddress: JsonField = JsonMissing.of(), @JsonProperty("vendor_address_recipient") @ExcludeMissing vendorAddressRecipient: JsonField = JsonMissing.of(), + @JsonProperty("vendor_company_id") + @ExcludeMissing + vendorCompanyId: JsonField = JsonMissing.of(), @JsonProperty("vendor_email") @ExcludeMissing vendorEmail: JsonField = JsonMissing.of(), @@ -190,13 +213,16 @@ private constructor( @ExcludeMissing vendorTaxId: JsonField = JsonMissing.of(), ) : this( + allowances, amountDue, attachments, billingAddress, billingAddressRecipient, + charges, currency, customerAddress, customerAddressRecipient, + customerCompanyId, customerEmail, customerId, customerName, @@ -223,11 +249,15 @@ private constructor( shippingAddressRecipient, state, subtotal, + taxCode, taxDetails, totalDiscount, totalTax, + vatex, + vatexNote, vendorAddress, vendorAddressRecipient, + vendorCompanyId, vendorEmail, vendorName, vendorTaxId, @@ -238,6 +268,14 @@ private constructor( * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the * server responded with an unexpected value). */ + fun allowances(): Optional> = allowances.getOptional("allowances") + + /** + * The amount due for payment. Must be positive and rounded to maximum 2 decimals + * + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ fun amountDue(): Optional = amountDue.getOptional("amount_due") /** @@ -248,12 +286,16 @@ private constructor( attachments.getOptional("attachments") /** + * The billing address (if different from customer address) + * * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the * server responded with an unexpected value). */ fun billingAddress(): Optional = billingAddress.getOptional("billing_address") /** + * The recipient name at the billing address + * * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the * server responded with an unexpected value). */ @@ -261,7 +303,13 @@ private constructor( billingAddressRecipient.getOptional("billing_address_recipient") /** - * Currency of the invoice + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun charges(): Optional> = charges.getOptional("charges") + + /** + * Currency of the invoice (ISO 4217 currency code) * * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the * server responded with an unexpected value). @@ -269,12 +317,16 @@ private constructor( fun currency(): Optional = currency.getOptional("currency") /** + * The address of the customer/buyer + * * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the * server responded with an unexpected value). */ fun customerAddress(): Optional = customerAddress.getOptional("customer_address") /** + * The recipient name at the customer address + * * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the * server responded with an unexpected value). */ @@ -282,72 +334,106 @@ private constructor( customerAddressRecipient.getOptional("customer_address_recipient") /** + * Customer company ID. For Belgium this is the CBE number or their EUID (European Unique + * Identifier) number. In the Netherlands this is the KVK number. + * + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun customerCompanyId(): Optional = customerCompanyId.getOptional("customer_company_id") + + /** + * The email address of the customer + * * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the * server responded with an unexpected value). */ fun customerEmail(): Optional = customerEmail.getOptional("customer_email") /** + * The unique identifier for the customer in your system + * * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the * server responded with an unexpected value). */ fun customerId(): Optional = customerId.getOptional("customer_id") /** + * The company name of the customer/buyer + * * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the * server responded with an unexpected value). */ fun customerName(): Optional = customerName.getOptional("customer_name") /** + * Customer tax ID. For Belgium this is the VAT number. Must include the country prefix + * * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the * server responded with an unexpected value). */ fun customerTaxId(): Optional = customerTaxId.getOptional("customer_tax_id") /** + * The direction of the document: INBOUND (purchases) or OUTBOUND (sales) + * * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the * server responded with an unexpected value). */ fun direction(): Optional = direction.getOptional("direction") /** + * The type of document: INVOICE, CREDIT_NOTE, or DEBIT_NOTE + * * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the * server responded with an unexpected value). */ fun documentType(): Optional = documentType.getOptional("document_type") /** + * The date when payment is due + * * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the * server responded with an unexpected value). */ fun dueDate(): Optional = dueDate.getOptional("due_date") /** + * The date when the invoice was issued + * * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the * server responded with an unexpected value). */ fun invoiceDate(): Optional = invoiceDate.getOptional("invoice_date") /** + * The unique invoice identifier/number + * * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the * server responded with an unexpected value). */ fun invoiceId(): Optional = invoiceId.getOptional("invoice_id") /** + * The total amount of the invoice including tax (invoice_total = subtotal + total_tax + + * total_discount). Must be positive and rounded to maximum 2 decimals + * * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the * server responded with an unexpected value). */ fun invoiceTotal(): Optional = invoiceTotal.getOptional("invoice_total") /** + * At least one line item is required + * * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the * server responded with an unexpected value). */ fun items(): Optional> = items.getOptional("items") /** + * Additional notes or comments for the invoice + * * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the * server responded with an unexpected value). */ @@ -361,12 +447,17 @@ private constructor( paymentDetails.getOptional("payment_details") /** + * The payment terms (e.g., 'Net 30', 'Due on receipt', '2/10 Net 30') + * * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the * server responded with an unexpected value). */ fun paymentTerm(): Optional = paymentTerm.getOptional("payment_term") /** + * The previous unpaid balance from prior invoices, if any. Must be positive and rounded to + * maximum 2 decimals + * * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the * server responded with an unexpected value). */ @@ -374,18 +465,24 @@ private constructor( previousUnpaidBalance.getOptional("previous_unpaid_balance") /** + * The purchase order reference number + * * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the * server responded with an unexpected value). */ fun purchaseOrder(): Optional = purchaseOrder.getOptional("purchase_order") /** + * The address where payment should be sent or remitted to + * * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the * server responded with an unexpected value). */ fun remittanceAddress(): Optional = remittanceAddress.getOptional("remittance_address") /** + * The recipient name at the remittance address + * * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the * server responded with an unexpected value). */ @@ -393,12 +490,16 @@ private constructor( remittanceAddressRecipient.getOptional("remittance_address_recipient") /** + * The address where services were performed or goods were delivered + * * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the * server responded with an unexpected value). */ fun serviceAddress(): Optional = serviceAddress.getOptional("service_address") /** + * The recipient name at the service address + * * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the * server responded with an unexpected value). */ @@ -406,24 +507,32 @@ private constructor( serviceAddressRecipient.getOptional("service_address_recipient") /** + * The end date of the service period or delivery period + * * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the * server responded with an unexpected value). */ fun serviceEndDate(): Optional = serviceEndDate.getOptional("service_end_date") /** + * The start date of the service period or delivery period + * * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the * server responded with an unexpected value). */ fun serviceStartDate(): Optional = serviceStartDate.getOptional("service_start_date") /** + * The shipping/delivery address + * * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the * server responded with an unexpected value). */ fun shippingAddress(): Optional = shippingAddress.getOptional("shipping_address") /** + * The recipient name at the shipping address + * * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the * server responded with an unexpected value). */ @@ -431,17 +540,31 @@ private constructor( shippingAddressRecipient.getOptional("shipping_address_recipient") /** + * The current state of the document: DRAFT, TRANSIT, FAILED, SENT, or RECEIVED + * * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the * server responded with an unexpected value). */ fun state(): Optional = state.getOptional("state") /** + * The taxable base of the invoice. Should be the sum of all line items - allowances (for + * example commercial discounts) + charges with impact on VAT. Must be positive and rounded to + * maximum 2 decimals + * * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the * server responded with an unexpected value). */ fun subtotal(): Optional = subtotal.getOptional("subtotal") + /** + * Tax category code of the invoice (e.g., S for standard rate, Z for zero rate, E for exempt) + * + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun taxCode(): Optional = taxCode.getOptional("tax_code") + /** * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the * server responded with an unexpected value). @@ -449,24 +572,52 @@ private constructor( fun taxDetails(): Optional> = taxDetails.getOptional("tax_details") /** + * The net financial discount/charge of the invoice (non-VAT charges minus non-VAT allowances). + * Can be positive (net charge), negative (net discount), or zero. Must be rounded to maximum 2 + * decimals + * * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the * server responded with an unexpected value). */ fun totalDiscount(): Optional = totalDiscount.getOptional("total_discount") /** + * The total tax amount of the invoice. Must be positive and rounded to maximum 2 decimals + * * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the * server responded with an unexpected value). */ fun totalTax(): Optional = totalTax.getOptional("total_tax") /** + * VATEX code list for VAT exemption reasons + * + * Agency: CEF Identifier: vatex + * + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun vatex(): Optional = vatex.getOptional("vatex") + + /** + * Textual explanation for VAT exemption + * + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun vatexNote(): Optional = vatexNote.getOptional("vatex_note") + + /** + * The address of the vendor/seller + * * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the * server responded with an unexpected value). */ fun vendorAddress(): Optional = vendorAddress.getOptional("vendor_address") /** + * The recipient name at the vendor address + * * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the * server responded with an unexpected value). */ @@ -474,23 +625,47 @@ private constructor( vendorAddressRecipient.getOptional("vendor_address_recipient") /** + * Vendor company ID. For Belgium this is the CBE number or their EUID (European Unique + * Identifier) number. In the Netherlands this is the KVK number. + * + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun vendorCompanyId(): Optional = vendorCompanyId.getOptional("vendor_company_id") + + /** + * The email address of the vendor + * * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the * server responded with an unexpected value). */ fun vendorEmail(): Optional = vendorEmail.getOptional("vendor_email") /** + * The name of the vendor/seller/supplier + * * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the * server responded with an unexpected value). */ fun vendorName(): Optional = vendorName.getOptional("vendor_name") /** + * Vendor tax ID. For Belgium this is the VAT number. Must include the country prefix + * * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the * server responded with an unexpected value). */ fun vendorTaxId(): Optional = vendorTaxId.getOptional("vendor_tax_id") + /** + * Returns the raw JSON value of [allowances]. + * + * Unlike [allowances], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("allowances") + @ExcludeMissing + fun _allowances(): JsonField> = allowances + /** * Returns the raw JSON value of [amountDue]. * @@ -526,6 +701,13 @@ private constructor( @ExcludeMissing fun _billingAddressRecipient(): JsonField = billingAddressRecipient + /** + * Returns the raw JSON value of [charges]. + * + * Unlike [charges], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("charges") @ExcludeMissing fun _charges(): JsonField> = charges + /** * Returns the raw JSON value of [currency]. * @@ -552,6 +734,16 @@ private constructor( @ExcludeMissing fun _customerAddressRecipient(): JsonField = customerAddressRecipient + /** + * Returns the raw JSON value of [customerCompanyId]. + * + * Unlike [customerCompanyId], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("customer_company_id") + @ExcludeMissing + fun _customerCompanyId(): JsonField = customerCompanyId + /** * Returns the raw JSON value of [customerEmail]. * @@ -778,6 +970,13 @@ private constructor( */ @JsonProperty("subtotal") @ExcludeMissing fun _subtotal(): JsonField = subtotal + /** + * Returns the raw JSON value of [taxCode]. + * + * Unlike [taxCode], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("tax_code") @ExcludeMissing fun _taxCode(): JsonField = taxCode + /** * Returns the raw JSON value of [taxDetails]. * @@ -803,6 +1002,20 @@ private constructor( */ @JsonProperty("total_tax") @ExcludeMissing fun _totalTax(): JsonField = totalTax + /** + * Returns the raw JSON value of [vatex]. + * + * Unlike [vatex], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("vatex") @ExcludeMissing fun _vatex(): JsonField = vatex + + /** + * Returns the raw JSON value of [vatexNote]. + * + * Unlike [vatexNote], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("vatex_note") @ExcludeMissing fun _vatexNote(): JsonField = vatexNote + /** * Returns the raw JSON value of [vendorAddress]. * @@ -822,6 +1035,15 @@ private constructor( @ExcludeMissing fun _vendorAddressRecipient(): JsonField = vendorAddressRecipient + /** + * Returns the raw JSON value of [vendorCompanyId]. + * + * Unlike [vendorCompanyId], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("vendor_company_id") + @ExcludeMissing + fun _vendorCompanyId(): JsonField = vendorCompanyId + /** * Returns the raw JSON value of [vendorEmail]. * @@ -868,13 +1090,16 @@ private constructor( /** A builder for [DocumentCreate]. */ class Builder internal constructor() { + private var allowances: JsonField>? = null private var amountDue: JsonField = JsonMissing.of() private var attachments: JsonField>? = null private var billingAddress: JsonField = JsonMissing.of() private var billingAddressRecipient: JsonField = JsonMissing.of() + private var charges: JsonField>? = null private var currency: JsonField = JsonMissing.of() private var customerAddress: JsonField = JsonMissing.of() private var customerAddressRecipient: JsonField = JsonMissing.of() + private var customerCompanyId: JsonField = JsonMissing.of() private var customerEmail: JsonField = JsonMissing.of() private var customerId: JsonField = JsonMissing.of() private var customerName: JsonField = JsonMissing.of() @@ -901,11 +1126,15 @@ private constructor( private var shippingAddressRecipient: JsonField = JsonMissing.of() private var state: JsonField = JsonMissing.of() private var subtotal: JsonField = JsonMissing.of() + private var taxCode: JsonField = JsonMissing.of() private var taxDetails: JsonField>? = null private var totalDiscount: JsonField = JsonMissing.of() private var totalTax: JsonField = JsonMissing.of() + private var vatex: JsonField = JsonMissing.of() + private var vatexNote: JsonField = JsonMissing.of() private var vendorAddress: JsonField = JsonMissing.of() private var vendorAddressRecipient: JsonField = JsonMissing.of() + private var vendorCompanyId: JsonField = JsonMissing.of() private var vendorEmail: JsonField = JsonMissing.of() private var vendorName: JsonField = JsonMissing.of() private var vendorTaxId: JsonField = JsonMissing.of() @@ -913,13 +1142,16 @@ private constructor( @JvmSynthetic internal fun from(documentCreate: DocumentCreate) = apply { + allowances = documentCreate.allowances.map { it.toMutableList() } amountDue = documentCreate.amountDue attachments = documentCreate.attachments.map { it.toMutableList() } billingAddress = documentCreate.billingAddress billingAddressRecipient = documentCreate.billingAddressRecipient + charges = documentCreate.charges.map { it.toMutableList() } currency = documentCreate.currency customerAddress = documentCreate.customerAddress customerAddressRecipient = documentCreate.customerAddressRecipient + customerCompanyId = documentCreate.customerCompanyId customerEmail = documentCreate.customerEmail customerId = documentCreate.customerId customerName = documentCreate.customerName @@ -946,17 +1178,50 @@ private constructor( shippingAddressRecipient = documentCreate.shippingAddressRecipient state = documentCreate.state subtotal = documentCreate.subtotal + taxCode = documentCreate.taxCode taxDetails = documentCreate.taxDetails.map { it.toMutableList() } totalDiscount = documentCreate.totalDiscount totalTax = documentCreate.totalTax + vatex = documentCreate.vatex + vatexNote = documentCreate.vatexNote vendorAddress = documentCreate.vendorAddress vendorAddressRecipient = documentCreate.vendorAddressRecipient + vendorCompanyId = documentCreate.vendorCompanyId vendorEmail = documentCreate.vendorEmail vendorName = documentCreate.vendorName vendorTaxId = documentCreate.vendorTaxId additionalProperties = documentCreate.additionalProperties.toMutableMap() } + fun allowances(allowances: List?) = allowances(JsonField.ofNullable(allowances)) + + /** Alias for calling [Builder.allowances] with `allowances.orElse(null)`. */ + fun allowances(allowances: Optional>) = allowances(allowances.getOrNull()) + + /** + * Sets [Builder.allowances] to an arbitrary JSON value. + * + * You should usually call [Builder.allowances] with a well-typed `List` value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun allowances(allowances: JsonField>) = apply { + this.allowances = allowances.map { it.toMutableList() } + } + + /** + * Adds a single [Allowance] to [allowances]. + * + * @throws IllegalStateException if the field was previously set to a non-list. + */ + fun addAllowance(allowance: Allowance) = apply { + allowances = + (allowances ?: JsonField.of(mutableListOf())).also { + checkKnown("allowances", it).add(allowance) + } + } + + /** The amount due for payment. Must be positive and rounded to maximum 2 decimals */ fun amountDue(amountDue: AmountDue?) = amountDue(JsonField.ofNullable(amountDue)) /** Alias for calling [Builder.amountDue] with `amountDue.orElse(null)`. */ @@ -1007,6 +1272,7 @@ private constructor( } } + /** The billing address (if different from customer address) */ fun billingAddress(billingAddress: String?) = billingAddress(JsonField.ofNullable(billingAddress)) @@ -1025,6 +1291,7 @@ private constructor( this.billingAddress = billingAddress } + /** The recipient name at the billing address */ fun billingAddressRecipient(billingAddressRecipient: String?) = billingAddressRecipient(JsonField.ofNullable(billingAddressRecipient)) @@ -1046,7 +1313,35 @@ private constructor( this.billingAddressRecipient = billingAddressRecipient } - /** Currency of the invoice */ + fun charges(charges: List?) = charges(JsonField.ofNullable(charges)) + + /** Alias for calling [Builder.charges] with `charges.orElse(null)`. */ + fun charges(charges: Optional>) = charges(charges.getOrNull()) + + /** + * Sets [Builder.charges] to an arbitrary JSON value. + * + * You should usually call [Builder.charges] with a well-typed `List` value instead. + * This method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun charges(charges: JsonField>) = apply { + this.charges = charges.map { it.toMutableList() } + } + + /** + * Adds a single [Charge] to [charges]. + * + * @throws IllegalStateException if the field was previously set to a non-list. + */ + fun addCharge(charge: Charge) = apply { + charges = + (charges ?: JsonField.of(mutableListOf())).also { + checkKnown("charges", it).add(charge) + } + } + + /** Currency of the invoice (ISO 4217 currency code) */ fun currency(currency: CurrencyCode) = currency(JsonField.of(currency)) /** @@ -1058,6 +1353,7 @@ private constructor( */ fun currency(currency: JsonField) = apply { this.currency = currency } + /** The address of the customer/buyer */ fun customerAddress(customerAddress: String?) = customerAddress(JsonField.ofNullable(customerAddress)) @@ -1076,6 +1372,7 @@ private constructor( this.customerAddress = customerAddress } + /** The recipient name at the customer address */ fun customerAddressRecipient(customerAddressRecipient: String?) = customerAddressRecipient(JsonField.ofNullable(customerAddressRecipient)) @@ -1097,6 +1394,29 @@ private constructor( this.customerAddressRecipient = customerAddressRecipient } + /** + * Customer company ID. For Belgium this is the CBE number or their EUID (European Unique + * Identifier) number. In the Netherlands this is the KVK number. + */ + fun customerCompanyId(customerCompanyId: String?) = + customerCompanyId(JsonField.ofNullable(customerCompanyId)) + + /** Alias for calling [Builder.customerCompanyId] with `customerCompanyId.orElse(null)`. */ + fun customerCompanyId(customerCompanyId: Optional) = + customerCompanyId(customerCompanyId.getOrNull()) + + /** + * Sets [Builder.customerCompanyId] to an arbitrary JSON value. + * + * You should usually call [Builder.customerCompanyId] with a well-typed [String] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun customerCompanyId(customerCompanyId: JsonField) = apply { + this.customerCompanyId = customerCompanyId + } + + /** The email address of the customer */ fun customerEmail(customerEmail: String?) = customerEmail(JsonField.ofNullable(customerEmail)) @@ -1115,6 +1435,7 @@ private constructor( this.customerEmail = customerEmail } + /** The unique identifier for the customer in your system */ fun customerId(customerId: String?) = customerId(JsonField.ofNullable(customerId)) /** Alias for calling [Builder.customerId] with `customerId.orElse(null)`. */ @@ -1129,6 +1450,7 @@ private constructor( */ fun customerId(customerId: JsonField) = apply { this.customerId = customerId } + /** The company name of the customer/buyer */ fun customerName(customerName: String?) = customerName(JsonField.ofNullable(customerName)) /** Alias for calling [Builder.customerName] with `customerName.orElse(null)`. */ @@ -1145,6 +1467,7 @@ private constructor( this.customerName = customerName } + /** Customer tax ID. For Belgium this is the VAT number. Must include the country prefix */ fun customerTaxId(customerTaxId: String?) = customerTaxId(JsonField.ofNullable(customerTaxId)) @@ -1163,6 +1486,7 @@ private constructor( this.customerTaxId = customerTaxId } + /** The direction of the document: INBOUND (purchases) or OUTBOUND (sales) */ fun direction(direction: DocumentDirection) = direction(JsonField.of(direction)) /** @@ -1176,6 +1500,7 @@ private constructor( this.direction = direction } + /** The type of document: INVOICE, CREDIT_NOTE, or DEBIT_NOTE */ fun documentType(documentType: DocumentType) = documentType(JsonField.of(documentType)) /** @@ -1189,6 +1514,7 @@ private constructor( this.documentType = documentType } + /** The date when payment is due */ fun dueDate(dueDate: LocalDate?) = dueDate(JsonField.ofNullable(dueDate)) /** Alias for calling [Builder.dueDate] with `dueDate.orElse(null)`. */ @@ -1203,6 +1529,7 @@ private constructor( */ fun dueDate(dueDate: JsonField) = apply { this.dueDate = dueDate } + /** The date when the invoice was issued */ fun invoiceDate(invoiceDate: LocalDate?) = invoiceDate(JsonField.ofNullable(invoiceDate)) /** Alias for calling [Builder.invoiceDate] with `invoiceDate.orElse(null)`. */ @@ -1219,6 +1546,7 @@ private constructor( this.invoiceDate = invoiceDate } + /** The unique invoice identifier/number */ fun invoiceId(invoiceId: String?) = invoiceId(JsonField.ofNullable(invoiceId)) /** Alias for calling [Builder.invoiceId] with `invoiceId.orElse(null)`. */ @@ -1233,6 +1561,10 @@ private constructor( */ fun invoiceId(invoiceId: JsonField) = apply { this.invoiceId = invoiceId } + /** + * The total amount of the invoice including tax (invoice_total = subtotal + total_tax + + * total_discount). Must be positive and rounded to maximum 2 decimals + */ fun invoiceTotal(invoiceTotal: InvoiceTotal?) = invoiceTotal(JsonField.ofNullable(invoiceTotal)) @@ -1257,10 +1589,8 @@ private constructor( /** Alias for calling [invoiceTotal] with `InvoiceTotal.ofString(string)`. */ fun invoiceTotal(string: String) = invoiceTotal(InvoiceTotal.ofString(string)) - fun items(items: List?) = items(JsonField.ofNullable(items)) - - /** Alias for calling [Builder.items] with `items.orElse(null)`. */ - fun items(items: Optional>) = items(items.getOrNull()) + /** At least one line item is required */ + fun items(items: List) = items(JsonField.of(items)) /** * Sets [Builder.items] to an arbitrary JSON value. @@ -1283,6 +1613,7 @@ private constructor( (items ?: JsonField.of(mutableListOf())).also { checkKnown("items", it).add(item) } } + /** Additional notes or comments for the invoice */ fun note(note: String?) = note(JsonField.ofNullable(note)) /** Alias for calling [Builder.note] with `note.orElse(null)`. */ @@ -1326,6 +1657,7 @@ private constructor( } } + /** The payment terms (e.g., 'Net 30', 'Due on receipt', '2/10 Net 30') */ fun paymentTerm(paymentTerm: String?) = paymentTerm(JsonField.ofNullable(paymentTerm)) /** Alias for calling [Builder.paymentTerm] with `paymentTerm.orElse(null)`. */ @@ -1340,6 +1672,10 @@ private constructor( */ fun paymentTerm(paymentTerm: JsonField) = apply { this.paymentTerm = paymentTerm } + /** + * The previous unpaid balance from prior invoices, if any. Must be positive and rounded to + * maximum 2 decimals + */ fun previousUnpaidBalance(previousUnpaidBalance: PreviousUnpaidBalance?) = previousUnpaidBalance(JsonField.ofNullable(previousUnpaidBalance)) @@ -1373,6 +1709,7 @@ private constructor( fun previousUnpaidBalance(string: String) = previousUnpaidBalance(PreviousUnpaidBalance.ofString(string)) + /** The purchase order reference number */ fun purchaseOrder(purchaseOrder: String?) = purchaseOrder(JsonField.ofNullable(purchaseOrder)) @@ -1391,6 +1728,7 @@ private constructor( this.purchaseOrder = purchaseOrder } + /** The address where payment should be sent or remitted to */ fun remittanceAddress(remittanceAddress: String?) = remittanceAddress(JsonField.ofNullable(remittanceAddress)) @@ -1409,6 +1747,7 @@ private constructor( this.remittanceAddress = remittanceAddress } + /** The recipient name at the remittance address */ fun remittanceAddressRecipient(remittanceAddressRecipient: String?) = remittanceAddressRecipient(JsonField.ofNullable(remittanceAddressRecipient)) @@ -1430,6 +1769,7 @@ private constructor( this.remittanceAddressRecipient = remittanceAddressRecipient } + /** The address where services were performed or goods were delivered */ fun serviceAddress(serviceAddress: String?) = serviceAddress(JsonField.ofNullable(serviceAddress)) @@ -1448,6 +1788,7 @@ private constructor( this.serviceAddress = serviceAddress } + /** The recipient name at the service address */ fun serviceAddressRecipient(serviceAddressRecipient: String?) = serviceAddressRecipient(JsonField.ofNullable(serviceAddressRecipient)) @@ -1469,6 +1810,7 @@ private constructor( this.serviceAddressRecipient = serviceAddressRecipient } + /** The end date of the service period or delivery period */ fun serviceEndDate(serviceEndDate: LocalDate?) = serviceEndDate(JsonField.ofNullable(serviceEndDate)) @@ -1487,6 +1829,7 @@ private constructor( this.serviceEndDate = serviceEndDate } + /** The start date of the service period or delivery period */ fun serviceStartDate(serviceStartDate: LocalDate?) = serviceStartDate(JsonField.ofNullable(serviceStartDate)) @@ -1505,6 +1848,7 @@ private constructor( this.serviceStartDate = serviceStartDate } + /** The shipping/delivery address */ fun shippingAddress(shippingAddress: String?) = shippingAddress(JsonField.ofNullable(shippingAddress)) @@ -1523,6 +1867,7 @@ private constructor( this.shippingAddress = shippingAddress } + /** The recipient name at the shipping address */ fun shippingAddressRecipient(shippingAddressRecipient: String?) = shippingAddressRecipient(JsonField.ofNullable(shippingAddressRecipient)) @@ -1544,6 +1889,7 @@ private constructor( this.shippingAddressRecipient = shippingAddressRecipient } + /** The current state of the document: DRAFT, TRANSIT, FAILED, SENT, or RECEIVED */ fun state(state: DocumentState) = state(JsonField.of(state)) /** @@ -1555,6 +1901,11 @@ private constructor( */ fun state(state: JsonField) = apply { this.state = state } + /** + * The taxable base of the invoice. Should be the sum of all line items - allowances (for + * example commercial discounts) + charges with impact on VAT. Must be positive and rounded + * to maximum 2 decimals + */ fun subtotal(subtotal: Subtotal?) = subtotal(JsonField.ofNullable(subtotal)) /** Alias for calling [Builder.subtotal] with `subtotal.orElse(null)`. */ @@ -1575,6 +1926,20 @@ private constructor( /** Alias for calling [subtotal] with `Subtotal.ofString(string)`. */ fun subtotal(string: String) = subtotal(Subtotal.ofString(string)) + /** + * Tax category code of the invoice (e.g., S for standard rate, Z for zero rate, E for + * exempt) + */ + fun taxCode(taxCode: TaxCode) = taxCode(JsonField.of(taxCode)) + + /** + * Sets [Builder.taxCode] to an arbitrary JSON value. + * + * You should usually call [Builder.taxCode] with a well-typed [TaxCode] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun taxCode(taxCode: JsonField) = apply { this.taxCode = taxCode } + fun taxDetails(taxDetails: List?) = taxDetails(JsonField.ofNullable(taxDetails)) /** Alias for calling [Builder.taxDetails] with `taxDetails.orElse(null)`. */ @@ -1603,6 +1968,11 @@ private constructor( } } + /** + * The net financial discount/charge of the invoice (non-VAT charges minus non-VAT + * allowances). Can be positive (net charge), negative (net discount), or zero. Must be + * rounded to maximum 2 decimals + */ fun totalDiscount(totalDiscount: TotalDiscount?) = totalDiscount(JsonField.ofNullable(totalDiscount)) @@ -1627,6 +1997,9 @@ private constructor( /** Alias for calling [totalDiscount] with `TotalDiscount.ofString(string)`. */ fun totalDiscount(string: String) = totalDiscount(TotalDiscount.ofString(string)) + /** + * The total tax amount of the invoice. Must be positive and rounded to maximum 2 decimals + */ fun totalTax(totalTax: TotalTax?) = totalTax(JsonField.ofNullable(totalTax)) /** Alias for calling [Builder.totalTax] with `totalTax.orElse(null)`. */ @@ -1647,6 +2020,40 @@ private constructor( /** Alias for calling [totalTax] with `TotalTax.ofString(string)`. */ fun totalTax(string: String) = totalTax(TotalTax.ofString(string)) + /** + * VATEX code list for VAT exemption reasons + * + * Agency: CEF Identifier: vatex + */ + fun vatex(vatex: Vatex?) = vatex(JsonField.ofNullable(vatex)) + + /** Alias for calling [Builder.vatex] with `vatex.orElse(null)`. */ + fun vatex(vatex: Optional) = vatex(vatex.getOrNull()) + + /** + * Sets [Builder.vatex] to an arbitrary JSON value. + * + * You should usually call [Builder.vatex] with a well-typed [Vatex] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun vatex(vatex: JsonField) = apply { this.vatex = vatex } + + /** Textual explanation for VAT exemption */ + fun vatexNote(vatexNote: String?) = vatexNote(JsonField.ofNullable(vatexNote)) + + /** Alias for calling [Builder.vatexNote] with `vatexNote.orElse(null)`. */ + fun vatexNote(vatexNote: Optional) = vatexNote(vatexNote.getOrNull()) + + /** + * Sets [Builder.vatexNote] to an arbitrary JSON value. + * + * You should usually call [Builder.vatexNote] with a well-typed [String] value instead. + * This method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun vatexNote(vatexNote: JsonField) = apply { this.vatexNote = vatexNote } + + /** The address of the vendor/seller */ fun vendorAddress(vendorAddress: String?) = vendorAddress(JsonField.ofNullable(vendorAddress)) @@ -1665,6 +2072,7 @@ private constructor( this.vendorAddress = vendorAddress } + /** The recipient name at the vendor address */ fun vendorAddressRecipient(vendorAddressRecipient: String?) = vendorAddressRecipient(JsonField.ofNullable(vendorAddressRecipient)) @@ -1686,6 +2094,29 @@ private constructor( this.vendorAddressRecipient = vendorAddressRecipient } + /** + * Vendor company ID. For Belgium this is the CBE number or their EUID (European Unique + * Identifier) number. In the Netherlands this is the KVK number. + */ + fun vendorCompanyId(vendorCompanyId: String?) = + vendorCompanyId(JsonField.ofNullable(vendorCompanyId)) + + /** Alias for calling [Builder.vendorCompanyId] with `vendorCompanyId.orElse(null)`. */ + fun vendorCompanyId(vendorCompanyId: Optional) = + vendorCompanyId(vendorCompanyId.getOrNull()) + + /** + * Sets [Builder.vendorCompanyId] to an arbitrary JSON value. + * + * You should usually call [Builder.vendorCompanyId] with a well-typed [String] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun vendorCompanyId(vendorCompanyId: JsonField) = apply { + this.vendorCompanyId = vendorCompanyId + } + + /** The email address of the vendor */ fun vendorEmail(vendorEmail: String?) = vendorEmail(JsonField.ofNullable(vendorEmail)) /** Alias for calling [Builder.vendorEmail] with `vendorEmail.orElse(null)`. */ @@ -1700,6 +2131,7 @@ private constructor( */ fun vendorEmail(vendorEmail: JsonField) = apply { this.vendorEmail = vendorEmail } + /** The name of the vendor/seller/supplier */ fun vendorName(vendorName: String?) = vendorName(JsonField.ofNullable(vendorName)) /** Alias for calling [Builder.vendorName] with `vendorName.orElse(null)`. */ @@ -1714,6 +2146,7 @@ private constructor( */ fun vendorName(vendorName: JsonField) = apply { this.vendorName = vendorName } + /** Vendor tax ID. For Belgium this is the VAT number. Must include the country prefix */ fun vendorTaxId(vendorTaxId: String?) = vendorTaxId(JsonField.ofNullable(vendorTaxId)) /** Alias for calling [Builder.vendorTaxId] with `vendorTaxId.orElse(null)`. */ @@ -1754,13 +2187,16 @@ private constructor( */ fun build(): DocumentCreate = DocumentCreate( + (allowances ?: JsonMissing.of()).map { it.toImmutable() }, amountDue, (attachments ?: JsonMissing.of()).map { it.toImmutable() }, billingAddress, billingAddressRecipient, + (charges ?: JsonMissing.of()).map { it.toImmutable() }, currency, customerAddress, customerAddressRecipient, + customerCompanyId, customerEmail, customerId, customerName, @@ -1787,11 +2223,15 @@ private constructor( shippingAddressRecipient, state, subtotal, + taxCode, (taxDetails ?: JsonMissing.of()).map { it.toImmutable() }, totalDiscount, totalTax, + vatex, + vatexNote, vendorAddress, vendorAddressRecipient, + vendorCompanyId, vendorEmail, vendorName, vendorTaxId, @@ -1806,13 +2246,16 @@ private constructor( return@apply } + allowances().ifPresent { it.forEach { it.validate() } } amountDue().ifPresent { it.validate() } attachments().ifPresent { it.forEach { it.validate() } } billingAddress() billingAddressRecipient() + charges().ifPresent { it.forEach { it.validate() } } currency().ifPresent { it.validate() } customerAddress() customerAddressRecipient() + customerCompanyId() customerEmail() customerId() customerName() @@ -1839,11 +2282,15 @@ private constructor( shippingAddressRecipient() state().ifPresent { it.validate() } subtotal().ifPresent { it.validate() } + taxCode().ifPresent { it.validate() } taxDetails().ifPresent { it.forEach { it.validate() } } totalDiscount().ifPresent { it.validate() } totalTax().ifPresent { it.validate() } + vatex().ifPresent { it.validate() } + vatexNote() vendorAddress() vendorAddressRecipient() + vendorCompanyId() vendorEmail() vendorName() vendorTaxId() @@ -1865,13 +2312,16 @@ private constructor( */ @JvmSynthetic internal fun validity(): Int = - (amountDue.asKnown().getOrNull()?.validity() ?: 0) + + (allowances.asKnown().getOrNull()?.sumOf { it.validity().toInt() } ?: 0) + + (amountDue.asKnown().getOrNull()?.validity() ?: 0) + (attachments.asKnown().getOrNull()?.sumOf { it.validity().toInt() } ?: 0) + (if (billingAddress.asKnown().isPresent) 1 else 0) + (if (billingAddressRecipient.asKnown().isPresent) 1 else 0) + + (charges.asKnown().getOrNull()?.sumOf { it.validity().toInt() } ?: 0) + (currency.asKnown().getOrNull()?.validity() ?: 0) + (if (customerAddress.asKnown().isPresent) 1 else 0) + (if (customerAddressRecipient.asKnown().isPresent) 1 else 0) + + (if (customerCompanyId.asKnown().isPresent) 1 else 0) + (if (customerEmail.asKnown().isPresent) 1 else 0) + (if (customerId.asKnown().isPresent) 1 else 0) + (if (customerName.asKnown().isPresent) 1 else 0) + @@ -1898,816 +2348,9415 @@ private constructor( (if (shippingAddressRecipient.asKnown().isPresent) 1 else 0) + (state.asKnown().getOrNull()?.validity() ?: 0) + (subtotal.asKnown().getOrNull()?.validity() ?: 0) + + (taxCode.asKnown().getOrNull()?.validity() ?: 0) + (taxDetails.asKnown().getOrNull()?.sumOf { it.validity().toInt() } ?: 0) + (totalDiscount.asKnown().getOrNull()?.validity() ?: 0) + (totalTax.asKnown().getOrNull()?.validity() ?: 0) + + (vatex.asKnown().getOrNull()?.validity() ?: 0) + + (if (vatexNote.asKnown().isPresent) 1 else 0) + (if (vendorAddress.asKnown().isPresent) 1 else 0) + (if (vendorAddressRecipient.asKnown().isPresent) 1 else 0) + + (if (vendorCompanyId.asKnown().isPresent) 1 else 0) + (if (vendorEmail.asKnown().isPresent) 1 else 0) + (if (vendorName.asKnown().isPresent) 1 else 0) + (if (vendorTaxId.asKnown().isPresent) 1 else 0) - @JsonDeserialize(using = AmountDue.Deserializer::class) - @JsonSerialize(using = AmountDue.Serializer::class) - class AmountDue + /** An allowance is a discount for example for early payment, volume discount, etc. */ + class Allowance + @JsonCreator(mode = JsonCreator.Mode.DISABLED) private constructor( - private val number: Double? = null, - private val string: String? = null, - private val _json: JsonValue? = null, + private val amount: JsonField, + private val baseAmount: JsonField, + private val multiplierFactor: JsonField, + private val reason: JsonField, + private val reasonCode: JsonField, + private val taxCode: JsonField, + private val taxRate: JsonField, + private val additionalProperties: MutableMap, ) { - fun number(): Optional = Optional.ofNullable(number) - - fun string(): Optional = Optional.ofNullable(string) - - fun isNumber(): Boolean = number != null + @JsonCreator + private constructor( + @JsonProperty("amount") @ExcludeMissing amount: JsonField = JsonMissing.of(), + @JsonProperty("base_amount") + @ExcludeMissing + baseAmount: JsonField = JsonMissing.of(), + @JsonProperty("multiplier_factor") + @ExcludeMissing + multiplierFactor: JsonField = JsonMissing.of(), + @JsonProperty("reason") @ExcludeMissing reason: JsonField = JsonMissing.of(), + @JsonProperty("reason_code") + @ExcludeMissing + reasonCode: JsonField = JsonMissing.of(), + @JsonProperty("tax_code") + @ExcludeMissing + taxCode: JsonField = JsonMissing.of(), + @JsonProperty("tax_rate") @ExcludeMissing taxRate: JsonField = JsonMissing.of(), + ) : this( + amount, + baseAmount, + multiplierFactor, + reason, + reasonCode, + taxCode, + taxRate, + mutableMapOf(), + ) - fun isString(): Boolean = string != null + /** + * The allowance amount, without VAT. Must be rounded to maximum 2 decimals + * + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun amount(): Optional = amount.getOptional("amount") - fun asNumber(): Double = number.getOrThrow("number") + /** + * The base amount that may be used, in conjunction with the allowance percentage, to + * calculate the allowance amount. Must be rounded to maximum 2 decimals + * + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun baseAmount(): Optional = baseAmount.getOptional("base_amount") - fun asString(): String = string.getOrThrow("string") + /** + * The percentage that may be used, in conjunction with the allowance base amount, to + * calculate the allowance amount. To state 20%, use value 20. Must be rounded to maximum 2 + * decimals + * + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun multiplierFactor(): Optional = + multiplierFactor.getOptional("multiplier_factor") - fun _json(): Optional = Optional.ofNullable(_json) + /** + * The reason for the allowance + * + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun reason(): Optional = reason.getOptional("reason") - fun accept(visitor: Visitor): T = - when { - number != null -> visitor.visitNumber(number) - string != null -> visitor.visitString(string) - else -> visitor.unknown(_json) - } + /** + * Allowance reason codes for invoice discounts and charges + * + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun reasonCode(): Optional = reasonCode.getOptional("reason_code") - private var validated: Boolean = false + /** + * The VAT category code that applies to the allowance + * + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun taxCode(): Optional = taxCode.getOptional("tax_code") - fun validate(): AmountDue = apply { - if (validated) { - return@apply - } + /** + * The VAT rate, represented as percentage that applies to the allowance. Must be rounded to + * maximum 2 decimals + * + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun taxRate(): Optional = taxRate.getOptional("tax_rate") - accept( - object : Visitor { - override fun visitNumber(number: Double) {} + /** + * Returns the raw JSON value of [amount]. + * + * Unlike [amount], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("amount") @ExcludeMissing fun _amount(): JsonField = amount - override fun visitString(string: String) {} - } - ) - validated = true - } + /** + * Returns the raw JSON value of [baseAmount]. + * + * Unlike [baseAmount], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("base_amount") + @ExcludeMissing + fun _baseAmount(): JsonField = baseAmount - fun isValid(): Boolean = - try { - validate() - true - } catch (e: EInvoiceInvalidDataException) { - false - } + /** + * Returns the raw JSON value of [multiplierFactor]. + * + * Unlike [multiplierFactor], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("multiplier_factor") + @ExcludeMissing + fun _multiplierFactor(): JsonField = multiplierFactor /** - * Returns a score indicating how many valid values are contained in this object - * recursively. + * Returns the raw JSON value of [reason]. * - * Used for best match union deserialization. + * Unlike [reason], this method doesn't throw if the JSON field has an unexpected type. */ - @JvmSynthetic - internal fun validity(): Int = - accept( - object : Visitor { - override fun visitNumber(number: Double) = 1 + @JsonProperty("reason") @ExcludeMissing fun _reason(): JsonField = reason - override fun visitString(string: String) = 1 + /** + * Returns the raw JSON value of [reasonCode]. + * + * Unlike [reasonCode], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("reason_code") + @ExcludeMissing + fun _reasonCode(): JsonField = reasonCode - override fun unknown(json: JsonValue?) = 0 - } - ) + /** + * Returns the raw JSON value of [taxCode]. + * + * Unlike [taxCode], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("tax_code") @ExcludeMissing fun _taxCode(): JsonField = taxCode - override fun equals(other: Any?): Boolean { - if (this === other) { - return true - } + /** + * Returns the raw JSON value of [taxRate]. + * + * Unlike [taxRate], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("tax_rate") @ExcludeMissing fun _taxRate(): JsonField = taxRate - return other is AmountDue && number == other.number && string == other.string + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) } - override fun hashCode(): Int = Objects.hash(number, string) + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) - override fun toString(): String = - when { - number != null -> "AmountDue{number=$number}" - string != null -> "AmountDue{string=$string}" - _json != null -> "AmountDue{_unknown=$_json}" - else -> throw IllegalStateException("Invalid AmountDue") - } + fun toBuilder() = Builder().from(this) companion object { - @JvmStatic fun ofNumber(number: Double) = AmountDue(number = number) - - @JvmStatic fun ofString(string: String) = AmountDue(string = string) + /** Returns a mutable builder for constructing an instance of [Allowance]. */ + @JvmStatic fun builder() = Builder() } - /** - * An interface that defines how to map each variant of [AmountDue] to a value of type [T]. - */ - interface Visitor { + /** A builder for [Allowance]. */ + class Builder internal constructor() { - fun visitNumber(number: Double): T + private var amount: JsonField = JsonMissing.of() + private var baseAmount: JsonField = JsonMissing.of() + private var multiplierFactor: JsonField = JsonMissing.of() + private var reason: JsonField = JsonMissing.of() + private var reasonCode: JsonField = JsonMissing.of() + private var taxCode: JsonField = JsonMissing.of() + private var taxRate: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = mutableMapOf() - fun visitString(string: String): T + @JvmSynthetic + internal fun from(allowance: Allowance) = apply { + amount = allowance.amount + baseAmount = allowance.baseAmount + multiplierFactor = allowance.multiplierFactor + reason = allowance.reason + reasonCode = allowance.reasonCode + taxCode = allowance.taxCode + taxRate = allowance.taxRate + additionalProperties = allowance.additionalProperties.toMutableMap() + } + + /** The allowance amount, without VAT. Must be rounded to maximum 2 decimals */ + fun amount(amount: Amount?) = amount(JsonField.ofNullable(amount)) + + /** Alias for calling [Builder.amount] with `amount.orElse(null)`. */ + fun amount(amount: Optional) = amount(amount.getOrNull()) /** - * Maps an unknown variant of [AmountDue] to a value of type [T]. - * - * An instance of [AmountDue] can contain an unknown variant if it was deserialized from - * data that doesn't match any known variant. For example, if the SDK is on an older - * version than the API, then the API may respond with new variants that the SDK is - * unaware of. + * Sets [Builder.amount] to an arbitrary JSON value. * - * @throws EInvoiceInvalidDataException in the default implementation. + * You should usually call [Builder.amount] with a well-typed [Amount] value instead. + * This method is primarily for setting the field to an undocumented or not yet + * supported value. */ - fun unknown(json: JsonValue?): T { - throw EInvoiceInvalidDataException("Unknown AmountDue: $json") - } - } + fun amount(amount: JsonField) = apply { this.amount = amount } - internal class Deserializer : BaseDeserializer(AmountDue::class) { + /** Alias for calling [amount] with `Amount.ofNumber(number)`. */ + fun amount(number: Double) = amount(Amount.ofNumber(number)) - override fun ObjectCodec.deserialize(node: JsonNode): AmountDue { - val json = JsonValue.fromJsonNode(node) + /** Alias for calling [amount] with `Amount.ofString(string)`. */ + fun amount(string: String) = amount(Amount.ofString(string)) - val bestMatches = - sequenceOf( - tryDeserialize(node, jacksonTypeRef())?.let { - AmountDue(number = it, _json = json) - }, - tryDeserialize(node, jacksonTypeRef())?.let { - AmountDue(string = it, _json = json) - }, - ) - .filterNotNull() - .allMaxBy { it.validity() } - .toList() - return when (bestMatches.size) { - // This can happen if what we're deserializing is completely incompatible with - // all the possible variants (e.g. deserializing from object). - 0 -> AmountDue(_json = json) - 1 -> bestMatches.single() - // If there's more than one match with the highest validity, then use the first - // completely valid match, or simply the first match if none are completely - // valid. - else -> bestMatches.firstOrNull { it.isValid() } ?: bestMatches.first() - } - } - } + /** + * The base amount that may be used, in conjunction with the allowance percentage, to + * calculate the allowance amount. Must be rounded to maximum 2 decimals + */ + fun baseAmount(baseAmount: BaseAmount?) = baseAmount(JsonField.ofNullable(baseAmount)) - internal class Serializer : BaseSerializer(AmountDue::class) { + /** Alias for calling [Builder.baseAmount] with `baseAmount.orElse(null)`. */ + fun baseAmount(baseAmount: Optional) = baseAmount(baseAmount.getOrNull()) - override fun serialize( - value: AmountDue, - generator: JsonGenerator, - provider: SerializerProvider, - ) { - when { - value.number != null -> generator.writeObject(value.number) - value.string != null -> generator.writeObject(value.string) - value._json != null -> generator.writeObject(value._json) - else -> throw IllegalStateException("Invalid AmountDue") - } + /** + * Sets [Builder.baseAmount] to an arbitrary JSON value. + * + * You should usually call [Builder.baseAmount] with a well-typed [BaseAmount] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun baseAmount(baseAmount: JsonField) = apply { + this.baseAmount = baseAmount } - } - } - @JsonDeserialize(using = InvoiceTotal.Deserializer::class) - @JsonSerialize(using = InvoiceTotal.Serializer::class) - class InvoiceTotal - private constructor( - private val number: Double? = null, - private val string: String? = null, - private val _json: JsonValue? = null, - ) { + /** Alias for calling [baseAmount] with `BaseAmount.ofNumber(number)`. */ + fun baseAmount(number: Double) = baseAmount(BaseAmount.ofNumber(number)) - fun number(): Optional = Optional.ofNullable(number) + /** Alias for calling [baseAmount] with `BaseAmount.ofString(string)`. */ + fun baseAmount(string: String) = baseAmount(BaseAmount.ofString(string)) - fun string(): Optional = Optional.ofNullable(string) + /** + * The percentage that may be used, in conjunction with the allowance base amount, to + * calculate the allowance amount. To state 20%, use value 20. Must be rounded to + * maximum 2 decimals + */ + fun multiplierFactor(multiplierFactor: MultiplierFactor?) = + multiplierFactor(JsonField.ofNullable(multiplierFactor)) - fun isNumber(): Boolean = number != null + /** + * Alias for calling [Builder.multiplierFactor] with `multiplierFactor.orElse(null)`. + */ + fun multiplierFactor(multiplierFactor: Optional) = + multiplierFactor(multiplierFactor.getOrNull()) - fun isString(): Boolean = string != null + /** + * Sets [Builder.multiplierFactor] to an arbitrary JSON value. + * + * You should usually call [Builder.multiplierFactor] with a well-typed + * [MultiplierFactor] value instead. This method is primarily for setting the field to + * an undocumented or not yet supported value. + */ + fun multiplierFactor(multiplierFactor: JsonField) = apply { + this.multiplierFactor = multiplierFactor + } - fun asNumber(): Double = number.getOrThrow("number") + /** Alias for calling [multiplierFactor] with `MultiplierFactor.ofNumber(number)`. */ + fun multiplierFactor(number: Double) = + multiplierFactor(MultiplierFactor.ofNumber(number)) - fun asString(): String = string.getOrThrow("string") + /** Alias for calling [multiplierFactor] with `MultiplierFactor.ofString(string)`. */ + fun multiplierFactor(string: String) = + multiplierFactor(MultiplierFactor.ofString(string)) - fun _json(): Optional = Optional.ofNullable(_json) + /** The reason for the allowance */ + fun reason(reason: String?) = reason(JsonField.ofNullable(reason)) - fun accept(visitor: Visitor): T = - when { - number != null -> visitor.visitNumber(number) - string != null -> visitor.visitString(string) - else -> visitor.unknown(_json) - } + /** Alias for calling [Builder.reason] with `reason.orElse(null)`. */ + fun reason(reason: Optional) = reason(reason.getOrNull()) - private var validated: Boolean = false + /** + * Sets [Builder.reason] to an arbitrary JSON value. + * + * You should usually call [Builder.reason] with a well-typed [String] value instead. + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun reason(reason: JsonField) = apply { this.reason = reason } - fun validate(): InvoiceTotal = apply { - if (validated) { - return@apply + /** Allowance reason codes for invoice discounts and charges */ + fun reasonCode(reasonCode: ReasonCode?) = reasonCode(JsonField.ofNullable(reasonCode)) + + /** Alias for calling [Builder.reasonCode] with `reasonCode.orElse(null)`. */ + fun reasonCode(reasonCode: Optional) = reasonCode(reasonCode.getOrNull()) + + /** + * Sets [Builder.reasonCode] to an arbitrary JSON value. + * + * You should usually call [Builder.reasonCode] with a well-typed [ReasonCode] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun reasonCode(reasonCode: JsonField) = apply { + this.reasonCode = reasonCode } - accept( - object : Visitor { - override fun visitNumber(number: Double) {} + /** The VAT category code that applies to the allowance */ + fun taxCode(taxCode: TaxCode) = taxCode(JsonField.of(taxCode)) - override fun visitString(string: String) {} - } - ) - validated = true - } + /** + * Sets [Builder.taxCode] to an arbitrary JSON value. + * + * You should usually call [Builder.taxCode] with a well-typed [TaxCode] value instead. + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun taxCode(taxCode: JsonField) = apply { this.taxCode = taxCode } - fun isValid(): Boolean = - try { - validate() - true - } catch (e: EInvoiceInvalidDataException) { - false - } + /** + * The VAT rate, represented as percentage that applies to the allowance. Must be + * rounded to maximum 2 decimals + */ + fun taxRate(taxRate: TaxRate?) = taxRate(JsonField.ofNullable(taxRate)) - /** - * Returns a score indicating how many valid values are contained in this object + /** Alias for calling [Builder.taxRate] with `taxRate.orElse(null)`. */ + fun taxRate(taxRate: Optional) = taxRate(taxRate.getOrNull()) + + /** + * Sets [Builder.taxRate] to an arbitrary JSON value. + * + * You should usually call [Builder.taxRate] with a well-typed [TaxRate] value instead. + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun taxRate(taxRate: JsonField) = apply { this.taxRate = taxRate } + + /** Alias for calling [taxRate] with `TaxRate.ofNumber(number)`. */ + fun taxRate(number: Double) = taxRate(TaxRate.ofNumber(number)) + + /** Alias for calling [taxRate] with `TaxRate.ofString(string)`. */ + fun taxRate(string: String) = taxRate(TaxRate.ofString(string)) + + fun additionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.clear() + putAllAdditionalProperties(additionalProperties) + } + + fun putAdditionalProperty(key: String, value: JsonValue) = apply { + additionalProperties.put(key, value) + } + + fun putAllAdditionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.putAll(additionalProperties) + } + + fun removeAdditionalProperty(key: String) = apply { additionalProperties.remove(key) } + + fun removeAllAdditionalProperties(keys: Set) = apply { + keys.forEach(::removeAdditionalProperty) + } + + /** + * Returns an immutable instance of [Allowance]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): Allowance = + Allowance( + amount, + baseAmount, + multiplierFactor, + reason, + reasonCode, + taxCode, + taxRate, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + fun validate(): Allowance = apply { + if (validated) { + return@apply + } + + amount().ifPresent { it.validate() } + baseAmount().ifPresent { it.validate() } + multiplierFactor().ifPresent { it.validate() } + reason() + reasonCode().ifPresent { it.validate() } + taxCode().ifPresent { it.validate() } + taxRate().ifPresent { it.validate() } + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: EInvoiceInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object * recursively. * * Used for best match union deserialization. */ @JvmSynthetic internal fun validity(): Int = - accept( - object : Visitor { - override fun visitNumber(number: Double) = 1 + (amount.asKnown().getOrNull()?.validity() ?: 0) + + (baseAmount.asKnown().getOrNull()?.validity() ?: 0) + + (multiplierFactor.asKnown().getOrNull()?.validity() ?: 0) + + (if (reason.asKnown().isPresent) 1 else 0) + + (reasonCode.asKnown().getOrNull()?.validity() ?: 0) + + (taxCode.asKnown().getOrNull()?.validity() ?: 0) + + (taxRate.asKnown().getOrNull()?.validity() ?: 0) + + /** The allowance amount, without VAT. Must be rounded to maximum 2 decimals */ + @JsonDeserialize(using = Amount.Deserializer::class) + @JsonSerialize(using = Amount.Serializer::class) + class Amount + private constructor( + private val number: Double? = null, + private val string: String? = null, + private val _json: JsonValue? = null, + ) { - override fun visitString(string: String) = 1 + fun number(): Optional = Optional.ofNullable(number) - override fun unknown(json: JsonValue?) = 0 - } - ) + fun string(): Optional = Optional.ofNullable(string) - override fun equals(other: Any?): Boolean { - if (this === other) { - return true - } + fun isNumber(): Boolean = number != null - return other is InvoiceTotal && number == other.number && string == other.string - } + fun isString(): Boolean = string != null - override fun hashCode(): Int = Objects.hash(number, string) + fun asNumber(): Double = number.getOrThrow("number") - override fun toString(): String = - when { - number != null -> "InvoiceTotal{number=$number}" - string != null -> "InvoiceTotal{string=$string}" - _json != null -> "InvoiceTotal{_unknown=$_json}" - else -> throw IllegalStateException("Invalid InvoiceTotal") - } + fun asString(): String = string.getOrThrow("string") - companion object { + fun _json(): Optional = Optional.ofNullable(_json) - @JvmStatic fun ofNumber(number: Double) = InvoiceTotal(number = number) + fun accept(visitor: Visitor): T = + when { + number != null -> visitor.visitNumber(number) + string != null -> visitor.visitString(string) + else -> visitor.unknown(_json) + } - @JvmStatic fun ofString(string: String) = InvoiceTotal(string = string) - } + private var validated: Boolean = false - /** - * An interface that defines how to map each variant of [InvoiceTotal] to a value of type - * [T]. - */ - interface Visitor { + fun validate(): Amount = apply { + if (validated) { + return@apply + } - fun visitNumber(number: Double): T + accept( + object : Visitor { + override fun visitNumber(number: Double) {} - fun visitString(string: String): T + override fun visitString(string: String) {} + } + ) + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: EInvoiceInvalidDataException) { + false + } /** - * Maps an unknown variant of [InvoiceTotal] to a value of type [T]. - * - * An instance of [InvoiceTotal] can contain an unknown variant if it was deserialized - * from data that doesn't match any known variant. For example, if the SDK is on an - * older version than the API, then the API may respond with new variants that the SDK - * is unaware of. + * Returns a score indicating how many valid values are contained in this object + * recursively. * - * @throws EInvoiceInvalidDataException in the default implementation. + * Used for best match union deserialization. */ - fun unknown(json: JsonValue?): T { - throw EInvoiceInvalidDataException("Unknown InvoiceTotal: $json") - } - } + @JvmSynthetic + internal fun validity(): Int = + accept( + object : Visitor { + override fun visitNumber(number: Double) = 1 - internal class Deserializer : BaseDeserializer(InvoiceTotal::class) { + override fun visitString(string: String) = 1 - override fun ObjectCodec.deserialize(node: JsonNode): InvoiceTotal { - val json = JsonValue.fromJsonNode(node) + override fun unknown(json: JsonValue?) = 0 + } + ) - val bestMatches = - sequenceOf( - tryDeserialize(node, jacksonTypeRef())?.let { - InvoiceTotal(number = it, _json = json) - }, - tryDeserialize(node, jacksonTypeRef())?.let { - InvoiceTotal(string = it, _json = json) - }, - ) - .filterNotNull() - .allMaxBy { it.validity() } - .toList() - return when (bestMatches.size) { - // This can happen if what we're deserializing is completely incompatible with - // all the possible variants (e.g. deserializing from object). - 0 -> InvoiceTotal(_json = json) - 1 -> bestMatches.single() - // If there's more than one match with the highest validity, then use the first - // completely valid match, or simply the first match if none are completely - // valid. - else -> bestMatches.firstOrNull { it.isValid() } ?: bestMatches.first() + override fun equals(other: Any?): Boolean { + if (this === other) { + return true } + + return other is Amount && number == other.number && string == other.string } - } - internal class Serializer : BaseSerializer(InvoiceTotal::class) { + override fun hashCode(): Int = Objects.hash(number, string) - override fun serialize( - value: InvoiceTotal, - generator: JsonGenerator, - provider: SerializerProvider, - ) { + override fun toString(): String = when { - value.number != null -> generator.writeObject(value.number) - value.string != null -> generator.writeObject(value.string) - value._json != null -> generator.writeObject(value._json) - else -> throw IllegalStateException("Invalid InvoiceTotal") + number != null -> "Amount{number=$number}" + string != null -> "Amount{string=$string}" + _json != null -> "Amount{_unknown=$_json}" + else -> throw IllegalStateException("Invalid Amount") } - } - } - } - class Item - @JsonCreator(mode = JsonCreator.Mode.DISABLED) - private constructor( - private val amount: JsonField, - private val date: JsonField, - private val description: JsonField, - private val productCode: JsonField, - private val quantity: JsonField, - private val tax: JsonField, - private val taxRate: JsonField, - private val unit: JsonField, - private val unitPrice: JsonField, - private val additionalProperties: MutableMap, - ) { + companion object { - @JsonCreator - private constructor( - @JsonProperty("amount") @ExcludeMissing amount: JsonField = JsonMissing.of(), - @JsonProperty("date") @ExcludeMissing date: JsonField = JsonMissing.of(), - @JsonProperty("description") - @ExcludeMissing - description: JsonField = JsonMissing.of(), - @JsonProperty("product_code") - @ExcludeMissing - productCode: JsonField = JsonMissing.of(), - @JsonProperty("quantity") - @ExcludeMissing - quantity: JsonField = JsonMissing.of(), - @JsonProperty("tax") @ExcludeMissing tax: JsonField = JsonMissing.of(), - @JsonProperty("tax_rate") @ExcludeMissing taxRate: JsonField = JsonMissing.of(), - @JsonProperty("unit") - @ExcludeMissing - unit: JsonField = JsonMissing.of(), - @JsonProperty("unit_price") - @ExcludeMissing - unitPrice: JsonField = JsonMissing.of(), - ) : this( - amount, - date, - description, - productCode, - quantity, - tax, - taxRate, - unit, - unitPrice, - mutableMapOf(), - ) + @JvmStatic fun ofNumber(number: Double) = Amount(number = number) - /** - * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if - * the server responded with an unexpected value). - */ - fun amount(): Optional = amount.getOptional("amount") + @JvmStatic fun ofString(string: String) = Amount(string = string) + } - /** - * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if - * the server responded with an unexpected value). - */ - fun date(): Optional = date.getOptional("date") + /** + * An interface that defines how to map each variant of [Amount] to a value of type [T]. + */ + interface Visitor { - /** - * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if - * the server responded with an unexpected value). - */ - fun description(): Optional = description.getOptional("description") + fun visitNumber(number: Double): T + + fun visitString(string: String): T + + /** + * Maps an unknown variant of [Amount] to a value of type [T]. + * + * An instance of [Amount] can contain an unknown variant if it was deserialized + * from data that doesn't match any known variant. For example, if the SDK is on an + * older version than the API, then the API may respond with new variants that the + * SDK is unaware of. + * + * @throws EInvoiceInvalidDataException in the default implementation. + */ + fun unknown(json: JsonValue?): T { + throw EInvoiceInvalidDataException("Unknown Amount: $json") + } + } + + internal class Deserializer : BaseDeserializer(Amount::class) { + + override fun ObjectCodec.deserialize(node: JsonNode): Amount { + val json = JsonValue.fromJsonNode(node) + + val bestMatches = + sequenceOf( + tryDeserialize(node, jacksonTypeRef())?.let { + Amount(string = it, _json = json) + }, + tryDeserialize(node, jacksonTypeRef())?.let { + Amount(number = it, _json = json) + }, + ) + .filterNotNull() + .allMaxBy { it.validity() } + .toList() + return when (bestMatches.size) { + // This can happen if what we're deserializing is completely incompatible + // with all the possible variants (e.g. deserializing from boolean). + 0 -> Amount(_json = json) + 1 -> bestMatches.single() + // If there's more than one match with the highest validity, then use the + // first completely valid match, or simply the first match if none are + // completely valid. + else -> bestMatches.firstOrNull { it.isValid() } ?: bestMatches.first() + } + } + } + + internal class Serializer : BaseSerializer(Amount::class) { + + override fun serialize( + value: Amount, + generator: JsonGenerator, + provider: SerializerProvider, + ) { + when { + value.number != null -> generator.writeObject(value.number) + value.string != null -> generator.writeObject(value.string) + value._json != null -> generator.writeObject(value._json) + else -> throw IllegalStateException("Invalid Amount") + } + } + } + } /** - * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if - * the server responded with an unexpected value). + * The base amount that may be used, in conjunction with the allowance percentage, to + * calculate the allowance amount. Must be rounded to maximum 2 decimals */ - fun productCode(): Optional = productCode.getOptional("product_code") + @JsonDeserialize(using = BaseAmount.Deserializer::class) + @JsonSerialize(using = BaseAmount.Serializer::class) + class BaseAmount + private constructor( + private val number: Double? = null, + private val string: String? = null, + private val _json: JsonValue? = null, + ) { + + fun number(): Optional = Optional.ofNullable(number) + + fun string(): Optional = Optional.ofNullable(string) + + fun isNumber(): Boolean = number != null + + fun isString(): Boolean = string != null + + fun asNumber(): Double = number.getOrThrow("number") + + fun asString(): String = string.getOrThrow("string") + + fun _json(): Optional = Optional.ofNullable(_json) + + fun accept(visitor: Visitor): T = + when { + number != null -> visitor.visitNumber(number) + string != null -> visitor.visitString(string) + else -> visitor.unknown(_json) + } + + private var validated: Boolean = false + + fun validate(): BaseAmount = apply { + if (validated) { + return@apply + } + + accept( + object : Visitor { + override fun visitNumber(number: Double) {} + + override fun visitString(string: String) {} + } + ) + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: EInvoiceInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic + internal fun validity(): Int = + accept( + object : Visitor { + override fun visitNumber(number: Double) = 1 + + override fun visitString(string: String) = 1 + + override fun unknown(json: JsonValue?) = 0 + } + ) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is BaseAmount && number == other.number && string == other.string + } + + override fun hashCode(): Int = Objects.hash(number, string) + + override fun toString(): String = + when { + number != null -> "BaseAmount{number=$number}" + string != null -> "BaseAmount{string=$string}" + _json != null -> "BaseAmount{_unknown=$_json}" + else -> throw IllegalStateException("Invalid BaseAmount") + } + + companion object { + + @JvmStatic fun ofNumber(number: Double) = BaseAmount(number = number) + + @JvmStatic fun ofString(string: String) = BaseAmount(string = string) + } + + /** + * An interface that defines how to map each variant of [BaseAmount] to a value of type + * [T]. + */ + interface Visitor { + + fun visitNumber(number: Double): T + + fun visitString(string: String): T + + /** + * Maps an unknown variant of [BaseAmount] to a value of type [T]. + * + * An instance of [BaseAmount] can contain an unknown variant if it was deserialized + * from data that doesn't match any known variant. For example, if the SDK is on an + * older version than the API, then the API may respond with new variants that the + * SDK is unaware of. + * + * @throws EInvoiceInvalidDataException in the default implementation. + */ + fun unknown(json: JsonValue?): T { + throw EInvoiceInvalidDataException("Unknown BaseAmount: $json") + } + } + + internal class Deserializer : BaseDeserializer(BaseAmount::class) { + + override fun ObjectCodec.deserialize(node: JsonNode): BaseAmount { + val json = JsonValue.fromJsonNode(node) + + val bestMatches = + sequenceOf( + tryDeserialize(node, jacksonTypeRef())?.let { + BaseAmount(string = it, _json = json) + }, + tryDeserialize(node, jacksonTypeRef())?.let { + BaseAmount(number = it, _json = json) + }, + ) + .filterNotNull() + .allMaxBy { it.validity() } + .toList() + return when (bestMatches.size) { + // This can happen if what we're deserializing is completely incompatible + // with all the possible variants (e.g. deserializing from boolean). + 0 -> BaseAmount(_json = json) + 1 -> bestMatches.single() + // If there's more than one match with the highest validity, then use the + // first completely valid match, or simply the first match if none are + // completely valid. + else -> bestMatches.firstOrNull { it.isValid() } ?: bestMatches.first() + } + } + } + + internal class Serializer : BaseSerializer(BaseAmount::class) { + + override fun serialize( + value: BaseAmount, + generator: JsonGenerator, + provider: SerializerProvider, + ) { + when { + value.number != null -> generator.writeObject(value.number) + value.string != null -> generator.writeObject(value.string) + value._json != null -> generator.writeObject(value._json) + else -> throw IllegalStateException("Invalid BaseAmount") + } + } + } + } /** - * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if - * the server responded with an unexpected value). + * The percentage that may be used, in conjunction with the allowance base amount, to + * calculate the allowance amount. To state 20%, use value 20. Must be rounded to maximum 2 + * decimals */ - fun quantity(): Optional = quantity.getOptional("quantity") + @JsonDeserialize(using = MultiplierFactor.Deserializer::class) + @JsonSerialize(using = MultiplierFactor.Serializer::class) + class MultiplierFactor + private constructor( + private val number: Double? = null, + private val string: String? = null, + private val _json: JsonValue? = null, + ) { + + fun number(): Optional = Optional.ofNullable(number) + + fun string(): Optional = Optional.ofNullable(string) + + fun isNumber(): Boolean = number != null + + fun isString(): Boolean = string != null + + fun asNumber(): Double = number.getOrThrow("number") + + fun asString(): String = string.getOrThrow("string") + + fun _json(): Optional = Optional.ofNullable(_json) + + fun accept(visitor: Visitor): T = + when { + number != null -> visitor.visitNumber(number) + string != null -> visitor.visitString(string) + else -> visitor.unknown(_json) + } + + private var validated: Boolean = false + + fun validate(): MultiplierFactor = apply { + if (validated) { + return@apply + } + + accept( + object : Visitor { + override fun visitNumber(number: Double) {} + + override fun visitString(string: String) {} + } + ) + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: EInvoiceInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic + internal fun validity(): Int = + accept( + object : Visitor { + override fun visitNumber(number: Double) = 1 + + override fun visitString(string: String) = 1 + + override fun unknown(json: JsonValue?) = 0 + } + ) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is MultiplierFactor && number == other.number && string == other.string + } + + override fun hashCode(): Int = Objects.hash(number, string) + + override fun toString(): String = + when { + number != null -> "MultiplierFactor{number=$number}" + string != null -> "MultiplierFactor{string=$string}" + _json != null -> "MultiplierFactor{_unknown=$_json}" + else -> throw IllegalStateException("Invalid MultiplierFactor") + } + + companion object { + + @JvmStatic fun ofNumber(number: Double) = MultiplierFactor(number = number) + + @JvmStatic fun ofString(string: String) = MultiplierFactor(string = string) + } + + /** + * An interface that defines how to map each variant of [MultiplierFactor] to a value of + * type [T]. + */ + interface Visitor { + + fun visitNumber(number: Double): T + + fun visitString(string: String): T + + /** + * Maps an unknown variant of [MultiplierFactor] to a value of type [T]. + * + * An instance of [MultiplierFactor] can contain an unknown variant if it was + * deserialized from data that doesn't match any known variant. For example, if the + * SDK is on an older version than the API, then the API may respond with new + * variants that the SDK is unaware of. + * + * @throws EInvoiceInvalidDataException in the default implementation. + */ + fun unknown(json: JsonValue?): T { + throw EInvoiceInvalidDataException("Unknown MultiplierFactor: $json") + } + } + + internal class Deserializer : + BaseDeserializer(MultiplierFactor::class) { + + override fun ObjectCodec.deserialize(node: JsonNode): MultiplierFactor { + val json = JsonValue.fromJsonNode(node) + + val bestMatches = + sequenceOf( + tryDeserialize(node, jacksonTypeRef())?.let { + MultiplierFactor(string = it, _json = json) + }, + tryDeserialize(node, jacksonTypeRef())?.let { + MultiplierFactor(number = it, _json = json) + }, + ) + .filterNotNull() + .allMaxBy { it.validity() } + .toList() + return when (bestMatches.size) { + // This can happen if what we're deserializing is completely incompatible + // with all the possible variants (e.g. deserializing from boolean). + 0 -> MultiplierFactor(_json = json) + 1 -> bestMatches.single() + // If there's more than one match with the highest validity, then use the + // first completely valid match, or simply the first match if none are + // completely valid. + else -> bestMatches.firstOrNull { it.isValid() } ?: bestMatches.first() + } + } + } + + internal class Serializer : BaseSerializer(MultiplierFactor::class) { + + override fun serialize( + value: MultiplierFactor, + generator: JsonGenerator, + provider: SerializerProvider, + ) { + when { + value.number != null -> generator.writeObject(value.number) + value.string != null -> generator.writeObject(value.string) + value._json != null -> generator.writeObject(value._json) + else -> throw IllegalStateException("Invalid MultiplierFactor") + } + } + } + } + + /** Allowance reason codes for invoice discounts and charges */ + class ReasonCode @JsonCreator private constructor(private val value: JsonField) : + Enum { + + /** + * Returns this class instance's raw value. + * + * This is usually only useful if this instance was deserialized from data that doesn't + * match any known member, and you want to know that value. For example, if the SDK is + * on an older version than the API, then the API may respond with new members that the + * SDK is unaware of. + */ + @com.fasterxml.jackson.annotation.JsonValue fun _value(): JsonField = value + + companion object { + + @JvmField val _41 = of("41") + + @JvmField val _42 = of("42") + + @JvmField val _60 = of("60") + + @JvmField val _62 = of("62") + + @JvmField val _63 = of("63") + + @JvmField val _64 = of("64") + + @JvmField val _65 = of("65") + + @JvmField val _66 = of("66") + + @JvmField val _67 = of("67") + + @JvmField val _68 = of("68") + + @JvmField val _70 = of("70") + + @JvmField val _71 = of("71") + + @JvmField val _88 = of("88") + + @JvmField val _95 = of("95") + + @JvmField val _100 = of("100") + + @JvmField val _102 = of("102") + + @JvmField val _103 = of("103") + + @JvmField val _104 = of("104") + + @JvmField val _105 = of("105") + + @JvmStatic fun of(value: String) = ReasonCode(JsonField.of(value)) + } + + /** An enum containing [ReasonCode]'s known values. */ + enum class Known { + _41, + _42, + _60, + _62, + _63, + _64, + _65, + _66, + _67, + _68, + _70, + _71, + _88, + _95, + _100, + _102, + _103, + _104, + _105, + } + + /** + * An enum containing [ReasonCode]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [ReasonCode] can contain an unknown value in a couple of cases: + * - It was deserialized from data that doesn't match any known member. For example, if + * the SDK is on an older version than the API, then the API may respond with new + * members that the SDK is unaware of. + * - It was constructed with an arbitrary value using the [of] method. + */ + enum class Value { + _41, + _42, + _60, + _62, + _63, + _64, + _65, + _66, + _67, + _68, + _70, + _71, + _88, + _95, + _100, + _102, + _103, + _104, + _105, + /** + * An enum member indicating that [ReasonCode] was instantiated with an unknown + * value. + */ + _UNKNOWN, + } + + /** + * Returns an enum member corresponding to this class instance's value, or + * [Value._UNKNOWN] if the class was instantiated with an unknown value. + * + * Use the [known] method instead if you're certain the value is always known or if you + * want to throw for the unknown case. + */ + fun value(): Value = + when (this) { + _41 -> Value._41 + _42 -> Value._42 + _60 -> Value._60 + _62 -> Value._62 + _63 -> Value._63 + _64 -> Value._64 + _65 -> Value._65 + _66 -> Value._66 + _67 -> Value._67 + _68 -> Value._68 + _70 -> Value._70 + _71 -> Value._71 + _88 -> Value._88 + _95 -> Value._95 + _100 -> Value._100 + _102 -> Value._102 + _103 -> Value._103 + _104 -> Value._104 + _105 -> Value._105 + else -> Value._UNKNOWN + } + + /** + * Returns an enum member corresponding to this class instance's value. + * + * Use the [value] method instead if you're uncertain the value is always known and + * don't want to throw for the unknown case. + * + * @throws EInvoiceInvalidDataException if this class instance's value is a not a known + * member. + */ + fun known(): Known = + when (this) { + _41 -> Known._41 + _42 -> Known._42 + _60 -> Known._60 + _62 -> Known._62 + _63 -> Known._63 + _64 -> Known._64 + _65 -> Known._65 + _66 -> Known._66 + _67 -> Known._67 + _68 -> Known._68 + _70 -> Known._70 + _71 -> Known._71 + _88 -> Known._88 + _95 -> Known._95 + _100 -> Known._100 + _102 -> Known._102 + _103 -> Known._103 + _104 -> Known._104 + _105 -> Known._105 + else -> throw EInvoiceInvalidDataException("Unknown ReasonCode: $value") + } + + /** + * Returns this class instance's primitive wire representation. + * + * This differs from the [toString] method because that method is primarily for + * debugging and generally doesn't throw. + * + * @throws EInvoiceInvalidDataException if this class instance's value does not have the + * expected primitive type. + */ + fun asString(): String = + _value().asString().orElseThrow { + EInvoiceInvalidDataException("Value is not a String") + } + + private var validated: Boolean = false + + fun validate(): ReasonCode = apply { + if (validated) { + return@apply + } + + known() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: EInvoiceInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic internal fun validity(): Int = if (value() == Value._UNKNOWN) 0 else 1 + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is ReasonCode && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + /** The VAT category code that applies to the allowance */ + class TaxCode @JsonCreator private constructor(private val value: JsonField) : + Enum { + + /** + * Returns this class instance's raw value. + * + * This is usually only useful if this instance was deserialized from data that doesn't + * match any known member, and you want to know that value. For example, if the SDK is + * on an older version than the API, then the API may respond with new members that the + * SDK is unaware of. + */ + @com.fasterxml.jackson.annotation.JsonValue fun _value(): JsonField = value + + companion object { + + @JvmField val AE = of("AE") + + @JvmField val E = of("E") + + @JvmField val S = of("S") + + @JvmField val Z = of("Z") + + @JvmField val G = of("G") + + @JvmField val O = of("O") + + @JvmField val K = of("K") + + @JvmField val L = of("L") + + @JvmField val M = of("M") + + @JvmField val B = of("B") + + @JvmStatic fun of(value: String) = TaxCode(JsonField.of(value)) + } + + /** An enum containing [TaxCode]'s known values. */ + enum class Known { + AE, + E, + S, + Z, + G, + O, + K, + L, + M, + B, + } + + /** + * An enum containing [TaxCode]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [TaxCode] can contain an unknown value in a couple of cases: + * - It was deserialized from data that doesn't match any known member. For example, if + * the SDK is on an older version than the API, then the API may respond with new + * members that the SDK is unaware of. + * - It was constructed with an arbitrary value using the [of] method. + */ + enum class Value { + AE, + E, + S, + Z, + G, + O, + K, + L, + M, + B, + /** + * An enum member indicating that [TaxCode] was instantiated with an unknown value. + */ + _UNKNOWN, + } + + /** + * Returns an enum member corresponding to this class instance's value, or + * [Value._UNKNOWN] if the class was instantiated with an unknown value. + * + * Use the [known] method instead if you're certain the value is always known or if you + * want to throw for the unknown case. + */ + fun value(): Value = + when (this) { + AE -> Value.AE + E -> Value.E + S -> Value.S + Z -> Value.Z + G -> Value.G + O -> Value.O + K -> Value.K + L -> Value.L + M -> Value.M + B -> Value.B + else -> Value._UNKNOWN + } + + /** + * Returns an enum member corresponding to this class instance's value. + * + * Use the [value] method instead if you're uncertain the value is always known and + * don't want to throw for the unknown case. + * + * @throws EInvoiceInvalidDataException if this class instance's value is a not a known + * member. + */ + fun known(): Known = + when (this) { + AE -> Known.AE + E -> Known.E + S -> Known.S + Z -> Known.Z + G -> Known.G + O -> Known.O + K -> Known.K + L -> Known.L + M -> Known.M + B -> Known.B + else -> throw EInvoiceInvalidDataException("Unknown TaxCode: $value") + } + + /** + * Returns this class instance's primitive wire representation. + * + * This differs from the [toString] method because that method is primarily for + * debugging and generally doesn't throw. + * + * @throws EInvoiceInvalidDataException if this class instance's value does not have the + * expected primitive type. + */ + fun asString(): String = + _value().asString().orElseThrow { + EInvoiceInvalidDataException("Value is not a String") + } + + private var validated: Boolean = false + + fun validate(): TaxCode = apply { + if (validated) { + return@apply + } + + known() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: EInvoiceInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic internal fun validity(): Int = if (value() == Value._UNKNOWN) 0 else 1 + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is TaxCode && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + /** + * The VAT rate, represented as percentage that applies to the allowance. Must be rounded to + * maximum 2 decimals + */ + @JsonDeserialize(using = TaxRate.Deserializer::class) + @JsonSerialize(using = TaxRate.Serializer::class) + class TaxRate + private constructor( + private val number: Double? = null, + private val string: String? = null, + private val _json: JsonValue? = null, + ) { + + fun number(): Optional = Optional.ofNullable(number) + + fun string(): Optional = Optional.ofNullable(string) + + fun isNumber(): Boolean = number != null + + fun isString(): Boolean = string != null + + fun asNumber(): Double = number.getOrThrow("number") + + fun asString(): String = string.getOrThrow("string") + + fun _json(): Optional = Optional.ofNullable(_json) + + fun accept(visitor: Visitor): T = + when { + number != null -> visitor.visitNumber(number) + string != null -> visitor.visitString(string) + else -> visitor.unknown(_json) + } + + private var validated: Boolean = false + + fun validate(): TaxRate = apply { + if (validated) { + return@apply + } + + accept( + object : Visitor { + override fun visitNumber(number: Double) {} + + override fun visitString(string: String) {} + } + ) + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: EInvoiceInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic + internal fun validity(): Int = + accept( + object : Visitor { + override fun visitNumber(number: Double) = 1 + + override fun visitString(string: String) = 1 + + override fun unknown(json: JsonValue?) = 0 + } + ) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is TaxRate && number == other.number && string == other.string + } + + override fun hashCode(): Int = Objects.hash(number, string) + + override fun toString(): String = + when { + number != null -> "TaxRate{number=$number}" + string != null -> "TaxRate{string=$string}" + _json != null -> "TaxRate{_unknown=$_json}" + else -> throw IllegalStateException("Invalid TaxRate") + } + + companion object { + + @JvmStatic fun ofNumber(number: Double) = TaxRate(number = number) + + @JvmStatic fun ofString(string: String) = TaxRate(string = string) + } + + /** + * An interface that defines how to map each variant of [TaxRate] to a value of type + * [T]. + */ + interface Visitor { + + fun visitNumber(number: Double): T + + fun visitString(string: String): T + + /** + * Maps an unknown variant of [TaxRate] to a value of type [T]. + * + * An instance of [TaxRate] can contain an unknown variant if it was deserialized + * from data that doesn't match any known variant. For example, if the SDK is on an + * older version than the API, then the API may respond with new variants that the + * SDK is unaware of. + * + * @throws EInvoiceInvalidDataException in the default implementation. + */ + fun unknown(json: JsonValue?): T { + throw EInvoiceInvalidDataException("Unknown TaxRate: $json") + } + } + + internal class Deserializer : BaseDeserializer(TaxRate::class) { + + override fun ObjectCodec.deserialize(node: JsonNode): TaxRate { + val json = JsonValue.fromJsonNode(node) + + val bestMatches = + sequenceOf( + tryDeserialize(node, jacksonTypeRef())?.let { + TaxRate(string = it, _json = json) + }, + tryDeserialize(node, jacksonTypeRef())?.let { + TaxRate(number = it, _json = json) + }, + ) + .filterNotNull() + .allMaxBy { it.validity() } + .toList() + return when (bestMatches.size) { + // This can happen if what we're deserializing is completely incompatible + // with all the possible variants (e.g. deserializing from boolean). + 0 -> TaxRate(_json = json) + 1 -> bestMatches.single() + // If there's more than one match with the highest validity, then use the + // first completely valid match, or simply the first match if none are + // completely valid. + else -> bestMatches.firstOrNull { it.isValid() } ?: bestMatches.first() + } + } + } + + internal class Serializer : BaseSerializer(TaxRate::class) { + + override fun serialize( + value: TaxRate, + generator: JsonGenerator, + provider: SerializerProvider, + ) { + when { + value.number != null -> generator.writeObject(value.number) + value.string != null -> generator.writeObject(value.string) + value._json != null -> generator.writeObject(value._json) + else -> throw IllegalStateException("Invalid TaxRate") + } + } + } + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Allowance && + amount == other.amount && + baseAmount == other.baseAmount && + multiplierFactor == other.multiplierFactor && + reason == other.reason && + reasonCode == other.reasonCode && + taxCode == other.taxCode && + taxRate == other.taxRate && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash( + amount, + baseAmount, + multiplierFactor, + reason, + reasonCode, + taxCode, + taxRate, + additionalProperties, + ) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "Allowance{amount=$amount, baseAmount=$baseAmount, multiplierFactor=$multiplierFactor, reason=$reason, reasonCode=$reasonCode, taxCode=$taxCode, taxRate=$taxRate, additionalProperties=$additionalProperties}" + } + + /** The amount due for payment. Must be positive and rounded to maximum 2 decimals */ + @JsonDeserialize(using = AmountDue.Deserializer::class) + @JsonSerialize(using = AmountDue.Serializer::class) + class AmountDue + private constructor( + private val number: Double? = null, + private val string: String? = null, + private val _json: JsonValue? = null, + ) { + + fun number(): Optional = Optional.ofNullable(number) + + fun string(): Optional = Optional.ofNullable(string) + + fun isNumber(): Boolean = number != null + + fun isString(): Boolean = string != null + + fun asNumber(): Double = number.getOrThrow("number") + + fun asString(): String = string.getOrThrow("string") + + fun _json(): Optional = Optional.ofNullable(_json) + + fun accept(visitor: Visitor): T = + when { + number != null -> visitor.visitNumber(number) + string != null -> visitor.visitString(string) + else -> visitor.unknown(_json) + } + + private var validated: Boolean = false + + fun validate(): AmountDue = apply { + if (validated) { + return@apply + } + + accept( + object : Visitor { + override fun visitNumber(number: Double) {} + + override fun visitString(string: String) {} + } + ) + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: EInvoiceInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic + internal fun validity(): Int = + accept( + object : Visitor { + override fun visitNumber(number: Double) = 1 + + override fun visitString(string: String) = 1 + + override fun unknown(json: JsonValue?) = 0 + } + ) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is AmountDue && number == other.number && string == other.string + } + + override fun hashCode(): Int = Objects.hash(number, string) + + override fun toString(): String = + when { + number != null -> "AmountDue{number=$number}" + string != null -> "AmountDue{string=$string}" + _json != null -> "AmountDue{_unknown=$_json}" + else -> throw IllegalStateException("Invalid AmountDue") + } + + companion object { + + @JvmStatic fun ofNumber(number: Double) = AmountDue(number = number) + + @JvmStatic fun ofString(string: String) = AmountDue(string = string) + } + + /** + * An interface that defines how to map each variant of [AmountDue] to a value of type [T]. + */ + interface Visitor { + + fun visitNumber(number: Double): T + + fun visitString(string: String): T + + /** + * Maps an unknown variant of [AmountDue] to a value of type [T]. + * + * An instance of [AmountDue] can contain an unknown variant if it was deserialized from + * data that doesn't match any known variant. For example, if the SDK is on an older + * version than the API, then the API may respond with new variants that the SDK is + * unaware of. + * + * @throws EInvoiceInvalidDataException in the default implementation. + */ + fun unknown(json: JsonValue?): T { + throw EInvoiceInvalidDataException("Unknown AmountDue: $json") + } + } + + internal class Deserializer : BaseDeserializer(AmountDue::class) { + + override fun ObjectCodec.deserialize(node: JsonNode): AmountDue { + val json = JsonValue.fromJsonNode(node) + + val bestMatches = + sequenceOf( + tryDeserialize(node, jacksonTypeRef())?.let { + AmountDue(string = it, _json = json) + }, + tryDeserialize(node, jacksonTypeRef())?.let { + AmountDue(number = it, _json = json) + }, + ) + .filterNotNull() + .allMaxBy { it.validity() } + .toList() + return when (bestMatches.size) { + // This can happen if what we're deserializing is completely incompatible with + // all the possible variants (e.g. deserializing from boolean). + 0 -> AmountDue(_json = json) + 1 -> bestMatches.single() + // If there's more than one match with the highest validity, then use the first + // completely valid match, or simply the first match if none are completely + // valid. + else -> bestMatches.firstOrNull { it.isValid() } ?: bestMatches.first() + } + } + } + + internal class Serializer : BaseSerializer(AmountDue::class) { + + override fun serialize( + value: AmountDue, + generator: JsonGenerator, + provider: SerializerProvider, + ) { + when { + value.number != null -> generator.writeObject(value.number) + value.string != null -> generator.writeObject(value.string) + value._json != null -> generator.writeObject(value._json) + else -> throw IllegalStateException("Invalid AmountDue") + } + } + } + } + + /** A charge is an additional fee for example for late payment, late delivery, etc. */ + class Charge + @JsonCreator(mode = JsonCreator.Mode.DISABLED) + private constructor( + private val amount: JsonField, + private val baseAmount: JsonField, + private val multiplierFactor: JsonField, + private val reason: JsonField, + private val reasonCode: JsonField, + private val taxCode: JsonField, + private val taxRate: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("amount") @ExcludeMissing amount: JsonField = JsonMissing.of(), + @JsonProperty("base_amount") + @ExcludeMissing + baseAmount: JsonField = JsonMissing.of(), + @JsonProperty("multiplier_factor") + @ExcludeMissing + multiplierFactor: JsonField = JsonMissing.of(), + @JsonProperty("reason") @ExcludeMissing reason: JsonField = JsonMissing.of(), + @JsonProperty("reason_code") + @ExcludeMissing + reasonCode: JsonField = JsonMissing.of(), + @JsonProperty("tax_code") + @ExcludeMissing + taxCode: JsonField = JsonMissing.of(), + @JsonProperty("tax_rate") @ExcludeMissing taxRate: JsonField = JsonMissing.of(), + ) : this( + amount, + baseAmount, + multiplierFactor, + reason, + reasonCode, + taxCode, + taxRate, + mutableMapOf(), + ) + + /** + * The charge amount, without VAT. Must be rounded to maximum 2 decimals + * + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun amount(): Optional = amount.getOptional("amount") + + /** + * The base amount that may be used, in conjunction with the charge percentage, to calculate + * the charge amount. Must be rounded to maximum 2 decimals + * + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun baseAmount(): Optional = baseAmount.getOptional("base_amount") + + /** + * The percentage that may be used, in conjunction with the charge base amount, to calculate + * the charge amount. To state 20%, use value 20 + * + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun multiplierFactor(): Optional = + multiplierFactor.getOptional("multiplier_factor") + + /** + * The reason for the charge + * + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun reason(): Optional = reason.getOptional("reason") + + /** + * Charge reason codes for invoice charges and fees + * + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun reasonCode(): Optional = reasonCode.getOptional("reason_code") + + /** + * Duty or tax or fee category codes (Subset of UNCL5305) + * + * Agency: UN/CEFACT Version: D.16B Subset: OpenPEPPOL + * + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun taxCode(): Optional = taxCode.getOptional("tax_code") + + /** + * The VAT rate, represented as percentage that applies to the charge + * + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun taxRate(): Optional = taxRate.getOptional("tax_rate") + + /** + * Returns the raw JSON value of [amount]. + * + * Unlike [amount], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("amount") @ExcludeMissing fun _amount(): JsonField = amount + + /** + * Returns the raw JSON value of [baseAmount]. + * + * Unlike [baseAmount], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("base_amount") + @ExcludeMissing + fun _baseAmount(): JsonField = baseAmount + + /** + * Returns the raw JSON value of [multiplierFactor]. + * + * Unlike [multiplierFactor], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("multiplier_factor") + @ExcludeMissing + fun _multiplierFactor(): JsonField = multiplierFactor + + /** + * Returns the raw JSON value of [reason]. + * + * Unlike [reason], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("reason") @ExcludeMissing fun _reason(): JsonField = reason + + /** + * Returns the raw JSON value of [reasonCode]. + * + * Unlike [reasonCode], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("reason_code") + @ExcludeMissing + fun _reasonCode(): JsonField = reasonCode + + /** + * Returns the raw JSON value of [taxCode]. + * + * Unlike [taxCode], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("tax_code") @ExcludeMissing fun _taxCode(): JsonField = taxCode + + /** + * Returns the raw JSON value of [taxRate]. + * + * Unlike [taxRate], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("tax_rate") @ExcludeMissing fun _taxRate(): JsonField = taxRate + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** Returns a mutable builder for constructing an instance of [Charge]. */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [Charge]. */ + class Builder internal constructor() { + + private var amount: JsonField = JsonMissing.of() + private var baseAmount: JsonField = JsonMissing.of() + private var multiplierFactor: JsonField = JsonMissing.of() + private var reason: JsonField = JsonMissing.of() + private var reasonCode: JsonField = JsonMissing.of() + private var taxCode: JsonField = JsonMissing.of() + private var taxRate: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(charge: Charge) = apply { + amount = charge.amount + baseAmount = charge.baseAmount + multiplierFactor = charge.multiplierFactor + reason = charge.reason + reasonCode = charge.reasonCode + taxCode = charge.taxCode + taxRate = charge.taxRate + additionalProperties = charge.additionalProperties.toMutableMap() + } + + /** The charge amount, without VAT. Must be rounded to maximum 2 decimals */ + fun amount(amount: Amount?) = amount(JsonField.ofNullable(amount)) + + /** Alias for calling [Builder.amount] with `amount.orElse(null)`. */ + fun amount(amount: Optional) = amount(amount.getOrNull()) + + /** + * Sets [Builder.amount] to an arbitrary JSON value. + * + * You should usually call [Builder.amount] with a well-typed [Amount] value instead. + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun amount(amount: JsonField) = apply { this.amount = amount } + + /** Alias for calling [amount] with `Amount.ofNumber(number)`. */ + fun amount(number: Double) = amount(Amount.ofNumber(number)) + + /** Alias for calling [amount] with `Amount.ofString(string)`. */ + fun amount(string: String) = amount(Amount.ofString(string)) + + /** + * The base amount that may be used, in conjunction with the charge percentage, to + * calculate the charge amount. Must be rounded to maximum 2 decimals + */ + fun baseAmount(baseAmount: BaseAmount?) = baseAmount(JsonField.ofNullable(baseAmount)) + + /** Alias for calling [Builder.baseAmount] with `baseAmount.orElse(null)`. */ + fun baseAmount(baseAmount: Optional) = baseAmount(baseAmount.getOrNull()) + + /** + * Sets [Builder.baseAmount] to an arbitrary JSON value. + * + * You should usually call [Builder.baseAmount] with a well-typed [BaseAmount] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun baseAmount(baseAmount: JsonField) = apply { + this.baseAmount = baseAmount + } + + /** Alias for calling [baseAmount] with `BaseAmount.ofNumber(number)`. */ + fun baseAmount(number: Double) = baseAmount(BaseAmount.ofNumber(number)) + + /** Alias for calling [baseAmount] with `BaseAmount.ofString(string)`. */ + fun baseAmount(string: String) = baseAmount(BaseAmount.ofString(string)) + + /** + * The percentage that may be used, in conjunction with the charge base amount, to + * calculate the charge amount. To state 20%, use value 20 + */ + fun multiplierFactor(multiplierFactor: MultiplierFactor?) = + multiplierFactor(JsonField.ofNullable(multiplierFactor)) + + /** + * Alias for calling [Builder.multiplierFactor] with `multiplierFactor.orElse(null)`. + */ + fun multiplierFactor(multiplierFactor: Optional) = + multiplierFactor(multiplierFactor.getOrNull()) + + /** + * Sets [Builder.multiplierFactor] to an arbitrary JSON value. + * + * You should usually call [Builder.multiplierFactor] with a well-typed + * [MultiplierFactor] value instead. This method is primarily for setting the field to + * an undocumented or not yet supported value. + */ + fun multiplierFactor(multiplierFactor: JsonField) = apply { + this.multiplierFactor = multiplierFactor + } + + /** Alias for calling [multiplierFactor] with `MultiplierFactor.ofNumber(number)`. */ + fun multiplierFactor(number: Double) = + multiplierFactor(MultiplierFactor.ofNumber(number)) + + /** Alias for calling [multiplierFactor] with `MultiplierFactor.ofString(string)`. */ + fun multiplierFactor(string: String) = + multiplierFactor(MultiplierFactor.ofString(string)) + + /** The reason for the charge */ + fun reason(reason: String?) = reason(JsonField.ofNullable(reason)) + + /** Alias for calling [Builder.reason] with `reason.orElse(null)`. */ + fun reason(reason: Optional) = reason(reason.getOrNull()) + + /** + * Sets [Builder.reason] to an arbitrary JSON value. + * + * You should usually call [Builder.reason] with a well-typed [String] value instead. + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun reason(reason: JsonField) = apply { this.reason = reason } + + /** Charge reason codes for invoice charges and fees */ + fun reasonCode(reasonCode: ReasonCode?) = reasonCode(JsonField.ofNullable(reasonCode)) + + /** Alias for calling [Builder.reasonCode] with `reasonCode.orElse(null)`. */ + fun reasonCode(reasonCode: Optional) = reasonCode(reasonCode.getOrNull()) + + /** + * Sets [Builder.reasonCode] to an arbitrary JSON value. + * + * You should usually call [Builder.reasonCode] with a well-typed [ReasonCode] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun reasonCode(reasonCode: JsonField) = apply { + this.reasonCode = reasonCode + } + + /** + * Duty or tax or fee category codes (Subset of UNCL5305) + * + * Agency: UN/CEFACT Version: D.16B Subset: OpenPEPPOL + */ + fun taxCode(taxCode: TaxCode?) = taxCode(JsonField.ofNullable(taxCode)) + + /** Alias for calling [Builder.taxCode] with `taxCode.orElse(null)`. */ + fun taxCode(taxCode: Optional) = taxCode(taxCode.getOrNull()) + + /** + * Sets [Builder.taxCode] to an arbitrary JSON value. + * + * You should usually call [Builder.taxCode] with a well-typed [TaxCode] value instead. + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun taxCode(taxCode: JsonField) = apply { this.taxCode = taxCode } + + /** The VAT rate, represented as percentage that applies to the charge */ + fun taxRate(taxRate: TaxRate?) = taxRate(JsonField.ofNullable(taxRate)) + + /** Alias for calling [Builder.taxRate] with `taxRate.orElse(null)`. */ + fun taxRate(taxRate: Optional) = taxRate(taxRate.getOrNull()) + + /** + * Sets [Builder.taxRate] to an arbitrary JSON value. + * + * You should usually call [Builder.taxRate] with a well-typed [TaxRate] value instead. + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun taxRate(taxRate: JsonField) = apply { this.taxRate = taxRate } + + /** Alias for calling [taxRate] with `TaxRate.ofNumber(number)`. */ + fun taxRate(number: Double) = taxRate(TaxRate.ofNumber(number)) + + /** Alias for calling [taxRate] with `TaxRate.ofString(string)`. */ + fun taxRate(string: String) = taxRate(TaxRate.ofString(string)) + + fun additionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.clear() + putAllAdditionalProperties(additionalProperties) + } + + fun putAdditionalProperty(key: String, value: JsonValue) = apply { + additionalProperties.put(key, value) + } + + fun putAllAdditionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.putAll(additionalProperties) + } + + fun removeAdditionalProperty(key: String) = apply { additionalProperties.remove(key) } + + fun removeAllAdditionalProperties(keys: Set) = apply { + keys.forEach(::removeAdditionalProperty) + } + + /** + * Returns an immutable instance of [Charge]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): Charge = + Charge( + amount, + baseAmount, + multiplierFactor, + reason, + reasonCode, + taxCode, + taxRate, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + fun validate(): Charge = apply { + if (validated) { + return@apply + } + + amount().ifPresent { it.validate() } + baseAmount().ifPresent { it.validate() } + multiplierFactor().ifPresent { it.validate() } + reason() + reasonCode().ifPresent { it.validate() } + taxCode().ifPresent { it.validate() } + taxRate().ifPresent { it.validate() } + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: EInvoiceInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic + internal fun validity(): Int = + (amount.asKnown().getOrNull()?.validity() ?: 0) + + (baseAmount.asKnown().getOrNull()?.validity() ?: 0) + + (multiplierFactor.asKnown().getOrNull()?.validity() ?: 0) + + (if (reason.asKnown().isPresent) 1 else 0) + + (reasonCode.asKnown().getOrNull()?.validity() ?: 0) + + (taxCode.asKnown().getOrNull()?.validity() ?: 0) + + (taxRate.asKnown().getOrNull()?.validity() ?: 0) + + /** The charge amount, without VAT. Must be rounded to maximum 2 decimals */ + @JsonDeserialize(using = Amount.Deserializer::class) + @JsonSerialize(using = Amount.Serializer::class) + class Amount + private constructor( + private val number: Double? = null, + private val string: String? = null, + private val _json: JsonValue? = null, + ) { + + fun number(): Optional = Optional.ofNullable(number) + + fun string(): Optional = Optional.ofNullable(string) + + fun isNumber(): Boolean = number != null + + fun isString(): Boolean = string != null + + fun asNumber(): Double = number.getOrThrow("number") + + fun asString(): String = string.getOrThrow("string") + + fun _json(): Optional = Optional.ofNullable(_json) + + fun accept(visitor: Visitor): T = + when { + number != null -> visitor.visitNumber(number) + string != null -> visitor.visitString(string) + else -> visitor.unknown(_json) + } + + private var validated: Boolean = false + + fun validate(): Amount = apply { + if (validated) { + return@apply + } + + accept( + object : Visitor { + override fun visitNumber(number: Double) {} + + override fun visitString(string: String) {} + } + ) + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: EInvoiceInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic + internal fun validity(): Int = + accept( + object : Visitor { + override fun visitNumber(number: Double) = 1 + + override fun visitString(string: String) = 1 + + override fun unknown(json: JsonValue?) = 0 + } + ) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Amount && number == other.number && string == other.string + } + + override fun hashCode(): Int = Objects.hash(number, string) + + override fun toString(): String = + when { + number != null -> "Amount{number=$number}" + string != null -> "Amount{string=$string}" + _json != null -> "Amount{_unknown=$_json}" + else -> throw IllegalStateException("Invalid Amount") + } + + companion object { + + @JvmStatic fun ofNumber(number: Double) = Amount(number = number) + + @JvmStatic fun ofString(string: String) = Amount(string = string) + } + + /** + * An interface that defines how to map each variant of [Amount] to a value of type [T]. + */ + interface Visitor { + + fun visitNumber(number: Double): T + + fun visitString(string: String): T + + /** + * Maps an unknown variant of [Amount] to a value of type [T]. + * + * An instance of [Amount] can contain an unknown variant if it was deserialized + * from data that doesn't match any known variant. For example, if the SDK is on an + * older version than the API, then the API may respond with new variants that the + * SDK is unaware of. + * + * @throws EInvoiceInvalidDataException in the default implementation. + */ + fun unknown(json: JsonValue?): T { + throw EInvoiceInvalidDataException("Unknown Amount: $json") + } + } + + internal class Deserializer : BaseDeserializer(Amount::class) { + + override fun ObjectCodec.deserialize(node: JsonNode): Amount { + val json = JsonValue.fromJsonNode(node) + + val bestMatches = + sequenceOf( + tryDeserialize(node, jacksonTypeRef())?.let { + Amount(string = it, _json = json) + }, + tryDeserialize(node, jacksonTypeRef())?.let { + Amount(number = it, _json = json) + }, + ) + .filterNotNull() + .allMaxBy { it.validity() } + .toList() + return when (bestMatches.size) { + // This can happen if what we're deserializing is completely incompatible + // with all the possible variants (e.g. deserializing from boolean). + 0 -> Amount(_json = json) + 1 -> bestMatches.single() + // If there's more than one match with the highest validity, then use the + // first completely valid match, or simply the first match if none are + // completely valid. + else -> bestMatches.firstOrNull { it.isValid() } ?: bestMatches.first() + } + } + } + + internal class Serializer : BaseSerializer(Amount::class) { + + override fun serialize( + value: Amount, + generator: JsonGenerator, + provider: SerializerProvider, + ) { + when { + value.number != null -> generator.writeObject(value.number) + value.string != null -> generator.writeObject(value.string) + value._json != null -> generator.writeObject(value._json) + else -> throw IllegalStateException("Invalid Amount") + } + } + } + } + + /** + * The base amount that may be used, in conjunction with the charge percentage, to calculate + * the charge amount. Must be rounded to maximum 2 decimals + */ + @JsonDeserialize(using = BaseAmount.Deserializer::class) + @JsonSerialize(using = BaseAmount.Serializer::class) + class BaseAmount + private constructor( + private val number: Double? = null, + private val string: String? = null, + private val _json: JsonValue? = null, + ) { + + fun number(): Optional = Optional.ofNullable(number) + + fun string(): Optional = Optional.ofNullable(string) + + fun isNumber(): Boolean = number != null + + fun isString(): Boolean = string != null + + fun asNumber(): Double = number.getOrThrow("number") + + fun asString(): String = string.getOrThrow("string") + + fun _json(): Optional = Optional.ofNullable(_json) + + fun accept(visitor: Visitor): T = + when { + number != null -> visitor.visitNumber(number) + string != null -> visitor.visitString(string) + else -> visitor.unknown(_json) + } + + private var validated: Boolean = false + + fun validate(): BaseAmount = apply { + if (validated) { + return@apply + } + + accept( + object : Visitor { + override fun visitNumber(number: Double) {} + + override fun visitString(string: String) {} + } + ) + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: EInvoiceInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic + internal fun validity(): Int = + accept( + object : Visitor { + override fun visitNumber(number: Double) = 1 + + override fun visitString(string: String) = 1 + + override fun unknown(json: JsonValue?) = 0 + } + ) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is BaseAmount && number == other.number && string == other.string + } + + override fun hashCode(): Int = Objects.hash(number, string) + + override fun toString(): String = + when { + number != null -> "BaseAmount{number=$number}" + string != null -> "BaseAmount{string=$string}" + _json != null -> "BaseAmount{_unknown=$_json}" + else -> throw IllegalStateException("Invalid BaseAmount") + } + + companion object { + + @JvmStatic fun ofNumber(number: Double) = BaseAmount(number = number) + + @JvmStatic fun ofString(string: String) = BaseAmount(string = string) + } + + /** + * An interface that defines how to map each variant of [BaseAmount] to a value of type + * [T]. + */ + interface Visitor { + + fun visitNumber(number: Double): T + + fun visitString(string: String): T + + /** + * Maps an unknown variant of [BaseAmount] to a value of type [T]. + * + * An instance of [BaseAmount] can contain an unknown variant if it was deserialized + * from data that doesn't match any known variant. For example, if the SDK is on an + * older version than the API, then the API may respond with new variants that the + * SDK is unaware of. + * + * @throws EInvoiceInvalidDataException in the default implementation. + */ + fun unknown(json: JsonValue?): T { + throw EInvoiceInvalidDataException("Unknown BaseAmount: $json") + } + } + + internal class Deserializer : BaseDeserializer(BaseAmount::class) { + + override fun ObjectCodec.deserialize(node: JsonNode): BaseAmount { + val json = JsonValue.fromJsonNode(node) + + val bestMatches = + sequenceOf( + tryDeserialize(node, jacksonTypeRef())?.let { + BaseAmount(string = it, _json = json) + }, + tryDeserialize(node, jacksonTypeRef())?.let { + BaseAmount(number = it, _json = json) + }, + ) + .filterNotNull() + .allMaxBy { it.validity() } + .toList() + return when (bestMatches.size) { + // This can happen if what we're deserializing is completely incompatible + // with all the possible variants (e.g. deserializing from boolean). + 0 -> BaseAmount(_json = json) + 1 -> bestMatches.single() + // If there's more than one match with the highest validity, then use the + // first completely valid match, or simply the first match if none are + // completely valid. + else -> bestMatches.firstOrNull { it.isValid() } ?: bestMatches.first() + } + } + } + + internal class Serializer : BaseSerializer(BaseAmount::class) { + + override fun serialize( + value: BaseAmount, + generator: JsonGenerator, + provider: SerializerProvider, + ) { + when { + value.number != null -> generator.writeObject(value.number) + value.string != null -> generator.writeObject(value.string) + value._json != null -> generator.writeObject(value._json) + else -> throw IllegalStateException("Invalid BaseAmount") + } + } + } + } + + /** + * The percentage that may be used, in conjunction with the charge base amount, to calculate + * the charge amount. To state 20%, use value 20 + */ + @JsonDeserialize(using = MultiplierFactor.Deserializer::class) + @JsonSerialize(using = MultiplierFactor.Serializer::class) + class MultiplierFactor + private constructor( + private val number: Double? = null, + private val string: String? = null, + private val _json: JsonValue? = null, + ) { + + fun number(): Optional = Optional.ofNullable(number) + + fun string(): Optional = Optional.ofNullable(string) + + fun isNumber(): Boolean = number != null + + fun isString(): Boolean = string != null + + fun asNumber(): Double = number.getOrThrow("number") + + fun asString(): String = string.getOrThrow("string") + + fun _json(): Optional = Optional.ofNullable(_json) + + fun accept(visitor: Visitor): T = + when { + number != null -> visitor.visitNumber(number) + string != null -> visitor.visitString(string) + else -> visitor.unknown(_json) + } + + private var validated: Boolean = false + + fun validate(): MultiplierFactor = apply { + if (validated) { + return@apply + } + + accept( + object : Visitor { + override fun visitNumber(number: Double) {} + + override fun visitString(string: String) {} + } + ) + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: EInvoiceInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic + internal fun validity(): Int = + accept( + object : Visitor { + override fun visitNumber(number: Double) = 1 + + override fun visitString(string: String) = 1 + + override fun unknown(json: JsonValue?) = 0 + } + ) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is MultiplierFactor && number == other.number && string == other.string + } + + override fun hashCode(): Int = Objects.hash(number, string) + + override fun toString(): String = + when { + number != null -> "MultiplierFactor{number=$number}" + string != null -> "MultiplierFactor{string=$string}" + _json != null -> "MultiplierFactor{_unknown=$_json}" + else -> throw IllegalStateException("Invalid MultiplierFactor") + } + + companion object { + + @JvmStatic fun ofNumber(number: Double) = MultiplierFactor(number = number) + + @JvmStatic fun ofString(string: String) = MultiplierFactor(string = string) + } + + /** + * An interface that defines how to map each variant of [MultiplierFactor] to a value of + * type [T]. + */ + interface Visitor { + + fun visitNumber(number: Double): T + + fun visitString(string: String): T + + /** + * Maps an unknown variant of [MultiplierFactor] to a value of type [T]. + * + * An instance of [MultiplierFactor] can contain an unknown variant if it was + * deserialized from data that doesn't match any known variant. For example, if the + * SDK is on an older version than the API, then the API may respond with new + * variants that the SDK is unaware of. + * + * @throws EInvoiceInvalidDataException in the default implementation. + */ + fun unknown(json: JsonValue?): T { + throw EInvoiceInvalidDataException("Unknown MultiplierFactor: $json") + } + } + + internal class Deserializer : + BaseDeserializer(MultiplierFactor::class) { + + override fun ObjectCodec.deserialize(node: JsonNode): MultiplierFactor { + val json = JsonValue.fromJsonNode(node) + + val bestMatches = + sequenceOf( + tryDeserialize(node, jacksonTypeRef())?.let { + MultiplierFactor(string = it, _json = json) + }, + tryDeserialize(node, jacksonTypeRef())?.let { + MultiplierFactor(number = it, _json = json) + }, + ) + .filterNotNull() + .allMaxBy { it.validity() } + .toList() + return when (bestMatches.size) { + // This can happen if what we're deserializing is completely incompatible + // with all the possible variants (e.g. deserializing from boolean). + 0 -> MultiplierFactor(_json = json) + 1 -> bestMatches.single() + // If there's more than one match with the highest validity, then use the + // first completely valid match, or simply the first match if none are + // completely valid. + else -> bestMatches.firstOrNull { it.isValid() } ?: bestMatches.first() + } + } + } + + internal class Serializer : BaseSerializer(MultiplierFactor::class) { + + override fun serialize( + value: MultiplierFactor, + generator: JsonGenerator, + provider: SerializerProvider, + ) { + when { + value.number != null -> generator.writeObject(value.number) + value.string != null -> generator.writeObject(value.string) + value._json != null -> generator.writeObject(value._json) + else -> throw IllegalStateException("Invalid MultiplierFactor") + } + } + } + } + + /** Charge reason codes for invoice charges and fees */ + class ReasonCode @JsonCreator private constructor(private val value: JsonField) : + Enum { + + /** + * Returns this class instance's raw value. + * + * This is usually only useful if this instance was deserialized from data that doesn't + * match any known member, and you want to know that value. For example, if the SDK is + * on an older version than the API, then the API may respond with new members that the + * SDK is unaware of. + */ + @com.fasterxml.jackson.annotation.JsonValue fun _value(): JsonField = value + + companion object { + + @JvmField val AA = of("AA") + + @JvmField val AAA = of("AAA") + + @JvmField val AAC = of("AAC") + + @JvmField val AAD = of("AAD") + + @JvmField val AAE = of("AAE") + + @JvmField val AAF = of("AAF") + + @JvmField val AAH = of("AAH") + + @JvmField val AAI = of("AAI") + + @JvmField val AAS = of("AAS") + + @JvmField val AAT = of("AAT") + + @JvmField val AAV = of("AAV") + + @JvmField val AAY = of("AAY") + + @JvmField val AAZ = of("AAZ") + + @JvmField val ABA = of("ABA") + + @JvmField val ABB = of("ABB") + + @JvmField val ABC = of("ABC") + + @JvmField val ABD = of("ABD") + + @JvmField val ABF = of("ABF") + + @JvmField val ABK = of("ABK") + + @JvmField val ABL = of("ABL") + + @JvmField val ABN = of("ABN") + + @JvmField val ABR = of("ABR") + + @JvmField val ABS = of("ABS") + + @JvmField val ABT = of("ABT") + + @JvmField val ABU = of("ABU") + + @JvmField val ACF = of("ACF") + + @JvmField val ACG = of("ACG") + + @JvmField val ACH = of("ACH") + + @JvmField val ACI = of("ACI") + + @JvmField val ACJ = of("ACJ") + + @JvmField val ACK = of("ACK") + + @JvmField val ACL = of("ACL") + + @JvmField val ACM = of("ACM") + + @JvmField val ACS = of("ACS") + + @JvmField val ADC = of("ADC") + + @JvmField val ADE = of("ADE") + + @JvmField val ADJ = of("ADJ") + + @JvmField val ADK = of("ADK") + + @JvmField val ADL = of("ADL") + + @JvmField val ADM = of("ADM") + + @JvmField val ADN = of("ADN") + + @JvmField val ADO = of("ADO") + + @JvmField val ADP = of("ADP") + + @JvmField val ADQ = of("ADQ") + + @JvmField val ADR = of("ADR") + + @JvmField val ADT = of("ADT") + + @JvmField val ADW = of("ADW") + + @JvmField val ADY = of("ADY") + + @JvmField val ADZ = of("ADZ") + + @JvmField val AEA = of("AEA") + + @JvmField val AEB = of("AEB") + + @JvmField val AEC = of("AEC") + + @JvmField val AED = of("AED") + + @JvmField val AEF = of("AEF") + + @JvmField val AEH = of("AEH") + + @JvmField val AEI = of("AEI") + + @JvmField val AEJ = of("AEJ") + + @JvmField val AEK = of("AEK") + + @JvmField val AEL = of("AEL") + + @JvmField val AEM = of("AEM") + + @JvmField val AEN = of("AEN") + + @JvmField val AEO = of("AEO") + + @JvmField val AEP = of("AEP") + + @JvmField val AES = of("AES") + + @JvmField val AET = of("AET") + + @JvmField val AEU = of("AEU") + + @JvmField val AEV = of("AEV") + + @JvmField val AEW = of("AEW") + + @JvmField val AEX = of("AEX") + + @JvmField val AEY = of("AEY") + + @JvmField val AEZ = of("AEZ") + + @JvmField val AJ = of("AJ") + + @JvmField val AU = of("AU") + + @JvmField val CA = of("CA") + + @JvmField val CAB = of("CAB") + + @JvmField val CAD = of("CAD") + + @JvmField val CAE = of("CAE") + + @JvmField val CAF = of("CAF") + + @JvmField val CAI = of("CAI") + + @JvmField val CAJ = of("CAJ") + + @JvmField val CAK = of("CAK") + + @JvmField val CAL = of("CAL") + + @JvmField val CAM = of("CAM") + + @JvmField val CAN = of("CAN") + + @JvmField val CAO = of("CAO") + + @JvmField val CAP = of("CAP") + + @JvmField val CAQ = of("CAQ") + + @JvmField val CAR = of("CAR") + + @JvmField val CAS = of("CAS") + + @JvmField val CAT = of("CAT") + + @JvmField val CAU = of("CAU") + + @JvmField val CAV = of("CAV") + + @JvmField val CAW = of("CAW") + + @JvmField val CAX = of("CAX") + + @JvmField val CAY = of("CAY") + + @JvmField val CAZ = of("CAZ") + + @JvmField val CD = of("CD") + + @JvmField val CG = of("CG") + + @JvmField val CS = of("CS") + + @JvmField val CT = of("CT") + + @JvmField val DAB = of("DAB") + + @JvmField val DAC = of("DAC") + + @JvmField val DAD = of("DAD") + + @JvmField val DAF = of("DAF") + + @JvmField val DAG = of("DAG") + + @JvmField val DAH = of("DAH") + + @JvmField val DAI = of("DAI") + + @JvmField val DAJ = of("DAJ") + + @JvmField val DAK = of("DAK") + + @JvmField val DAL = of("DAL") + + @JvmField val DAM = of("DAM") + + @JvmField val DAN = of("DAN") + + @JvmField val DAO = of("DAO") + + @JvmField val DAP = of("DAP") + + @JvmField val DAQ = of("DAQ") + + @JvmField val DL = of("DL") + + @JvmField val EG = of("EG") + + @JvmField val EP = of("EP") + + @JvmField val ER = of("ER") + + @JvmField val FAA = of("FAA") + + @JvmField val FAB = of("FAB") + + @JvmField val FAC = of("FAC") + + @JvmField val FC = of("FC") + + @JvmField val FH = of("FH") + + @JvmField val FI = of("FI") + + @JvmField val GAA = of("GAA") + + @JvmField val HAA = of("HAA") + + @JvmField val HD = of("HD") + + @JvmField val HH = of("HH") + + @JvmField val IAA = of("IAA") + + @JvmField val IAB = of("IAB") + + @JvmField val ID = of("ID") + + @JvmField val IF = of("IF") + + @JvmField val IR = of("IR") + + @JvmField val IS = of("IS") + + @JvmField val KO = of("KO") + + @JvmField val L1 = of("L1") + + @JvmField val LA = of("LA") + + @JvmField val LAA = of("LAA") + + @JvmField val LAB = of("LAB") + + @JvmField val LF = of("LF") + + @JvmField val MAE = of("MAE") + + @JvmField val MI = of("MI") + + @JvmField val ML = of("ML") + + @JvmField val NAA = of("NAA") + + @JvmField val OA = of("OA") + + @JvmField val PA = of("PA") + + @JvmField val PAA = of("PAA") + + @JvmField val PC = of("PC") + + @JvmField val PL = of("PL") + + @JvmField val PRV = of("PRV") + + @JvmField val RAB = of("RAB") + + @JvmField val RAC = of("RAC") + + @JvmField val RAD = of("RAD") + + @JvmField val RAF = of("RAF") + + @JvmField val RE = of("RE") + + @JvmField val RF = of("RF") + + @JvmField val RH = of("RH") + + @JvmField val RV = of("RV") + + @JvmField val SA = of("SA") + + @JvmField val SAA = of("SAA") + + @JvmField val SAD = of("SAD") + + @JvmField val SAE = of("SAE") + + @JvmField val SAI = of("SAI") + + @JvmField val SG = of("SG") + + @JvmField val SH = of("SH") + + @JvmField val SM = of("SM") + + @JvmField val SU = of("SU") + + @JvmField val TAB = of("TAB") + + @JvmField val TAC = of("TAC") + + @JvmField val TT = of("TT") + + @JvmField val TV = of("TV") + + @JvmField val V1 = of("V1") + + @JvmField val V2 = of("V2") + + @JvmField val WH = of("WH") + + @JvmField val XAA = of("XAA") + + @JvmField val YY = of("YY") + + @JvmField val ZZZ = of("ZZZ") + + @JvmStatic fun of(value: String) = ReasonCode(JsonField.of(value)) + } + + /** An enum containing [ReasonCode]'s known values. */ + enum class Known { + AA, + AAA, + AAC, + AAD, + AAE, + AAF, + AAH, + AAI, + AAS, + AAT, + AAV, + AAY, + AAZ, + ABA, + ABB, + ABC, + ABD, + ABF, + ABK, + ABL, + ABN, + ABR, + ABS, + ABT, + ABU, + ACF, + ACG, + ACH, + ACI, + ACJ, + ACK, + ACL, + ACM, + ACS, + ADC, + ADE, + ADJ, + ADK, + ADL, + ADM, + ADN, + ADO, + ADP, + ADQ, + ADR, + ADT, + ADW, + ADY, + ADZ, + AEA, + AEB, + AEC, + AED, + AEF, + AEH, + AEI, + AEJ, + AEK, + AEL, + AEM, + AEN, + AEO, + AEP, + AES, + AET, + AEU, + AEV, + AEW, + AEX, + AEY, + AEZ, + AJ, + AU, + CA, + CAB, + CAD, + CAE, + CAF, + CAI, + CAJ, + CAK, + CAL, + CAM, + CAN, + CAO, + CAP, + CAQ, + CAR, + CAS, + CAT, + CAU, + CAV, + CAW, + CAX, + CAY, + CAZ, + CD, + CG, + CS, + CT, + DAB, + DAC, + DAD, + DAF, + DAG, + DAH, + DAI, + DAJ, + DAK, + DAL, + DAM, + DAN, + DAO, + DAP, + DAQ, + DL, + EG, + EP, + ER, + FAA, + FAB, + FAC, + FC, + FH, + FI, + GAA, + HAA, + HD, + HH, + IAA, + IAB, + ID, + IF, + IR, + IS, + KO, + L1, + LA, + LAA, + LAB, + LF, + MAE, + MI, + ML, + NAA, + OA, + PA, + PAA, + PC, + PL, + PRV, + RAB, + RAC, + RAD, + RAF, + RE, + RF, + RH, + RV, + SA, + SAA, + SAD, + SAE, + SAI, + SG, + SH, + SM, + SU, + TAB, + TAC, + TT, + TV, + V1, + V2, + WH, + XAA, + YY, + ZZZ, + } + + /** + * An enum containing [ReasonCode]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [ReasonCode] can contain an unknown value in a couple of cases: + * - It was deserialized from data that doesn't match any known member. For example, if + * the SDK is on an older version than the API, then the API may respond with new + * members that the SDK is unaware of. + * - It was constructed with an arbitrary value using the [of] method. + */ + enum class Value { + AA, + AAA, + AAC, + AAD, + AAE, + AAF, + AAH, + AAI, + AAS, + AAT, + AAV, + AAY, + AAZ, + ABA, + ABB, + ABC, + ABD, + ABF, + ABK, + ABL, + ABN, + ABR, + ABS, + ABT, + ABU, + ACF, + ACG, + ACH, + ACI, + ACJ, + ACK, + ACL, + ACM, + ACS, + ADC, + ADE, + ADJ, + ADK, + ADL, + ADM, + ADN, + ADO, + ADP, + ADQ, + ADR, + ADT, + ADW, + ADY, + ADZ, + AEA, + AEB, + AEC, + AED, + AEF, + AEH, + AEI, + AEJ, + AEK, + AEL, + AEM, + AEN, + AEO, + AEP, + AES, + AET, + AEU, + AEV, + AEW, + AEX, + AEY, + AEZ, + AJ, + AU, + CA, + CAB, + CAD, + CAE, + CAF, + CAI, + CAJ, + CAK, + CAL, + CAM, + CAN, + CAO, + CAP, + CAQ, + CAR, + CAS, + CAT, + CAU, + CAV, + CAW, + CAX, + CAY, + CAZ, + CD, + CG, + CS, + CT, + DAB, + DAC, + DAD, + DAF, + DAG, + DAH, + DAI, + DAJ, + DAK, + DAL, + DAM, + DAN, + DAO, + DAP, + DAQ, + DL, + EG, + EP, + ER, + FAA, + FAB, + FAC, + FC, + FH, + FI, + GAA, + HAA, + HD, + HH, + IAA, + IAB, + ID, + IF, + IR, + IS, + KO, + L1, + LA, + LAA, + LAB, + LF, + MAE, + MI, + ML, + NAA, + OA, + PA, + PAA, + PC, + PL, + PRV, + RAB, + RAC, + RAD, + RAF, + RE, + RF, + RH, + RV, + SA, + SAA, + SAD, + SAE, + SAI, + SG, + SH, + SM, + SU, + TAB, + TAC, + TT, + TV, + V1, + V2, + WH, + XAA, + YY, + ZZZ, + /** + * An enum member indicating that [ReasonCode] was instantiated with an unknown + * value. + */ + _UNKNOWN, + } + + /** + * Returns an enum member corresponding to this class instance's value, or + * [Value._UNKNOWN] if the class was instantiated with an unknown value. + * + * Use the [known] method instead if you're certain the value is always known or if you + * want to throw for the unknown case. + */ + fun value(): Value = + when (this) { + AA -> Value.AA + AAA -> Value.AAA + AAC -> Value.AAC + AAD -> Value.AAD + AAE -> Value.AAE + AAF -> Value.AAF + AAH -> Value.AAH + AAI -> Value.AAI + AAS -> Value.AAS + AAT -> Value.AAT + AAV -> Value.AAV + AAY -> Value.AAY + AAZ -> Value.AAZ + ABA -> Value.ABA + ABB -> Value.ABB + ABC -> Value.ABC + ABD -> Value.ABD + ABF -> Value.ABF + ABK -> Value.ABK + ABL -> Value.ABL + ABN -> Value.ABN + ABR -> Value.ABR + ABS -> Value.ABS + ABT -> Value.ABT + ABU -> Value.ABU + ACF -> Value.ACF + ACG -> Value.ACG + ACH -> Value.ACH + ACI -> Value.ACI + ACJ -> Value.ACJ + ACK -> Value.ACK + ACL -> Value.ACL + ACM -> Value.ACM + ACS -> Value.ACS + ADC -> Value.ADC + ADE -> Value.ADE + ADJ -> Value.ADJ + ADK -> Value.ADK + ADL -> Value.ADL + ADM -> Value.ADM + ADN -> Value.ADN + ADO -> Value.ADO + ADP -> Value.ADP + ADQ -> Value.ADQ + ADR -> Value.ADR + ADT -> Value.ADT + ADW -> Value.ADW + ADY -> Value.ADY + ADZ -> Value.ADZ + AEA -> Value.AEA + AEB -> Value.AEB + AEC -> Value.AEC + AED -> Value.AED + AEF -> Value.AEF + AEH -> Value.AEH + AEI -> Value.AEI + AEJ -> Value.AEJ + AEK -> Value.AEK + AEL -> Value.AEL + AEM -> Value.AEM + AEN -> Value.AEN + AEO -> Value.AEO + AEP -> Value.AEP + AES -> Value.AES + AET -> Value.AET + AEU -> Value.AEU + AEV -> Value.AEV + AEW -> Value.AEW + AEX -> Value.AEX + AEY -> Value.AEY + AEZ -> Value.AEZ + AJ -> Value.AJ + AU -> Value.AU + CA -> Value.CA + CAB -> Value.CAB + CAD -> Value.CAD + CAE -> Value.CAE + CAF -> Value.CAF + CAI -> Value.CAI + CAJ -> Value.CAJ + CAK -> Value.CAK + CAL -> Value.CAL + CAM -> Value.CAM + CAN -> Value.CAN + CAO -> Value.CAO + CAP -> Value.CAP + CAQ -> Value.CAQ + CAR -> Value.CAR + CAS -> Value.CAS + CAT -> Value.CAT + CAU -> Value.CAU + CAV -> Value.CAV + CAW -> Value.CAW + CAX -> Value.CAX + CAY -> Value.CAY + CAZ -> Value.CAZ + CD -> Value.CD + CG -> Value.CG + CS -> Value.CS + CT -> Value.CT + DAB -> Value.DAB + DAC -> Value.DAC + DAD -> Value.DAD + DAF -> Value.DAF + DAG -> Value.DAG + DAH -> Value.DAH + DAI -> Value.DAI + DAJ -> Value.DAJ + DAK -> Value.DAK + DAL -> Value.DAL + DAM -> Value.DAM + DAN -> Value.DAN + DAO -> Value.DAO + DAP -> Value.DAP + DAQ -> Value.DAQ + DL -> Value.DL + EG -> Value.EG + EP -> Value.EP + ER -> Value.ER + FAA -> Value.FAA + FAB -> Value.FAB + FAC -> Value.FAC + FC -> Value.FC + FH -> Value.FH + FI -> Value.FI + GAA -> Value.GAA + HAA -> Value.HAA + HD -> Value.HD + HH -> Value.HH + IAA -> Value.IAA + IAB -> Value.IAB + ID -> Value.ID + IF -> Value.IF + IR -> Value.IR + IS -> Value.IS + KO -> Value.KO + L1 -> Value.L1 + LA -> Value.LA + LAA -> Value.LAA + LAB -> Value.LAB + LF -> Value.LF + MAE -> Value.MAE + MI -> Value.MI + ML -> Value.ML + NAA -> Value.NAA + OA -> Value.OA + PA -> Value.PA + PAA -> Value.PAA + PC -> Value.PC + PL -> Value.PL + PRV -> Value.PRV + RAB -> Value.RAB + RAC -> Value.RAC + RAD -> Value.RAD + RAF -> Value.RAF + RE -> Value.RE + RF -> Value.RF + RH -> Value.RH + RV -> Value.RV + SA -> Value.SA + SAA -> Value.SAA + SAD -> Value.SAD + SAE -> Value.SAE + SAI -> Value.SAI + SG -> Value.SG + SH -> Value.SH + SM -> Value.SM + SU -> Value.SU + TAB -> Value.TAB + TAC -> Value.TAC + TT -> Value.TT + TV -> Value.TV + V1 -> Value.V1 + V2 -> Value.V2 + WH -> Value.WH + XAA -> Value.XAA + YY -> Value.YY + ZZZ -> Value.ZZZ + else -> Value._UNKNOWN + } + + /** + * Returns an enum member corresponding to this class instance's value. + * + * Use the [value] method instead if you're uncertain the value is always known and + * don't want to throw for the unknown case. + * + * @throws EInvoiceInvalidDataException if this class instance's value is a not a known + * member. + */ + fun known(): Known = + when (this) { + AA -> Known.AA + AAA -> Known.AAA + AAC -> Known.AAC + AAD -> Known.AAD + AAE -> Known.AAE + AAF -> Known.AAF + AAH -> Known.AAH + AAI -> Known.AAI + AAS -> Known.AAS + AAT -> Known.AAT + AAV -> Known.AAV + AAY -> Known.AAY + AAZ -> Known.AAZ + ABA -> Known.ABA + ABB -> Known.ABB + ABC -> Known.ABC + ABD -> Known.ABD + ABF -> Known.ABF + ABK -> Known.ABK + ABL -> Known.ABL + ABN -> Known.ABN + ABR -> Known.ABR + ABS -> Known.ABS + ABT -> Known.ABT + ABU -> Known.ABU + ACF -> Known.ACF + ACG -> Known.ACG + ACH -> Known.ACH + ACI -> Known.ACI + ACJ -> Known.ACJ + ACK -> Known.ACK + ACL -> Known.ACL + ACM -> Known.ACM + ACS -> Known.ACS + ADC -> Known.ADC + ADE -> Known.ADE + ADJ -> Known.ADJ + ADK -> Known.ADK + ADL -> Known.ADL + ADM -> Known.ADM + ADN -> Known.ADN + ADO -> Known.ADO + ADP -> Known.ADP + ADQ -> Known.ADQ + ADR -> Known.ADR + ADT -> Known.ADT + ADW -> Known.ADW + ADY -> Known.ADY + ADZ -> Known.ADZ + AEA -> Known.AEA + AEB -> Known.AEB + AEC -> Known.AEC + AED -> Known.AED + AEF -> Known.AEF + AEH -> Known.AEH + AEI -> Known.AEI + AEJ -> Known.AEJ + AEK -> Known.AEK + AEL -> Known.AEL + AEM -> Known.AEM + AEN -> Known.AEN + AEO -> Known.AEO + AEP -> Known.AEP + AES -> Known.AES + AET -> Known.AET + AEU -> Known.AEU + AEV -> Known.AEV + AEW -> Known.AEW + AEX -> Known.AEX + AEY -> Known.AEY + AEZ -> Known.AEZ + AJ -> Known.AJ + AU -> Known.AU + CA -> Known.CA + CAB -> Known.CAB + CAD -> Known.CAD + CAE -> Known.CAE + CAF -> Known.CAF + CAI -> Known.CAI + CAJ -> Known.CAJ + CAK -> Known.CAK + CAL -> Known.CAL + CAM -> Known.CAM + CAN -> Known.CAN + CAO -> Known.CAO + CAP -> Known.CAP + CAQ -> Known.CAQ + CAR -> Known.CAR + CAS -> Known.CAS + CAT -> Known.CAT + CAU -> Known.CAU + CAV -> Known.CAV + CAW -> Known.CAW + CAX -> Known.CAX + CAY -> Known.CAY + CAZ -> Known.CAZ + CD -> Known.CD + CG -> Known.CG + CS -> Known.CS + CT -> Known.CT + DAB -> Known.DAB + DAC -> Known.DAC + DAD -> Known.DAD + DAF -> Known.DAF + DAG -> Known.DAG + DAH -> Known.DAH + DAI -> Known.DAI + DAJ -> Known.DAJ + DAK -> Known.DAK + DAL -> Known.DAL + DAM -> Known.DAM + DAN -> Known.DAN + DAO -> Known.DAO + DAP -> Known.DAP + DAQ -> Known.DAQ + DL -> Known.DL + EG -> Known.EG + EP -> Known.EP + ER -> Known.ER + FAA -> Known.FAA + FAB -> Known.FAB + FAC -> Known.FAC + FC -> Known.FC + FH -> Known.FH + FI -> Known.FI + GAA -> Known.GAA + HAA -> Known.HAA + HD -> Known.HD + HH -> Known.HH + IAA -> Known.IAA + IAB -> Known.IAB + ID -> Known.ID + IF -> Known.IF + IR -> Known.IR + IS -> Known.IS + KO -> Known.KO + L1 -> Known.L1 + LA -> Known.LA + LAA -> Known.LAA + LAB -> Known.LAB + LF -> Known.LF + MAE -> Known.MAE + MI -> Known.MI + ML -> Known.ML + NAA -> Known.NAA + OA -> Known.OA + PA -> Known.PA + PAA -> Known.PAA + PC -> Known.PC + PL -> Known.PL + PRV -> Known.PRV + RAB -> Known.RAB + RAC -> Known.RAC + RAD -> Known.RAD + RAF -> Known.RAF + RE -> Known.RE + RF -> Known.RF + RH -> Known.RH + RV -> Known.RV + SA -> Known.SA + SAA -> Known.SAA + SAD -> Known.SAD + SAE -> Known.SAE + SAI -> Known.SAI + SG -> Known.SG + SH -> Known.SH + SM -> Known.SM + SU -> Known.SU + TAB -> Known.TAB + TAC -> Known.TAC + TT -> Known.TT + TV -> Known.TV + V1 -> Known.V1 + V2 -> Known.V2 + WH -> Known.WH + XAA -> Known.XAA + YY -> Known.YY + ZZZ -> Known.ZZZ + else -> throw EInvoiceInvalidDataException("Unknown ReasonCode: $value") + } + + /** + * Returns this class instance's primitive wire representation. + * + * This differs from the [toString] method because that method is primarily for + * debugging and generally doesn't throw. + * + * @throws EInvoiceInvalidDataException if this class instance's value does not have the + * expected primitive type. + */ + fun asString(): String = + _value().asString().orElseThrow { + EInvoiceInvalidDataException("Value is not a String") + } + + private var validated: Boolean = false + + fun validate(): ReasonCode = apply { + if (validated) { + return@apply + } + + known() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: EInvoiceInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic internal fun validity(): Int = if (value() == Value._UNKNOWN) 0 else 1 + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is ReasonCode && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + /** + * Duty or tax or fee category codes (Subset of UNCL5305) + * + * Agency: UN/CEFACT Version: D.16B Subset: OpenPEPPOL + */ + class TaxCode @JsonCreator private constructor(private val value: JsonField) : + Enum { + + /** + * Returns this class instance's raw value. + * + * This is usually only useful if this instance was deserialized from data that doesn't + * match any known member, and you want to know that value. For example, if the SDK is + * on an older version than the API, then the API may respond with new members that the + * SDK is unaware of. + */ + @com.fasterxml.jackson.annotation.JsonValue fun _value(): JsonField = value + + companion object { + + @JvmField val AE = of("AE") + + @JvmField val E = of("E") + + @JvmField val S = of("S") + + @JvmField val Z = of("Z") + + @JvmField val G = of("G") + + @JvmField val O = of("O") + + @JvmField val K = of("K") + + @JvmField val L = of("L") + + @JvmField val M = of("M") + + @JvmField val B = of("B") + + @JvmStatic fun of(value: String) = TaxCode(JsonField.of(value)) + } + + /** An enum containing [TaxCode]'s known values. */ + enum class Known { + AE, + E, + S, + Z, + G, + O, + K, + L, + M, + B, + } + + /** + * An enum containing [TaxCode]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [TaxCode] can contain an unknown value in a couple of cases: + * - It was deserialized from data that doesn't match any known member. For example, if + * the SDK is on an older version than the API, then the API may respond with new + * members that the SDK is unaware of. + * - It was constructed with an arbitrary value using the [of] method. + */ + enum class Value { + AE, + E, + S, + Z, + G, + O, + K, + L, + M, + B, + /** + * An enum member indicating that [TaxCode] was instantiated with an unknown value. + */ + _UNKNOWN, + } + + /** + * Returns an enum member corresponding to this class instance's value, or + * [Value._UNKNOWN] if the class was instantiated with an unknown value. + * + * Use the [known] method instead if you're certain the value is always known or if you + * want to throw for the unknown case. + */ + fun value(): Value = + when (this) { + AE -> Value.AE + E -> Value.E + S -> Value.S + Z -> Value.Z + G -> Value.G + O -> Value.O + K -> Value.K + L -> Value.L + M -> Value.M + B -> Value.B + else -> Value._UNKNOWN + } + + /** + * Returns an enum member corresponding to this class instance's value. + * + * Use the [value] method instead if you're uncertain the value is always known and + * don't want to throw for the unknown case. + * + * @throws EInvoiceInvalidDataException if this class instance's value is a not a known + * member. + */ + fun known(): Known = + when (this) { + AE -> Known.AE + E -> Known.E + S -> Known.S + Z -> Known.Z + G -> Known.G + O -> Known.O + K -> Known.K + L -> Known.L + M -> Known.M + B -> Known.B + else -> throw EInvoiceInvalidDataException("Unknown TaxCode: $value") + } + + /** + * Returns this class instance's primitive wire representation. + * + * This differs from the [toString] method because that method is primarily for + * debugging and generally doesn't throw. + * + * @throws EInvoiceInvalidDataException if this class instance's value does not have the + * expected primitive type. + */ + fun asString(): String = + _value().asString().orElseThrow { + EInvoiceInvalidDataException("Value is not a String") + } + + private var validated: Boolean = false + + fun validate(): TaxCode = apply { + if (validated) { + return@apply + } + + known() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: EInvoiceInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic internal fun validity(): Int = if (value() == Value._UNKNOWN) 0 else 1 + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is TaxCode && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + /** The VAT rate, represented as percentage that applies to the charge */ + @JsonDeserialize(using = TaxRate.Deserializer::class) + @JsonSerialize(using = TaxRate.Serializer::class) + class TaxRate + private constructor( + private val number: Double? = null, + private val string: String? = null, + private val _json: JsonValue? = null, + ) { + + fun number(): Optional = Optional.ofNullable(number) + + fun string(): Optional = Optional.ofNullable(string) + + fun isNumber(): Boolean = number != null + + fun isString(): Boolean = string != null + + fun asNumber(): Double = number.getOrThrow("number") + + fun asString(): String = string.getOrThrow("string") + + fun _json(): Optional = Optional.ofNullable(_json) + + fun accept(visitor: Visitor): T = + when { + number != null -> visitor.visitNumber(number) + string != null -> visitor.visitString(string) + else -> visitor.unknown(_json) + } + + private var validated: Boolean = false + + fun validate(): TaxRate = apply { + if (validated) { + return@apply + } + + accept( + object : Visitor { + override fun visitNumber(number: Double) {} + + override fun visitString(string: String) {} + } + ) + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: EInvoiceInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic + internal fun validity(): Int = + accept( + object : Visitor { + override fun visitNumber(number: Double) = 1 + + override fun visitString(string: String) = 1 + + override fun unknown(json: JsonValue?) = 0 + } + ) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is TaxRate && number == other.number && string == other.string + } + + override fun hashCode(): Int = Objects.hash(number, string) + + override fun toString(): String = + when { + number != null -> "TaxRate{number=$number}" + string != null -> "TaxRate{string=$string}" + _json != null -> "TaxRate{_unknown=$_json}" + else -> throw IllegalStateException("Invalid TaxRate") + } + + companion object { + + @JvmStatic fun ofNumber(number: Double) = TaxRate(number = number) + + @JvmStatic fun ofString(string: String) = TaxRate(string = string) + } + + /** + * An interface that defines how to map each variant of [TaxRate] to a value of type + * [T]. + */ + interface Visitor { + + fun visitNumber(number: Double): T + + fun visitString(string: String): T + + /** + * Maps an unknown variant of [TaxRate] to a value of type [T]. + * + * An instance of [TaxRate] can contain an unknown variant if it was deserialized + * from data that doesn't match any known variant. For example, if the SDK is on an + * older version than the API, then the API may respond with new variants that the + * SDK is unaware of. + * + * @throws EInvoiceInvalidDataException in the default implementation. + */ + fun unknown(json: JsonValue?): T { + throw EInvoiceInvalidDataException("Unknown TaxRate: $json") + } + } + + internal class Deserializer : BaseDeserializer(TaxRate::class) { + + override fun ObjectCodec.deserialize(node: JsonNode): TaxRate { + val json = JsonValue.fromJsonNode(node) + + val bestMatches = + sequenceOf( + tryDeserialize(node, jacksonTypeRef())?.let { + TaxRate(string = it, _json = json) + }, + tryDeserialize(node, jacksonTypeRef())?.let { + TaxRate(number = it, _json = json) + }, + ) + .filterNotNull() + .allMaxBy { it.validity() } + .toList() + return when (bestMatches.size) { + // This can happen if what we're deserializing is completely incompatible + // with all the possible variants (e.g. deserializing from boolean). + 0 -> TaxRate(_json = json) + 1 -> bestMatches.single() + // If there's more than one match with the highest validity, then use the + // first completely valid match, or simply the first match if none are + // completely valid. + else -> bestMatches.firstOrNull { it.isValid() } ?: bestMatches.first() + } + } + } + + internal class Serializer : BaseSerializer(TaxRate::class) { + + override fun serialize( + value: TaxRate, + generator: JsonGenerator, + provider: SerializerProvider, + ) { + when { + value.number != null -> generator.writeObject(value.number) + value.string != null -> generator.writeObject(value.string) + value._json != null -> generator.writeObject(value._json) + else -> throw IllegalStateException("Invalid TaxRate") + } + } + } + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Charge && + amount == other.amount && + baseAmount == other.baseAmount && + multiplierFactor == other.multiplierFactor && + reason == other.reason && + reasonCode == other.reasonCode && + taxCode == other.taxCode && + taxRate == other.taxRate && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash( + amount, + baseAmount, + multiplierFactor, + reason, + reasonCode, + taxCode, + taxRate, + additionalProperties, + ) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "Charge{amount=$amount, baseAmount=$baseAmount, multiplierFactor=$multiplierFactor, reason=$reason, reasonCode=$reasonCode, taxCode=$taxCode, taxRate=$taxRate, additionalProperties=$additionalProperties}" + } + + /** + * The total amount of the invoice including tax (invoice_total = subtotal + total_tax + + * total_discount). Must be positive and rounded to maximum 2 decimals + */ + @JsonDeserialize(using = InvoiceTotal.Deserializer::class) + @JsonSerialize(using = InvoiceTotal.Serializer::class) + class InvoiceTotal + private constructor( + private val number: Double? = null, + private val string: String? = null, + private val _json: JsonValue? = null, + ) { + + fun number(): Optional = Optional.ofNullable(number) + + fun string(): Optional = Optional.ofNullable(string) + + fun isNumber(): Boolean = number != null + + fun isString(): Boolean = string != null + + fun asNumber(): Double = number.getOrThrow("number") + + fun asString(): String = string.getOrThrow("string") + + fun _json(): Optional = Optional.ofNullable(_json) + + fun accept(visitor: Visitor): T = + when { + number != null -> visitor.visitNumber(number) + string != null -> visitor.visitString(string) + else -> visitor.unknown(_json) + } + + private var validated: Boolean = false + + fun validate(): InvoiceTotal = apply { + if (validated) { + return@apply + } + + accept( + object : Visitor { + override fun visitNumber(number: Double) {} + + override fun visitString(string: String) {} + } + ) + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: EInvoiceInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic + internal fun validity(): Int = + accept( + object : Visitor { + override fun visitNumber(number: Double) = 1 + + override fun visitString(string: String) = 1 + + override fun unknown(json: JsonValue?) = 0 + } + ) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is InvoiceTotal && number == other.number && string == other.string + } + + override fun hashCode(): Int = Objects.hash(number, string) + + override fun toString(): String = + when { + number != null -> "InvoiceTotal{number=$number}" + string != null -> "InvoiceTotal{string=$string}" + _json != null -> "InvoiceTotal{_unknown=$_json}" + else -> throw IllegalStateException("Invalid InvoiceTotal") + } + + companion object { + + @JvmStatic fun ofNumber(number: Double) = InvoiceTotal(number = number) + + @JvmStatic fun ofString(string: String) = InvoiceTotal(string = string) + } + + /** + * An interface that defines how to map each variant of [InvoiceTotal] to a value of type + * [T]. + */ + interface Visitor { + + fun visitNumber(number: Double): T + + fun visitString(string: String): T + + /** + * Maps an unknown variant of [InvoiceTotal] to a value of type [T]. + * + * An instance of [InvoiceTotal] can contain an unknown variant if it was deserialized + * from data that doesn't match any known variant. For example, if the SDK is on an + * older version than the API, then the API may respond with new variants that the SDK + * is unaware of. + * + * @throws EInvoiceInvalidDataException in the default implementation. + */ + fun unknown(json: JsonValue?): T { + throw EInvoiceInvalidDataException("Unknown InvoiceTotal: $json") + } + } + + internal class Deserializer : BaseDeserializer(InvoiceTotal::class) { + + override fun ObjectCodec.deserialize(node: JsonNode): InvoiceTotal { + val json = JsonValue.fromJsonNode(node) + + val bestMatches = + sequenceOf( + tryDeserialize(node, jacksonTypeRef())?.let { + InvoiceTotal(string = it, _json = json) + }, + tryDeserialize(node, jacksonTypeRef())?.let { + InvoiceTotal(number = it, _json = json) + }, + ) + .filterNotNull() + .allMaxBy { it.validity() } + .toList() + return when (bestMatches.size) { + // This can happen if what we're deserializing is completely incompatible with + // all the possible variants (e.g. deserializing from boolean). + 0 -> InvoiceTotal(_json = json) + 1 -> bestMatches.single() + // If there's more than one match with the highest validity, then use the first + // completely valid match, or simply the first match if none are completely + // valid. + else -> bestMatches.firstOrNull { it.isValid() } ?: bestMatches.first() + } + } + } + + internal class Serializer : BaseSerializer(InvoiceTotal::class) { + + override fun serialize( + value: InvoiceTotal, + generator: JsonGenerator, + provider: SerializerProvider, + ) { + when { + value.number != null -> generator.writeObject(value.number) + value.string != null -> generator.writeObject(value.string) + value._json != null -> generator.writeObject(value._json) + else -> throw IllegalStateException("Invalid InvoiceTotal") + } + } + } + } + + class Item + @JsonCreator(mode = JsonCreator.Mode.DISABLED) + private constructor( + private val allowances: JsonField>, + private val amount: JsonField, + private val charges: JsonField>, + private val date: JsonField, + private val description: JsonField, + private val productCode: JsonField, + private val quantity: JsonField, + private val tax: JsonField, + private val taxRate: JsonField, + private val unit: JsonField, + private val unitPrice: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("allowances") + @ExcludeMissing + allowances: JsonField> = JsonMissing.of(), + @JsonProperty("amount") @ExcludeMissing amount: JsonField = JsonMissing.of(), + @JsonProperty("charges") + @ExcludeMissing + charges: JsonField> = JsonMissing.of(), + @JsonProperty("date") @ExcludeMissing date: JsonField = JsonMissing.of(), + @JsonProperty("description") + @ExcludeMissing + description: JsonField = JsonMissing.of(), + @JsonProperty("product_code") + @ExcludeMissing + productCode: JsonField = JsonMissing.of(), + @JsonProperty("quantity") + @ExcludeMissing + quantity: JsonField = JsonMissing.of(), + @JsonProperty("tax") @ExcludeMissing tax: JsonField = JsonMissing.of(), + @JsonProperty("tax_rate") + @ExcludeMissing + taxRate: JsonField = JsonMissing.of(), + @JsonProperty("unit") + @ExcludeMissing + unit: JsonField = JsonMissing.of(), + @JsonProperty("unit_price") + @ExcludeMissing + unitPrice: JsonField = JsonMissing.of(), + ) : this( + allowances, + amount, + charges, + date, + description, + productCode, + quantity, + tax, + taxRate, + unit, + unitPrice, + mutableMapOf(), + ) + + /** + * The allowances of the line item. + * + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun allowances(): Optional> = allowances.getOptional("allowances") + + /** + * The invoice line net amount (BT-131), exclusive of VAT, inclusive of line level + * allowances and charges. Calculated as: ((unit_price / price_base_quantity) * quantity) - + * allowances + charges. Must be rounded to maximum 2 decimals. Can be negative for credit + * notes or corrections. + * + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun amount(): Optional = amount.getOptional("amount") + + /** + * The charges of the line item. + * + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun charges(): Optional> = charges.getOptional("charges") + + /** + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun date(): Optional = date.getOptional("date") + + /** + * The description of the line item. + * + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun description(): Optional = description.getOptional("description") + + /** + * The product code of the line item. + * + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun productCode(): Optional = productCode.getOptional("product_code") + + /** + * The quantity of items (goods or services) that is the subject of the line item. Must be + * rounded to maximum 4 decimals. Can be negative for credit notes or corrections. + * + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun quantity(): Optional = quantity.getOptional("quantity") + + /** + * The total VAT amount for the line item. Must be rounded to maximum 2 decimals. Can be + * negative for credit notes or corrections. + * + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun tax(): Optional = tax.getOptional("tax") + + /** + * The VAT rate of the line item expressed as percentage with 2 decimals + * + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun taxRate(): Optional = taxRate.getOptional("tax_rate") + + /** + * Unit of Measure Codes from UNECERec20 used in Peppol BIS Billing 3.0. + * + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun unit(): Optional = unit.getOptional("unit") + + /** + * The item net price (BT-146). The price of an item, exclusive of VAT, after subtracting + * item price discount. Must be rounded to maximum 4 decimals + * + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun unitPrice(): Optional = unitPrice.getOptional("unit_price") + + /** + * Returns the raw JSON value of [allowances]. + * + * Unlike [allowances], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("allowances") + @ExcludeMissing + fun _allowances(): JsonField> = allowances + + /** + * Returns the raw JSON value of [amount]. + * + * Unlike [amount], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("amount") @ExcludeMissing fun _amount(): JsonField = amount + + /** + * Returns the raw JSON value of [charges]. + * + * Unlike [charges], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("charges") @ExcludeMissing fun _charges(): JsonField> = charges + + /** + * Returns the raw JSON value of [date]. + * + * Unlike [date], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("date") @ExcludeMissing fun _date(): JsonField = date + + /** + * Returns the raw JSON value of [description]. + * + * Unlike [description], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("description") + @ExcludeMissing + fun _description(): JsonField = description + + /** + * Returns the raw JSON value of [productCode]. + * + * Unlike [productCode], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("product_code") + @ExcludeMissing + fun _productCode(): JsonField = productCode + + /** + * Returns the raw JSON value of [quantity]. + * + * Unlike [quantity], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("quantity") @ExcludeMissing fun _quantity(): JsonField = quantity + + /** + * Returns the raw JSON value of [tax]. + * + * Unlike [tax], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("tax") @ExcludeMissing fun _tax(): JsonField = tax + + /** + * Returns the raw JSON value of [taxRate]. + * + * Unlike [taxRate], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("tax_rate") @ExcludeMissing fun _taxRate(): JsonField = taxRate + + /** + * Returns the raw JSON value of [unit]. + * + * Unlike [unit], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("unit") @ExcludeMissing fun _unit(): JsonField = unit + + /** + * Returns the raw JSON value of [unitPrice]. + * + * Unlike [unitPrice], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("unit_price") + @ExcludeMissing + fun _unitPrice(): JsonField = unitPrice + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** Returns a mutable builder for constructing an instance of [Item]. */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [Item]. */ + class Builder internal constructor() { + + private var allowances: JsonField>? = null + private var amount: JsonField = JsonMissing.of() + private var charges: JsonField>? = null + private var date: JsonField = JsonMissing.of() + private var description: JsonField = JsonMissing.of() + private var productCode: JsonField = JsonMissing.of() + private var quantity: JsonField = JsonMissing.of() + private var tax: JsonField = JsonMissing.of() + private var taxRate: JsonField = JsonMissing.of() + private var unit: JsonField = JsonMissing.of() + private var unitPrice: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(item: Item) = apply { + allowances = item.allowances.map { it.toMutableList() } + amount = item.amount + charges = item.charges.map { it.toMutableList() } + date = item.date + description = item.description + productCode = item.productCode + quantity = item.quantity + tax = item.tax + taxRate = item.taxRate + unit = item.unit + unitPrice = item.unitPrice + additionalProperties = item.additionalProperties.toMutableMap() + } + + /** The allowances of the line item. */ + fun allowances(allowances: List?) = + allowances(JsonField.ofNullable(allowances)) + + /** Alias for calling [Builder.allowances] with `allowances.orElse(null)`. */ + fun allowances(allowances: Optional>) = + allowances(allowances.getOrNull()) + + /** + * Sets [Builder.allowances] to an arbitrary JSON value. + * + * You should usually call [Builder.allowances] with a well-typed `List` + * value instead. This method is primarily for setting the field to an undocumented or + * not yet supported value. + */ + fun allowances(allowances: JsonField>) = apply { + this.allowances = allowances.map { it.toMutableList() } + } + + /** + * Adds a single [Allowance] to [allowances]. + * + * @throws IllegalStateException if the field was previously set to a non-list. + */ + fun addAllowance(allowance: Allowance) = apply { + allowances = + (allowances ?: JsonField.of(mutableListOf())).also { + checkKnown("allowances", it).add(allowance) + } + } + + /** + * The invoice line net amount (BT-131), exclusive of VAT, inclusive of line level + * allowances and charges. Calculated as: ((unit_price / price_base_quantity) * + * quantity) - allowances + charges. Must be rounded to maximum 2 decimals. Can be + * negative for credit notes or corrections. + */ + fun amount(amount: Amount?) = amount(JsonField.ofNullable(amount)) + + /** Alias for calling [Builder.amount] with `amount.orElse(null)`. */ + fun amount(amount: Optional) = amount(amount.getOrNull()) + + /** + * Sets [Builder.amount] to an arbitrary JSON value. + * + * You should usually call [Builder.amount] with a well-typed [Amount] value instead. + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun amount(amount: JsonField) = apply { this.amount = amount } + + /** Alias for calling [amount] with `Amount.ofNumber(number)`. */ + fun amount(number: Double) = amount(Amount.ofNumber(number)) + + /** Alias for calling [amount] with `Amount.ofString(string)`. */ + fun amount(string: String) = amount(Amount.ofString(string)) + + /** The charges of the line item. */ + fun charges(charges: List?) = charges(JsonField.ofNullable(charges)) + + /** Alias for calling [Builder.charges] with `charges.orElse(null)`. */ + fun charges(charges: Optional>) = charges(charges.getOrNull()) + + /** + * Sets [Builder.charges] to an arbitrary JSON value. + * + * You should usually call [Builder.charges] with a well-typed `List` value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun charges(charges: JsonField>) = apply { + this.charges = charges.map { it.toMutableList() } + } + + /** + * Adds a single [Charge] to [charges]. + * + * @throws IllegalStateException if the field was previously set to a non-list. + */ + fun addCharge(charge: Charge) = apply { + charges = + (charges ?: JsonField.of(mutableListOf())).also { + checkKnown("charges", it).add(charge) + } + } + + fun date(date: Void?) = date(JsonField.ofNullable(date)) + + /** Alias for calling [Builder.date] with `date.orElse(null)`. */ + fun date(date: Optional) = date(date.getOrNull()) + + /** + * Sets [Builder.date] to an arbitrary JSON value. + * + * You should usually call [Builder.date] with a well-typed [Void] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun date(date: JsonField) = apply { this.date = date } + + /** The description of the line item. */ + fun description(description: String?) = description(JsonField.ofNullable(description)) + + /** Alias for calling [Builder.description] with `description.orElse(null)`. */ + fun description(description: Optional) = description(description.getOrNull()) + + /** + * Sets [Builder.description] to an arbitrary JSON value. + * + * You should usually call [Builder.description] with a well-typed [String] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun description(description: JsonField) = apply { + this.description = description + } + + /** The product code of the line item. */ + fun productCode(productCode: String?) = productCode(JsonField.ofNullable(productCode)) + + /** Alias for calling [Builder.productCode] with `productCode.orElse(null)`. */ + fun productCode(productCode: Optional) = productCode(productCode.getOrNull()) + + /** + * Sets [Builder.productCode] to an arbitrary JSON value. + * + * You should usually call [Builder.productCode] with a well-typed [String] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun productCode(productCode: JsonField) = apply { + this.productCode = productCode + } + + /** + * The quantity of items (goods or services) that is the subject of the line item. Must + * be rounded to maximum 4 decimals. Can be negative for credit notes or corrections. + */ + fun quantity(quantity: Quantity?) = quantity(JsonField.ofNullable(quantity)) + + /** Alias for calling [Builder.quantity] with `quantity.orElse(null)`. */ + fun quantity(quantity: Optional) = quantity(quantity.getOrNull()) + + /** + * Sets [Builder.quantity] to an arbitrary JSON value. + * + * You should usually call [Builder.quantity] with a well-typed [Quantity] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun quantity(quantity: JsonField) = apply { this.quantity = quantity } + + /** Alias for calling [quantity] with `Quantity.ofNumber(number)`. */ + fun quantity(number: Double) = quantity(Quantity.ofNumber(number)) + + /** Alias for calling [quantity] with `Quantity.ofString(string)`. */ + fun quantity(string: String) = quantity(Quantity.ofString(string)) + + /** + * The total VAT amount for the line item. Must be rounded to maximum 2 decimals. Can be + * negative for credit notes or corrections. + */ + fun tax(tax: Tax?) = tax(JsonField.ofNullable(tax)) + + /** Alias for calling [Builder.tax] with `tax.orElse(null)`. */ + fun tax(tax: Optional) = tax(tax.getOrNull()) + + /** + * Sets [Builder.tax] to an arbitrary JSON value. + * + * You should usually call [Builder.tax] with a well-typed [Tax] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun tax(tax: JsonField) = apply { this.tax = tax } + + /** Alias for calling [tax] with `Tax.ofNumber(number)`. */ + fun tax(number: Double) = tax(Tax.ofNumber(number)) + + /** Alias for calling [tax] with `Tax.ofString(string)`. */ + fun tax(string: String) = tax(Tax.ofString(string)) + + /** The VAT rate of the line item expressed as percentage with 2 decimals */ + fun taxRate(taxRate: TaxRate?) = taxRate(JsonField.ofNullable(taxRate)) + + /** Alias for calling [Builder.taxRate] with `taxRate.orElse(null)`. */ + fun taxRate(taxRate: Optional) = taxRate(taxRate.getOrNull()) + + /** + * Sets [Builder.taxRate] to an arbitrary JSON value. + * + * You should usually call [Builder.taxRate] with a well-typed [TaxRate] value instead. + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun taxRate(taxRate: JsonField) = apply { this.taxRate = taxRate } + + /** Alias for calling [taxRate] with `TaxRate.ofNumber(number)`. */ + fun taxRate(number: Double) = taxRate(TaxRate.ofNumber(number)) + + /** Alias for calling [taxRate] with `TaxRate.ofString(string)`. */ + fun taxRate(string: String) = taxRate(TaxRate.ofString(string)) + + /** Unit of Measure Codes from UNECERec20 used in Peppol BIS Billing 3.0. */ + fun unit(unit: UnitOfMeasureCode?) = unit(JsonField.ofNullable(unit)) + + /** Alias for calling [Builder.unit] with `unit.orElse(null)`. */ + fun unit(unit: Optional) = unit(unit.getOrNull()) + + /** + * Sets [Builder.unit] to an arbitrary JSON value. + * + * You should usually call [Builder.unit] with a well-typed [UnitOfMeasureCode] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun unit(unit: JsonField) = apply { this.unit = unit } + + /** + * The item net price (BT-146). The price of an item, exclusive of VAT, after + * subtracting item price discount. Must be rounded to maximum 4 decimals + */ + fun unitPrice(unitPrice: UnitPrice?) = unitPrice(JsonField.ofNullable(unitPrice)) + + /** Alias for calling [Builder.unitPrice] with `unitPrice.orElse(null)`. */ + fun unitPrice(unitPrice: Optional) = unitPrice(unitPrice.getOrNull()) + + /** + * Sets [Builder.unitPrice] to an arbitrary JSON value. + * + * You should usually call [Builder.unitPrice] with a well-typed [UnitPrice] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun unitPrice(unitPrice: JsonField) = apply { this.unitPrice = unitPrice } + + /** Alias for calling [unitPrice] with `UnitPrice.ofNumber(number)`. */ + fun unitPrice(number: Double) = unitPrice(UnitPrice.ofNumber(number)) + + /** Alias for calling [unitPrice] with `UnitPrice.ofString(string)`. */ + fun unitPrice(string: String) = unitPrice(UnitPrice.ofString(string)) + + fun additionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.clear() + putAllAdditionalProperties(additionalProperties) + } + + fun putAdditionalProperty(key: String, value: JsonValue) = apply { + additionalProperties.put(key, value) + } + + fun putAllAdditionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.putAll(additionalProperties) + } + + fun removeAdditionalProperty(key: String) = apply { additionalProperties.remove(key) } + + fun removeAllAdditionalProperties(keys: Set) = apply { + keys.forEach(::removeAdditionalProperty) + } + + /** + * Returns an immutable instance of [Item]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): Item = + Item( + (allowances ?: JsonMissing.of()).map { it.toImmutable() }, + amount, + (charges ?: JsonMissing.of()).map { it.toImmutable() }, + date, + description, + productCode, + quantity, + tax, + taxRate, + unit, + unitPrice, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + fun validate(): Item = apply { + if (validated) { + return@apply + } + + allowances().ifPresent { it.forEach { it.validate() } } + amount().ifPresent { it.validate() } + charges().ifPresent { it.forEach { it.validate() } } + date() + description() + productCode() + quantity().ifPresent { it.validate() } + tax().ifPresent { it.validate() } + taxRate().ifPresent { it.validate() } + unit().ifPresent { it.validate() } + unitPrice().ifPresent { it.validate() } + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: EInvoiceInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic + internal fun validity(): Int = + (allowances.asKnown().getOrNull()?.sumOf { it.validity().toInt() } ?: 0) + + (amount.asKnown().getOrNull()?.validity() ?: 0) + + (charges.asKnown().getOrNull()?.sumOf { it.validity().toInt() } ?: 0) + + (if (date.asKnown().isPresent) 1 else 0) + + (if (description.asKnown().isPresent) 1 else 0) + + (if (productCode.asKnown().isPresent) 1 else 0) + + (quantity.asKnown().getOrNull()?.validity() ?: 0) + + (tax.asKnown().getOrNull()?.validity() ?: 0) + + (taxRate.asKnown().getOrNull()?.validity() ?: 0) + + (unit.asKnown().getOrNull()?.validity() ?: 0) + + (unitPrice.asKnown().getOrNull()?.validity() ?: 0) + + /** An allowance is a discount for example for early payment, volume discount, etc. */ + class Allowance + @JsonCreator(mode = JsonCreator.Mode.DISABLED) + private constructor( + private val amount: JsonField, + private val baseAmount: JsonField, + private val multiplierFactor: JsonField, + private val reason: JsonField, + private val reasonCode: JsonField, + private val taxCode: JsonField, + private val taxRate: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("amount") + @ExcludeMissing + amount: JsonField = JsonMissing.of(), + @JsonProperty("base_amount") + @ExcludeMissing + baseAmount: JsonField = JsonMissing.of(), + @JsonProperty("multiplier_factor") + @ExcludeMissing + multiplierFactor: JsonField = JsonMissing.of(), + @JsonProperty("reason") + @ExcludeMissing + reason: JsonField = JsonMissing.of(), + @JsonProperty("reason_code") + @ExcludeMissing + reasonCode: JsonField = JsonMissing.of(), + @JsonProperty("tax_code") + @ExcludeMissing + taxCode: JsonField = JsonMissing.of(), + @JsonProperty("tax_rate") + @ExcludeMissing + taxRate: JsonField = JsonMissing.of(), + ) : this( + amount, + baseAmount, + multiplierFactor, + reason, + reasonCode, + taxCode, + taxRate, + mutableMapOf(), + ) + + /** + * The allowance amount, without VAT. Must be rounded to maximum 2 decimals + * + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. + * if the server responded with an unexpected value). + */ + fun amount(): Optional = amount.getOptional("amount") + + /** + * The base amount that may be used, in conjunction with the allowance percentage, to + * calculate the allowance amount. Must be rounded to maximum 2 decimals + * + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. + * if the server responded with an unexpected value). + */ + fun baseAmount(): Optional = baseAmount.getOptional("base_amount") + + /** + * The percentage that may be used, in conjunction with the allowance base amount, to + * calculate the allowance amount. To state 20%, use value 20. Must be rounded to + * maximum 2 decimals + * + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. + * if the server responded with an unexpected value). + */ + fun multiplierFactor(): Optional = + multiplierFactor.getOptional("multiplier_factor") + + /** + * The reason for the allowance + * + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. + * if the server responded with an unexpected value). + */ + fun reason(): Optional = reason.getOptional("reason") + + /** + * Allowance reason codes for invoice discounts and charges + * + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. + * if the server responded with an unexpected value). + */ + fun reasonCode(): Optional = reasonCode.getOptional("reason_code") + + /** + * The VAT category code that applies to the allowance + * + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. + * if the server responded with an unexpected value). + */ + fun taxCode(): Optional = taxCode.getOptional("tax_code") + + /** + * The VAT rate, represented as percentage that applies to the allowance. Must be + * rounded to maximum 2 decimals + * + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. + * if the server responded with an unexpected value). + */ + fun taxRate(): Optional = taxRate.getOptional("tax_rate") + + /** + * Returns the raw JSON value of [amount]. + * + * Unlike [amount], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("amount") @ExcludeMissing fun _amount(): JsonField = amount + + /** + * Returns the raw JSON value of [baseAmount]. + * + * Unlike [baseAmount], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("base_amount") + @ExcludeMissing + fun _baseAmount(): JsonField = baseAmount + + /** + * Returns the raw JSON value of [multiplierFactor]. + * + * Unlike [multiplierFactor], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("multiplier_factor") + @ExcludeMissing + fun _multiplierFactor(): JsonField = multiplierFactor + + /** + * Returns the raw JSON value of [reason]. + * + * Unlike [reason], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("reason") @ExcludeMissing fun _reason(): JsonField = reason + + /** + * Returns the raw JSON value of [reasonCode]. + * + * Unlike [reasonCode], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("reason_code") + @ExcludeMissing + fun _reasonCode(): JsonField = reasonCode + + /** + * Returns the raw JSON value of [taxCode]. + * + * Unlike [taxCode], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("tax_code") @ExcludeMissing fun _taxCode(): JsonField = taxCode + + /** + * Returns the raw JSON value of [taxRate]. + * + * Unlike [taxRate], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("tax_rate") @ExcludeMissing fun _taxRate(): JsonField = taxRate + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** Returns a mutable builder for constructing an instance of [Allowance]. */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [Allowance]. */ + class Builder internal constructor() { + + private var amount: JsonField = JsonMissing.of() + private var baseAmount: JsonField = JsonMissing.of() + private var multiplierFactor: JsonField = JsonMissing.of() + private var reason: JsonField = JsonMissing.of() + private var reasonCode: JsonField = JsonMissing.of() + private var taxCode: JsonField = JsonMissing.of() + private var taxRate: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(allowance: Allowance) = apply { + amount = allowance.amount + baseAmount = allowance.baseAmount + multiplierFactor = allowance.multiplierFactor + reason = allowance.reason + reasonCode = allowance.reasonCode + taxCode = allowance.taxCode + taxRate = allowance.taxRate + additionalProperties = allowance.additionalProperties.toMutableMap() + } + + /** The allowance amount, without VAT. Must be rounded to maximum 2 decimals */ + fun amount(amount: Amount?) = amount(JsonField.ofNullable(amount)) + + /** Alias for calling [Builder.amount] with `amount.orElse(null)`. */ + fun amount(amount: Optional) = amount(amount.getOrNull()) + + /** + * Sets [Builder.amount] to an arbitrary JSON value. + * + * You should usually call [Builder.amount] with a well-typed [Amount] value + * instead. This method is primarily for setting the field to an undocumented or not + * yet supported value. + */ + fun amount(amount: JsonField) = apply { this.amount = amount } + + /** Alias for calling [amount] with `Amount.ofNumber(number)`. */ + fun amount(number: Double) = amount(Amount.ofNumber(number)) + + /** Alias for calling [amount] with `Amount.ofString(string)`. */ + fun amount(string: String) = amount(Amount.ofString(string)) + + /** + * The base amount that may be used, in conjunction with the allowance percentage, + * to calculate the allowance amount. Must be rounded to maximum 2 decimals + */ + fun baseAmount(baseAmount: BaseAmount?) = + baseAmount(JsonField.ofNullable(baseAmount)) + + /** Alias for calling [Builder.baseAmount] with `baseAmount.orElse(null)`. */ + fun baseAmount(baseAmount: Optional) = + baseAmount(baseAmount.getOrNull()) + + /** + * Sets [Builder.baseAmount] to an arbitrary JSON value. + * + * You should usually call [Builder.baseAmount] with a well-typed [BaseAmount] value + * instead. This method is primarily for setting the field to an undocumented or not + * yet supported value. + */ + fun baseAmount(baseAmount: JsonField) = apply { + this.baseAmount = baseAmount + } + + /** Alias for calling [baseAmount] with `BaseAmount.ofNumber(number)`. */ + fun baseAmount(number: Double) = baseAmount(BaseAmount.ofNumber(number)) + + /** Alias for calling [baseAmount] with `BaseAmount.ofString(string)`. */ + fun baseAmount(string: String) = baseAmount(BaseAmount.ofString(string)) + + /** + * The percentage that may be used, in conjunction with the allowance base amount, + * to calculate the allowance amount. To state 20%, use value 20. Must be rounded to + * maximum 2 decimals + */ + fun multiplierFactor(multiplierFactor: MultiplierFactor?) = + multiplierFactor(JsonField.ofNullable(multiplierFactor)) + + /** + * Alias for calling [Builder.multiplierFactor] with + * `multiplierFactor.orElse(null)`. + */ + fun multiplierFactor(multiplierFactor: Optional) = + multiplierFactor(multiplierFactor.getOrNull()) + + /** + * Sets [Builder.multiplierFactor] to an arbitrary JSON value. + * + * You should usually call [Builder.multiplierFactor] with a well-typed + * [MultiplierFactor] value instead. This method is primarily for setting the field + * to an undocumented or not yet supported value. + */ + fun multiplierFactor(multiplierFactor: JsonField) = apply { + this.multiplierFactor = multiplierFactor + } + + /** + * Alias for calling [multiplierFactor] with `MultiplierFactor.ofNumber(number)`. + */ + fun multiplierFactor(number: Double) = + multiplierFactor(MultiplierFactor.ofNumber(number)) + + /** + * Alias for calling [multiplierFactor] with `MultiplierFactor.ofString(string)`. + */ + fun multiplierFactor(string: String) = + multiplierFactor(MultiplierFactor.ofString(string)) + + /** The reason for the allowance */ + fun reason(reason: String?) = reason(JsonField.ofNullable(reason)) + + /** Alias for calling [Builder.reason] with `reason.orElse(null)`. */ + fun reason(reason: Optional) = reason(reason.getOrNull()) + + /** + * Sets [Builder.reason] to an arbitrary JSON value. + * + * You should usually call [Builder.reason] with a well-typed [String] value + * instead. This method is primarily for setting the field to an undocumented or not + * yet supported value. + */ + fun reason(reason: JsonField) = apply { this.reason = reason } + + /** Allowance reason codes for invoice discounts and charges */ + fun reasonCode(reasonCode: ReasonCode?) = + reasonCode(JsonField.ofNullable(reasonCode)) + + /** Alias for calling [Builder.reasonCode] with `reasonCode.orElse(null)`. */ + fun reasonCode(reasonCode: Optional) = + reasonCode(reasonCode.getOrNull()) + + /** + * Sets [Builder.reasonCode] to an arbitrary JSON value. + * + * You should usually call [Builder.reasonCode] with a well-typed [ReasonCode] value + * instead. This method is primarily for setting the field to an undocumented or not + * yet supported value. + */ + fun reasonCode(reasonCode: JsonField) = apply { + this.reasonCode = reasonCode + } + + /** The VAT category code that applies to the allowance */ + fun taxCode(taxCode: TaxCode) = taxCode(JsonField.of(taxCode)) + + /** + * Sets [Builder.taxCode] to an arbitrary JSON value. + * + * You should usually call [Builder.taxCode] with a well-typed [TaxCode] value + * instead. This method is primarily for setting the field to an undocumented or not + * yet supported value. + */ + fun taxCode(taxCode: JsonField) = apply { this.taxCode = taxCode } + + /** + * The VAT rate, represented as percentage that applies to the allowance. Must be + * rounded to maximum 2 decimals + */ + fun taxRate(taxRate: TaxRate?) = taxRate(JsonField.ofNullable(taxRate)) + + /** Alias for calling [Builder.taxRate] with `taxRate.orElse(null)`. */ + fun taxRate(taxRate: Optional) = taxRate(taxRate.getOrNull()) + + /** + * Sets [Builder.taxRate] to an arbitrary JSON value. + * + * You should usually call [Builder.taxRate] with a well-typed [TaxRate] value + * instead. This method is primarily for setting the field to an undocumented or not + * yet supported value. + */ + fun taxRate(taxRate: JsonField) = apply { this.taxRate = taxRate } + + /** Alias for calling [taxRate] with `TaxRate.ofNumber(number)`. */ + fun taxRate(number: Double) = taxRate(TaxRate.ofNumber(number)) + + /** Alias for calling [taxRate] with `TaxRate.ofString(string)`. */ + fun taxRate(string: String) = taxRate(TaxRate.ofString(string)) + + fun additionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.clear() + putAllAdditionalProperties(additionalProperties) + } + + fun putAdditionalProperty(key: String, value: JsonValue) = apply { + additionalProperties.put(key, value) + } + + fun putAllAdditionalProperties(additionalProperties: Map) = + apply { + this.additionalProperties.putAll(additionalProperties) + } + + fun removeAdditionalProperty(key: String) = apply { + additionalProperties.remove(key) + } + + fun removeAllAdditionalProperties(keys: Set) = apply { + keys.forEach(::removeAdditionalProperty) + } + + /** + * Returns an immutable instance of [Allowance]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): Allowance = + Allowance( + amount, + baseAmount, + multiplierFactor, + reason, + reasonCode, + taxCode, + taxRate, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + fun validate(): Allowance = apply { + if (validated) { + return@apply + } + + amount().ifPresent { it.validate() } + baseAmount().ifPresent { it.validate() } + multiplierFactor().ifPresent { it.validate() } + reason() + reasonCode().ifPresent { it.validate() } + taxCode().ifPresent { it.validate() } + taxRate().ifPresent { it.validate() } + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: EInvoiceInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic + internal fun validity(): Int = + (amount.asKnown().getOrNull()?.validity() ?: 0) + + (baseAmount.asKnown().getOrNull()?.validity() ?: 0) + + (multiplierFactor.asKnown().getOrNull()?.validity() ?: 0) + + (if (reason.asKnown().isPresent) 1 else 0) + + (reasonCode.asKnown().getOrNull()?.validity() ?: 0) + + (taxCode.asKnown().getOrNull()?.validity() ?: 0) + + (taxRate.asKnown().getOrNull()?.validity() ?: 0) + + /** The allowance amount, without VAT. Must be rounded to maximum 2 decimals */ + @JsonDeserialize(using = Amount.Deserializer::class) + @JsonSerialize(using = Amount.Serializer::class) + class Amount + private constructor( + private val number: Double? = null, + private val string: String? = null, + private val _json: JsonValue? = null, + ) { + + fun number(): Optional = Optional.ofNullable(number) + + fun string(): Optional = Optional.ofNullable(string) + + fun isNumber(): Boolean = number != null + + fun isString(): Boolean = string != null + + fun asNumber(): Double = number.getOrThrow("number") + + fun asString(): String = string.getOrThrow("string") + + fun _json(): Optional = Optional.ofNullable(_json) + + fun accept(visitor: Visitor): T = + when { + number != null -> visitor.visitNumber(number) + string != null -> visitor.visitString(string) + else -> visitor.unknown(_json) + } + + private var validated: Boolean = false + + fun validate(): Amount = apply { + if (validated) { + return@apply + } + + accept( + object : Visitor { + override fun visitNumber(number: Double) {} + + override fun visitString(string: String) {} + } + ) + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: EInvoiceInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic + internal fun validity(): Int = + accept( + object : Visitor { + override fun visitNumber(number: Double) = 1 + + override fun visitString(string: String) = 1 + + override fun unknown(json: JsonValue?) = 0 + } + ) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Amount && number == other.number && string == other.string + } + + override fun hashCode(): Int = Objects.hash(number, string) + + override fun toString(): String = + when { + number != null -> "Amount{number=$number}" + string != null -> "Amount{string=$string}" + _json != null -> "Amount{_unknown=$_json}" + else -> throw IllegalStateException("Invalid Amount") + } + + companion object { + + @JvmStatic fun ofNumber(number: Double) = Amount(number = number) + + @JvmStatic fun ofString(string: String) = Amount(string = string) + } + + /** + * An interface that defines how to map each variant of [Amount] to a value of type + * [T]. + */ + interface Visitor { + + fun visitNumber(number: Double): T + + fun visitString(string: String): T + + /** + * Maps an unknown variant of [Amount] to a value of type [T]. + * + * An instance of [Amount] can contain an unknown variant if it was deserialized + * from data that doesn't match any known variant. For example, if the SDK is on + * an older version than the API, then the API may respond with new variants + * that the SDK is unaware of. + * + * @throws EInvoiceInvalidDataException in the default implementation. + */ + fun unknown(json: JsonValue?): T { + throw EInvoiceInvalidDataException("Unknown Amount: $json") + } + } + + internal class Deserializer : BaseDeserializer(Amount::class) { + + override fun ObjectCodec.deserialize(node: JsonNode): Amount { + val json = JsonValue.fromJsonNode(node) + + val bestMatches = + sequenceOf( + tryDeserialize(node, jacksonTypeRef())?.let { + Amount(string = it, _json = json) + }, + tryDeserialize(node, jacksonTypeRef())?.let { + Amount(number = it, _json = json) + }, + ) + .filterNotNull() + .allMaxBy { it.validity() } + .toList() + return when (bestMatches.size) { + // This can happen if what we're deserializing is completely + // incompatible with all the possible variants (e.g. deserializing from + // boolean). + 0 -> Amount(_json = json) + 1 -> bestMatches.single() + // If there's more than one match with the highest validity, then use + // the first completely valid match, or simply the first match if none + // are completely valid. + else -> bestMatches.firstOrNull { it.isValid() } ?: bestMatches.first() + } + } + } + + internal class Serializer : BaseSerializer(Amount::class) { + + override fun serialize( + value: Amount, + generator: JsonGenerator, + provider: SerializerProvider, + ) { + when { + value.number != null -> generator.writeObject(value.number) + value.string != null -> generator.writeObject(value.string) + value._json != null -> generator.writeObject(value._json) + else -> throw IllegalStateException("Invalid Amount") + } + } + } + } + + /** + * The base amount that may be used, in conjunction with the allowance percentage, to + * calculate the allowance amount. Must be rounded to maximum 2 decimals + */ + @JsonDeserialize(using = BaseAmount.Deserializer::class) + @JsonSerialize(using = BaseAmount.Serializer::class) + class BaseAmount + private constructor( + private val number: Double? = null, + private val string: String? = null, + private val _json: JsonValue? = null, + ) { + + fun number(): Optional = Optional.ofNullable(number) + + fun string(): Optional = Optional.ofNullable(string) + + fun isNumber(): Boolean = number != null + + fun isString(): Boolean = string != null + + fun asNumber(): Double = number.getOrThrow("number") + + fun asString(): String = string.getOrThrow("string") + + fun _json(): Optional = Optional.ofNullable(_json) + + fun accept(visitor: Visitor): T = + when { + number != null -> visitor.visitNumber(number) + string != null -> visitor.visitString(string) + else -> visitor.unknown(_json) + } + + private var validated: Boolean = false + + fun validate(): BaseAmount = apply { + if (validated) { + return@apply + } + + accept( + object : Visitor { + override fun visitNumber(number: Double) {} + + override fun visitString(string: String) {} + } + ) + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: EInvoiceInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic + internal fun validity(): Int = + accept( + object : Visitor { + override fun visitNumber(number: Double) = 1 + + override fun visitString(string: String) = 1 + + override fun unknown(json: JsonValue?) = 0 + } + ) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is BaseAmount && number == other.number && string == other.string + } + + override fun hashCode(): Int = Objects.hash(number, string) + + override fun toString(): String = + when { + number != null -> "BaseAmount{number=$number}" + string != null -> "BaseAmount{string=$string}" + _json != null -> "BaseAmount{_unknown=$_json}" + else -> throw IllegalStateException("Invalid BaseAmount") + } + + companion object { + + @JvmStatic fun ofNumber(number: Double) = BaseAmount(number = number) + + @JvmStatic fun ofString(string: String) = BaseAmount(string = string) + } + + /** + * An interface that defines how to map each variant of [BaseAmount] to a value of + * type [T]. + */ + interface Visitor { + + fun visitNumber(number: Double): T + + fun visitString(string: String): T + + /** + * Maps an unknown variant of [BaseAmount] to a value of type [T]. + * + * An instance of [BaseAmount] can contain an unknown variant if it was + * deserialized from data that doesn't match any known variant. For example, if + * the SDK is on an older version than the API, then the API may respond with + * new variants that the SDK is unaware of. + * + * @throws EInvoiceInvalidDataException in the default implementation. + */ + fun unknown(json: JsonValue?): T { + throw EInvoiceInvalidDataException("Unknown BaseAmount: $json") + } + } + + internal class Deserializer : BaseDeserializer(BaseAmount::class) { + + override fun ObjectCodec.deserialize(node: JsonNode): BaseAmount { + val json = JsonValue.fromJsonNode(node) + + val bestMatches = + sequenceOf( + tryDeserialize(node, jacksonTypeRef())?.let { + BaseAmount(string = it, _json = json) + }, + tryDeserialize(node, jacksonTypeRef())?.let { + BaseAmount(number = it, _json = json) + }, + ) + .filterNotNull() + .allMaxBy { it.validity() } + .toList() + return when (bestMatches.size) { + // This can happen if what we're deserializing is completely + // incompatible with all the possible variants (e.g. deserializing from + // boolean). + 0 -> BaseAmount(_json = json) + 1 -> bestMatches.single() + // If there's more than one match with the highest validity, then use + // the first completely valid match, or simply the first match if none + // are completely valid. + else -> bestMatches.firstOrNull { it.isValid() } ?: bestMatches.first() + } + } + } + + internal class Serializer : BaseSerializer(BaseAmount::class) { + + override fun serialize( + value: BaseAmount, + generator: JsonGenerator, + provider: SerializerProvider, + ) { + when { + value.number != null -> generator.writeObject(value.number) + value.string != null -> generator.writeObject(value.string) + value._json != null -> generator.writeObject(value._json) + else -> throw IllegalStateException("Invalid BaseAmount") + } + } + } + } + + /** + * The percentage that may be used, in conjunction with the allowance base amount, to + * calculate the allowance amount. To state 20%, use value 20. Must be rounded to + * maximum 2 decimals + */ + @JsonDeserialize(using = MultiplierFactor.Deserializer::class) + @JsonSerialize(using = MultiplierFactor.Serializer::class) + class MultiplierFactor + private constructor( + private val number: Double? = null, + private val string: String? = null, + private val _json: JsonValue? = null, + ) { + + fun number(): Optional = Optional.ofNullable(number) + + fun string(): Optional = Optional.ofNullable(string) + + fun isNumber(): Boolean = number != null + + fun isString(): Boolean = string != null + + fun asNumber(): Double = number.getOrThrow("number") + + fun asString(): String = string.getOrThrow("string") + + fun _json(): Optional = Optional.ofNullable(_json) + + fun accept(visitor: Visitor): T = + when { + number != null -> visitor.visitNumber(number) + string != null -> visitor.visitString(string) + else -> visitor.unknown(_json) + } + + private var validated: Boolean = false + + fun validate(): MultiplierFactor = apply { + if (validated) { + return@apply + } + + accept( + object : Visitor { + override fun visitNumber(number: Double) {} + + override fun visitString(string: String) {} + } + ) + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: EInvoiceInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic + internal fun validity(): Int = + accept( + object : Visitor { + override fun visitNumber(number: Double) = 1 + + override fun visitString(string: String) = 1 + + override fun unknown(json: JsonValue?) = 0 + } + ) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is MultiplierFactor && + number == other.number && + string == other.string + } + + override fun hashCode(): Int = Objects.hash(number, string) + + override fun toString(): String = + when { + number != null -> "MultiplierFactor{number=$number}" + string != null -> "MultiplierFactor{string=$string}" + _json != null -> "MultiplierFactor{_unknown=$_json}" + else -> throw IllegalStateException("Invalid MultiplierFactor") + } + + companion object { + + @JvmStatic fun ofNumber(number: Double) = MultiplierFactor(number = number) + + @JvmStatic fun ofString(string: String) = MultiplierFactor(string = string) + } + + /** + * An interface that defines how to map each variant of [MultiplierFactor] to a + * value of type [T]. + */ + interface Visitor { + + fun visitNumber(number: Double): T + + fun visitString(string: String): T + + /** + * Maps an unknown variant of [MultiplierFactor] to a value of type [T]. + * + * An instance of [MultiplierFactor] can contain an unknown variant if it was + * deserialized from data that doesn't match any known variant. For example, if + * the SDK is on an older version than the API, then the API may respond with + * new variants that the SDK is unaware of. + * + * @throws EInvoiceInvalidDataException in the default implementation. + */ + fun unknown(json: JsonValue?): T { + throw EInvoiceInvalidDataException("Unknown MultiplierFactor: $json") + } + } + + internal class Deserializer : + BaseDeserializer(MultiplierFactor::class) { + + override fun ObjectCodec.deserialize(node: JsonNode): MultiplierFactor { + val json = JsonValue.fromJsonNode(node) + + val bestMatches = + sequenceOf( + tryDeserialize(node, jacksonTypeRef())?.let { + MultiplierFactor(string = it, _json = json) + }, + tryDeserialize(node, jacksonTypeRef())?.let { + MultiplierFactor(number = it, _json = json) + }, + ) + .filterNotNull() + .allMaxBy { it.validity() } + .toList() + return when (bestMatches.size) { + // This can happen if what we're deserializing is completely + // incompatible with all the possible variants (e.g. deserializing from + // boolean). + 0 -> MultiplierFactor(_json = json) + 1 -> bestMatches.single() + // If there's more than one match with the highest validity, then use + // the first completely valid match, or simply the first match if none + // are completely valid. + else -> bestMatches.firstOrNull { it.isValid() } ?: bestMatches.first() + } + } + } + + internal class Serializer : + BaseSerializer(MultiplierFactor::class) { + + override fun serialize( + value: MultiplierFactor, + generator: JsonGenerator, + provider: SerializerProvider, + ) { + when { + value.number != null -> generator.writeObject(value.number) + value.string != null -> generator.writeObject(value.string) + value._json != null -> generator.writeObject(value._json) + else -> throw IllegalStateException("Invalid MultiplierFactor") + } + } + } + } + + /** Allowance reason codes for invoice discounts and charges */ + class ReasonCode + @JsonCreator + private constructor(private val value: JsonField) : Enum { + + /** + * Returns this class instance's raw value. + * + * This is usually only useful if this instance was deserialized from data that + * doesn't match any known member, and you want to know that value. For example, if + * the SDK is on an older version than the API, then the API may respond with new + * members that the SDK is unaware of. + */ + @com.fasterxml.jackson.annotation.JsonValue fun _value(): JsonField = value + + companion object { + + @JvmField val _41 = of("41") + + @JvmField val _42 = of("42") + + @JvmField val _60 = of("60") + + @JvmField val _62 = of("62") + + @JvmField val _63 = of("63") + + @JvmField val _64 = of("64") + + @JvmField val _65 = of("65") + + @JvmField val _66 = of("66") + + @JvmField val _67 = of("67") + + @JvmField val _68 = of("68") + + @JvmField val _70 = of("70") + + @JvmField val _71 = of("71") + + @JvmField val _88 = of("88") + + @JvmField val _95 = of("95") + + @JvmField val _100 = of("100") + + @JvmField val _102 = of("102") + + @JvmField val _103 = of("103") + + @JvmField val _104 = of("104") + + @JvmField val _105 = of("105") + + @JvmStatic fun of(value: String) = ReasonCode(JsonField.of(value)) + } + + /** An enum containing [ReasonCode]'s known values. */ + enum class Known { + _41, + _42, + _60, + _62, + _63, + _64, + _65, + _66, + _67, + _68, + _70, + _71, + _88, + _95, + _100, + _102, + _103, + _104, + _105, + } + + /** + * An enum containing [ReasonCode]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [ReasonCode] can contain an unknown value in a couple of cases: + * - It was deserialized from data that doesn't match any known member. For example, + * if the SDK is on an older version than the API, then the API may respond with + * new members that the SDK is unaware of. + * - It was constructed with an arbitrary value using the [of] method. + */ + enum class Value { + _41, + _42, + _60, + _62, + _63, + _64, + _65, + _66, + _67, + _68, + _70, + _71, + _88, + _95, + _100, + _102, + _103, + _104, + _105, + /** + * An enum member indicating that [ReasonCode] was instantiated with an unknown + * value. + */ + _UNKNOWN, + } + + /** + * Returns an enum member corresponding to this class instance's value, or + * [Value._UNKNOWN] if the class was instantiated with an unknown value. + * + * Use the [known] method instead if you're certain the value is always known or if + * you want to throw for the unknown case. + */ + fun value(): Value = + when (this) { + _41 -> Value._41 + _42 -> Value._42 + _60 -> Value._60 + _62 -> Value._62 + _63 -> Value._63 + _64 -> Value._64 + _65 -> Value._65 + _66 -> Value._66 + _67 -> Value._67 + _68 -> Value._68 + _70 -> Value._70 + _71 -> Value._71 + _88 -> Value._88 + _95 -> Value._95 + _100 -> Value._100 + _102 -> Value._102 + _103 -> Value._103 + _104 -> Value._104 + _105 -> Value._105 + else -> Value._UNKNOWN + } + + /** + * Returns an enum member corresponding to this class instance's value. + * + * Use the [value] method instead if you're uncertain the value is always known and + * don't want to throw for the unknown case. + * + * @throws EInvoiceInvalidDataException if this class instance's value is a not a + * known member. + */ + fun known(): Known = + when (this) { + _41 -> Known._41 + _42 -> Known._42 + _60 -> Known._60 + _62 -> Known._62 + _63 -> Known._63 + _64 -> Known._64 + _65 -> Known._65 + _66 -> Known._66 + _67 -> Known._67 + _68 -> Known._68 + _70 -> Known._70 + _71 -> Known._71 + _88 -> Known._88 + _95 -> Known._95 + _100 -> Known._100 + _102 -> Known._102 + _103 -> Known._103 + _104 -> Known._104 + _105 -> Known._105 + else -> throw EInvoiceInvalidDataException("Unknown ReasonCode: $value") + } + + /** + * Returns this class instance's primitive wire representation. + * + * This differs from the [toString] method because that method is primarily for + * debugging and generally doesn't throw. + * + * @throws EInvoiceInvalidDataException if this class instance's value does not have + * the expected primitive type. + */ + fun asString(): String = + _value().asString().orElseThrow { + EInvoiceInvalidDataException("Value is not a String") + } + + private var validated: Boolean = false + + fun validate(): ReasonCode = apply { + if (validated) { + return@apply + } + + known() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: EInvoiceInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic internal fun validity(): Int = if (value() == Value._UNKNOWN) 0 else 1 + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is ReasonCode && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + /** The VAT category code that applies to the allowance */ + class TaxCode @JsonCreator private constructor(private val value: JsonField) : + Enum { + + /** + * Returns this class instance's raw value. + * + * This is usually only useful if this instance was deserialized from data that + * doesn't match any known member, and you want to know that value. For example, if + * the SDK is on an older version than the API, then the API may respond with new + * members that the SDK is unaware of. + */ + @com.fasterxml.jackson.annotation.JsonValue fun _value(): JsonField = value + + companion object { + + @JvmField val AE = of("AE") + + @JvmField val E = of("E") + + @JvmField val S = of("S") + + @JvmField val Z = of("Z") + + @JvmField val G = of("G") + + @JvmField val O = of("O") + + @JvmField val K = of("K") + + @JvmField val L = of("L") + + @JvmField val M = of("M") + + @JvmField val B = of("B") + + @JvmStatic fun of(value: String) = TaxCode(JsonField.of(value)) + } + + /** An enum containing [TaxCode]'s known values. */ + enum class Known { + AE, + E, + S, + Z, + G, + O, + K, + L, + M, + B, + } + + /** + * An enum containing [TaxCode]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [TaxCode] can contain an unknown value in a couple of cases: + * - It was deserialized from data that doesn't match any known member. For example, + * if the SDK is on an older version than the API, then the API may respond with + * new members that the SDK is unaware of. + * - It was constructed with an arbitrary value using the [of] method. + */ + enum class Value { + AE, + E, + S, + Z, + G, + O, + K, + L, + M, + B, + /** + * An enum member indicating that [TaxCode] was instantiated with an unknown + * value. + */ + _UNKNOWN, + } + + /** + * Returns an enum member corresponding to this class instance's value, or + * [Value._UNKNOWN] if the class was instantiated with an unknown value. + * + * Use the [known] method instead if you're certain the value is always known or if + * you want to throw for the unknown case. + */ + fun value(): Value = + when (this) { + AE -> Value.AE + E -> Value.E + S -> Value.S + Z -> Value.Z + G -> Value.G + O -> Value.O + K -> Value.K + L -> Value.L + M -> Value.M + B -> Value.B + else -> Value._UNKNOWN + } + + /** + * Returns an enum member corresponding to this class instance's value. + * + * Use the [value] method instead if you're uncertain the value is always known and + * don't want to throw for the unknown case. + * + * @throws EInvoiceInvalidDataException if this class instance's value is a not a + * known member. + */ + fun known(): Known = + when (this) { + AE -> Known.AE + E -> Known.E + S -> Known.S + Z -> Known.Z + G -> Known.G + O -> Known.O + K -> Known.K + L -> Known.L + M -> Known.M + B -> Known.B + else -> throw EInvoiceInvalidDataException("Unknown TaxCode: $value") + } + + /** + * Returns this class instance's primitive wire representation. + * + * This differs from the [toString] method because that method is primarily for + * debugging and generally doesn't throw. + * + * @throws EInvoiceInvalidDataException if this class instance's value does not have + * the expected primitive type. + */ + fun asString(): String = + _value().asString().orElseThrow { + EInvoiceInvalidDataException("Value is not a String") + } + + private var validated: Boolean = false + + fun validate(): TaxCode = apply { + if (validated) { + return@apply + } + + known() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: EInvoiceInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic internal fun validity(): Int = if (value() == Value._UNKNOWN) 0 else 1 + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is TaxCode && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + /** + * The VAT rate, represented as percentage that applies to the allowance. Must be + * rounded to maximum 2 decimals + */ + @JsonDeserialize(using = TaxRate.Deserializer::class) + @JsonSerialize(using = TaxRate.Serializer::class) + class TaxRate + private constructor( + private val number: Double? = null, + private val string: String? = null, + private val _json: JsonValue? = null, + ) { + + fun number(): Optional = Optional.ofNullable(number) + + fun string(): Optional = Optional.ofNullable(string) + + fun isNumber(): Boolean = number != null + + fun isString(): Boolean = string != null + + fun asNumber(): Double = number.getOrThrow("number") + + fun asString(): String = string.getOrThrow("string") + + fun _json(): Optional = Optional.ofNullable(_json) + + fun accept(visitor: Visitor): T = + when { + number != null -> visitor.visitNumber(number) + string != null -> visitor.visitString(string) + else -> visitor.unknown(_json) + } + + private var validated: Boolean = false + + fun validate(): TaxRate = apply { + if (validated) { + return@apply + } + + accept( + object : Visitor { + override fun visitNumber(number: Double) {} + + override fun visitString(string: String) {} + } + ) + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: EInvoiceInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic + internal fun validity(): Int = + accept( + object : Visitor { + override fun visitNumber(number: Double) = 1 + + override fun visitString(string: String) = 1 + + override fun unknown(json: JsonValue?) = 0 + } + ) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is TaxRate && number == other.number && string == other.string + } + + override fun hashCode(): Int = Objects.hash(number, string) + + override fun toString(): String = + when { + number != null -> "TaxRate{number=$number}" + string != null -> "TaxRate{string=$string}" + _json != null -> "TaxRate{_unknown=$_json}" + else -> throw IllegalStateException("Invalid TaxRate") + } + + companion object { + + @JvmStatic fun ofNumber(number: Double) = TaxRate(number = number) + + @JvmStatic fun ofString(string: String) = TaxRate(string = string) + } + + /** + * An interface that defines how to map each variant of [TaxRate] to a value of type + * [T]. + */ + interface Visitor { + + fun visitNumber(number: Double): T + + fun visitString(string: String): T + + /** + * Maps an unknown variant of [TaxRate] to a value of type [T]. + * + * An instance of [TaxRate] can contain an unknown variant if it was + * deserialized from data that doesn't match any known variant. For example, if + * the SDK is on an older version than the API, then the API may respond with + * new variants that the SDK is unaware of. + * + * @throws EInvoiceInvalidDataException in the default implementation. + */ + fun unknown(json: JsonValue?): T { + throw EInvoiceInvalidDataException("Unknown TaxRate: $json") + } + } + + internal class Deserializer : BaseDeserializer(TaxRate::class) { + + override fun ObjectCodec.deserialize(node: JsonNode): TaxRate { + val json = JsonValue.fromJsonNode(node) + + val bestMatches = + sequenceOf( + tryDeserialize(node, jacksonTypeRef())?.let { + TaxRate(string = it, _json = json) + }, + tryDeserialize(node, jacksonTypeRef())?.let { + TaxRate(number = it, _json = json) + }, + ) + .filterNotNull() + .allMaxBy { it.validity() } + .toList() + return when (bestMatches.size) { + // This can happen if what we're deserializing is completely + // incompatible with all the possible variants (e.g. deserializing from + // boolean). + 0 -> TaxRate(_json = json) + 1 -> bestMatches.single() + // If there's more than one match with the highest validity, then use + // the first completely valid match, or simply the first match if none + // are completely valid. + else -> bestMatches.firstOrNull { it.isValid() } ?: bestMatches.first() + } + } + } + + internal class Serializer : BaseSerializer(TaxRate::class) { + + override fun serialize( + value: TaxRate, + generator: JsonGenerator, + provider: SerializerProvider, + ) { + when { + value.number != null -> generator.writeObject(value.number) + value.string != null -> generator.writeObject(value.string) + value._json != null -> generator.writeObject(value._json) + else -> throw IllegalStateException("Invalid TaxRate") + } + } + } + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Allowance && + amount == other.amount && + baseAmount == other.baseAmount && + multiplierFactor == other.multiplierFactor && + reason == other.reason && + reasonCode == other.reasonCode && + taxCode == other.taxCode && + taxRate == other.taxRate && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash( + amount, + baseAmount, + multiplierFactor, + reason, + reasonCode, + taxCode, + taxRate, + additionalProperties, + ) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "Allowance{amount=$amount, baseAmount=$baseAmount, multiplierFactor=$multiplierFactor, reason=$reason, reasonCode=$reasonCode, taxCode=$taxCode, taxRate=$taxRate, additionalProperties=$additionalProperties}" + } + + /** + * The invoice line net amount (BT-131), exclusive of VAT, inclusive of line level + * allowances and charges. Calculated as: ((unit_price / price_base_quantity) * quantity) - + * allowances + charges. Must be rounded to maximum 2 decimals. Can be negative for credit + * notes or corrections. + */ + @JsonDeserialize(using = Amount.Deserializer::class) + @JsonSerialize(using = Amount.Serializer::class) + class Amount + private constructor( + private val number: Double? = null, + private val string: String? = null, + private val _json: JsonValue? = null, + ) { + + fun number(): Optional = Optional.ofNullable(number) + + fun string(): Optional = Optional.ofNullable(string) + + fun isNumber(): Boolean = number != null + + fun isString(): Boolean = string != null + + fun asNumber(): Double = number.getOrThrow("number") + + fun asString(): String = string.getOrThrow("string") + + fun _json(): Optional = Optional.ofNullable(_json) + + fun accept(visitor: Visitor): T = + when { + number != null -> visitor.visitNumber(number) + string != null -> visitor.visitString(string) + else -> visitor.unknown(_json) + } + + private var validated: Boolean = false + + fun validate(): Amount = apply { + if (validated) { + return@apply + } + + accept( + object : Visitor { + override fun visitNumber(number: Double) {} + + override fun visitString(string: String) {} + } + ) + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: EInvoiceInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic + internal fun validity(): Int = + accept( + object : Visitor { + override fun visitNumber(number: Double) = 1 + + override fun visitString(string: String) = 1 + + override fun unknown(json: JsonValue?) = 0 + } + ) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Amount && number == other.number && string == other.string + } + + override fun hashCode(): Int = Objects.hash(number, string) + + override fun toString(): String = + when { + number != null -> "Amount{number=$number}" + string != null -> "Amount{string=$string}" + _json != null -> "Amount{_unknown=$_json}" + else -> throw IllegalStateException("Invalid Amount") + } + + companion object { + + @JvmStatic fun ofNumber(number: Double) = Amount(number = number) + + @JvmStatic fun ofString(string: String) = Amount(string = string) + } + + /** + * An interface that defines how to map each variant of [Amount] to a value of type [T]. + */ + interface Visitor { + + fun visitNumber(number: Double): T + + fun visitString(string: String): T + + /** + * Maps an unknown variant of [Amount] to a value of type [T]. + * + * An instance of [Amount] can contain an unknown variant if it was deserialized + * from data that doesn't match any known variant. For example, if the SDK is on an + * older version than the API, then the API may respond with new variants that the + * SDK is unaware of. + * + * @throws EInvoiceInvalidDataException in the default implementation. + */ + fun unknown(json: JsonValue?): T { + throw EInvoiceInvalidDataException("Unknown Amount: $json") + } + } + + internal class Deserializer : BaseDeserializer(Amount::class) { + + override fun ObjectCodec.deserialize(node: JsonNode): Amount { + val json = JsonValue.fromJsonNode(node) + + val bestMatches = + sequenceOf( + tryDeserialize(node, jacksonTypeRef())?.let { + Amount(string = it, _json = json) + }, + tryDeserialize(node, jacksonTypeRef())?.let { + Amount(number = it, _json = json) + }, + ) + .filterNotNull() + .allMaxBy { it.validity() } + .toList() + return when (bestMatches.size) { + // This can happen if what we're deserializing is completely incompatible + // with all the possible variants (e.g. deserializing from boolean). + 0 -> Amount(_json = json) + 1 -> bestMatches.single() + // If there's more than one match with the highest validity, then use the + // first completely valid match, or simply the first match if none are + // completely valid. + else -> bestMatches.firstOrNull { it.isValid() } ?: bestMatches.first() + } + } + } + + internal class Serializer : BaseSerializer(Amount::class) { + + override fun serialize( + value: Amount, + generator: JsonGenerator, + provider: SerializerProvider, + ) { + when { + value.number != null -> generator.writeObject(value.number) + value.string != null -> generator.writeObject(value.string) + value._json != null -> generator.writeObject(value._json) + else -> throw IllegalStateException("Invalid Amount") + } + } + } + } + + /** A charge is an additional fee for example for late payment, late delivery, etc. */ + class Charge + @JsonCreator(mode = JsonCreator.Mode.DISABLED) + private constructor( + private val amount: JsonField, + private val baseAmount: JsonField, + private val multiplierFactor: JsonField, + private val reason: JsonField, + private val reasonCode: JsonField, + private val taxCode: JsonField, + private val taxRate: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("amount") + @ExcludeMissing + amount: JsonField = JsonMissing.of(), + @JsonProperty("base_amount") + @ExcludeMissing + baseAmount: JsonField = JsonMissing.of(), + @JsonProperty("multiplier_factor") + @ExcludeMissing + multiplierFactor: JsonField = JsonMissing.of(), + @JsonProperty("reason") + @ExcludeMissing + reason: JsonField = JsonMissing.of(), + @JsonProperty("reason_code") + @ExcludeMissing + reasonCode: JsonField = JsonMissing.of(), + @JsonProperty("tax_code") + @ExcludeMissing + taxCode: JsonField = JsonMissing.of(), + @JsonProperty("tax_rate") + @ExcludeMissing + taxRate: JsonField = JsonMissing.of(), + ) : this( + amount, + baseAmount, + multiplierFactor, + reason, + reasonCode, + taxCode, + taxRate, + mutableMapOf(), + ) + + /** + * The charge amount, without VAT. Must be rounded to maximum 2 decimals + * + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. + * if the server responded with an unexpected value). + */ + fun amount(): Optional = amount.getOptional("amount") + + /** + * The base amount that may be used, in conjunction with the charge percentage, to + * calculate the charge amount. Must be rounded to maximum 2 decimals + * + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. + * if the server responded with an unexpected value). + */ + fun baseAmount(): Optional = baseAmount.getOptional("base_amount") + + /** + * The percentage that may be used, in conjunction with the charge base amount, to + * calculate the charge amount. To state 20%, use value 20 + * + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. + * if the server responded with an unexpected value). + */ + fun multiplierFactor(): Optional = + multiplierFactor.getOptional("multiplier_factor") + + /** + * The reason for the charge + * + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. + * if the server responded with an unexpected value). + */ + fun reason(): Optional = reason.getOptional("reason") + + /** + * Charge reason codes for invoice charges and fees + * + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. + * if the server responded with an unexpected value). + */ + fun reasonCode(): Optional = reasonCode.getOptional("reason_code") + + /** + * Duty or tax or fee category codes (Subset of UNCL5305) + * + * Agency: UN/CEFACT Version: D.16B Subset: OpenPEPPOL + * + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. + * if the server responded with an unexpected value). + */ + fun taxCode(): Optional = taxCode.getOptional("tax_code") + + /** + * The VAT rate, represented as percentage that applies to the charge + * + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. + * if the server responded with an unexpected value). + */ + fun taxRate(): Optional = taxRate.getOptional("tax_rate") + + /** + * Returns the raw JSON value of [amount]. + * + * Unlike [amount], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("amount") @ExcludeMissing fun _amount(): JsonField = amount + + /** + * Returns the raw JSON value of [baseAmount]. + * + * Unlike [baseAmount], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("base_amount") + @ExcludeMissing + fun _baseAmount(): JsonField = baseAmount + + /** + * Returns the raw JSON value of [multiplierFactor]. + * + * Unlike [multiplierFactor], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("multiplier_factor") + @ExcludeMissing + fun _multiplierFactor(): JsonField = multiplierFactor + + /** + * Returns the raw JSON value of [reason]. + * + * Unlike [reason], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("reason") @ExcludeMissing fun _reason(): JsonField = reason + + /** + * Returns the raw JSON value of [reasonCode]. + * + * Unlike [reasonCode], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("reason_code") + @ExcludeMissing + fun _reasonCode(): JsonField = reasonCode + + /** + * Returns the raw JSON value of [taxCode]. + * + * Unlike [taxCode], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("tax_code") @ExcludeMissing fun _taxCode(): JsonField = taxCode + + /** + * Returns the raw JSON value of [taxRate]. + * + * Unlike [taxRate], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("tax_rate") @ExcludeMissing fun _taxRate(): JsonField = taxRate + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** Returns a mutable builder for constructing an instance of [Charge]. */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [Charge]. */ + class Builder internal constructor() { + + private var amount: JsonField = JsonMissing.of() + private var baseAmount: JsonField = JsonMissing.of() + private var multiplierFactor: JsonField = JsonMissing.of() + private var reason: JsonField = JsonMissing.of() + private var reasonCode: JsonField = JsonMissing.of() + private var taxCode: JsonField = JsonMissing.of() + private var taxRate: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(charge: Charge) = apply { + amount = charge.amount + baseAmount = charge.baseAmount + multiplierFactor = charge.multiplierFactor + reason = charge.reason + reasonCode = charge.reasonCode + taxCode = charge.taxCode + taxRate = charge.taxRate + additionalProperties = charge.additionalProperties.toMutableMap() + } + + /** The charge amount, without VAT. Must be rounded to maximum 2 decimals */ + fun amount(amount: Amount?) = amount(JsonField.ofNullable(amount)) + + /** Alias for calling [Builder.amount] with `amount.orElse(null)`. */ + fun amount(amount: Optional) = amount(amount.getOrNull()) + + /** + * Sets [Builder.amount] to an arbitrary JSON value. + * + * You should usually call [Builder.amount] with a well-typed [Amount] value + * instead. This method is primarily for setting the field to an undocumented or not + * yet supported value. + */ + fun amount(amount: JsonField) = apply { this.amount = amount } + + /** Alias for calling [amount] with `Amount.ofNumber(number)`. */ + fun amount(number: Double) = amount(Amount.ofNumber(number)) + + /** Alias for calling [amount] with `Amount.ofString(string)`. */ + fun amount(string: String) = amount(Amount.ofString(string)) + + /** + * The base amount that may be used, in conjunction with the charge percentage, to + * calculate the charge amount. Must be rounded to maximum 2 decimals + */ + fun baseAmount(baseAmount: BaseAmount?) = + baseAmount(JsonField.ofNullable(baseAmount)) + + /** Alias for calling [Builder.baseAmount] with `baseAmount.orElse(null)`. */ + fun baseAmount(baseAmount: Optional) = + baseAmount(baseAmount.getOrNull()) + + /** + * Sets [Builder.baseAmount] to an arbitrary JSON value. + * + * You should usually call [Builder.baseAmount] with a well-typed [BaseAmount] value + * instead. This method is primarily for setting the field to an undocumented or not + * yet supported value. + */ + fun baseAmount(baseAmount: JsonField) = apply { + this.baseAmount = baseAmount + } + + /** Alias for calling [baseAmount] with `BaseAmount.ofNumber(number)`. */ + fun baseAmount(number: Double) = baseAmount(BaseAmount.ofNumber(number)) + + /** Alias for calling [baseAmount] with `BaseAmount.ofString(string)`. */ + fun baseAmount(string: String) = baseAmount(BaseAmount.ofString(string)) + + /** + * The percentage that may be used, in conjunction with the charge base amount, to + * calculate the charge amount. To state 20%, use value 20 + */ + fun multiplierFactor(multiplierFactor: MultiplierFactor?) = + multiplierFactor(JsonField.ofNullable(multiplierFactor)) + + /** + * Alias for calling [Builder.multiplierFactor] with + * `multiplierFactor.orElse(null)`. + */ + fun multiplierFactor(multiplierFactor: Optional) = + multiplierFactor(multiplierFactor.getOrNull()) + + /** + * Sets [Builder.multiplierFactor] to an arbitrary JSON value. + * + * You should usually call [Builder.multiplierFactor] with a well-typed + * [MultiplierFactor] value instead. This method is primarily for setting the field + * to an undocumented or not yet supported value. + */ + fun multiplierFactor(multiplierFactor: JsonField) = apply { + this.multiplierFactor = multiplierFactor + } + + /** + * Alias for calling [multiplierFactor] with `MultiplierFactor.ofNumber(number)`. + */ + fun multiplierFactor(number: Double) = + multiplierFactor(MultiplierFactor.ofNumber(number)) + + /** + * Alias for calling [multiplierFactor] with `MultiplierFactor.ofString(string)`. + */ + fun multiplierFactor(string: String) = + multiplierFactor(MultiplierFactor.ofString(string)) + + /** The reason for the charge */ + fun reason(reason: String?) = reason(JsonField.ofNullable(reason)) + + /** Alias for calling [Builder.reason] with `reason.orElse(null)`. */ + fun reason(reason: Optional) = reason(reason.getOrNull()) + + /** + * Sets [Builder.reason] to an arbitrary JSON value. + * + * You should usually call [Builder.reason] with a well-typed [String] value + * instead. This method is primarily for setting the field to an undocumented or not + * yet supported value. + */ + fun reason(reason: JsonField) = apply { this.reason = reason } + + /** Charge reason codes for invoice charges and fees */ + fun reasonCode(reasonCode: ReasonCode?) = + reasonCode(JsonField.ofNullable(reasonCode)) + + /** Alias for calling [Builder.reasonCode] with `reasonCode.orElse(null)`. */ + fun reasonCode(reasonCode: Optional) = + reasonCode(reasonCode.getOrNull()) + + /** + * Sets [Builder.reasonCode] to an arbitrary JSON value. + * + * You should usually call [Builder.reasonCode] with a well-typed [ReasonCode] value + * instead. This method is primarily for setting the field to an undocumented or not + * yet supported value. + */ + fun reasonCode(reasonCode: JsonField) = apply { + this.reasonCode = reasonCode + } + + /** + * Duty or tax or fee category codes (Subset of UNCL5305) + * + * Agency: UN/CEFACT Version: D.16B Subset: OpenPEPPOL + */ + fun taxCode(taxCode: TaxCode?) = taxCode(JsonField.ofNullable(taxCode)) + + /** Alias for calling [Builder.taxCode] with `taxCode.orElse(null)`. */ + fun taxCode(taxCode: Optional) = taxCode(taxCode.getOrNull()) + + /** + * Sets [Builder.taxCode] to an arbitrary JSON value. + * + * You should usually call [Builder.taxCode] with a well-typed [TaxCode] value + * instead. This method is primarily for setting the field to an undocumented or not + * yet supported value. + */ + fun taxCode(taxCode: JsonField) = apply { this.taxCode = taxCode } + + /** The VAT rate, represented as percentage that applies to the charge */ + fun taxRate(taxRate: TaxRate?) = taxRate(JsonField.ofNullable(taxRate)) + + /** Alias for calling [Builder.taxRate] with `taxRate.orElse(null)`. */ + fun taxRate(taxRate: Optional) = taxRate(taxRate.getOrNull()) + + /** + * Sets [Builder.taxRate] to an arbitrary JSON value. + * + * You should usually call [Builder.taxRate] with a well-typed [TaxRate] value + * instead. This method is primarily for setting the field to an undocumented or not + * yet supported value. + */ + fun taxRate(taxRate: JsonField) = apply { this.taxRate = taxRate } + + /** Alias for calling [taxRate] with `TaxRate.ofNumber(number)`. */ + fun taxRate(number: Double) = taxRate(TaxRate.ofNumber(number)) + + /** Alias for calling [taxRate] with `TaxRate.ofString(string)`. */ + fun taxRate(string: String) = taxRate(TaxRate.ofString(string)) + + fun additionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.clear() + putAllAdditionalProperties(additionalProperties) + } + + fun putAdditionalProperty(key: String, value: JsonValue) = apply { + additionalProperties.put(key, value) + } + + fun putAllAdditionalProperties(additionalProperties: Map) = + apply { + this.additionalProperties.putAll(additionalProperties) + } + + fun removeAdditionalProperty(key: String) = apply { + additionalProperties.remove(key) + } + + fun removeAllAdditionalProperties(keys: Set) = apply { + keys.forEach(::removeAdditionalProperty) + } + + /** + * Returns an immutable instance of [Charge]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): Charge = + Charge( + amount, + baseAmount, + multiplierFactor, + reason, + reasonCode, + taxCode, + taxRate, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + fun validate(): Charge = apply { + if (validated) { + return@apply + } + + amount().ifPresent { it.validate() } + baseAmount().ifPresent { it.validate() } + multiplierFactor().ifPresent { it.validate() } + reason() + reasonCode().ifPresent { it.validate() } + taxCode().ifPresent { it.validate() } + taxRate().ifPresent { it.validate() } + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: EInvoiceInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic + internal fun validity(): Int = + (amount.asKnown().getOrNull()?.validity() ?: 0) + + (baseAmount.asKnown().getOrNull()?.validity() ?: 0) + + (multiplierFactor.asKnown().getOrNull()?.validity() ?: 0) + + (if (reason.asKnown().isPresent) 1 else 0) + + (reasonCode.asKnown().getOrNull()?.validity() ?: 0) + + (taxCode.asKnown().getOrNull()?.validity() ?: 0) + + (taxRate.asKnown().getOrNull()?.validity() ?: 0) + + /** The charge amount, without VAT. Must be rounded to maximum 2 decimals */ + @JsonDeserialize(using = Amount.Deserializer::class) + @JsonSerialize(using = Amount.Serializer::class) + class Amount + private constructor( + private val number: Double? = null, + private val string: String? = null, + private val _json: JsonValue? = null, + ) { + + fun number(): Optional = Optional.ofNullable(number) + + fun string(): Optional = Optional.ofNullable(string) + + fun isNumber(): Boolean = number != null + + fun isString(): Boolean = string != null + + fun asNumber(): Double = number.getOrThrow("number") + + fun asString(): String = string.getOrThrow("string") + + fun _json(): Optional = Optional.ofNullable(_json) + + fun accept(visitor: Visitor): T = + when { + number != null -> visitor.visitNumber(number) + string != null -> visitor.visitString(string) + else -> visitor.unknown(_json) + } + + private var validated: Boolean = false + + fun validate(): Amount = apply { + if (validated) { + return@apply + } + + accept( + object : Visitor { + override fun visitNumber(number: Double) {} + + override fun visitString(string: String) {} + } + ) + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: EInvoiceInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic + internal fun validity(): Int = + accept( + object : Visitor { + override fun visitNumber(number: Double) = 1 + + override fun visitString(string: String) = 1 + + override fun unknown(json: JsonValue?) = 0 + } + ) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Amount && number == other.number && string == other.string + } + + override fun hashCode(): Int = Objects.hash(number, string) + + override fun toString(): String = + when { + number != null -> "Amount{number=$number}" + string != null -> "Amount{string=$string}" + _json != null -> "Amount{_unknown=$_json}" + else -> throw IllegalStateException("Invalid Amount") + } + + companion object { + + @JvmStatic fun ofNumber(number: Double) = Amount(number = number) + + @JvmStatic fun ofString(string: String) = Amount(string = string) + } + + /** + * An interface that defines how to map each variant of [Amount] to a value of type + * [T]. + */ + interface Visitor { + + fun visitNumber(number: Double): T + + fun visitString(string: String): T + + /** + * Maps an unknown variant of [Amount] to a value of type [T]. + * + * An instance of [Amount] can contain an unknown variant if it was deserialized + * from data that doesn't match any known variant. For example, if the SDK is on + * an older version than the API, then the API may respond with new variants + * that the SDK is unaware of. + * + * @throws EInvoiceInvalidDataException in the default implementation. + */ + fun unknown(json: JsonValue?): T { + throw EInvoiceInvalidDataException("Unknown Amount: $json") + } + } + + internal class Deserializer : BaseDeserializer(Amount::class) { + + override fun ObjectCodec.deserialize(node: JsonNode): Amount { + val json = JsonValue.fromJsonNode(node) + + val bestMatches = + sequenceOf( + tryDeserialize(node, jacksonTypeRef())?.let { + Amount(string = it, _json = json) + }, + tryDeserialize(node, jacksonTypeRef())?.let { + Amount(number = it, _json = json) + }, + ) + .filterNotNull() + .allMaxBy { it.validity() } + .toList() + return when (bestMatches.size) { + // This can happen if what we're deserializing is completely + // incompatible with all the possible variants (e.g. deserializing from + // boolean). + 0 -> Amount(_json = json) + 1 -> bestMatches.single() + // If there's more than one match with the highest validity, then use + // the first completely valid match, or simply the first match if none + // are completely valid. + else -> bestMatches.firstOrNull { it.isValid() } ?: bestMatches.first() + } + } + } + + internal class Serializer : BaseSerializer(Amount::class) { + + override fun serialize( + value: Amount, + generator: JsonGenerator, + provider: SerializerProvider, + ) { + when { + value.number != null -> generator.writeObject(value.number) + value.string != null -> generator.writeObject(value.string) + value._json != null -> generator.writeObject(value._json) + else -> throw IllegalStateException("Invalid Amount") + } + } + } + } + + /** + * The base amount that may be used, in conjunction with the charge percentage, to + * calculate the charge amount. Must be rounded to maximum 2 decimals + */ + @JsonDeserialize(using = BaseAmount.Deserializer::class) + @JsonSerialize(using = BaseAmount.Serializer::class) + class BaseAmount + private constructor( + private val number: Double? = null, + private val string: String? = null, + private val _json: JsonValue? = null, + ) { + + fun number(): Optional = Optional.ofNullable(number) + + fun string(): Optional = Optional.ofNullable(string) + + fun isNumber(): Boolean = number != null + + fun isString(): Boolean = string != null + + fun asNumber(): Double = number.getOrThrow("number") + + fun asString(): String = string.getOrThrow("string") + + fun _json(): Optional = Optional.ofNullable(_json) + + fun accept(visitor: Visitor): T = + when { + number != null -> visitor.visitNumber(number) + string != null -> visitor.visitString(string) + else -> visitor.unknown(_json) + } + + private var validated: Boolean = false + + fun validate(): BaseAmount = apply { + if (validated) { + return@apply + } + + accept( + object : Visitor { + override fun visitNumber(number: Double) {} + + override fun visitString(string: String) {} + } + ) + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: EInvoiceInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic + internal fun validity(): Int = + accept( + object : Visitor { + override fun visitNumber(number: Double) = 1 + + override fun visitString(string: String) = 1 + + override fun unknown(json: JsonValue?) = 0 + } + ) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is BaseAmount && number == other.number && string == other.string + } + + override fun hashCode(): Int = Objects.hash(number, string) + + override fun toString(): String = + when { + number != null -> "BaseAmount{number=$number}" + string != null -> "BaseAmount{string=$string}" + _json != null -> "BaseAmount{_unknown=$_json}" + else -> throw IllegalStateException("Invalid BaseAmount") + } + + companion object { + + @JvmStatic fun ofNumber(number: Double) = BaseAmount(number = number) + + @JvmStatic fun ofString(string: String) = BaseAmount(string = string) + } + + /** + * An interface that defines how to map each variant of [BaseAmount] to a value of + * type [T]. + */ + interface Visitor { + + fun visitNumber(number: Double): T + + fun visitString(string: String): T + + /** + * Maps an unknown variant of [BaseAmount] to a value of type [T]. + * + * An instance of [BaseAmount] can contain an unknown variant if it was + * deserialized from data that doesn't match any known variant. For example, if + * the SDK is on an older version than the API, then the API may respond with + * new variants that the SDK is unaware of. + * + * @throws EInvoiceInvalidDataException in the default implementation. + */ + fun unknown(json: JsonValue?): T { + throw EInvoiceInvalidDataException("Unknown BaseAmount: $json") + } + } + + internal class Deserializer : BaseDeserializer(BaseAmount::class) { + + override fun ObjectCodec.deserialize(node: JsonNode): BaseAmount { + val json = JsonValue.fromJsonNode(node) + + val bestMatches = + sequenceOf( + tryDeserialize(node, jacksonTypeRef())?.let { + BaseAmount(string = it, _json = json) + }, + tryDeserialize(node, jacksonTypeRef())?.let { + BaseAmount(number = it, _json = json) + }, + ) + .filterNotNull() + .allMaxBy { it.validity() } + .toList() + return when (bestMatches.size) { + // This can happen if what we're deserializing is completely + // incompatible with all the possible variants (e.g. deserializing from + // boolean). + 0 -> BaseAmount(_json = json) + 1 -> bestMatches.single() + // If there's more than one match with the highest validity, then use + // the first completely valid match, or simply the first match if none + // are completely valid. + else -> bestMatches.firstOrNull { it.isValid() } ?: bestMatches.first() + } + } + } + + internal class Serializer : BaseSerializer(BaseAmount::class) { + + override fun serialize( + value: BaseAmount, + generator: JsonGenerator, + provider: SerializerProvider, + ) { + when { + value.number != null -> generator.writeObject(value.number) + value.string != null -> generator.writeObject(value.string) + value._json != null -> generator.writeObject(value._json) + else -> throw IllegalStateException("Invalid BaseAmount") + } + } + } + } + + /** + * The percentage that may be used, in conjunction with the charge base amount, to + * calculate the charge amount. To state 20%, use value 20 + */ + @JsonDeserialize(using = MultiplierFactor.Deserializer::class) + @JsonSerialize(using = MultiplierFactor.Serializer::class) + class MultiplierFactor + private constructor( + private val number: Double? = null, + private val string: String? = null, + private val _json: JsonValue? = null, + ) { + + fun number(): Optional = Optional.ofNullable(number) + + fun string(): Optional = Optional.ofNullable(string) + + fun isNumber(): Boolean = number != null + + fun isString(): Boolean = string != null + + fun asNumber(): Double = number.getOrThrow("number") + + fun asString(): String = string.getOrThrow("string") + + fun _json(): Optional = Optional.ofNullable(_json) + + fun accept(visitor: Visitor): T = + when { + number != null -> visitor.visitNumber(number) + string != null -> visitor.visitString(string) + else -> visitor.unknown(_json) + } + + private var validated: Boolean = false + + fun validate(): MultiplierFactor = apply { + if (validated) { + return@apply + } + + accept( + object : Visitor { + override fun visitNumber(number: Double) {} + + override fun visitString(string: String) {} + } + ) + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: EInvoiceInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic + internal fun validity(): Int = + accept( + object : Visitor { + override fun visitNumber(number: Double) = 1 + + override fun visitString(string: String) = 1 + + override fun unknown(json: JsonValue?) = 0 + } + ) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is MultiplierFactor && + number == other.number && + string == other.string + } + + override fun hashCode(): Int = Objects.hash(number, string) + + override fun toString(): String = + when { + number != null -> "MultiplierFactor{number=$number}" + string != null -> "MultiplierFactor{string=$string}" + _json != null -> "MultiplierFactor{_unknown=$_json}" + else -> throw IllegalStateException("Invalid MultiplierFactor") + } + + companion object { + + @JvmStatic fun ofNumber(number: Double) = MultiplierFactor(number = number) + + @JvmStatic fun ofString(string: String) = MultiplierFactor(string = string) + } + + /** + * An interface that defines how to map each variant of [MultiplierFactor] to a + * value of type [T]. + */ + interface Visitor { + + fun visitNumber(number: Double): T + + fun visitString(string: String): T + + /** + * Maps an unknown variant of [MultiplierFactor] to a value of type [T]. + * + * An instance of [MultiplierFactor] can contain an unknown variant if it was + * deserialized from data that doesn't match any known variant. For example, if + * the SDK is on an older version than the API, then the API may respond with + * new variants that the SDK is unaware of. + * + * @throws EInvoiceInvalidDataException in the default implementation. + */ + fun unknown(json: JsonValue?): T { + throw EInvoiceInvalidDataException("Unknown MultiplierFactor: $json") + } + } + + internal class Deserializer : + BaseDeserializer(MultiplierFactor::class) { + + override fun ObjectCodec.deserialize(node: JsonNode): MultiplierFactor { + val json = JsonValue.fromJsonNode(node) + + val bestMatches = + sequenceOf( + tryDeserialize(node, jacksonTypeRef())?.let { + MultiplierFactor(string = it, _json = json) + }, + tryDeserialize(node, jacksonTypeRef())?.let { + MultiplierFactor(number = it, _json = json) + }, + ) + .filterNotNull() + .allMaxBy { it.validity() } + .toList() + return when (bestMatches.size) { + // This can happen if what we're deserializing is completely + // incompatible with all the possible variants (e.g. deserializing from + // boolean). + 0 -> MultiplierFactor(_json = json) + 1 -> bestMatches.single() + // If there's more than one match with the highest validity, then use + // the first completely valid match, or simply the first match if none + // are completely valid. + else -> bestMatches.firstOrNull { it.isValid() } ?: bestMatches.first() + } + } + } + + internal class Serializer : + BaseSerializer(MultiplierFactor::class) { + + override fun serialize( + value: MultiplierFactor, + generator: JsonGenerator, + provider: SerializerProvider, + ) { + when { + value.number != null -> generator.writeObject(value.number) + value.string != null -> generator.writeObject(value.string) + value._json != null -> generator.writeObject(value._json) + else -> throw IllegalStateException("Invalid MultiplierFactor") + } + } + } + } + + /** Charge reason codes for invoice charges and fees */ + class ReasonCode + @JsonCreator + private constructor(private val value: JsonField) : Enum { + + /** + * Returns this class instance's raw value. + * + * This is usually only useful if this instance was deserialized from data that + * doesn't match any known member, and you want to know that value. For example, if + * the SDK is on an older version than the API, then the API may respond with new + * members that the SDK is unaware of. + */ + @com.fasterxml.jackson.annotation.JsonValue fun _value(): JsonField = value + + companion object { + + @JvmField val AA = of("AA") + + @JvmField val AAA = of("AAA") + + @JvmField val AAC = of("AAC") + + @JvmField val AAD = of("AAD") + + @JvmField val AAE = of("AAE") + + @JvmField val AAF = of("AAF") + + @JvmField val AAH = of("AAH") + + @JvmField val AAI = of("AAI") + + @JvmField val AAS = of("AAS") + + @JvmField val AAT = of("AAT") + + @JvmField val AAV = of("AAV") + + @JvmField val AAY = of("AAY") + + @JvmField val AAZ = of("AAZ") + + @JvmField val ABA = of("ABA") + + @JvmField val ABB = of("ABB") + + @JvmField val ABC = of("ABC") + + @JvmField val ABD = of("ABD") + + @JvmField val ABF = of("ABF") + + @JvmField val ABK = of("ABK") + + @JvmField val ABL = of("ABL") + + @JvmField val ABN = of("ABN") + + @JvmField val ABR = of("ABR") + + @JvmField val ABS = of("ABS") + + @JvmField val ABT = of("ABT") + + @JvmField val ABU = of("ABU") + + @JvmField val ACF = of("ACF") + + @JvmField val ACG = of("ACG") + + @JvmField val ACH = of("ACH") + + @JvmField val ACI = of("ACI") + + @JvmField val ACJ = of("ACJ") + + @JvmField val ACK = of("ACK") + + @JvmField val ACL = of("ACL") + + @JvmField val ACM = of("ACM") + + @JvmField val ACS = of("ACS") + + @JvmField val ADC = of("ADC") + + @JvmField val ADE = of("ADE") + + @JvmField val ADJ = of("ADJ") + + @JvmField val ADK = of("ADK") + + @JvmField val ADL = of("ADL") + + @JvmField val ADM = of("ADM") + + @JvmField val ADN = of("ADN") + + @JvmField val ADO = of("ADO") + + @JvmField val ADP = of("ADP") + + @JvmField val ADQ = of("ADQ") + + @JvmField val ADR = of("ADR") + + @JvmField val ADT = of("ADT") + + @JvmField val ADW = of("ADW") + + @JvmField val ADY = of("ADY") + + @JvmField val ADZ = of("ADZ") + + @JvmField val AEA = of("AEA") + + @JvmField val AEB = of("AEB") + + @JvmField val AEC = of("AEC") + + @JvmField val AED = of("AED") + + @JvmField val AEF = of("AEF") + + @JvmField val AEH = of("AEH") + + @JvmField val AEI = of("AEI") + + @JvmField val AEJ = of("AEJ") + + @JvmField val AEK = of("AEK") + + @JvmField val AEL = of("AEL") + + @JvmField val AEM = of("AEM") + + @JvmField val AEN = of("AEN") + + @JvmField val AEO = of("AEO") + + @JvmField val AEP = of("AEP") + + @JvmField val AES = of("AES") + + @JvmField val AET = of("AET") + + @JvmField val AEU = of("AEU") + + @JvmField val AEV = of("AEV") + + @JvmField val AEW = of("AEW") + + @JvmField val AEX = of("AEX") + + @JvmField val AEY = of("AEY") + + @JvmField val AEZ = of("AEZ") + + @JvmField val AJ = of("AJ") + + @JvmField val AU = of("AU") + + @JvmField val CA = of("CA") + + @JvmField val CAB = of("CAB") + + @JvmField val CAD = of("CAD") + + @JvmField val CAE = of("CAE") + + @JvmField val CAF = of("CAF") + + @JvmField val CAI = of("CAI") + + @JvmField val CAJ = of("CAJ") + + @JvmField val CAK = of("CAK") + + @JvmField val CAL = of("CAL") + + @JvmField val CAM = of("CAM") + + @JvmField val CAN = of("CAN") + + @JvmField val CAO = of("CAO") + + @JvmField val CAP = of("CAP") + + @JvmField val CAQ = of("CAQ") + + @JvmField val CAR = of("CAR") + + @JvmField val CAS = of("CAS") + + @JvmField val CAT = of("CAT") + + @JvmField val CAU = of("CAU") + + @JvmField val CAV = of("CAV") + + @JvmField val CAW = of("CAW") + + @JvmField val CAX = of("CAX") + + @JvmField val CAY = of("CAY") + + @JvmField val CAZ = of("CAZ") + + @JvmField val CD = of("CD") + + @JvmField val CG = of("CG") + + @JvmField val CS = of("CS") + + @JvmField val CT = of("CT") + + @JvmField val DAB = of("DAB") + + @JvmField val DAC = of("DAC") + + @JvmField val DAD = of("DAD") + + @JvmField val DAF = of("DAF") + + @JvmField val DAG = of("DAG") + + @JvmField val DAH = of("DAH") + + @JvmField val DAI = of("DAI") + + @JvmField val DAJ = of("DAJ") + + @JvmField val DAK = of("DAK") + + @JvmField val DAL = of("DAL") + + @JvmField val DAM = of("DAM") + + @JvmField val DAN = of("DAN") + + @JvmField val DAO = of("DAO") + + @JvmField val DAP = of("DAP") + + @JvmField val DAQ = of("DAQ") + + @JvmField val DL = of("DL") + + @JvmField val EG = of("EG") + + @JvmField val EP = of("EP") + + @JvmField val ER = of("ER") + + @JvmField val FAA = of("FAA") + + @JvmField val FAB = of("FAB") + + @JvmField val FAC = of("FAC") + + @JvmField val FC = of("FC") + + @JvmField val FH = of("FH") + + @JvmField val FI = of("FI") + + @JvmField val GAA = of("GAA") + + @JvmField val HAA = of("HAA") + + @JvmField val HD = of("HD") + + @JvmField val HH = of("HH") + + @JvmField val IAA = of("IAA") + + @JvmField val IAB = of("IAB") + + @JvmField val ID = of("ID") + + @JvmField val IF = of("IF") + + @JvmField val IR = of("IR") + + @JvmField val IS = of("IS") + + @JvmField val KO = of("KO") + + @JvmField val L1 = of("L1") + + @JvmField val LA = of("LA") + + @JvmField val LAA = of("LAA") + + @JvmField val LAB = of("LAB") + + @JvmField val LF = of("LF") + + @JvmField val MAE = of("MAE") + + @JvmField val MI = of("MI") + + @JvmField val ML = of("ML") + + @JvmField val NAA = of("NAA") + + @JvmField val OA = of("OA") + + @JvmField val PA = of("PA") + + @JvmField val PAA = of("PAA") + + @JvmField val PC = of("PC") + + @JvmField val PL = of("PL") + + @JvmField val PRV = of("PRV") + + @JvmField val RAB = of("RAB") + + @JvmField val RAC = of("RAC") + + @JvmField val RAD = of("RAD") + + @JvmField val RAF = of("RAF") + + @JvmField val RE = of("RE") + + @JvmField val RF = of("RF") + + @JvmField val RH = of("RH") + + @JvmField val RV = of("RV") + + @JvmField val SA = of("SA") + + @JvmField val SAA = of("SAA") + + @JvmField val SAD = of("SAD") + + @JvmField val SAE = of("SAE") + + @JvmField val SAI = of("SAI") + + @JvmField val SG = of("SG") + + @JvmField val SH = of("SH") + + @JvmField val SM = of("SM") + + @JvmField val SU = of("SU") + + @JvmField val TAB = of("TAB") + + @JvmField val TAC = of("TAC") + + @JvmField val TT = of("TT") + + @JvmField val TV = of("TV") + + @JvmField val V1 = of("V1") + + @JvmField val V2 = of("V2") + + @JvmField val WH = of("WH") + + @JvmField val XAA = of("XAA") + + @JvmField val YY = of("YY") + + @JvmField val ZZZ = of("ZZZ") + + @JvmStatic fun of(value: String) = ReasonCode(JsonField.of(value)) + } + + /** An enum containing [ReasonCode]'s known values. */ + enum class Known { + AA, + AAA, + AAC, + AAD, + AAE, + AAF, + AAH, + AAI, + AAS, + AAT, + AAV, + AAY, + AAZ, + ABA, + ABB, + ABC, + ABD, + ABF, + ABK, + ABL, + ABN, + ABR, + ABS, + ABT, + ABU, + ACF, + ACG, + ACH, + ACI, + ACJ, + ACK, + ACL, + ACM, + ACS, + ADC, + ADE, + ADJ, + ADK, + ADL, + ADM, + ADN, + ADO, + ADP, + ADQ, + ADR, + ADT, + ADW, + ADY, + ADZ, + AEA, + AEB, + AEC, + AED, + AEF, + AEH, + AEI, + AEJ, + AEK, + AEL, + AEM, + AEN, + AEO, + AEP, + AES, + AET, + AEU, + AEV, + AEW, + AEX, + AEY, + AEZ, + AJ, + AU, + CA, + CAB, + CAD, + CAE, + CAF, + CAI, + CAJ, + CAK, + CAL, + CAM, + CAN, + CAO, + CAP, + CAQ, + CAR, + CAS, + CAT, + CAU, + CAV, + CAW, + CAX, + CAY, + CAZ, + CD, + CG, + CS, + CT, + DAB, + DAC, + DAD, + DAF, + DAG, + DAH, + DAI, + DAJ, + DAK, + DAL, + DAM, + DAN, + DAO, + DAP, + DAQ, + DL, + EG, + EP, + ER, + FAA, + FAB, + FAC, + FC, + FH, + FI, + GAA, + HAA, + HD, + HH, + IAA, + IAB, + ID, + IF, + IR, + IS, + KO, + L1, + LA, + LAA, + LAB, + LF, + MAE, + MI, + ML, + NAA, + OA, + PA, + PAA, + PC, + PL, + PRV, + RAB, + RAC, + RAD, + RAF, + RE, + RF, + RH, + RV, + SA, + SAA, + SAD, + SAE, + SAI, + SG, + SH, + SM, + SU, + TAB, + TAC, + TT, + TV, + V1, + V2, + WH, + XAA, + YY, + ZZZ, + } + + /** + * An enum containing [ReasonCode]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [ReasonCode] can contain an unknown value in a couple of cases: + * - It was deserialized from data that doesn't match any known member. For example, + * if the SDK is on an older version than the API, then the API may respond with + * new members that the SDK is unaware of. + * - It was constructed with an arbitrary value using the [of] method. + */ + enum class Value { + AA, + AAA, + AAC, + AAD, + AAE, + AAF, + AAH, + AAI, + AAS, + AAT, + AAV, + AAY, + AAZ, + ABA, + ABB, + ABC, + ABD, + ABF, + ABK, + ABL, + ABN, + ABR, + ABS, + ABT, + ABU, + ACF, + ACG, + ACH, + ACI, + ACJ, + ACK, + ACL, + ACM, + ACS, + ADC, + ADE, + ADJ, + ADK, + ADL, + ADM, + ADN, + ADO, + ADP, + ADQ, + ADR, + ADT, + ADW, + ADY, + ADZ, + AEA, + AEB, + AEC, + AED, + AEF, + AEH, + AEI, + AEJ, + AEK, + AEL, + AEM, + AEN, + AEO, + AEP, + AES, + AET, + AEU, + AEV, + AEW, + AEX, + AEY, + AEZ, + AJ, + AU, + CA, + CAB, + CAD, + CAE, + CAF, + CAI, + CAJ, + CAK, + CAL, + CAM, + CAN, + CAO, + CAP, + CAQ, + CAR, + CAS, + CAT, + CAU, + CAV, + CAW, + CAX, + CAY, + CAZ, + CD, + CG, + CS, + CT, + DAB, + DAC, + DAD, + DAF, + DAG, + DAH, + DAI, + DAJ, + DAK, + DAL, + DAM, + DAN, + DAO, + DAP, + DAQ, + DL, + EG, + EP, + ER, + FAA, + FAB, + FAC, + FC, + FH, + FI, + GAA, + HAA, + HD, + HH, + IAA, + IAB, + ID, + IF, + IR, + IS, + KO, + L1, + LA, + LAA, + LAB, + LF, + MAE, + MI, + ML, + NAA, + OA, + PA, + PAA, + PC, + PL, + PRV, + RAB, + RAC, + RAD, + RAF, + RE, + RF, + RH, + RV, + SA, + SAA, + SAD, + SAE, + SAI, + SG, + SH, + SM, + SU, + TAB, + TAC, + TT, + TV, + V1, + V2, + WH, + XAA, + YY, + ZZZ, + /** + * An enum member indicating that [ReasonCode] was instantiated with an unknown + * value. + */ + _UNKNOWN, + } + + /** + * Returns an enum member corresponding to this class instance's value, or + * [Value._UNKNOWN] if the class was instantiated with an unknown value. + * + * Use the [known] method instead if you're certain the value is always known or if + * you want to throw for the unknown case. + */ + fun value(): Value = + when (this) { + AA -> Value.AA + AAA -> Value.AAA + AAC -> Value.AAC + AAD -> Value.AAD + AAE -> Value.AAE + AAF -> Value.AAF + AAH -> Value.AAH + AAI -> Value.AAI + AAS -> Value.AAS + AAT -> Value.AAT + AAV -> Value.AAV + AAY -> Value.AAY + AAZ -> Value.AAZ + ABA -> Value.ABA + ABB -> Value.ABB + ABC -> Value.ABC + ABD -> Value.ABD + ABF -> Value.ABF + ABK -> Value.ABK + ABL -> Value.ABL + ABN -> Value.ABN + ABR -> Value.ABR + ABS -> Value.ABS + ABT -> Value.ABT + ABU -> Value.ABU + ACF -> Value.ACF + ACG -> Value.ACG + ACH -> Value.ACH + ACI -> Value.ACI + ACJ -> Value.ACJ + ACK -> Value.ACK + ACL -> Value.ACL + ACM -> Value.ACM + ACS -> Value.ACS + ADC -> Value.ADC + ADE -> Value.ADE + ADJ -> Value.ADJ + ADK -> Value.ADK + ADL -> Value.ADL + ADM -> Value.ADM + ADN -> Value.ADN + ADO -> Value.ADO + ADP -> Value.ADP + ADQ -> Value.ADQ + ADR -> Value.ADR + ADT -> Value.ADT + ADW -> Value.ADW + ADY -> Value.ADY + ADZ -> Value.ADZ + AEA -> Value.AEA + AEB -> Value.AEB + AEC -> Value.AEC + AED -> Value.AED + AEF -> Value.AEF + AEH -> Value.AEH + AEI -> Value.AEI + AEJ -> Value.AEJ + AEK -> Value.AEK + AEL -> Value.AEL + AEM -> Value.AEM + AEN -> Value.AEN + AEO -> Value.AEO + AEP -> Value.AEP + AES -> Value.AES + AET -> Value.AET + AEU -> Value.AEU + AEV -> Value.AEV + AEW -> Value.AEW + AEX -> Value.AEX + AEY -> Value.AEY + AEZ -> Value.AEZ + AJ -> Value.AJ + AU -> Value.AU + CA -> Value.CA + CAB -> Value.CAB + CAD -> Value.CAD + CAE -> Value.CAE + CAF -> Value.CAF + CAI -> Value.CAI + CAJ -> Value.CAJ + CAK -> Value.CAK + CAL -> Value.CAL + CAM -> Value.CAM + CAN -> Value.CAN + CAO -> Value.CAO + CAP -> Value.CAP + CAQ -> Value.CAQ + CAR -> Value.CAR + CAS -> Value.CAS + CAT -> Value.CAT + CAU -> Value.CAU + CAV -> Value.CAV + CAW -> Value.CAW + CAX -> Value.CAX + CAY -> Value.CAY + CAZ -> Value.CAZ + CD -> Value.CD + CG -> Value.CG + CS -> Value.CS + CT -> Value.CT + DAB -> Value.DAB + DAC -> Value.DAC + DAD -> Value.DAD + DAF -> Value.DAF + DAG -> Value.DAG + DAH -> Value.DAH + DAI -> Value.DAI + DAJ -> Value.DAJ + DAK -> Value.DAK + DAL -> Value.DAL + DAM -> Value.DAM + DAN -> Value.DAN + DAO -> Value.DAO + DAP -> Value.DAP + DAQ -> Value.DAQ + DL -> Value.DL + EG -> Value.EG + EP -> Value.EP + ER -> Value.ER + FAA -> Value.FAA + FAB -> Value.FAB + FAC -> Value.FAC + FC -> Value.FC + FH -> Value.FH + FI -> Value.FI + GAA -> Value.GAA + HAA -> Value.HAA + HD -> Value.HD + HH -> Value.HH + IAA -> Value.IAA + IAB -> Value.IAB + ID -> Value.ID + IF -> Value.IF + IR -> Value.IR + IS -> Value.IS + KO -> Value.KO + L1 -> Value.L1 + LA -> Value.LA + LAA -> Value.LAA + LAB -> Value.LAB + LF -> Value.LF + MAE -> Value.MAE + MI -> Value.MI + ML -> Value.ML + NAA -> Value.NAA + OA -> Value.OA + PA -> Value.PA + PAA -> Value.PAA + PC -> Value.PC + PL -> Value.PL + PRV -> Value.PRV + RAB -> Value.RAB + RAC -> Value.RAC + RAD -> Value.RAD + RAF -> Value.RAF + RE -> Value.RE + RF -> Value.RF + RH -> Value.RH + RV -> Value.RV + SA -> Value.SA + SAA -> Value.SAA + SAD -> Value.SAD + SAE -> Value.SAE + SAI -> Value.SAI + SG -> Value.SG + SH -> Value.SH + SM -> Value.SM + SU -> Value.SU + TAB -> Value.TAB + TAC -> Value.TAC + TT -> Value.TT + TV -> Value.TV + V1 -> Value.V1 + V2 -> Value.V2 + WH -> Value.WH + XAA -> Value.XAA + YY -> Value.YY + ZZZ -> Value.ZZZ + else -> Value._UNKNOWN + } + + /** + * Returns an enum member corresponding to this class instance's value. + * + * Use the [value] method instead if you're uncertain the value is always known and + * don't want to throw for the unknown case. + * + * @throws EInvoiceInvalidDataException if this class instance's value is a not a + * known member. + */ + fun known(): Known = + when (this) { + AA -> Known.AA + AAA -> Known.AAA + AAC -> Known.AAC + AAD -> Known.AAD + AAE -> Known.AAE + AAF -> Known.AAF + AAH -> Known.AAH + AAI -> Known.AAI + AAS -> Known.AAS + AAT -> Known.AAT + AAV -> Known.AAV + AAY -> Known.AAY + AAZ -> Known.AAZ + ABA -> Known.ABA + ABB -> Known.ABB + ABC -> Known.ABC + ABD -> Known.ABD + ABF -> Known.ABF + ABK -> Known.ABK + ABL -> Known.ABL + ABN -> Known.ABN + ABR -> Known.ABR + ABS -> Known.ABS + ABT -> Known.ABT + ABU -> Known.ABU + ACF -> Known.ACF + ACG -> Known.ACG + ACH -> Known.ACH + ACI -> Known.ACI + ACJ -> Known.ACJ + ACK -> Known.ACK + ACL -> Known.ACL + ACM -> Known.ACM + ACS -> Known.ACS + ADC -> Known.ADC + ADE -> Known.ADE + ADJ -> Known.ADJ + ADK -> Known.ADK + ADL -> Known.ADL + ADM -> Known.ADM + ADN -> Known.ADN + ADO -> Known.ADO + ADP -> Known.ADP + ADQ -> Known.ADQ + ADR -> Known.ADR + ADT -> Known.ADT + ADW -> Known.ADW + ADY -> Known.ADY + ADZ -> Known.ADZ + AEA -> Known.AEA + AEB -> Known.AEB + AEC -> Known.AEC + AED -> Known.AED + AEF -> Known.AEF + AEH -> Known.AEH + AEI -> Known.AEI + AEJ -> Known.AEJ + AEK -> Known.AEK + AEL -> Known.AEL + AEM -> Known.AEM + AEN -> Known.AEN + AEO -> Known.AEO + AEP -> Known.AEP + AES -> Known.AES + AET -> Known.AET + AEU -> Known.AEU + AEV -> Known.AEV + AEW -> Known.AEW + AEX -> Known.AEX + AEY -> Known.AEY + AEZ -> Known.AEZ + AJ -> Known.AJ + AU -> Known.AU + CA -> Known.CA + CAB -> Known.CAB + CAD -> Known.CAD + CAE -> Known.CAE + CAF -> Known.CAF + CAI -> Known.CAI + CAJ -> Known.CAJ + CAK -> Known.CAK + CAL -> Known.CAL + CAM -> Known.CAM + CAN -> Known.CAN + CAO -> Known.CAO + CAP -> Known.CAP + CAQ -> Known.CAQ + CAR -> Known.CAR + CAS -> Known.CAS + CAT -> Known.CAT + CAU -> Known.CAU + CAV -> Known.CAV + CAW -> Known.CAW + CAX -> Known.CAX + CAY -> Known.CAY + CAZ -> Known.CAZ + CD -> Known.CD + CG -> Known.CG + CS -> Known.CS + CT -> Known.CT + DAB -> Known.DAB + DAC -> Known.DAC + DAD -> Known.DAD + DAF -> Known.DAF + DAG -> Known.DAG + DAH -> Known.DAH + DAI -> Known.DAI + DAJ -> Known.DAJ + DAK -> Known.DAK + DAL -> Known.DAL + DAM -> Known.DAM + DAN -> Known.DAN + DAO -> Known.DAO + DAP -> Known.DAP + DAQ -> Known.DAQ + DL -> Known.DL + EG -> Known.EG + EP -> Known.EP + ER -> Known.ER + FAA -> Known.FAA + FAB -> Known.FAB + FAC -> Known.FAC + FC -> Known.FC + FH -> Known.FH + FI -> Known.FI + GAA -> Known.GAA + HAA -> Known.HAA + HD -> Known.HD + HH -> Known.HH + IAA -> Known.IAA + IAB -> Known.IAB + ID -> Known.ID + IF -> Known.IF + IR -> Known.IR + IS -> Known.IS + KO -> Known.KO + L1 -> Known.L1 + LA -> Known.LA + LAA -> Known.LAA + LAB -> Known.LAB + LF -> Known.LF + MAE -> Known.MAE + MI -> Known.MI + ML -> Known.ML + NAA -> Known.NAA + OA -> Known.OA + PA -> Known.PA + PAA -> Known.PAA + PC -> Known.PC + PL -> Known.PL + PRV -> Known.PRV + RAB -> Known.RAB + RAC -> Known.RAC + RAD -> Known.RAD + RAF -> Known.RAF + RE -> Known.RE + RF -> Known.RF + RH -> Known.RH + RV -> Known.RV + SA -> Known.SA + SAA -> Known.SAA + SAD -> Known.SAD + SAE -> Known.SAE + SAI -> Known.SAI + SG -> Known.SG + SH -> Known.SH + SM -> Known.SM + SU -> Known.SU + TAB -> Known.TAB + TAC -> Known.TAC + TT -> Known.TT + TV -> Known.TV + V1 -> Known.V1 + V2 -> Known.V2 + WH -> Known.WH + XAA -> Known.XAA + YY -> Known.YY + ZZZ -> Known.ZZZ + else -> throw EInvoiceInvalidDataException("Unknown ReasonCode: $value") + } + + /** + * Returns this class instance's primitive wire representation. + * + * This differs from the [toString] method because that method is primarily for + * debugging and generally doesn't throw. + * + * @throws EInvoiceInvalidDataException if this class instance's value does not have + * the expected primitive type. + */ + fun asString(): String = + _value().asString().orElseThrow { + EInvoiceInvalidDataException("Value is not a String") + } + + private var validated: Boolean = false + + fun validate(): ReasonCode = apply { + if (validated) { + return@apply + } + + known() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: EInvoiceInvalidDataException) { + false + } - /** - * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if - * the server responded with an unexpected value). - */ - fun tax(): Optional = tax.getOptional("tax") + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic internal fun validity(): Int = if (value() == Value._UNKNOWN) 0 else 1 - /** - * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if - * the server responded with an unexpected value). - */ - fun taxRate(): Optional = taxRate.getOptional("tax_rate") + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } - /** - * Unit of Measure Codes from UNECERec20 used in Peppol BIS Billing 3.0. - * - * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if - * the server responded with an unexpected value). - */ - fun unit(): Optional = unit.getOptional("unit") + return other is ReasonCode && value == other.value + } - /** - * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if - * the server responded with an unexpected value). - */ - fun unitPrice(): Optional = unitPrice.getOptional("unit_price") + override fun hashCode() = value.hashCode() - /** - * Returns the raw JSON value of [amount]. - * - * Unlike [amount], this method doesn't throw if the JSON field has an unexpected type. - */ - @JsonProperty("amount") @ExcludeMissing fun _amount(): JsonField = amount + override fun toString() = value.toString() + } - /** - * Returns the raw JSON value of [date]. - * - * Unlike [date], this method doesn't throw if the JSON field has an unexpected type. - */ - @JsonProperty("date") @ExcludeMissing fun _date(): JsonField = date + /** + * Duty or tax or fee category codes (Subset of UNCL5305) + * + * Agency: UN/CEFACT Version: D.16B Subset: OpenPEPPOL + */ + class TaxCode @JsonCreator private constructor(private val value: JsonField) : + Enum { - /** - * Returns the raw JSON value of [description]. - * - * Unlike [description], this method doesn't throw if the JSON field has an unexpected type. - */ - @JsonProperty("description") - @ExcludeMissing - fun _description(): JsonField = description + /** + * Returns this class instance's raw value. + * + * This is usually only useful if this instance was deserialized from data that + * doesn't match any known member, and you want to know that value. For example, if + * the SDK is on an older version than the API, then the API may respond with new + * members that the SDK is unaware of. + */ + @com.fasterxml.jackson.annotation.JsonValue fun _value(): JsonField = value - /** - * Returns the raw JSON value of [productCode]. - * - * Unlike [productCode], this method doesn't throw if the JSON field has an unexpected type. - */ - @JsonProperty("product_code") - @ExcludeMissing - fun _productCode(): JsonField = productCode + companion object { - /** - * Returns the raw JSON value of [quantity]. - * - * Unlike [quantity], this method doesn't throw if the JSON field has an unexpected type. - */ - @JsonProperty("quantity") @ExcludeMissing fun _quantity(): JsonField = quantity + @JvmField val AE = of("AE") - /** - * Returns the raw JSON value of [tax]. - * - * Unlike [tax], this method doesn't throw if the JSON field has an unexpected type. - */ - @JsonProperty("tax") @ExcludeMissing fun _tax(): JsonField = tax + @JvmField val E = of("E") - /** - * Returns the raw JSON value of [taxRate]. - * - * Unlike [taxRate], this method doesn't throw if the JSON field has an unexpected type. - */ - @JsonProperty("tax_rate") @ExcludeMissing fun _taxRate(): JsonField = taxRate + @JvmField val S = of("S") - /** - * Returns the raw JSON value of [unit]. - * - * Unlike [unit], this method doesn't throw if the JSON field has an unexpected type. - */ - @JsonProperty("unit") @ExcludeMissing fun _unit(): JsonField = unit + @JvmField val Z = of("Z") - /** - * Returns the raw JSON value of [unitPrice]. - * - * Unlike [unitPrice], this method doesn't throw if the JSON field has an unexpected type. - */ - @JsonProperty("unit_price") - @ExcludeMissing - fun _unitPrice(): JsonField = unitPrice + @JvmField val G = of("G") - @JsonAnySetter - private fun putAdditionalProperty(key: String, value: JsonValue) { - additionalProperties.put(key, value) - } + @JvmField val O = of("O") - @JsonAnyGetter - @ExcludeMissing - fun _additionalProperties(): Map = - Collections.unmodifiableMap(additionalProperties) + @JvmField val K = of("K") - fun toBuilder() = Builder().from(this) + @JvmField val L = of("L") - companion object { + @JvmField val M = of("M") - /** Returns a mutable builder for constructing an instance of [Item]. */ - @JvmStatic fun builder() = Builder() - } + @JvmField val B = of("B") - /** A builder for [Item]. */ - class Builder internal constructor() { + @JvmStatic fun of(value: String) = TaxCode(JsonField.of(value)) + } - private var amount: JsonField = JsonMissing.of() - private var date: JsonField = JsonMissing.of() - private var description: JsonField = JsonMissing.of() - private var productCode: JsonField = JsonMissing.of() - private var quantity: JsonField = JsonMissing.of() - private var tax: JsonField = JsonMissing.of() - private var taxRate: JsonField = JsonMissing.of() - private var unit: JsonField = JsonMissing.of() - private var unitPrice: JsonField = JsonMissing.of() - private var additionalProperties: MutableMap = mutableMapOf() + /** An enum containing [TaxCode]'s known values. */ + enum class Known { + AE, + E, + S, + Z, + G, + O, + K, + L, + M, + B, + } - @JvmSynthetic - internal fun from(item: Item) = apply { - amount = item.amount - date = item.date - description = item.description - productCode = item.productCode - quantity = item.quantity - tax = item.tax - taxRate = item.taxRate - unit = item.unit - unitPrice = item.unitPrice - additionalProperties = item.additionalProperties.toMutableMap() - } + /** + * An enum containing [TaxCode]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [TaxCode] can contain an unknown value in a couple of cases: + * - It was deserialized from data that doesn't match any known member. For example, + * if the SDK is on an older version than the API, then the API may respond with + * new members that the SDK is unaware of. + * - It was constructed with an arbitrary value using the [of] method. + */ + enum class Value { + AE, + E, + S, + Z, + G, + O, + K, + L, + M, + B, + /** + * An enum member indicating that [TaxCode] was instantiated with an unknown + * value. + */ + _UNKNOWN, + } - fun amount(amount: Amount?) = amount(JsonField.ofNullable(amount)) + /** + * Returns an enum member corresponding to this class instance's value, or + * [Value._UNKNOWN] if the class was instantiated with an unknown value. + * + * Use the [known] method instead if you're certain the value is always known or if + * you want to throw for the unknown case. + */ + fun value(): Value = + when (this) { + AE -> Value.AE + E -> Value.E + S -> Value.S + Z -> Value.Z + G -> Value.G + O -> Value.O + K -> Value.K + L -> Value.L + M -> Value.M + B -> Value.B + else -> Value._UNKNOWN + } - /** Alias for calling [Builder.amount] with `amount.orElse(null)`. */ - fun amount(amount: Optional) = amount(amount.getOrNull()) + /** + * Returns an enum member corresponding to this class instance's value. + * + * Use the [value] method instead if you're uncertain the value is always known and + * don't want to throw for the unknown case. + * + * @throws EInvoiceInvalidDataException if this class instance's value is a not a + * known member. + */ + fun known(): Known = + when (this) { + AE -> Known.AE + E -> Known.E + S -> Known.S + Z -> Known.Z + G -> Known.G + O -> Known.O + K -> Known.K + L -> Known.L + M -> Known.M + B -> Known.B + else -> throw EInvoiceInvalidDataException("Unknown TaxCode: $value") + } - /** - * Sets [Builder.amount] to an arbitrary JSON value. - * - * You should usually call [Builder.amount] with a well-typed [Amount] value instead. - * This method is primarily for setting the field to an undocumented or not yet - * supported value. - */ - fun amount(amount: JsonField) = apply { this.amount = amount } + /** + * Returns this class instance's primitive wire representation. + * + * This differs from the [toString] method because that method is primarily for + * debugging and generally doesn't throw. + * + * @throws EInvoiceInvalidDataException if this class instance's value does not have + * the expected primitive type. + */ + fun asString(): String = + _value().asString().orElseThrow { + EInvoiceInvalidDataException("Value is not a String") + } - /** Alias for calling [amount] with `Amount.ofNumber(number)`. */ - fun amount(number: Double) = amount(Amount.ofNumber(number)) + private var validated: Boolean = false - /** Alias for calling [amount] with `Amount.ofString(string)`. */ - fun amount(string: String) = amount(Amount.ofString(string)) + fun validate(): TaxCode = apply { + if (validated) { + return@apply + } - fun date(date: Void?) = date(JsonField.ofNullable(date)) + known() + validated = true + } - /** Alias for calling [Builder.date] with `date.orElse(null)`. */ - fun date(date: Optional) = date(date.getOrNull()) + fun isValid(): Boolean = + try { + validate() + true + } catch (e: EInvoiceInvalidDataException) { + false + } - /** - * Sets [Builder.date] to an arbitrary JSON value. - * - * You should usually call [Builder.date] with a well-typed [Void] value instead. This - * method is primarily for setting the field to an undocumented or not yet supported - * value. - */ - fun date(date: JsonField) = apply { this.date = date } + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic internal fun validity(): Int = if (value() == Value._UNKNOWN) 0 else 1 - fun description(description: String?) = description(JsonField.ofNullable(description)) + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } - /** Alias for calling [Builder.description] with `description.orElse(null)`. */ - fun description(description: Optional) = description(description.getOrNull()) + return other is TaxCode && value == other.value + } - /** - * Sets [Builder.description] to an arbitrary JSON value. - * - * You should usually call [Builder.description] with a well-typed [String] value - * instead. This method is primarily for setting the field to an undocumented or not yet - * supported value. - */ - fun description(description: JsonField) = apply { - this.description = description + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() } - fun productCode(productCode: String?) = productCode(JsonField.ofNullable(productCode)) + /** The VAT rate, represented as percentage that applies to the charge */ + @JsonDeserialize(using = TaxRate.Deserializer::class) + @JsonSerialize(using = TaxRate.Serializer::class) + class TaxRate + private constructor( + private val number: Double? = null, + private val string: String? = null, + private val _json: JsonValue? = null, + ) { - /** Alias for calling [Builder.productCode] with `productCode.orElse(null)`. */ - fun productCode(productCode: Optional) = productCode(productCode.getOrNull()) + fun number(): Optional = Optional.ofNullable(number) - /** - * Sets [Builder.productCode] to an arbitrary JSON value. - * - * You should usually call [Builder.productCode] with a well-typed [String] value - * instead. This method is primarily for setting the field to an undocumented or not yet - * supported value. - */ - fun productCode(productCode: JsonField) = apply { - this.productCode = productCode - } + fun string(): Optional = Optional.ofNullable(string) - fun quantity(quantity: Quantity?) = quantity(JsonField.ofNullable(quantity)) + fun isNumber(): Boolean = number != null - /** Alias for calling [Builder.quantity] with `quantity.orElse(null)`. */ - fun quantity(quantity: Optional) = quantity(quantity.getOrNull()) + fun isString(): Boolean = string != null - /** - * Sets [Builder.quantity] to an arbitrary JSON value. - * - * You should usually call [Builder.quantity] with a well-typed [Quantity] value - * instead. This method is primarily for setting the field to an undocumented or not yet - * supported value. - */ - fun quantity(quantity: JsonField) = apply { this.quantity = quantity } + fun asNumber(): Double = number.getOrThrow("number") - /** Alias for calling [quantity] with `Quantity.ofNumber(number)`. */ - fun quantity(number: Double) = quantity(Quantity.ofNumber(number)) + fun asString(): String = string.getOrThrow("string") - /** Alias for calling [quantity] with `Quantity.ofString(string)`. */ - fun quantity(string: String) = quantity(Quantity.ofString(string)) + fun _json(): Optional = Optional.ofNullable(_json) - fun tax(tax: Tax?) = tax(JsonField.ofNullable(tax)) + fun accept(visitor: Visitor): T = + when { + number != null -> visitor.visitNumber(number) + string != null -> visitor.visitString(string) + else -> visitor.unknown(_json) + } - /** Alias for calling [Builder.tax] with `tax.orElse(null)`. */ - fun tax(tax: Optional) = tax(tax.getOrNull()) + private var validated: Boolean = false - /** - * Sets [Builder.tax] to an arbitrary JSON value. - * - * You should usually call [Builder.tax] with a well-typed [Tax] value instead. This - * method is primarily for setting the field to an undocumented or not yet supported - * value. - */ - fun tax(tax: JsonField) = apply { this.tax = tax } + fun validate(): TaxRate = apply { + if (validated) { + return@apply + } - /** Alias for calling [tax] with `Tax.ofNumber(number)`. */ - fun tax(number: Double) = tax(Tax.ofNumber(number)) + accept( + object : Visitor { + override fun visitNumber(number: Double) {} - /** Alias for calling [tax] with `Tax.ofString(string)`. */ - fun tax(string: String) = tax(Tax.ofString(string)) + override fun visitString(string: String) {} + } + ) + validated = true + } - fun taxRate(taxRate: String?) = taxRate(JsonField.ofNullable(taxRate)) + fun isValid(): Boolean = + try { + validate() + true + } catch (e: EInvoiceInvalidDataException) { + false + } - /** Alias for calling [Builder.taxRate] with `taxRate.orElse(null)`. */ - fun taxRate(taxRate: Optional) = taxRate(taxRate.getOrNull()) + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic + internal fun validity(): Int = + accept( + object : Visitor { + override fun visitNumber(number: Double) = 1 - /** - * Sets [Builder.taxRate] to an arbitrary JSON value. - * - * You should usually call [Builder.taxRate] with a well-typed [String] value instead. - * This method is primarily for setting the field to an undocumented or not yet - * supported value. - */ - fun taxRate(taxRate: JsonField) = apply { this.taxRate = taxRate } + override fun visitString(string: String) = 1 - /** Unit of Measure Codes from UNECERec20 used in Peppol BIS Billing 3.0. */ - fun unit(unit: UnitOfMeasureCode?) = unit(JsonField.ofNullable(unit)) + override fun unknown(json: JsonValue?) = 0 + } + ) - /** Alias for calling [Builder.unit] with `unit.orElse(null)`. */ - fun unit(unit: Optional) = unit(unit.getOrNull()) + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } - /** - * Sets [Builder.unit] to an arbitrary JSON value. - * - * You should usually call [Builder.unit] with a well-typed [UnitOfMeasureCode] value - * instead. This method is primarily for setting the field to an undocumented or not yet - * supported value. - */ - fun unit(unit: JsonField) = apply { this.unit = unit } + return other is TaxRate && number == other.number && string == other.string + } - fun unitPrice(unitPrice: UnitPrice?) = unitPrice(JsonField.ofNullable(unitPrice)) + override fun hashCode(): Int = Objects.hash(number, string) - /** Alias for calling [Builder.unitPrice] with `unitPrice.orElse(null)`. */ - fun unitPrice(unitPrice: Optional) = unitPrice(unitPrice.getOrNull()) + override fun toString(): String = + when { + number != null -> "TaxRate{number=$number}" + string != null -> "TaxRate{string=$string}" + _json != null -> "TaxRate{_unknown=$_json}" + else -> throw IllegalStateException("Invalid TaxRate") + } - /** - * Sets [Builder.unitPrice] to an arbitrary JSON value. - * - * You should usually call [Builder.unitPrice] with a well-typed [UnitPrice] value - * instead. This method is primarily for setting the field to an undocumented or not yet - * supported value. - */ - fun unitPrice(unitPrice: JsonField) = apply { this.unitPrice = unitPrice } + companion object { - /** Alias for calling [unitPrice] with `UnitPrice.ofNumber(number)`. */ - fun unitPrice(number: Double) = unitPrice(UnitPrice.ofNumber(number)) + @JvmStatic fun ofNumber(number: Double) = TaxRate(number = number) - /** Alias for calling [unitPrice] with `UnitPrice.ofString(string)`. */ - fun unitPrice(string: String) = unitPrice(UnitPrice.ofString(string)) + @JvmStatic fun ofString(string: String) = TaxRate(string = string) + } - fun additionalProperties(additionalProperties: Map) = apply { - this.additionalProperties.clear() - putAllAdditionalProperties(additionalProperties) - } + /** + * An interface that defines how to map each variant of [TaxRate] to a value of type + * [T]. + */ + interface Visitor { + + fun visitNumber(number: Double): T + + fun visitString(string: String): T + + /** + * Maps an unknown variant of [TaxRate] to a value of type [T]. + * + * An instance of [TaxRate] can contain an unknown variant if it was + * deserialized from data that doesn't match any known variant. For example, if + * the SDK is on an older version than the API, then the API may respond with + * new variants that the SDK is unaware of. + * + * @throws EInvoiceInvalidDataException in the default implementation. + */ + fun unknown(json: JsonValue?): T { + throw EInvoiceInvalidDataException("Unknown TaxRate: $json") + } + } - fun putAdditionalProperty(key: String, value: JsonValue) = apply { - additionalProperties.put(key, value) - } + internal class Deserializer : BaseDeserializer(TaxRate::class) { + + override fun ObjectCodec.deserialize(node: JsonNode): TaxRate { + val json = JsonValue.fromJsonNode(node) + + val bestMatches = + sequenceOf( + tryDeserialize(node, jacksonTypeRef())?.let { + TaxRate(string = it, _json = json) + }, + tryDeserialize(node, jacksonTypeRef())?.let { + TaxRate(number = it, _json = json) + }, + ) + .filterNotNull() + .allMaxBy { it.validity() } + .toList() + return when (bestMatches.size) { + // This can happen if what we're deserializing is completely + // incompatible with all the possible variants (e.g. deserializing from + // boolean). + 0 -> TaxRate(_json = json) + 1 -> bestMatches.single() + // If there's more than one match with the highest validity, then use + // the first completely valid match, or simply the first match if none + // are completely valid. + else -> bestMatches.firstOrNull { it.isValid() } ?: bestMatches.first() + } + } + } - fun putAllAdditionalProperties(additionalProperties: Map) = apply { - this.additionalProperties.putAll(additionalProperties) + internal class Serializer : BaseSerializer(TaxRate::class) { + + override fun serialize( + value: TaxRate, + generator: JsonGenerator, + provider: SerializerProvider, + ) { + when { + value.number != null -> generator.writeObject(value.number) + value.string != null -> generator.writeObject(value.string) + value._json != null -> generator.writeObject(value._json) + else -> throw IllegalStateException("Invalid TaxRate") + } + } + } } - fun removeAdditionalProperty(key: String) = apply { additionalProperties.remove(key) } + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } - fun removeAllAdditionalProperties(keys: Set) = apply { - keys.forEach(::removeAdditionalProperty) + return other is Charge && + amount == other.amount && + baseAmount == other.baseAmount && + multiplierFactor == other.multiplierFactor && + reason == other.reason && + reasonCode == other.reasonCode && + taxCode == other.taxCode && + taxRate == other.taxRate && + additionalProperties == other.additionalProperties } - /** - * Returns an immutable instance of [Item]. - * - * Further updates to this [Builder] will not mutate the returned instance. - */ - fun build(): Item = - Item( + private val hashCode: Int by lazy { + Objects.hash( amount, - date, - description, - productCode, - quantity, - tax, + baseAmount, + multiplierFactor, + reason, + reasonCode, + taxCode, taxRate, - unit, - unitPrice, - additionalProperties.toMutableMap(), + additionalProperties, ) - } - - private var validated: Boolean = false - - fun validate(): Item = apply { - if (validated) { - return@apply } - amount().ifPresent { it.validate() } - date() - description() - productCode() - quantity().ifPresent { it.validate() } - tax().ifPresent { it.validate() } - taxRate() - unit().ifPresent { it.validate() } - unitPrice().ifPresent { it.validate() } - validated = true - } + override fun hashCode(): Int = hashCode - fun isValid(): Boolean = - try { - validate() - true - } catch (e: EInvoiceInvalidDataException) { - false - } + override fun toString() = + "Charge{amount=$amount, baseAmount=$baseAmount, multiplierFactor=$multiplierFactor, reason=$reason, reasonCode=$reasonCode, taxCode=$taxCode, taxRate=$taxRate, additionalProperties=$additionalProperties}" + } /** - * Returns a score indicating how many valid values are contained in this object - * recursively. - * - * Used for best match union deserialization. + * The quantity of items (goods or services) that is the subject of the line item. Must be + * rounded to maximum 4 decimals. Can be negative for credit notes or corrections. */ - @JvmSynthetic - internal fun validity(): Int = - (amount.asKnown().getOrNull()?.validity() ?: 0) + - (if (date.asKnown().isPresent) 1 else 0) + - (if (description.asKnown().isPresent) 1 else 0) + - (if (productCode.asKnown().isPresent) 1 else 0) + - (quantity.asKnown().getOrNull()?.validity() ?: 0) + - (tax.asKnown().getOrNull()?.validity() ?: 0) + - (if (taxRate.asKnown().isPresent) 1 else 0) + - (unit.asKnown().getOrNull()?.validity() ?: 0) + - (unitPrice.asKnown().getOrNull()?.validity() ?: 0) - - @JsonDeserialize(using = Amount.Deserializer::class) - @JsonSerialize(using = Amount.Serializer::class) - class Amount + @JsonDeserialize(using = Quantity.Deserializer::class) + @JsonSerialize(using = Quantity.Serializer::class) + class Quantity private constructor( private val number: Double? = null, private val string: String? = null, @@ -2737,7 +11786,7 @@ private constructor( private var validated: Boolean = false - fun validate(): Amount = apply { + fun validate(): Quantity = apply { if (validated) { return@apply } @@ -2783,28 +11832,29 @@ private constructor( return true } - return other is Amount && number == other.number && string == other.string + return other is Quantity && number == other.number && string == other.string } override fun hashCode(): Int = Objects.hash(number, string) override fun toString(): String = when { - number != null -> "Amount{number=$number}" - string != null -> "Amount{string=$string}" - _json != null -> "Amount{_unknown=$_json}" - else -> throw IllegalStateException("Invalid Amount") + number != null -> "Quantity{number=$number}" + string != null -> "Quantity{string=$string}" + _json != null -> "Quantity{_unknown=$_json}" + else -> throw IllegalStateException("Invalid Quantity") } companion object { - @JvmStatic fun ofNumber(number: Double) = Amount(number = number) + @JvmStatic fun ofNumber(number: Double) = Quantity(number = number) - @JvmStatic fun ofString(string: String) = Amount(string = string) + @JvmStatic fun ofString(string: String) = Quantity(string = string) } /** - * An interface that defines how to map each variant of [Amount] to a value of type [T]. + * An interface that defines how to map each variant of [Quantity] to a value of type + * [T]. */ interface Visitor { @@ -2813,9 +11863,9 @@ private constructor( fun visitString(string: String): T /** - * Maps an unknown variant of [Amount] to a value of type [T]. + * Maps an unknown variant of [Quantity] to a value of type [T]. * - * An instance of [Amount] can contain an unknown variant if it was deserialized + * An instance of [Quantity] can contain an unknown variant if it was deserialized * from data that doesn't match any known variant. For example, if the SDK is on an * older version than the API, then the API may respond with new variants that the * SDK is unaware of. @@ -2823,22 +11873,22 @@ private constructor( * @throws EInvoiceInvalidDataException in the default implementation. */ fun unknown(json: JsonValue?): T { - throw EInvoiceInvalidDataException("Unknown Amount: $json") + throw EInvoiceInvalidDataException("Unknown Quantity: $json") } } - internal class Deserializer : BaseDeserializer(Amount::class) { + internal class Deserializer : BaseDeserializer(Quantity::class) { - override fun ObjectCodec.deserialize(node: JsonNode): Amount { + override fun ObjectCodec.deserialize(node: JsonNode): Quantity { val json = JsonValue.fromJsonNode(node) val bestMatches = sequenceOf( - tryDeserialize(node, jacksonTypeRef())?.let { - Amount(number = it, _json = json) - }, tryDeserialize(node, jacksonTypeRef())?.let { - Amount(string = it, _json = json) + Quantity(string = it, _json = json) + }, + tryDeserialize(node, jacksonTypeRef())?.let { + Quantity(number = it, _json = json) }, ) .filterNotNull() @@ -2846,8 +11896,8 @@ private constructor( .toList() return when (bestMatches.size) { // This can happen if what we're deserializing is completely incompatible - // with all the possible variants (e.g. deserializing from object). - 0 -> Amount(_json = json) + // with all the possible variants (e.g. deserializing from boolean). + 0 -> Quantity(_json = json) 1 -> bestMatches.single() // If there's more than one match with the highest validity, then use the // first completely valid match, or simply the first match if none are @@ -2857,10 +11907,10 @@ private constructor( } } - internal class Serializer : BaseSerializer(Amount::class) { + internal class Serializer : BaseSerializer(Quantity::class) { override fun serialize( - value: Amount, + value: Quantity, generator: JsonGenerator, provider: SerializerProvider, ) { @@ -2868,15 +11918,19 @@ private constructor( value.number != null -> generator.writeObject(value.number) value.string != null -> generator.writeObject(value.string) value._json != null -> generator.writeObject(value._json) - else -> throw IllegalStateException("Invalid Amount") + else -> throw IllegalStateException("Invalid Quantity") } } } } - @JsonDeserialize(using = Quantity.Deserializer::class) - @JsonSerialize(using = Quantity.Serializer::class) - class Quantity + /** + * The total VAT amount for the line item. Must be rounded to maximum 2 decimals. Can be + * negative for credit notes or corrections. + */ + @JsonDeserialize(using = Tax.Deserializer::class) + @JsonSerialize(using = Tax.Serializer::class) + class Tax private constructor( private val number: Double? = null, private val string: String? = null, @@ -2906,7 +11960,7 @@ private constructor( private var validated: Boolean = false - fun validate(): Quantity = apply { + fun validate(): Tax = apply { if (validated) { return@apply } @@ -2952,29 +12006,28 @@ private constructor( return true } - return other is Quantity && number == other.number && string == other.string + return other is Tax && number == other.number && string == other.string } override fun hashCode(): Int = Objects.hash(number, string) override fun toString(): String = when { - number != null -> "Quantity{number=$number}" - string != null -> "Quantity{string=$string}" - _json != null -> "Quantity{_unknown=$_json}" - else -> throw IllegalStateException("Invalid Quantity") + number != null -> "Tax{number=$number}" + string != null -> "Tax{string=$string}" + _json != null -> "Tax{_unknown=$_json}" + else -> throw IllegalStateException("Invalid Tax") } companion object { - @JvmStatic fun ofNumber(number: Double) = Quantity(number = number) + @JvmStatic fun ofNumber(number: Double) = Tax(number = number) - @JvmStatic fun ofString(string: String) = Quantity(string = string) + @JvmStatic fun ofString(string: String) = Tax(string = string) } /** - * An interface that defines how to map each variant of [Quantity] to a value of type - * [T]. + * An interface that defines how to map each variant of [Tax] to a value of type [T]. */ interface Visitor { @@ -2983,32 +12036,32 @@ private constructor( fun visitString(string: String): T /** - * Maps an unknown variant of [Quantity] to a value of type [T]. + * Maps an unknown variant of [Tax] to a value of type [T]. * - * An instance of [Quantity] can contain an unknown variant if it was deserialized - * from data that doesn't match any known variant. For example, if the SDK is on an - * older version than the API, then the API may respond with new variants that the - * SDK is unaware of. + * An instance of [Tax] can contain an unknown variant if it was deserialized from + * data that doesn't match any known variant. For example, if the SDK is on an older + * version than the API, then the API may respond with new variants that the SDK is + * unaware of. * * @throws EInvoiceInvalidDataException in the default implementation. */ fun unknown(json: JsonValue?): T { - throw EInvoiceInvalidDataException("Unknown Quantity: $json") + throw EInvoiceInvalidDataException("Unknown Tax: $json") } } - internal class Deserializer : BaseDeserializer(Quantity::class) { + internal class Deserializer : BaseDeserializer(Tax::class) { - override fun ObjectCodec.deserialize(node: JsonNode): Quantity { + override fun ObjectCodec.deserialize(node: JsonNode): Tax { val json = JsonValue.fromJsonNode(node) val bestMatches = sequenceOf( - tryDeserialize(node, jacksonTypeRef())?.let { - Quantity(number = it, _json = json) - }, tryDeserialize(node, jacksonTypeRef())?.let { - Quantity(string = it, _json = json) + Tax(string = it, _json = json) + }, + tryDeserialize(node, jacksonTypeRef())?.let { + Tax(number = it, _json = json) }, ) .filterNotNull() @@ -3016,8 +12069,8 @@ private constructor( .toList() return when (bestMatches.size) { // This can happen if what we're deserializing is completely incompatible - // with all the possible variants (e.g. deserializing from object). - 0 -> Quantity(_json = json) + // with all the possible variants (e.g. deserializing from boolean). + 0 -> Tax(_json = json) 1 -> bestMatches.single() // If there's more than one match with the highest validity, then use the // first completely valid match, or simply the first match if none are @@ -3027,10 +12080,10 @@ private constructor( } } - internal class Serializer : BaseSerializer(Quantity::class) { + internal class Serializer : BaseSerializer(Tax::class) { override fun serialize( - value: Quantity, + value: Tax, generator: JsonGenerator, provider: SerializerProvider, ) { @@ -3038,15 +12091,16 @@ private constructor( value.number != null -> generator.writeObject(value.number) value.string != null -> generator.writeObject(value.string) value._json != null -> generator.writeObject(value._json) - else -> throw IllegalStateException("Invalid Quantity") + else -> throw IllegalStateException("Invalid Tax") } } } } - @JsonDeserialize(using = Tax.Deserializer::class) - @JsonSerialize(using = Tax.Serializer::class) - class Tax + /** The VAT rate of the line item expressed as percentage with 2 decimals */ + @JsonDeserialize(using = TaxRate.Deserializer::class) + @JsonSerialize(using = TaxRate.Serializer::class) + class TaxRate private constructor( private val number: Double? = null, private val string: String? = null, @@ -3076,7 +12130,7 @@ private constructor( private var validated: Boolean = false - fun validate(): Tax = apply { + fun validate(): TaxRate = apply { if (validated) { return@apply } @@ -3122,28 +12176,29 @@ private constructor( return true } - return other is Tax && number == other.number && string == other.string + return other is TaxRate && number == other.number && string == other.string } override fun hashCode(): Int = Objects.hash(number, string) override fun toString(): String = when { - number != null -> "Tax{number=$number}" - string != null -> "Tax{string=$string}" - _json != null -> "Tax{_unknown=$_json}" - else -> throw IllegalStateException("Invalid Tax") + number != null -> "TaxRate{number=$number}" + string != null -> "TaxRate{string=$string}" + _json != null -> "TaxRate{_unknown=$_json}" + else -> throw IllegalStateException("Invalid TaxRate") } companion object { - @JvmStatic fun ofNumber(number: Double) = Tax(number = number) + @JvmStatic fun ofNumber(number: Double) = TaxRate(number = number) - @JvmStatic fun ofString(string: String) = Tax(string = string) + @JvmStatic fun ofString(string: String) = TaxRate(string = string) } /** - * An interface that defines how to map each variant of [Tax] to a value of type [T]. + * An interface that defines how to map each variant of [TaxRate] to a value of type + * [T]. */ interface Visitor { @@ -3152,32 +12207,32 @@ private constructor( fun visitString(string: String): T /** - * Maps an unknown variant of [Tax] to a value of type [T]. + * Maps an unknown variant of [TaxRate] to a value of type [T]. * - * An instance of [Tax] can contain an unknown variant if it was deserialized from - * data that doesn't match any known variant. For example, if the SDK is on an older - * version than the API, then the API may respond with new variants that the SDK is - * unaware of. + * An instance of [TaxRate] can contain an unknown variant if it was deserialized + * from data that doesn't match any known variant. For example, if the SDK is on an + * older version than the API, then the API may respond with new variants that the + * SDK is unaware of. * * @throws EInvoiceInvalidDataException in the default implementation. */ fun unknown(json: JsonValue?): T { - throw EInvoiceInvalidDataException("Unknown Tax: $json") + throw EInvoiceInvalidDataException("Unknown TaxRate: $json") } } - internal class Deserializer : BaseDeserializer(Tax::class) { + internal class Deserializer : BaseDeserializer(TaxRate::class) { - override fun ObjectCodec.deserialize(node: JsonNode): Tax { + override fun ObjectCodec.deserialize(node: JsonNode): TaxRate { val json = JsonValue.fromJsonNode(node) val bestMatches = sequenceOf( - tryDeserialize(node, jacksonTypeRef())?.let { - Tax(number = it, _json = json) - }, tryDeserialize(node, jacksonTypeRef())?.let { - Tax(string = it, _json = json) + TaxRate(string = it, _json = json) + }, + tryDeserialize(node, jacksonTypeRef())?.let { + TaxRate(number = it, _json = json) }, ) .filterNotNull() @@ -3185,8 +12240,8 @@ private constructor( .toList() return when (bestMatches.size) { // This can happen if what we're deserializing is completely incompatible - // with all the possible variants (e.g. deserializing from object). - 0 -> Tax(_json = json) + // with all the possible variants (e.g. deserializing from boolean). + 0 -> TaxRate(_json = json) 1 -> bestMatches.single() // If there's more than one match with the highest validity, then use the // first completely valid match, or simply the first match if none are @@ -3196,10 +12251,10 @@ private constructor( } } - internal class Serializer : BaseSerializer(Tax::class) { + internal class Serializer : BaseSerializer(TaxRate::class) { override fun serialize( - value: Tax, + value: TaxRate, generator: JsonGenerator, provider: SerializerProvider, ) { @@ -3207,12 +12262,16 @@ private constructor( value.number != null -> generator.writeObject(value.number) value.string != null -> generator.writeObject(value.string) value._json != null -> generator.writeObject(value._json) - else -> throw IllegalStateException("Invalid Tax") + else -> throw IllegalStateException("Invalid TaxRate") } } } } + /** + * The item net price (BT-146). The price of an item, exclusive of VAT, after subtracting + * item price discount. Must be rounded to maximum 4 decimals + */ @JsonDeserialize(using = UnitPrice.Deserializer::class) @JsonSerialize(using = UnitPrice.Serializer::class) class UnitPrice @@ -3343,19 +12402,19 @@ private constructor( val bestMatches = sequenceOf( - tryDeserialize(node, jacksonTypeRef())?.let { - UnitPrice(number = it, _json = json) - }, tryDeserialize(node, jacksonTypeRef())?.let { UnitPrice(string = it, _json = json) }, + tryDeserialize(node, jacksonTypeRef())?.let { + UnitPrice(number = it, _json = json) + }, ) .filterNotNull() .allMaxBy { it.validity() } .toList() return when (bestMatches.size) { // This can happen if what we're deserializing is completely incompatible - // with all the possible variants (e.g. deserializing from object). + // with all the possible variants (e.g. deserializing from boolean). 0 -> UnitPrice(_json = json) 1 -> bestMatches.single() // If there's more than one match with the highest validity, then use the @@ -3389,7 +12448,9 @@ private constructor( } return other is Item && + allowances == other.allowances && amount == other.amount && + charges == other.charges && date == other.date && description == other.description && productCode == other.productCode && @@ -3403,7 +12464,9 @@ private constructor( private val hashCode: Int by lazy { Objects.hash( + allowances, amount, + charges, date, description, productCode, @@ -3419,9 +12482,13 @@ private constructor( override fun hashCode(): Int = hashCode override fun toString() = - "Item{amount=$amount, date=$date, description=$description, productCode=$productCode, quantity=$quantity, tax=$tax, taxRate=$taxRate, unit=$unit, unitPrice=$unitPrice, additionalProperties=$additionalProperties}" + "Item{allowances=$allowances, amount=$amount, charges=$charges, date=$date, description=$description, productCode=$productCode, quantity=$quantity, tax=$tax, taxRate=$taxRate, unit=$unit, unitPrice=$unitPrice, additionalProperties=$additionalProperties}" } + /** + * The previous unpaid balance from prior invoices, if any. Must be positive and rounded to + * maximum 2 decimals + */ @JsonDeserialize(using = PreviousUnpaidBalance.Deserializer::class) @JsonSerialize(using = PreviousUnpaidBalance.Serializer::class) class PreviousUnpaidBalance @@ -3555,19 +12622,19 @@ private constructor( val bestMatches = sequenceOf( - tryDeserialize(node, jacksonTypeRef())?.let { - PreviousUnpaidBalance(number = it, _json = json) - }, tryDeserialize(node, jacksonTypeRef())?.let { PreviousUnpaidBalance(string = it, _json = json) }, + tryDeserialize(node, jacksonTypeRef())?.let { + PreviousUnpaidBalance(number = it, _json = json) + }, ) .filterNotNull() .allMaxBy { it.validity() } .toList() return when (bestMatches.size) { // This can happen if what we're deserializing is completely incompatible with - // all the possible variants (e.g. deserializing from object). + // all the possible variants (e.g. deserializing from boolean). 0 -> PreviousUnpaidBalance(_json = json) 1 -> bestMatches.single() // If there's more than one match with the highest validity, then use the first @@ -3596,6 +12663,11 @@ private constructor( } } + /** + * The taxable base of the invoice. Should be the sum of all line items - allowances (for + * example commercial discounts) + charges with impact on VAT. Must be positive and rounded to + * maximum 2 decimals + */ @JsonDeserialize(using = Subtotal.Deserializer::class) @JsonSerialize(using = Subtotal.Serializer::class) class Subtotal @@ -3725,19 +12797,19 @@ private constructor( val bestMatches = sequenceOf( - tryDeserialize(node, jacksonTypeRef())?.let { - Subtotal(number = it, _json = json) - }, tryDeserialize(node, jacksonTypeRef())?.let { Subtotal(string = it, _json = json) }, + tryDeserialize(node, jacksonTypeRef())?.let { + Subtotal(number = it, _json = json) + }, ) .filterNotNull() .allMaxBy { it.validity() } .toList() return when (bestMatches.size) { // This can happen if what we're deserializing is completely incompatible with - // all the possible variants (e.g. deserializing from object). + // all the possible variants (e.g. deserializing from boolean). 0 -> Subtotal(_json = json) 1 -> bestMatches.single() // If there's more than one match with the highest validity, then use the first @@ -3765,6 +12837,184 @@ private constructor( } } + /** + * Tax category code of the invoice (e.g., S for standard rate, Z for zero rate, E for exempt) + */ + class TaxCode @JsonCreator private constructor(private val value: JsonField) : Enum { + + /** + * Returns this class instance's raw value. + * + * This is usually only useful if this instance was deserialized from data that doesn't + * match any known member, and you want to know that value. For example, if the SDK is on an + * older version than the API, then the API may respond with new members that the SDK is + * unaware of. + */ + @com.fasterxml.jackson.annotation.JsonValue fun _value(): JsonField = value + + companion object { + + @JvmField val AE = of("AE") + + @JvmField val E = of("E") + + @JvmField val S = of("S") + + @JvmField val Z = of("Z") + + @JvmField val G = of("G") + + @JvmField val O = of("O") + + @JvmField val K = of("K") + + @JvmField val L = of("L") + + @JvmField val M = of("M") + + @JvmField val B = of("B") + + @JvmStatic fun of(value: String) = TaxCode(JsonField.of(value)) + } + + /** An enum containing [TaxCode]'s known values. */ + enum class Known { + AE, + E, + S, + Z, + G, + O, + K, + L, + M, + B, + } + + /** + * An enum containing [TaxCode]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [TaxCode] can contain an unknown value in a couple of cases: + * - It was deserialized from data that doesn't match any known member. For example, if the + * SDK is on an older version than the API, then the API may respond with new members that + * the SDK is unaware of. + * - It was constructed with an arbitrary value using the [of] method. + */ + enum class Value { + AE, + E, + S, + Z, + G, + O, + K, + L, + M, + B, + /** An enum member indicating that [TaxCode] was instantiated with an unknown value. */ + _UNKNOWN, + } + + /** + * Returns an enum member corresponding to this class instance's value, or [Value._UNKNOWN] + * if the class was instantiated with an unknown value. + * + * Use the [known] method instead if you're certain the value is always known or if you want + * to throw for the unknown case. + */ + fun value(): Value = + when (this) { + AE -> Value.AE + E -> Value.E + S -> Value.S + Z -> Value.Z + G -> Value.G + O -> Value.O + K -> Value.K + L -> Value.L + M -> Value.M + B -> Value.B + else -> Value._UNKNOWN + } + + /** + * Returns an enum member corresponding to this class instance's value. + * + * Use the [value] method instead if you're uncertain the value is always known and don't + * want to throw for the unknown case. + * + * @throws EInvoiceInvalidDataException if this class instance's value is a not a known + * member. + */ + fun known(): Known = + when (this) { + AE -> Known.AE + E -> Known.E + S -> Known.S + Z -> Known.Z + G -> Known.G + O -> Known.O + K -> Known.K + L -> Known.L + M -> Known.M + B -> Known.B + else -> throw EInvoiceInvalidDataException("Unknown TaxCode: $value") + } + + /** + * Returns this class instance's primitive wire representation. + * + * This differs from the [toString] method because that method is primarily for debugging + * and generally doesn't throw. + * + * @throws EInvoiceInvalidDataException if this class instance's value does not have the + * expected primitive type. + */ + fun asString(): String = + _value().asString().orElseThrow { + EInvoiceInvalidDataException("Value is not a String") + } + + private var validated: Boolean = false + + fun validate(): TaxCode = apply { + if (validated) { + return@apply + } + + known() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: EInvoiceInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic internal fun validity(): Int = if (value() == Value._UNKNOWN) 0 else 1 + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is TaxCode && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + class TaxDetail @JsonCreator(mode = JsonCreator.Mode.DISABLED) private constructor( @@ -3780,12 +13030,16 @@ private constructor( ) : this(amount, rate, mutableMapOf()) /** + * The tax amount for this tax category. Must be rounded to maximum 2 decimals + * * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if * the server responded with an unexpected value). */ fun amount(): Optional = amount.getOptional("amount") /** + * The tax rate as a percentage (e.g., '21.00', '6.00', '0.00') + * * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if * the server responded with an unexpected value). */ @@ -3837,6 +13091,7 @@ private constructor( additionalProperties = taxDetail.additionalProperties.toMutableMap() } + /** The tax amount for this tax category. Must be rounded to maximum 2 decimals */ fun amount(amount: Amount?) = amount(JsonField.ofNullable(amount)) /** Alias for calling [Builder.amount] with `amount.orElse(null)`. */ @@ -3857,6 +13112,7 @@ private constructor( /** Alias for calling [amount] with `Amount.ofString(string)`. */ fun amount(string: String) = amount(Amount.ofString(string)) + /** The tax rate as a percentage (e.g., '21.00', '6.00', '0.00') */ fun rate(rate: String?) = rate(JsonField.ofNullable(rate)) /** Alias for calling [Builder.rate] with `rate.orElse(null)`. */ @@ -3929,6 +13185,7 @@ private constructor( (amount.asKnown().getOrNull()?.validity() ?: 0) + (if (rate.asKnown().isPresent) 1 else 0) + /** The tax amount for this tax category. Must be rounded to maximum 2 decimals */ @JsonDeserialize(using = Amount.Deserializer::class) @JsonSerialize(using = Amount.Serializer::class) class Amount @@ -4058,19 +13315,19 @@ private constructor( val bestMatches = sequenceOf( - tryDeserialize(node, jacksonTypeRef())?.let { - Amount(number = it, _json = json) - }, tryDeserialize(node, jacksonTypeRef())?.let { Amount(string = it, _json = json) }, + tryDeserialize(node, jacksonTypeRef())?.let { + Amount(number = it, _json = json) + }, ) .filterNotNull() .allMaxBy { it.validity() } .toList() return when (bestMatches.size) { // This can happen if what we're deserializing is completely incompatible - // with all the possible variants (e.g. deserializing from object). + // with all the possible variants (e.g. deserializing from boolean). 0 -> Amount(_json = json) 1 -> bestMatches.single() // If there's more than one match with the highest validity, then use the @@ -4117,6 +13374,11 @@ private constructor( "TaxDetail{amount=$amount, rate=$rate, additionalProperties=$additionalProperties}" } + /** + * The net financial discount/charge of the invoice (non-VAT charges minus non-VAT allowances). + * Can be positive (net charge), negative (net discount), or zero. Must be rounded to maximum 2 + * decimals + */ @JsonDeserialize(using = TotalDiscount.Deserializer::class) @JsonSerialize(using = TotalDiscount.Serializer::class) class TotalDiscount @@ -4247,19 +13509,19 @@ private constructor( val bestMatches = sequenceOf( - tryDeserialize(node, jacksonTypeRef())?.let { - TotalDiscount(number = it, _json = json) - }, tryDeserialize(node, jacksonTypeRef())?.let { TotalDiscount(string = it, _json = json) }, + tryDeserialize(node, jacksonTypeRef())?.let { + TotalDiscount(number = it, _json = json) + }, ) .filterNotNull() .allMaxBy { it.validity() } .toList() return when (bestMatches.size) { // This can happen if what we're deserializing is completely incompatible with - // all the possible variants (e.g. deserializing from object). + // all the possible variants (e.g. deserializing from boolean). 0 -> TotalDiscount(_json = json) 1 -> bestMatches.single() // If there's more than one match with the highest validity, then use the first @@ -4287,6 +13549,7 @@ private constructor( } } + /** The total tax amount of the invoice. Must be positive and rounded to maximum 2 decimals */ @JsonDeserialize(using = TotalTax.Deserializer::class) @JsonSerialize(using = TotalTax.Serializer::class) class TotalTax @@ -4416,19 +13679,19 @@ private constructor( val bestMatches = sequenceOf( - tryDeserialize(node, jacksonTypeRef())?.let { - TotalTax(number = it, _json = json) - }, tryDeserialize(node, jacksonTypeRef())?.let { TotalTax(string = it, _json = json) }, + tryDeserialize(node, jacksonTypeRef())?.let { + TotalTax(number = it, _json = json) + }, ) .filterNotNull() .allMaxBy { it.validity() } .toList() return when (bestMatches.size) { // This can happen if what we're deserializing is completely incompatible with - // all the possible variants (e.g. deserializing from object). + // all the possible variants (e.g. deserializing from boolean). 0 -> TotalTax(_json = json) 1 -> bestMatches.single() // If there's more than one match with the highest validity, then use the first @@ -4456,19 +13719,514 @@ private constructor( } } + /** + * VATEX code list for VAT exemption reasons + * + * Agency: CEF Identifier: vatex + */ + class Vatex @JsonCreator private constructor(private val value: JsonField) : Enum { + + /** + * Returns this class instance's raw value. + * + * This is usually only useful if this instance was deserialized from data that doesn't + * match any known member, and you want to know that value. For example, if the SDK is on an + * older version than the API, then the API may respond with new members that the SDK is + * unaware of. + */ + @com.fasterxml.jackson.annotation.JsonValue fun _value(): JsonField = value + + companion object { + + @JvmField val VATEX_EU_79_C = of("VATEX-EU-79-C") + + @JvmField val VATEX_EU_132 = of("VATEX-EU-132") + + @JvmField val VATEX_EU_132_1_A = of("VATEX-EU-132-1A") + + @JvmField val VATEX_EU_132_1_B = of("VATEX-EU-132-1B") + + @JvmField val VATEX_EU_132_1_C = of("VATEX-EU-132-1C") + + @JvmField val VATEX_EU_132_1_D = of("VATEX-EU-132-1D") + + @JvmField val VATEX_EU_132_1_E = of("VATEX-EU-132-1E") + + @JvmField val VATEX_EU_132_1_F = of("VATEX-EU-132-1F") + + @JvmField val VATEX_EU_132_1_G = of("VATEX-EU-132-1G") + + @JvmField val VATEX_EU_132_1_H = of("VATEX-EU-132-1H") + + @JvmField val VATEX_EU_132_1_I = of("VATEX-EU-132-1I") + + @JvmField val VATEX_EU_132_1_J = of("VATEX-EU-132-1J") + + @JvmField val VATEX_EU_132_1_K = of("VATEX-EU-132-1K") + + @JvmField val VATEX_EU_132_1_L = of("VATEX-EU-132-1L") + + @JvmField val VATEX_EU_132_1_M = of("VATEX-EU-132-1M") + + @JvmField val VATEX_EU_132_1_N = of("VATEX-EU-132-1N") + + @JvmField val VATEX_EU_132_1_O = of("VATEX-EU-132-1O") + + @JvmField val VATEX_EU_132_1_P = of("VATEX-EU-132-1P") + + @JvmField val VATEX_EU_132_1_Q = of("VATEX-EU-132-1Q") + + @JvmField val VATEX_EU_143 = of("VATEX-EU-143") + + @JvmField val VATEX_EU_143_1_A = of("VATEX-EU-143-1A") + + @JvmField val VATEX_EU_143_1_B = of("VATEX-EU-143-1B") + + @JvmField val VATEX_EU_143_1_C = of("VATEX-EU-143-1C") + + @JvmField val VATEX_EU_143_1_D = of("VATEX-EU-143-1D") + + @JvmField val VATEX_EU_143_1_E = of("VATEX-EU-143-1E") + + @JvmField val VATEX_EU_143_1_F = of("VATEX-EU-143-1F") + + @JvmField val VATEX_EU_143_1_FA = of("VATEX-EU-143-1FA") + + @JvmField val VATEX_EU_143_1_G = of("VATEX-EU-143-1G") + + @JvmField val VATEX_EU_143_1_H = of("VATEX-EU-143-1H") + + @JvmField val VATEX_EU_143_1_I = of("VATEX-EU-143-1I") + + @JvmField val VATEX_EU_143_1_J = of("VATEX-EU-143-1J") + + @JvmField val VATEX_EU_143_1_K = of("VATEX-EU-143-1K") + + @JvmField val VATEX_EU_143_1_L = of("VATEX-EU-143-1L") + + @JvmField val VATEX_EU_144 = of("VATEX-EU-144") + + @JvmField val VATEX_EU_146_1_E = of("VATEX-EU-146-1E") + + @JvmField val VATEX_EU_148 = of("VATEX-EU-148") + + @JvmField val VATEX_EU_148_A = of("VATEX-EU-148-A") + + @JvmField val VATEX_EU_148_B = of("VATEX-EU-148-B") + + @JvmField val VATEX_EU_148_C = of("VATEX-EU-148-C") + + @JvmField val VATEX_EU_148_D = of("VATEX-EU-148-D") + + @JvmField val VATEX_EU_148_E = of("VATEX-EU-148-E") + + @JvmField val VATEX_EU_148_F = of("VATEX-EU-148-F") + + @JvmField val VATEX_EU_148_G = of("VATEX-EU-148-G") + + @JvmField val VATEX_EU_151 = of("VATEX-EU-151") + + @JvmField val VATEX_EU_151_1_A = of("VATEX-EU-151-1A") + + @JvmField val VATEX_EU_151_1_AA = of("VATEX-EU-151-1AA") + + @JvmField val VATEX_EU_151_1_B = of("VATEX-EU-151-1B") + + @JvmField val VATEX_EU_151_1_C = of("VATEX-EU-151-1C") + + @JvmField val VATEX_EU_151_1_D = of("VATEX-EU-151-1D") + + @JvmField val VATEX_EU_151_1_E = of("VATEX-EU-151-1E") + + @JvmField val VATEX_EU_159 = of("VATEX-EU-159") + + @JvmField val VATEX_EU_309 = of("VATEX-EU-309") + + @JvmField val VATEX_EU_AE = of("VATEX-EU-AE") + + @JvmField val VATEX_EU_D = of("VATEX-EU-D") + + @JvmField val VATEX_EU_F = of("VATEX-EU-F") + + @JvmField val VATEX_EU_G = of("VATEX-EU-G") + + @JvmField val VATEX_EU_I = of("VATEX-EU-I") + + @JvmField val VATEX_EU_IC = of("VATEX-EU-IC") + + @JvmField val VATEX_EU_O = of("VATEX-EU-O") + + @JvmField val VATEX_EU_J = of("VATEX-EU-J") + + @JvmField val VATEX_FR_FRANCHISE = of("VATEX-FR-FRANCHISE") + + @JvmField val VATEX_FR_CNWVAT = of("VATEX-FR-CNWVAT") + + @JvmStatic fun of(value: String) = Vatex(JsonField.of(value)) + } + + /** An enum containing [Vatex]'s known values. */ + enum class Known { + VATEX_EU_79_C, + VATEX_EU_132, + VATEX_EU_132_1_A, + VATEX_EU_132_1_B, + VATEX_EU_132_1_C, + VATEX_EU_132_1_D, + VATEX_EU_132_1_E, + VATEX_EU_132_1_F, + VATEX_EU_132_1_G, + VATEX_EU_132_1_H, + VATEX_EU_132_1_I, + VATEX_EU_132_1_J, + VATEX_EU_132_1_K, + VATEX_EU_132_1_L, + VATEX_EU_132_1_M, + VATEX_EU_132_1_N, + VATEX_EU_132_1_O, + VATEX_EU_132_1_P, + VATEX_EU_132_1_Q, + VATEX_EU_143, + VATEX_EU_143_1_A, + VATEX_EU_143_1_B, + VATEX_EU_143_1_C, + VATEX_EU_143_1_D, + VATEX_EU_143_1_E, + VATEX_EU_143_1_F, + VATEX_EU_143_1_FA, + VATEX_EU_143_1_G, + VATEX_EU_143_1_H, + VATEX_EU_143_1_I, + VATEX_EU_143_1_J, + VATEX_EU_143_1_K, + VATEX_EU_143_1_L, + VATEX_EU_144, + VATEX_EU_146_1_E, + VATEX_EU_148, + VATEX_EU_148_A, + VATEX_EU_148_B, + VATEX_EU_148_C, + VATEX_EU_148_D, + VATEX_EU_148_E, + VATEX_EU_148_F, + VATEX_EU_148_G, + VATEX_EU_151, + VATEX_EU_151_1_A, + VATEX_EU_151_1_AA, + VATEX_EU_151_1_B, + VATEX_EU_151_1_C, + VATEX_EU_151_1_D, + VATEX_EU_151_1_E, + VATEX_EU_159, + VATEX_EU_309, + VATEX_EU_AE, + VATEX_EU_D, + VATEX_EU_F, + VATEX_EU_G, + VATEX_EU_I, + VATEX_EU_IC, + VATEX_EU_O, + VATEX_EU_J, + VATEX_FR_FRANCHISE, + VATEX_FR_CNWVAT, + } + + /** + * An enum containing [Vatex]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [Vatex] can contain an unknown value in a couple of cases: + * - It was deserialized from data that doesn't match any known member. For example, if the + * SDK is on an older version than the API, then the API may respond with new members that + * the SDK is unaware of. + * - It was constructed with an arbitrary value using the [of] method. + */ + enum class Value { + VATEX_EU_79_C, + VATEX_EU_132, + VATEX_EU_132_1_A, + VATEX_EU_132_1_B, + VATEX_EU_132_1_C, + VATEX_EU_132_1_D, + VATEX_EU_132_1_E, + VATEX_EU_132_1_F, + VATEX_EU_132_1_G, + VATEX_EU_132_1_H, + VATEX_EU_132_1_I, + VATEX_EU_132_1_J, + VATEX_EU_132_1_K, + VATEX_EU_132_1_L, + VATEX_EU_132_1_M, + VATEX_EU_132_1_N, + VATEX_EU_132_1_O, + VATEX_EU_132_1_P, + VATEX_EU_132_1_Q, + VATEX_EU_143, + VATEX_EU_143_1_A, + VATEX_EU_143_1_B, + VATEX_EU_143_1_C, + VATEX_EU_143_1_D, + VATEX_EU_143_1_E, + VATEX_EU_143_1_F, + VATEX_EU_143_1_FA, + VATEX_EU_143_1_G, + VATEX_EU_143_1_H, + VATEX_EU_143_1_I, + VATEX_EU_143_1_J, + VATEX_EU_143_1_K, + VATEX_EU_143_1_L, + VATEX_EU_144, + VATEX_EU_146_1_E, + VATEX_EU_148, + VATEX_EU_148_A, + VATEX_EU_148_B, + VATEX_EU_148_C, + VATEX_EU_148_D, + VATEX_EU_148_E, + VATEX_EU_148_F, + VATEX_EU_148_G, + VATEX_EU_151, + VATEX_EU_151_1_A, + VATEX_EU_151_1_AA, + VATEX_EU_151_1_B, + VATEX_EU_151_1_C, + VATEX_EU_151_1_D, + VATEX_EU_151_1_E, + VATEX_EU_159, + VATEX_EU_309, + VATEX_EU_AE, + VATEX_EU_D, + VATEX_EU_F, + VATEX_EU_G, + VATEX_EU_I, + VATEX_EU_IC, + VATEX_EU_O, + VATEX_EU_J, + VATEX_FR_FRANCHISE, + VATEX_FR_CNWVAT, + /** An enum member indicating that [Vatex] was instantiated with an unknown value. */ + _UNKNOWN, + } + + /** + * Returns an enum member corresponding to this class instance's value, or [Value._UNKNOWN] + * if the class was instantiated with an unknown value. + * + * Use the [known] method instead if you're certain the value is always known or if you want + * to throw for the unknown case. + */ + fun value(): Value = + when (this) { + VATEX_EU_79_C -> Value.VATEX_EU_79_C + VATEX_EU_132 -> Value.VATEX_EU_132 + VATEX_EU_132_1_A -> Value.VATEX_EU_132_1_A + VATEX_EU_132_1_B -> Value.VATEX_EU_132_1_B + VATEX_EU_132_1_C -> Value.VATEX_EU_132_1_C + VATEX_EU_132_1_D -> Value.VATEX_EU_132_1_D + VATEX_EU_132_1_E -> Value.VATEX_EU_132_1_E + VATEX_EU_132_1_F -> Value.VATEX_EU_132_1_F + VATEX_EU_132_1_G -> Value.VATEX_EU_132_1_G + VATEX_EU_132_1_H -> Value.VATEX_EU_132_1_H + VATEX_EU_132_1_I -> Value.VATEX_EU_132_1_I + VATEX_EU_132_1_J -> Value.VATEX_EU_132_1_J + VATEX_EU_132_1_K -> Value.VATEX_EU_132_1_K + VATEX_EU_132_1_L -> Value.VATEX_EU_132_1_L + VATEX_EU_132_1_M -> Value.VATEX_EU_132_1_M + VATEX_EU_132_1_N -> Value.VATEX_EU_132_1_N + VATEX_EU_132_1_O -> Value.VATEX_EU_132_1_O + VATEX_EU_132_1_P -> Value.VATEX_EU_132_1_P + VATEX_EU_132_1_Q -> Value.VATEX_EU_132_1_Q + VATEX_EU_143 -> Value.VATEX_EU_143 + VATEX_EU_143_1_A -> Value.VATEX_EU_143_1_A + VATEX_EU_143_1_B -> Value.VATEX_EU_143_1_B + VATEX_EU_143_1_C -> Value.VATEX_EU_143_1_C + VATEX_EU_143_1_D -> Value.VATEX_EU_143_1_D + VATEX_EU_143_1_E -> Value.VATEX_EU_143_1_E + VATEX_EU_143_1_F -> Value.VATEX_EU_143_1_F + VATEX_EU_143_1_FA -> Value.VATEX_EU_143_1_FA + VATEX_EU_143_1_G -> Value.VATEX_EU_143_1_G + VATEX_EU_143_1_H -> Value.VATEX_EU_143_1_H + VATEX_EU_143_1_I -> Value.VATEX_EU_143_1_I + VATEX_EU_143_1_J -> Value.VATEX_EU_143_1_J + VATEX_EU_143_1_K -> Value.VATEX_EU_143_1_K + VATEX_EU_143_1_L -> Value.VATEX_EU_143_1_L + VATEX_EU_144 -> Value.VATEX_EU_144 + VATEX_EU_146_1_E -> Value.VATEX_EU_146_1_E + VATEX_EU_148 -> Value.VATEX_EU_148 + VATEX_EU_148_A -> Value.VATEX_EU_148_A + VATEX_EU_148_B -> Value.VATEX_EU_148_B + VATEX_EU_148_C -> Value.VATEX_EU_148_C + VATEX_EU_148_D -> Value.VATEX_EU_148_D + VATEX_EU_148_E -> Value.VATEX_EU_148_E + VATEX_EU_148_F -> Value.VATEX_EU_148_F + VATEX_EU_148_G -> Value.VATEX_EU_148_G + VATEX_EU_151 -> Value.VATEX_EU_151 + VATEX_EU_151_1_A -> Value.VATEX_EU_151_1_A + VATEX_EU_151_1_AA -> Value.VATEX_EU_151_1_AA + VATEX_EU_151_1_B -> Value.VATEX_EU_151_1_B + VATEX_EU_151_1_C -> Value.VATEX_EU_151_1_C + VATEX_EU_151_1_D -> Value.VATEX_EU_151_1_D + VATEX_EU_151_1_E -> Value.VATEX_EU_151_1_E + VATEX_EU_159 -> Value.VATEX_EU_159 + VATEX_EU_309 -> Value.VATEX_EU_309 + VATEX_EU_AE -> Value.VATEX_EU_AE + VATEX_EU_D -> Value.VATEX_EU_D + VATEX_EU_F -> Value.VATEX_EU_F + VATEX_EU_G -> Value.VATEX_EU_G + VATEX_EU_I -> Value.VATEX_EU_I + VATEX_EU_IC -> Value.VATEX_EU_IC + VATEX_EU_O -> Value.VATEX_EU_O + VATEX_EU_J -> Value.VATEX_EU_J + VATEX_FR_FRANCHISE -> Value.VATEX_FR_FRANCHISE + VATEX_FR_CNWVAT -> Value.VATEX_FR_CNWVAT + else -> Value._UNKNOWN + } + + /** + * Returns an enum member corresponding to this class instance's value. + * + * Use the [value] method instead if you're uncertain the value is always known and don't + * want to throw for the unknown case. + * + * @throws EInvoiceInvalidDataException if this class instance's value is a not a known + * member. + */ + fun known(): Known = + when (this) { + VATEX_EU_79_C -> Known.VATEX_EU_79_C + VATEX_EU_132 -> Known.VATEX_EU_132 + VATEX_EU_132_1_A -> Known.VATEX_EU_132_1_A + VATEX_EU_132_1_B -> Known.VATEX_EU_132_1_B + VATEX_EU_132_1_C -> Known.VATEX_EU_132_1_C + VATEX_EU_132_1_D -> Known.VATEX_EU_132_1_D + VATEX_EU_132_1_E -> Known.VATEX_EU_132_1_E + VATEX_EU_132_1_F -> Known.VATEX_EU_132_1_F + VATEX_EU_132_1_G -> Known.VATEX_EU_132_1_G + VATEX_EU_132_1_H -> Known.VATEX_EU_132_1_H + VATEX_EU_132_1_I -> Known.VATEX_EU_132_1_I + VATEX_EU_132_1_J -> Known.VATEX_EU_132_1_J + VATEX_EU_132_1_K -> Known.VATEX_EU_132_1_K + VATEX_EU_132_1_L -> Known.VATEX_EU_132_1_L + VATEX_EU_132_1_M -> Known.VATEX_EU_132_1_M + VATEX_EU_132_1_N -> Known.VATEX_EU_132_1_N + VATEX_EU_132_1_O -> Known.VATEX_EU_132_1_O + VATEX_EU_132_1_P -> Known.VATEX_EU_132_1_P + VATEX_EU_132_1_Q -> Known.VATEX_EU_132_1_Q + VATEX_EU_143 -> Known.VATEX_EU_143 + VATEX_EU_143_1_A -> Known.VATEX_EU_143_1_A + VATEX_EU_143_1_B -> Known.VATEX_EU_143_1_B + VATEX_EU_143_1_C -> Known.VATEX_EU_143_1_C + VATEX_EU_143_1_D -> Known.VATEX_EU_143_1_D + VATEX_EU_143_1_E -> Known.VATEX_EU_143_1_E + VATEX_EU_143_1_F -> Known.VATEX_EU_143_1_F + VATEX_EU_143_1_FA -> Known.VATEX_EU_143_1_FA + VATEX_EU_143_1_G -> Known.VATEX_EU_143_1_G + VATEX_EU_143_1_H -> Known.VATEX_EU_143_1_H + VATEX_EU_143_1_I -> Known.VATEX_EU_143_1_I + VATEX_EU_143_1_J -> Known.VATEX_EU_143_1_J + VATEX_EU_143_1_K -> Known.VATEX_EU_143_1_K + VATEX_EU_143_1_L -> Known.VATEX_EU_143_1_L + VATEX_EU_144 -> Known.VATEX_EU_144 + VATEX_EU_146_1_E -> Known.VATEX_EU_146_1_E + VATEX_EU_148 -> Known.VATEX_EU_148 + VATEX_EU_148_A -> Known.VATEX_EU_148_A + VATEX_EU_148_B -> Known.VATEX_EU_148_B + VATEX_EU_148_C -> Known.VATEX_EU_148_C + VATEX_EU_148_D -> Known.VATEX_EU_148_D + VATEX_EU_148_E -> Known.VATEX_EU_148_E + VATEX_EU_148_F -> Known.VATEX_EU_148_F + VATEX_EU_148_G -> Known.VATEX_EU_148_G + VATEX_EU_151 -> Known.VATEX_EU_151 + VATEX_EU_151_1_A -> Known.VATEX_EU_151_1_A + VATEX_EU_151_1_AA -> Known.VATEX_EU_151_1_AA + VATEX_EU_151_1_B -> Known.VATEX_EU_151_1_B + VATEX_EU_151_1_C -> Known.VATEX_EU_151_1_C + VATEX_EU_151_1_D -> Known.VATEX_EU_151_1_D + VATEX_EU_151_1_E -> Known.VATEX_EU_151_1_E + VATEX_EU_159 -> Known.VATEX_EU_159 + VATEX_EU_309 -> Known.VATEX_EU_309 + VATEX_EU_AE -> Known.VATEX_EU_AE + VATEX_EU_D -> Known.VATEX_EU_D + VATEX_EU_F -> Known.VATEX_EU_F + VATEX_EU_G -> Known.VATEX_EU_G + VATEX_EU_I -> Known.VATEX_EU_I + VATEX_EU_IC -> Known.VATEX_EU_IC + VATEX_EU_O -> Known.VATEX_EU_O + VATEX_EU_J -> Known.VATEX_EU_J + VATEX_FR_FRANCHISE -> Known.VATEX_FR_FRANCHISE + VATEX_FR_CNWVAT -> Known.VATEX_FR_CNWVAT + else -> throw EInvoiceInvalidDataException("Unknown Vatex: $value") + } + + /** + * Returns this class instance's primitive wire representation. + * + * This differs from the [toString] method because that method is primarily for debugging + * and generally doesn't throw. + * + * @throws EInvoiceInvalidDataException if this class instance's value does not have the + * expected primitive type. + */ + fun asString(): String = + _value().asString().orElseThrow { + EInvoiceInvalidDataException("Value is not a String") + } + + private var validated: Boolean = false + + fun validate(): Vatex = apply { + if (validated) { + return@apply + } + + known() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: EInvoiceInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic internal fun validity(): Int = if (value() == Value._UNKNOWN) 0 else 1 + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Vatex && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + override fun equals(other: Any?): Boolean { if (this === other) { return true } return other is DocumentCreate && + allowances == other.allowances && amountDue == other.amountDue && attachments == other.attachments && billingAddress == other.billingAddress && billingAddressRecipient == other.billingAddressRecipient && + charges == other.charges && currency == other.currency && customerAddress == other.customerAddress && customerAddressRecipient == other.customerAddressRecipient && + customerCompanyId == other.customerCompanyId && customerEmail == other.customerEmail && customerId == other.customerId && customerName == other.customerName && @@ -4495,11 +14253,15 @@ private constructor( shippingAddressRecipient == other.shippingAddressRecipient && state == other.state && subtotal == other.subtotal && + taxCode == other.taxCode && taxDetails == other.taxDetails && totalDiscount == other.totalDiscount && totalTax == other.totalTax && + vatex == other.vatex && + vatexNote == other.vatexNote && vendorAddress == other.vendorAddress && vendorAddressRecipient == other.vendorAddressRecipient && + vendorCompanyId == other.vendorCompanyId && vendorEmail == other.vendorEmail && vendorName == other.vendorName && vendorTaxId == other.vendorTaxId && @@ -4508,13 +14270,16 @@ private constructor( private val hashCode: Int by lazy { Objects.hash( + allowances, amountDue, attachments, billingAddress, billingAddressRecipient, + charges, currency, customerAddress, customerAddressRecipient, + customerCompanyId, customerEmail, customerId, customerName, @@ -4541,11 +14306,15 @@ private constructor( shippingAddressRecipient, state, subtotal, + taxCode, taxDetails, totalDiscount, totalTax, + vatex, + vatexNote, vendorAddress, vendorAddressRecipient, + vendorCompanyId, vendorEmail, vendorName, vendorTaxId, @@ -4556,5 +14325,5 @@ private constructor( override fun hashCode(): Int = hashCode override fun toString() = - "DocumentCreate{amountDue=$amountDue, attachments=$attachments, billingAddress=$billingAddress, billingAddressRecipient=$billingAddressRecipient, currency=$currency, customerAddress=$customerAddress, customerAddressRecipient=$customerAddressRecipient, customerEmail=$customerEmail, customerId=$customerId, customerName=$customerName, customerTaxId=$customerTaxId, direction=$direction, documentType=$documentType, dueDate=$dueDate, invoiceDate=$invoiceDate, invoiceId=$invoiceId, invoiceTotal=$invoiceTotal, items=$items, note=$note, paymentDetails=$paymentDetails, paymentTerm=$paymentTerm, previousUnpaidBalance=$previousUnpaidBalance, purchaseOrder=$purchaseOrder, remittanceAddress=$remittanceAddress, remittanceAddressRecipient=$remittanceAddressRecipient, serviceAddress=$serviceAddress, serviceAddressRecipient=$serviceAddressRecipient, serviceEndDate=$serviceEndDate, serviceStartDate=$serviceStartDate, shippingAddress=$shippingAddress, shippingAddressRecipient=$shippingAddressRecipient, state=$state, subtotal=$subtotal, taxDetails=$taxDetails, totalDiscount=$totalDiscount, totalTax=$totalTax, vendorAddress=$vendorAddress, vendorAddressRecipient=$vendorAddressRecipient, vendorEmail=$vendorEmail, vendorName=$vendorName, vendorTaxId=$vendorTaxId, additionalProperties=$additionalProperties}" + "DocumentCreate{allowances=$allowances, amountDue=$amountDue, attachments=$attachments, billingAddress=$billingAddress, billingAddressRecipient=$billingAddressRecipient, charges=$charges, currency=$currency, customerAddress=$customerAddress, customerAddressRecipient=$customerAddressRecipient, customerCompanyId=$customerCompanyId, customerEmail=$customerEmail, customerId=$customerId, customerName=$customerName, customerTaxId=$customerTaxId, direction=$direction, documentType=$documentType, dueDate=$dueDate, invoiceDate=$invoiceDate, invoiceId=$invoiceId, invoiceTotal=$invoiceTotal, items=$items, note=$note, paymentDetails=$paymentDetails, paymentTerm=$paymentTerm, previousUnpaidBalance=$previousUnpaidBalance, purchaseOrder=$purchaseOrder, remittanceAddress=$remittanceAddress, remittanceAddressRecipient=$remittanceAddressRecipient, serviceAddress=$serviceAddress, serviceAddressRecipient=$serviceAddressRecipient, serviceEndDate=$serviceEndDate, serviceStartDate=$serviceStartDate, shippingAddress=$shippingAddress, shippingAddressRecipient=$shippingAddressRecipient, state=$state, subtotal=$subtotal, taxCode=$taxCode, taxDetails=$taxDetails, totalDiscount=$totalDiscount, totalTax=$totalTax, vatex=$vatex, vatexNote=$vatexNote, vendorAddress=$vendorAddress, vendorAddressRecipient=$vendorAddressRecipient, vendorCompanyId=$vendorCompanyId, vendorEmail=$vendorEmail, vendorName=$vendorName, vendorTaxId=$vendorTaxId, additionalProperties=$additionalProperties}" } diff --git a/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/models/documents/DocumentCreateFromPdfParams.kt b/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/models/documents/DocumentCreateFromPdfParams.kt new file mode 100644 index 0000000..f418bfd --- /dev/null +++ b/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/models/documents/DocumentCreateFromPdfParams.kt @@ -0,0 +1,455 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.e_invoice.api.models.documents + +import com.e_invoice.api.core.ExcludeMissing +import com.e_invoice.api.core.JsonValue +import com.e_invoice.api.core.MultipartField +import com.e_invoice.api.core.Params +import com.e_invoice.api.core.checkRequired +import com.e_invoice.api.core.http.Headers +import com.e_invoice.api.core.http.QueryParams +import com.e_invoice.api.core.toImmutable +import com.e_invoice.api.errors.EInvoiceInvalidDataException +import com.fasterxml.jackson.annotation.JsonAnyGetter +import com.fasterxml.jackson.annotation.JsonAnySetter +import com.fasterxml.jackson.annotation.JsonProperty +import java.io.InputStream +import java.nio.file.Path +import java.util.Collections +import java.util.Objects +import java.util.Optional +import kotlin.io.path.inputStream +import kotlin.io.path.name +import kotlin.jvm.optionals.getOrNull + +/** + * Create a new invoice or credit note from a PDF file. If the 'ubl_document' field is set in the + * response, it indicates that sufficient details were extracted from the PDF to automatically + * generate a valid UBL document ready for sending. If 'ubl_document' is not set, human intervention + * may be required to ensure compliance. + */ +class DocumentCreateFromPdfParams +private constructor( + private val customerTaxId: String?, + private val vendorTaxId: String?, + private val body: Body, + private val additionalHeaders: Headers, + private val additionalQueryParams: QueryParams, +) : Params { + + fun customerTaxId(): Optional = Optional.ofNullable(customerTaxId) + + fun vendorTaxId(): Optional = Optional.ofNullable(vendorTaxId) + + /** + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun file(): InputStream = body.file() + + /** + * Returns the raw multipart value of [file]. + * + * Unlike [file], this method doesn't throw if the multipart field has an unexpected type. + */ + fun _file(): MultipartField = body._file() + + fun _additionalBodyProperties(): Map = body._additionalProperties() + + /** Additional headers to send with the request. */ + fun _additionalHeaders(): Headers = additionalHeaders + + /** Additional query param to send with the request. */ + fun _additionalQueryParams(): QueryParams = additionalQueryParams + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of [DocumentCreateFromPdfParams]. + * + * The following fields are required: + * ```java + * .file() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [DocumentCreateFromPdfParams]. */ + class Builder internal constructor() { + + private var customerTaxId: String? = null + private var vendorTaxId: String? = null + private var body: Body.Builder = Body.builder() + private var additionalHeaders: Headers.Builder = Headers.builder() + private var additionalQueryParams: QueryParams.Builder = QueryParams.builder() + + @JvmSynthetic + internal fun from(documentCreateFromPdfParams: DocumentCreateFromPdfParams) = apply { + customerTaxId = documentCreateFromPdfParams.customerTaxId + vendorTaxId = documentCreateFromPdfParams.vendorTaxId + body = documentCreateFromPdfParams.body.toBuilder() + additionalHeaders = documentCreateFromPdfParams.additionalHeaders.toBuilder() + additionalQueryParams = documentCreateFromPdfParams.additionalQueryParams.toBuilder() + } + + fun customerTaxId(customerTaxId: String?) = apply { this.customerTaxId = customerTaxId } + + /** Alias for calling [Builder.customerTaxId] with `customerTaxId.orElse(null)`. */ + fun customerTaxId(customerTaxId: Optional) = + customerTaxId(customerTaxId.getOrNull()) + + fun vendorTaxId(vendorTaxId: String?) = apply { this.vendorTaxId = vendorTaxId } + + /** Alias for calling [Builder.vendorTaxId] with `vendorTaxId.orElse(null)`. */ + fun vendorTaxId(vendorTaxId: Optional) = vendorTaxId(vendorTaxId.getOrNull()) + + /** + * Sets the entire request body. + * + * This is generally only useful if you are already constructing the body separately. + * Otherwise, it's more convenient to use the top-level setters instead: + * - [file] + */ + fun body(body: Body) = apply { this.body = body.toBuilder() } + + fun file(file: InputStream) = apply { body.file(file) } + + /** + * Sets [Builder.file] to an arbitrary multipart value. + * + * You should usually call [Builder.file] with a well-typed [InputStream] value instead. + * This method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun file(file: MultipartField) = apply { body.file(file) } + + fun file(file: ByteArray) = apply { body.file(file) } + + fun file(path: Path) = apply { body.file(path) } + + fun additionalBodyProperties(additionalBodyProperties: Map) = apply { + body.additionalProperties(additionalBodyProperties) + } + + fun putAdditionalBodyProperty(key: String, value: JsonValue) = apply { + body.putAdditionalProperty(key, value) + } + + fun putAllAdditionalBodyProperties(additionalBodyProperties: Map) = + apply { + body.putAllAdditionalProperties(additionalBodyProperties) + } + + fun removeAdditionalBodyProperty(key: String) = apply { body.removeAdditionalProperty(key) } + + fun removeAllAdditionalBodyProperties(keys: Set) = apply { + body.removeAllAdditionalProperties(keys) + } + + fun additionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun additionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun putAdditionalHeader(name: String, value: String) = apply { + additionalHeaders.put(name, value) + } + + fun putAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.put(name, values) + } + + fun putAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun putAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun replaceAdditionalHeaders(name: String, value: String) = apply { + additionalHeaders.replace(name, value) + } + + fun replaceAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.replace(name, values) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun removeAdditionalHeaders(name: String) = apply { additionalHeaders.remove(name) } + + fun removeAllAdditionalHeaders(names: Set) = apply { + additionalHeaders.removeAll(names) + } + + fun additionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun additionalQueryParams(additionalQueryParams: Map>) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun putAdditionalQueryParam(key: String, value: String) = apply { + additionalQueryParams.put(key, value) + } + + fun putAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.put(key, values) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun replaceAdditionalQueryParams(key: String, value: String) = apply { + additionalQueryParams.replace(key, value) + } + + fun replaceAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.replace(key, values) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun removeAdditionalQueryParams(key: String) = apply { additionalQueryParams.remove(key) } + + fun removeAllAdditionalQueryParams(keys: Set) = apply { + additionalQueryParams.removeAll(keys) + } + + /** + * Returns an immutable instance of [DocumentCreateFromPdfParams]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .file() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): DocumentCreateFromPdfParams = + DocumentCreateFromPdfParams( + customerTaxId, + vendorTaxId, + body.build(), + additionalHeaders.build(), + additionalQueryParams.build(), + ) + } + + fun _body(): Map> = + (mapOf("file" to _file()) + + _additionalBodyProperties().mapValues { (_, value) -> MultipartField.of(value) }) + .toImmutable() + + override fun _headers(): Headers = additionalHeaders + + override fun _queryParams(): QueryParams = + QueryParams.builder() + .apply { + customerTaxId?.let { put("customer_tax_id", it) } + vendorTaxId?.let { put("vendor_tax_id", it) } + putAll(additionalQueryParams) + } + .build() + + class Body + private constructor( + private val file: MultipartField, + private val additionalProperties: MutableMap, + ) { + + /** + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun file(): InputStream = file.value.getRequired("file") + + /** + * Returns the raw multipart value of [file]. + * + * Unlike [file], this method doesn't throw if the multipart field has an unexpected type. + */ + @JsonProperty("file") @ExcludeMissing fun _file(): MultipartField = file + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of [Body]. + * + * The following fields are required: + * ```java + * .file() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [Body]. */ + class Builder internal constructor() { + + private var file: MultipartField? = null + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(body: Body) = apply { + file = body.file + additionalProperties = body.additionalProperties.toMutableMap() + } + + fun file(file: InputStream) = file(MultipartField.of(file)) + + /** + * Sets [Builder.file] to an arbitrary multipart value. + * + * You should usually call [Builder.file] with a well-typed [InputStream] value instead. + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun file(file: MultipartField) = apply { this.file = file } + + fun file(file: ByteArray) = file(file.inputStream()) + + fun file(path: Path) = + file( + MultipartField.builder() + .value(path.inputStream()) + .filename(path.name) + .build() + ) + + fun additionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.clear() + putAllAdditionalProperties(additionalProperties) + } + + fun putAdditionalProperty(key: String, value: JsonValue) = apply { + additionalProperties.put(key, value) + } + + fun putAllAdditionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.putAll(additionalProperties) + } + + fun removeAdditionalProperty(key: String) = apply { additionalProperties.remove(key) } + + fun removeAllAdditionalProperties(keys: Set) = apply { + keys.forEach(::removeAdditionalProperty) + } + + /** + * Returns an immutable instance of [Body]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .file() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): Body = + Body(checkRequired("file", file), additionalProperties.toMutableMap()) + } + + private var validated: Boolean = false + + fun validate(): Body = apply { + if (validated) { + return@apply + } + + file() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: EInvoiceInvalidDataException) { + false + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Body && + file == other.file && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { Objects.hash(file, additionalProperties) } + + override fun hashCode(): Int = hashCode + + override fun toString() = "Body{file=$file, additionalProperties=$additionalProperties}" + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is DocumentCreateFromPdfParams && + customerTaxId == other.customerTaxId && + vendorTaxId == other.vendorTaxId && + body == other.body && + additionalHeaders == other.additionalHeaders && + additionalQueryParams == other.additionalQueryParams + } + + override fun hashCode(): Int = + Objects.hash(customerTaxId, vendorTaxId, body, additionalHeaders, additionalQueryParams) + + override fun toString() = + "DocumentCreateFromPdfParams{customerTaxId=$customerTaxId, vendorTaxId=$vendorTaxId, body=$body, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams}" +} diff --git a/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/models/documents/DocumentCreateFromPdfResponse.kt b/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/models/documents/DocumentCreateFromPdfResponse.kt new file mode 100644 index 0000000..51fa325 --- /dev/null +++ b/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/models/documents/DocumentCreateFromPdfResponse.kt @@ -0,0 +1,3927 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.e_invoice.api.models.documents + +import com.e_invoice.api.core.Enum +import com.e_invoice.api.core.ExcludeMissing +import com.e_invoice.api.core.JsonField +import com.e_invoice.api.core.JsonMissing +import com.e_invoice.api.core.JsonValue +import com.e_invoice.api.core.checkKnown +import com.e_invoice.api.core.toImmutable +import com.e_invoice.api.errors.EInvoiceInvalidDataException +import com.e_invoice.api.models.inbox.DocumentState +import com.fasterxml.jackson.annotation.JsonAnyGetter +import com.fasterxml.jackson.annotation.JsonAnySetter +import com.fasterxml.jackson.annotation.JsonCreator +import com.fasterxml.jackson.annotation.JsonProperty +import java.time.LocalDate +import java.util.Collections +import java.util.Objects +import java.util.Optional +import kotlin.jvm.optionals.getOrNull + +class DocumentCreateFromPdfResponse +@JsonCreator(mode = JsonCreator.Mode.DISABLED) +private constructor( + private val allowances: JsonField>, + private val amountDue: JsonField, + private val attachments: JsonField>, + private val billingAddress: JsonField, + private val billingAddressRecipient: JsonField, + private val charges: JsonField>, + private val currency: JsonField, + private val customerAddress: JsonField, + private val customerAddressRecipient: JsonField, + private val customerCompanyId: JsonField, + private val customerEmail: JsonField, + private val customerId: JsonField, + private val customerName: JsonField, + private val customerTaxId: JsonField, + private val direction: JsonField, + private val documentType: JsonField, + private val dueDate: JsonField, + private val invoiceDate: JsonField, + private val invoiceId: JsonField, + private val invoiceTotal: JsonField, + private val items: JsonField>, + private val note: JsonField, + private val paymentDetails: JsonField>, + private val paymentTerm: JsonField, + private val purchaseOrder: JsonField, + private val remittanceAddress: JsonField, + private val remittanceAddressRecipient: JsonField, + private val serviceAddress: JsonField, + private val serviceAddressRecipient: JsonField, + private val serviceEndDate: JsonField, + private val serviceStartDate: JsonField, + private val shippingAddress: JsonField, + private val shippingAddressRecipient: JsonField, + private val state: JsonField, + private val subtotal: JsonField, + private val success: JsonField, + private val taxCode: JsonField, + private val taxDetails: JsonField>, + private val totalDiscount: JsonField, + private val totalTax: JsonField, + private val ublDocument: JsonField, + private val vatex: JsonField, + private val vatexNote: JsonField, + private val vendorAddress: JsonField, + private val vendorAddressRecipient: JsonField, + private val vendorCompanyId: JsonField, + private val vendorEmail: JsonField, + private val vendorName: JsonField, + private val vendorTaxId: JsonField, + private val additionalProperties: MutableMap, +) { + + @JsonCreator + private constructor( + @JsonProperty("allowances") + @ExcludeMissing + allowances: JsonField> = JsonMissing.of(), + @JsonProperty("amount_due") @ExcludeMissing amountDue: JsonField = JsonMissing.of(), + @JsonProperty("attachments") + @ExcludeMissing + attachments: JsonField> = JsonMissing.of(), + @JsonProperty("billing_address") + @ExcludeMissing + billingAddress: JsonField = JsonMissing.of(), + @JsonProperty("billing_address_recipient") + @ExcludeMissing + billingAddressRecipient: JsonField = JsonMissing.of(), + @JsonProperty("charges") + @ExcludeMissing + charges: JsonField> = JsonMissing.of(), + @JsonProperty("currency") + @ExcludeMissing + currency: JsonField = JsonMissing.of(), + @JsonProperty("customer_address") + @ExcludeMissing + customerAddress: JsonField = JsonMissing.of(), + @JsonProperty("customer_address_recipient") + @ExcludeMissing + customerAddressRecipient: JsonField = JsonMissing.of(), + @JsonProperty("customer_company_id") + @ExcludeMissing + customerCompanyId: JsonField = JsonMissing.of(), + @JsonProperty("customer_email") + @ExcludeMissing + customerEmail: JsonField = JsonMissing.of(), + @JsonProperty("customer_id") + @ExcludeMissing + customerId: JsonField = JsonMissing.of(), + @JsonProperty("customer_name") + @ExcludeMissing + customerName: JsonField = JsonMissing.of(), + @JsonProperty("customer_tax_id") + @ExcludeMissing + customerTaxId: JsonField = JsonMissing.of(), + @JsonProperty("direction") + @ExcludeMissing + direction: JsonField = JsonMissing.of(), + @JsonProperty("document_type") + @ExcludeMissing + documentType: JsonField = JsonMissing.of(), + @JsonProperty("due_date") @ExcludeMissing dueDate: JsonField = JsonMissing.of(), + @JsonProperty("invoice_date") + @ExcludeMissing + invoiceDate: JsonField = JsonMissing.of(), + @JsonProperty("invoice_id") @ExcludeMissing invoiceId: JsonField = JsonMissing.of(), + @JsonProperty("invoice_total") + @ExcludeMissing + invoiceTotal: JsonField = JsonMissing.of(), + @JsonProperty("items") @ExcludeMissing items: JsonField> = JsonMissing.of(), + @JsonProperty("note") @ExcludeMissing note: JsonField = JsonMissing.of(), + @JsonProperty("payment_details") + @ExcludeMissing + paymentDetails: JsonField> = JsonMissing.of(), + @JsonProperty("payment_term") + @ExcludeMissing + paymentTerm: JsonField = JsonMissing.of(), + @JsonProperty("purchase_order") + @ExcludeMissing + purchaseOrder: JsonField = JsonMissing.of(), + @JsonProperty("remittance_address") + @ExcludeMissing + remittanceAddress: JsonField = JsonMissing.of(), + @JsonProperty("remittance_address_recipient") + @ExcludeMissing + remittanceAddressRecipient: JsonField = JsonMissing.of(), + @JsonProperty("service_address") + @ExcludeMissing + serviceAddress: JsonField = JsonMissing.of(), + @JsonProperty("service_address_recipient") + @ExcludeMissing + serviceAddressRecipient: JsonField = JsonMissing.of(), + @JsonProperty("service_end_date") + @ExcludeMissing + serviceEndDate: JsonField = JsonMissing.of(), + @JsonProperty("service_start_date") + @ExcludeMissing + serviceStartDate: JsonField = JsonMissing.of(), + @JsonProperty("shipping_address") + @ExcludeMissing + shippingAddress: JsonField = JsonMissing.of(), + @JsonProperty("shipping_address_recipient") + @ExcludeMissing + shippingAddressRecipient: JsonField = JsonMissing.of(), + @JsonProperty("state") @ExcludeMissing state: JsonField = JsonMissing.of(), + @JsonProperty("subtotal") @ExcludeMissing subtotal: JsonField = JsonMissing.of(), + @JsonProperty("success") @ExcludeMissing success: JsonField = JsonMissing.of(), + @JsonProperty("tax_code") @ExcludeMissing taxCode: JsonField = JsonMissing.of(), + @JsonProperty("tax_details") + @ExcludeMissing + taxDetails: JsonField> = JsonMissing.of(), + @JsonProperty("total_discount") + @ExcludeMissing + totalDiscount: JsonField = JsonMissing.of(), + @JsonProperty("total_tax") @ExcludeMissing totalTax: JsonField = JsonMissing.of(), + @JsonProperty("ubl_document") + @ExcludeMissing + ublDocument: JsonField = JsonMissing.of(), + @JsonProperty("vatex") @ExcludeMissing vatex: JsonField = JsonMissing.of(), + @JsonProperty("vatex_note") @ExcludeMissing vatexNote: JsonField = JsonMissing.of(), + @JsonProperty("vendor_address") + @ExcludeMissing + vendorAddress: JsonField = JsonMissing.of(), + @JsonProperty("vendor_address_recipient") + @ExcludeMissing + vendorAddressRecipient: JsonField = JsonMissing.of(), + @JsonProperty("vendor_company_id") + @ExcludeMissing + vendorCompanyId: JsonField = JsonMissing.of(), + @JsonProperty("vendor_email") + @ExcludeMissing + vendorEmail: JsonField = JsonMissing.of(), + @JsonProperty("vendor_name") + @ExcludeMissing + vendorName: JsonField = JsonMissing.of(), + @JsonProperty("vendor_tax_id") + @ExcludeMissing + vendorTaxId: JsonField = JsonMissing.of(), + ) : this( + allowances, + amountDue, + attachments, + billingAddress, + billingAddressRecipient, + charges, + currency, + customerAddress, + customerAddressRecipient, + customerCompanyId, + customerEmail, + customerId, + customerName, + customerTaxId, + direction, + documentType, + dueDate, + invoiceDate, + invoiceId, + invoiceTotal, + items, + note, + paymentDetails, + paymentTerm, + purchaseOrder, + remittanceAddress, + remittanceAddressRecipient, + serviceAddress, + serviceAddressRecipient, + serviceEndDate, + serviceStartDate, + shippingAddress, + shippingAddressRecipient, + state, + subtotal, + success, + taxCode, + taxDetails, + totalDiscount, + totalTax, + ublDocument, + vatex, + vatexNote, + vendorAddress, + vendorAddressRecipient, + vendorCompanyId, + vendorEmail, + vendorName, + vendorTaxId, + mutableMapOf(), + ) + + /** + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun allowances(): Optional> = allowances.getOptional("allowances") + + /** + * The amount due for payment. Must be positive and rounded to maximum 2 decimals + * + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun amountDue(): Optional = amountDue.getOptional("amount_due") + + /** + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun attachments(): Optional> = + attachments.getOptional("attachments") + + /** + * The billing address (if different from customer address) + * + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun billingAddress(): Optional = billingAddress.getOptional("billing_address") + + /** + * The recipient name at the billing address + * + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun billingAddressRecipient(): Optional = + billingAddressRecipient.getOptional("billing_address_recipient") + + /** + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun charges(): Optional> = charges.getOptional("charges") + + /** + * Currency of the invoice (ISO 4217 currency code) + * + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun currency(): Optional = currency.getOptional("currency") + + /** + * The address of the customer/buyer + * + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun customerAddress(): Optional = customerAddress.getOptional("customer_address") + + /** + * The recipient name at the customer address + * + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun customerAddressRecipient(): Optional = + customerAddressRecipient.getOptional("customer_address_recipient") + + /** + * Customer company ID. For Belgium this is the CBE number or their EUID (European Unique + * Identifier) number. In the Netherlands this is the KVK number. + * + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun customerCompanyId(): Optional = customerCompanyId.getOptional("customer_company_id") + + /** + * The email address of the customer + * + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun customerEmail(): Optional = customerEmail.getOptional("customer_email") + + /** + * The unique identifier for the customer in your system + * + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun customerId(): Optional = customerId.getOptional("customer_id") + + /** + * The company name of the customer/buyer + * + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun customerName(): Optional = customerName.getOptional("customer_name") + + /** + * Customer tax ID. For Belgium this is the VAT number. Must include the country prefix + * + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun customerTaxId(): Optional = customerTaxId.getOptional("customer_tax_id") + + /** + * The direction of the document: INBOUND (purchases) or OUTBOUND (sales) + * + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun direction(): Optional = direction.getOptional("direction") + + /** + * The type of document: INVOICE, CREDIT_NOTE, or DEBIT_NOTE + * + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun documentType(): Optional = documentType.getOptional("document_type") + + /** + * The date when payment is due + * + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun dueDate(): Optional = dueDate.getOptional("due_date") + + /** + * The date when the invoice was issued + * + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun invoiceDate(): Optional = invoiceDate.getOptional("invoice_date") + + /** + * The unique invoice identifier/number + * + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun invoiceId(): Optional = invoiceId.getOptional("invoice_id") + + /** + * The total amount of the invoice including tax (invoice_total = subtotal + total_tax + + * total_discount). Must be positive and rounded to maximum 2 decimals + * + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun invoiceTotal(): Optional = invoiceTotal.getOptional("invoice_total") + + /** + * At least one line item is required + * + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun items(): Optional> = items.getOptional("items") + + /** + * Additional notes or comments for the invoice + * + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun note(): Optional = note.getOptional("note") + + /** + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun paymentDetails(): Optional> = + paymentDetails.getOptional("payment_details") + + /** + * The payment terms (e.g., 'Net 30', 'Due on receipt', '2/10 Net 30') + * + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun paymentTerm(): Optional = paymentTerm.getOptional("payment_term") + + /** + * The purchase order reference number + * + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun purchaseOrder(): Optional = purchaseOrder.getOptional("purchase_order") + + /** + * The address where payment should be sent or remitted to + * + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun remittanceAddress(): Optional = remittanceAddress.getOptional("remittance_address") + + /** + * The recipient name at the remittance address + * + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun remittanceAddressRecipient(): Optional = + remittanceAddressRecipient.getOptional("remittance_address_recipient") + + /** + * The address where services were performed or goods were delivered + * + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun serviceAddress(): Optional = serviceAddress.getOptional("service_address") + + /** + * The recipient name at the service address + * + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun serviceAddressRecipient(): Optional = + serviceAddressRecipient.getOptional("service_address_recipient") + + /** + * The end date of the service period or delivery period + * + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun serviceEndDate(): Optional = serviceEndDate.getOptional("service_end_date") + + /** + * The start date of the service period or delivery period + * + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun serviceStartDate(): Optional = serviceStartDate.getOptional("service_start_date") + + /** + * The shipping/delivery address + * + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun shippingAddress(): Optional = shippingAddress.getOptional("shipping_address") + + /** + * The recipient name at the shipping address + * + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun shippingAddressRecipient(): Optional = + shippingAddressRecipient.getOptional("shipping_address_recipient") + + /** + * The current state of the document: DRAFT, TRANSIT, FAILED, SENT, or RECEIVED + * + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun state(): Optional = state.getOptional("state") + + /** + * The taxable base of the invoice. Should be the sum of all line items - allowances (for + * example commercial discounts) + charges with impact on VAT. Must be positive and rounded to + * maximum 2 decimals + * + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun subtotal(): Optional = subtotal.getOptional("subtotal") + + /** + * Whether the PDF was successfully converted into a compliant e-invoice + * + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun success(): Optional = success.getOptional("success") + + /** + * Tax category code of the invoice (e.g., S for standard rate, Z for zero rate, E for exempt) + * + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun taxCode(): Optional = taxCode.getOptional("tax_code") + + /** + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun taxDetails(): Optional> = taxDetails.getOptional("tax_details") + + /** + * The net financial discount/charge of the invoice (non-VAT charges minus non-VAT allowances). + * Can be positive (net charge), negative (net discount), or zero. Must be rounded to maximum 2 + * decimals + * + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun totalDiscount(): Optional = totalDiscount.getOptional("total_discount") + + /** + * The total tax amount of the invoice. Must be positive and rounded to maximum 2 decimals + * + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun totalTax(): Optional = totalTax.getOptional("total_tax") + + /** + * The UBL document as an XML string + * + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun ublDocument(): Optional = ublDocument.getOptional("ubl_document") + + /** + * VATEX code list for VAT exemption reasons + * + * Agency: CEF Identifier: vatex + * + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun vatex(): Optional = vatex.getOptional("vatex") + + /** + * Textual explanation for VAT exemption + * + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun vatexNote(): Optional = vatexNote.getOptional("vatex_note") + + /** + * The address of the vendor/seller + * + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun vendorAddress(): Optional = vendorAddress.getOptional("vendor_address") + + /** + * The recipient name at the vendor address + * + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun vendorAddressRecipient(): Optional = + vendorAddressRecipient.getOptional("vendor_address_recipient") + + /** + * Vendor company ID. For Belgium this is the CBE number or their EUID (European Unique + * Identifier) number. In the Netherlands this is the KVK number. + * + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun vendorCompanyId(): Optional = vendorCompanyId.getOptional("vendor_company_id") + + /** + * The email address of the vendor + * + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun vendorEmail(): Optional = vendorEmail.getOptional("vendor_email") + + /** + * The name of the vendor/seller/supplier + * + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun vendorName(): Optional = vendorName.getOptional("vendor_name") + + /** + * Vendor tax ID. For Belgium this is the VAT number. Must include the country prefix + * + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun vendorTaxId(): Optional = vendorTaxId.getOptional("vendor_tax_id") + + /** + * Returns the raw JSON value of [allowances]. + * + * Unlike [allowances], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("allowances") + @ExcludeMissing + fun _allowances(): JsonField> = allowances + + /** + * Returns the raw JSON value of [amountDue]. + * + * Unlike [amountDue], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("amount_due") @ExcludeMissing fun _amountDue(): JsonField = amountDue + + /** + * Returns the raw JSON value of [attachments]. + * + * Unlike [attachments], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("attachments") + @ExcludeMissing + fun _attachments(): JsonField> = attachments + + /** + * Returns the raw JSON value of [billingAddress]. + * + * Unlike [billingAddress], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("billing_address") + @ExcludeMissing + fun _billingAddress(): JsonField = billingAddress + + /** + * Returns the raw JSON value of [billingAddressRecipient]. + * + * Unlike [billingAddressRecipient], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("billing_address_recipient") + @ExcludeMissing + fun _billingAddressRecipient(): JsonField = billingAddressRecipient + + /** + * Returns the raw JSON value of [charges]. + * + * Unlike [charges], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("charges") @ExcludeMissing fun _charges(): JsonField> = charges + + /** + * Returns the raw JSON value of [currency]. + * + * Unlike [currency], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("currency") @ExcludeMissing fun _currency(): JsonField = currency + + /** + * Returns the raw JSON value of [customerAddress]. + * + * Unlike [customerAddress], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("customer_address") + @ExcludeMissing + fun _customerAddress(): JsonField = customerAddress + + /** + * Returns the raw JSON value of [customerAddressRecipient]. + * + * Unlike [customerAddressRecipient], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("customer_address_recipient") + @ExcludeMissing + fun _customerAddressRecipient(): JsonField = customerAddressRecipient + + /** + * Returns the raw JSON value of [customerCompanyId]. + * + * Unlike [customerCompanyId], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("customer_company_id") + @ExcludeMissing + fun _customerCompanyId(): JsonField = customerCompanyId + + /** + * Returns the raw JSON value of [customerEmail]. + * + * Unlike [customerEmail], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("customer_email") + @ExcludeMissing + fun _customerEmail(): JsonField = customerEmail + + /** + * Returns the raw JSON value of [customerId]. + * + * Unlike [customerId], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("customer_id") @ExcludeMissing fun _customerId(): JsonField = customerId + + /** + * Returns the raw JSON value of [customerName]. + * + * Unlike [customerName], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("customer_name") + @ExcludeMissing + fun _customerName(): JsonField = customerName + + /** + * Returns the raw JSON value of [customerTaxId]. + * + * Unlike [customerTaxId], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("customer_tax_id") + @ExcludeMissing + fun _customerTaxId(): JsonField = customerTaxId + + /** + * Returns the raw JSON value of [direction]. + * + * Unlike [direction], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("direction") + @ExcludeMissing + fun _direction(): JsonField = direction + + /** + * Returns the raw JSON value of [documentType]. + * + * Unlike [documentType], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("document_type") + @ExcludeMissing + fun _documentType(): JsonField = documentType + + /** + * Returns the raw JSON value of [dueDate]. + * + * Unlike [dueDate], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("due_date") @ExcludeMissing fun _dueDate(): JsonField = dueDate + + /** + * Returns the raw JSON value of [invoiceDate]. + * + * Unlike [invoiceDate], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("invoice_date") + @ExcludeMissing + fun _invoiceDate(): JsonField = invoiceDate + + /** + * Returns the raw JSON value of [invoiceId]. + * + * Unlike [invoiceId], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("invoice_id") @ExcludeMissing fun _invoiceId(): JsonField = invoiceId + + /** + * Returns the raw JSON value of [invoiceTotal]. + * + * Unlike [invoiceTotal], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("invoice_total") + @ExcludeMissing + fun _invoiceTotal(): JsonField = invoiceTotal + + /** + * Returns the raw JSON value of [items]. + * + * Unlike [items], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("items") @ExcludeMissing fun _items(): JsonField> = items + + /** + * Returns the raw JSON value of [note]. + * + * Unlike [note], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("note") @ExcludeMissing fun _note(): JsonField = note + + /** + * Returns the raw JSON value of [paymentDetails]. + * + * Unlike [paymentDetails], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("payment_details") + @ExcludeMissing + fun _paymentDetails(): JsonField> = paymentDetails + + /** + * Returns the raw JSON value of [paymentTerm]. + * + * Unlike [paymentTerm], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("payment_term") + @ExcludeMissing + fun _paymentTerm(): JsonField = paymentTerm + + /** + * Returns the raw JSON value of [purchaseOrder]. + * + * Unlike [purchaseOrder], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("purchase_order") + @ExcludeMissing + fun _purchaseOrder(): JsonField = purchaseOrder + + /** + * Returns the raw JSON value of [remittanceAddress]. + * + * Unlike [remittanceAddress], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("remittance_address") + @ExcludeMissing + fun _remittanceAddress(): JsonField = remittanceAddress + + /** + * Returns the raw JSON value of [remittanceAddressRecipient]. + * + * Unlike [remittanceAddressRecipient], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("remittance_address_recipient") + @ExcludeMissing + fun _remittanceAddressRecipient(): JsonField = remittanceAddressRecipient + + /** + * Returns the raw JSON value of [serviceAddress]. + * + * Unlike [serviceAddress], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("service_address") + @ExcludeMissing + fun _serviceAddress(): JsonField = serviceAddress + + /** + * Returns the raw JSON value of [serviceAddressRecipient]. + * + * Unlike [serviceAddressRecipient], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("service_address_recipient") + @ExcludeMissing + fun _serviceAddressRecipient(): JsonField = serviceAddressRecipient + + /** + * Returns the raw JSON value of [serviceEndDate]. + * + * Unlike [serviceEndDate], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("service_end_date") + @ExcludeMissing + fun _serviceEndDate(): JsonField = serviceEndDate + + /** + * Returns the raw JSON value of [serviceStartDate]. + * + * Unlike [serviceStartDate], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("service_start_date") + @ExcludeMissing + fun _serviceStartDate(): JsonField = serviceStartDate + + /** + * Returns the raw JSON value of [shippingAddress]. + * + * Unlike [shippingAddress], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("shipping_address") + @ExcludeMissing + fun _shippingAddress(): JsonField = shippingAddress + + /** + * Returns the raw JSON value of [shippingAddressRecipient]. + * + * Unlike [shippingAddressRecipient], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("shipping_address_recipient") + @ExcludeMissing + fun _shippingAddressRecipient(): JsonField = shippingAddressRecipient + + /** + * Returns the raw JSON value of [state]. + * + * Unlike [state], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("state") @ExcludeMissing fun _state(): JsonField = state + + /** + * Returns the raw JSON value of [subtotal]. + * + * Unlike [subtotal], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("subtotal") @ExcludeMissing fun _subtotal(): JsonField = subtotal + + /** + * Returns the raw JSON value of [success]. + * + * Unlike [success], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("success") @ExcludeMissing fun _success(): JsonField = success + + /** + * Returns the raw JSON value of [taxCode]. + * + * Unlike [taxCode], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("tax_code") @ExcludeMissing fun _taxCode(): JsonField = taxCode + + /** + * Returns the raw JSON value of [taxDetails]. + * + * Unlike [taxDetails], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("tax_details") + @ExcludeMissing + fun _taxDetails(): JsonField> = taxDetails + + /** + * Returns the raw JSON value of [totalDiscount]. + * + * Unlike [totalDiscount], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("total_discount") + @ExcludeMissing + fun _totalDiscount(): JsonField = totalDiscount + + /** + * Returns the raw JSON value of [totalTax]. + * + * Unlike [totalTax], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("total_tax") @ExcludeMissing fun _totalTax(): JsonField = totalTax + + /** + * Returns the raw JSON value of [ublDocument]. + * + * Unlike [ublDocument], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("ubl_document") + @ExcludeMissing + fun _ublDocument(): JsonField = ublDocument + + /** + * Returns the raw JSON value of [vatex]. + * + * Unlike [vatex], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("vatex") @ExcludeMissing fun _vatex(): JsonField = vatex + + /** + * Returns the raw JSON value of [vatexNote]. + * + * Unlike [vatexNote], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("vatex_note") @ExcludeMissing fun _vatexNote(): JsonField = vatexNote + + /** + * Returns the raw JSON value of [vendorAddress]. + * + * Unlike [vendorAddress], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("vendor_address") + @ExcludeMissing + fun _vendorAddress(): JsonField = vendorAddress + + /** + * Returns the raw JSON value of [vendorAddressRecipient]. + * + * Unlike [vendorAddressRecipient], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("vendor_address_recipient") + @ExcludeMissing + fun _vendorAddressRecipient(): JsonField = vendorAddressRecipient + + /** + * Returns the raw JSON value of [vendorCompanyId]. + * + * Unlike [vendorCompanyId], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("vendor_company_id") + @ExcludeMissing + fun _vendorCompanyId(): JsonField = vendorCompanyId + + /** + * Returns the raw JSON value of [vendorEmail]. + * + * Unlike [vendorEmail], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("vendor_email") + @ExcludeMissing + fun _vendorEmail(): JsonField = vendorEmail + + /** + * Returns the raw JSON value of [vendorName]. + * + * Unlike [vendorName], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("vendor_name") @ExcludeMissing fun _vendorName(): JsonField = vendorName + + /** + * Returns the raw JSON value of [vendorTaxId]. + * + * Unlike [vendorTaxId], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("vendor_tax_id") + @ExcludeMissing + fun _vendorTaxId(): JsonField = vendorTaxId + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of + * [DocumentCreateFromPdfResponse]. + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [DocumentCreateFromPdfResponse]. */ + class Builder internal constructor() { + + private var allowances: JsonField>? = null + private var amountDue: JsonField = JsonMissing.of() + private var attachments: JsonField>? = null + private var billingAddress: JsonField = JsonMissing.of() + private var billingAddressRecipient: JsonField = JsonMissing.of() + private var charges: JsonField>? = null + private var currency: JsonField = JsonMissing.of() + private var customerAddress: JsonField = JsonMissing.of() + private var customerAddressRecipient: JsonField = JsonMissing.of() + private var customerCompanyId: JsonField = JsonMissing.of() + private var customerEmail: JsonField = JsonMissing.of() + private var customerId: JsonField = JsonMissing.of() + private var customerName: JsonField = JsonMissing.of() + private var customerTaxId: JsonField = JsonMissing.of() + private var direction: JsonField = JsonMissing.of() + private var documentType: JsonField = JsonMissing.of() + private var dueDate: JsonField = JsonMissing.of() + private var invoiceDate: JsonField = JsonMissing.of() + private var invoiceId: JsonField = JsonMissing.of() + private var invoiceTotal: JsonField = JsonMissing.of() + private var items: JsonField>? = null + private var note: JsonField = JsonMissing.of() + private var paymentDetails: JsonField>? = null + private var paymentTerm: JsonField = JsonMissing.of() + private var purchaseOrder: JsonField = JsonMissing.of() + private var remittanceAddress: JsonField = JsonMissing.of() + private var remittanceAddressRecipient: JsonField = JsonMissing.of() + private var serviceAddress: JsonField = JsonMissing.of() + private var serviceAddressRecipient: JsonField = JsonMissing.of() + private var serviceEndDate: JsonField = JsonMissing.of() + private var serviceStartDate: JsonField = JsonMissing.of() + private var shippingAddress: JsonField = JsonMissing.of() + private var shippingAddressRecipient: JsonField = JsonMissing.of() + private var state: JsonField = JsonMissing.of() + private var subtotal: JsonField = JsonMissing.of() + private var success: JsonField = JsonMissing.of() + private var taxCode: JsonField = JsonMissing.of() + private var taxDetails: JsonField>? = null + private var totalDiscount: JsonField = JsonMissing.of() + private var totalTax: JsonField = JsonMissing.of() + private var ublDocument: JsonField = JsonMissing.of() + private var vatex: JsonField = JsonMissing.of() + private var vatexNote: JsonField = JsonMissing.of() + private var vendorAddress: JsonField = JsonMissing.of() + private var vendorAddressRecipient: JsonField = JsonMissing.of() + private var vendorCompanyId: JsonField = JsonMissing.of() + private var vendorEmail: JsonField = JsonMissing.of() + private var vendorName: JsonField = JsonMissing.of() + private var vendorTaxId: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(documentCreateFromPdfResponse: DocumentCreateFromPdfResponse) = apply { + allowances = documentCreateFromPdfResponse.allowances.map { it.toMutableList() } + amountDue = documentCreateFromPdfResponse.amountDue + attachments = documentCreateFromPdfResponse.attachments.map { it.toMutableList() } + billingAddress = documentCreateFromPdfResponse.billingAddress + billingAddressRecipient = documentCreateFromPdfResponse.billingAddressRecipient + charges = documentCreateFromPdfResponse.charges.map { it.toMutableList() } + currency = documentCreateFromPdfResponse.currency + customerAddress = documentCreateFromPdfResponse.customerAddress + customerAddressRecipient = documentCreateFromPdfResponse.customerAddressRecipient + customerCompanyId = documentCreateFromPdfResponse.customerCompanyId + customerEmail = documentCreateFromPdfResponse.customerEmail + customerId = documentCreateFromPdfResponse.customerId + customerName = documentCreateFromPdfResponse.customerName + customerTaxId = documentCreateFromPdfResponse.customerTaxId + direction = documentCreateFromPdfResponse.direction + documentType = documentCreateFromPdfResponse.documentType + dueDate = documentCreateFromPdfResponse.dueDate + invoiceDate = documentCreateFromPdfResponse.invoiceDate + invoiceId = documentCreateFromPdfResponse.invoiceId + invoiceTotal = documentCreateFromPdfResponse.invoiceTotal + items = documentCreateFromPdfResponse.items.map { it.toMutableList() } + note = documentCreateFromPdfResponse.note + paymentDetails = documentCreateFromPdfResponse.paymentDetails.map { it.toMutableList() } + paymentTerm = documentCreateFromPdfResponse.paymentTerm + purchaseOrder = documentCreateFromPdfResponse.purchaseOrder + remittanceAddress = documentCreateFromPdfResponse.remittanceAddress + remittanceAddressRecipient = documentCreateFromPdfResponse.remittanceAddressRecipient + serviceAddress = documentCreateFromPdfResponse.serviceAddress + serviceAddressRecipient = documentCreateFromPdfResponse.serviceAddressRecipient + serviceEndDate = documentCreateFromPdfResponse.serviceEndDate + serviceStartDate = documentCreateFromPdfResponse.serviceStartDate + shippingAddress = documentCreateFromPdfResponse.shippingAddress + shippingAddressRecipient = documentCreateFromPdfResponse.shippingAddressRecipient + state = documentCreateFromPdfResponse.state + subtotal = documentCreateFromPdfResponse.subtotal + success = documentCreateFromPdfResponse.success + taxCode = documentCreateFromPdfResponse.taxCode + taxDetails = documentCreateFromPdfResponse.taxDetails.map { it.toMutableList() } + totalDiscount = documentCreateFromPdfResponse.totalDiscount + totalTax = documentCreateFromPdfResponse.totalTax + ublDocument = documentCreateFromPdfResponse.ublDocument + vatex = documentCreateFromPdfResponse.vatex + vatexNote = documentCreateFromPdfResponse.vatexNote + vendorAddress = documentCreateFromPdfResponse.vendorAddress + vendorAddressRecipient = documentCreateFromPdfResponse.vendorAddressRecipient + vendorCompanyId = documentCreateFromPdfResponse.vendorCompanyId + vendorEmail = documentCreateFromPdfResponse.vendorEmail + vendorName = documentCreateFromPdfResponse.vendorName + vendorTaxId = documentCreateFromPdfResponse.vendorTaxId + additionalProperties = documentCreateFromPdfResponse.additionalProperties.toMutableMap() + } + + fun allowances(allowances: List?) = allowances(JsonField.ofNullable(allowances)) + + /** Alias for calling [Builder.allowances] with `allowances.orElse(null)`. */ + fun allowances(allowances: Optional>) = allowances(allowances.getOrNull()) + + /** + * Sets [Builder.allowances] to an arbitrary JSON value. + * + * You should usually call [Builder.allowances] with a well-typed `List` value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun allowances(allowances: JsonField>) = apply { + this.allowances = allowances.map { it.toMutableList() } + } + + /** + * Adds a single [Allowance] to [allowances]. + * + * @throws IllegalStateException if the field was previously set to a non-list. + */ + fun addAllowance(allowance: Allowance) = apply { + allowances = + (allowances ?: JsonField.of(mutableListOf())).also { + checkKnown("allowances", it).add(allowance) + } + } + + /** The amount due for payment. Must be positive and rounded to maximum 2 decimals */ + fun amountDue(amountDue: String?) = amountDue(JsonField.ofNullable(amountDue)) + + /** Alias for calling [Builder.amountDue] with `amountDue.orElse(null)`. */ + fun amountDue(amountDue: Optional) = amountDue(amountDue.getOrNull()) + + /** + * Sets [Builder.amountDue] to an arbitrary JSON value. + * + * You should usually call [Builder.amountDue] with a well-typed [String] value instead. + * This method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun amountDue(amountDue: JsonField) = apply { this.amountDue = amountDue } + + fun attachments(attachments: List?) = + attachments(JsonField.ofNullable(attachments)) + + /** Alias for calling [Builder.attachments] with `attachments.orElse(null)`. */ + fun attachments(attachments: Optional>) = + attachments(attachments.getOrNull()) + + /** + * Sets [Builder.attachments] to an arbitrary JSON value. + * + * You should usually call [Builder.attachments] with a well-typed + * `List` value instead. This method is primarily for setting the + * field to an undocumented or not yet supported value. + */ + fun attachments(attachments: JsonField>) = apply { + this.attachments = attachments.map { it.toMutableList() } + } + + /** + * Adds a single [DocumentAttachmentCreate] to [attachments]. + * + * @throws IllegalStateException if the field was previously set to a non-list. + */ + fun addAttachment(attachment: DocumentAttachmentCreate) = apply { + attachments = + (attachments ?: JsonField.of(mutableListOf())).also { + checkKnown("attachments", it).add(attachment) + } + } + + /** The billing address (if different from customer address) */ + fun billingAddress(billingAddress: String?) = + billingAddress(JsonField.ofNullable(billingAddress)) + + /** Alias for calling [Builder.billingAddress] with `billingAddress.orElse(null)`. */ + fun billingAddress(billingAddress: Optional) = + billingAddress(billingAddress.getOrNull()) + + /** + * Sets [Builder.billingAddress] to an arbitrary JSON value. + * + * You should usually call [Builder.billingAddress] with a well-typed [String] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun billingAddress(billingAddress: JsonField) = apply { + this.billingAddress = billingAddress + } + + /** The recipient name at the billing address */ + fun billingAddressRecipient(billingAddressRecipient: String?) = + billingAddressRecipient(JsonField.ofNullable(billingAddressRecipient)) + + /** + * Alias for calling [Builder.billingAddressRecipient] with + * `billingAddressRecipient.orElse(null)`. + */ + fun billingAddressRecipient(billingAddressRecipient: Optional) = + billingAddressRecipient(billingAddressRecipient.getOrNull()) + + /** + * Sets [Builder.billingAddressRecipient] to an arbitrary JSON value. + * + * You should usually call [Builder.billingAddressRecipient] with a well-typed [String] + * value instead. This method is primarily for setting the field to an undocumented or not + * yet supported value. + */ + fun billingAddressRecipient(billingAddressRecipient: JsonField) = apply { + this.billingAddressRecipient = billingAddressRecipient + } + + fun charges(charges: List?) = charges(JsonField.ofNullable(charges)) + + /** Alias for calling [Builder.charges] with `charges.orElse(null)`. */ + fun charges(charges: Optional>) = charges(charges.getOrNull()) + + /** + * Sets [Builder.charges] to an arbitrary JSON value. + * + * You should usually call [Builder.charges] with a well-typed `List` value instead. + * This method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun charges(charges: JsonField>) = apply { + this.charges = charges.map { it.toMutableList() } + } + + /** + * Adds a single [Charge] to [charges]. + * + * @throws IllegalStateException if the field was previously set to a non-list. + */ + fun addCharge(charge: Charge) = apply { + charges = + (charges ?: JsonField.of(mutableListOf())).also { + checkKnown("charges", it).add(charge) + } + } + + /** Currency of the invoice (ISO 4217 currency code) */ + fun currency(currency: CurrencyCode) = currency(JsonField.of(currency)) + + /** + * Sets [Builder.currency] to an arbitrary JSON value. + * + * You should usually call [Builder.currency] with a well-typed [CurrencyCode] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun currency(currency: JsonField) = apply { this.currency = currency } + + /** The address of the customer/buyer */ + fun customerAddress(customerAddress: String?) = + customerAddress(JsonField.ofNullable(customerAddress)) + + /** Alias for calling [Builder.customerAddress] with `customerAddress.orElse(null)`. */ + fun customerAddress(customerAddress: Optional) = + customerAddress(customerAddress.getOrNull()) + + /** + * Sets [Builder.customerAddress] to an arbitrary JSON value. + * + * You should usually call [Builder.customerAddress] with a well-typed [String] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun customerAddress(customerAddress: JsonField) = apply { + this.customerAddress = customerAddress + } + + /** The recipient name at the customer address */ + fun customerAddressRecipient(customerAddressRecipient: String?) = + customerAddressRecipient(JsonField.ofNullable(customerAddressRecipient)) + + /** + * Alias for calling [Builder.customerAddressRecipient] with + * `customerAddressRecipient.orElse(null)`. + */ + fun customerAddressRecipient(customerAddressRecipient: Optional) = + customerAddressRecipient(customerAddressRecipient.getOrNull()) + + /** + * Sets [Builder.customerAddressRecipient] to an arbitrary JSON value. + * + * You should usually call [Builder.customerAddressRecipient] with a well-typed [String] + * value instead. This method is primarily for setting the field to an undocumented or not + * yet supported value. + */ + fun customerAddressRecipient(customerAddressRecipient: JsonField) = apply { + this.customerAddressRecipient = customerAddressRecipient + } + + /** + * Customer company ID. For Belgium this is the CBE number or their EUID (European Unique + * Identifier) number. In the Netherlands this is the KVK number. + */ + fun customerCompanyId(customerCompanyId: String?) = + customerCompanyId(JsonField.ofNullable(customerCompanyId)) + + /** Alias for calling [Builder.customerCompanyId] with `customerCompanyId.orElse(null)`. */ + fun customerCompanyId(customerCompanyId: Optional) = + customerCompanyId(customerCompanyId.getOrNull()) + + /** + * Sets [Builder.customerCompanyId] to an arbitrary JSON value. + * + * You should usually call [Builder.customerCompanyId] with a well-typed [String] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun customerCompanyId(customerCompanyId: JsonField) = apply { + this.customerCompanyId = customerCompanyId + } + + /** The email address of the customer */ + fun customerEmail(customerEmail: String?) = + customerEmail(JsonField.ofNullable(customerEmail)) + + /** Alias for calling [Builder.customerEmail] with `customerEmail.orElse(null)`. */ + fun customerEmail(customerEmail: Optional) = + customerEmail(customerEmail.getOrNull()) + + /** + * Sets [Builder.customerEmail] to an arbitrary JSON value. + * + * You should usually call [Builder.customerEmail] with a well-typed [String] value instead. + * This method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun customerEmail(customerEmail: JsonField) = apply { + this.customerEmail = customerEmail + } + + /** The unique identifier for the customer in your system */ + fun customerId(customerId: String?) = customerId(JsonField.ofNullable(customerId)) + + /** Alias for calling [Builder.customerId] with `customerId.orElse(null)`. */ + fun customerId(customerId: Optional) = customerId(customerId.getOrNull()) + + /** + * Sets [Builder.customerId] to an arbitrary JSON value. + * + * You should usually call [Builder.customerId] with a well-typed [String] value instead. + * This method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun customerId(customerId: JsonField) = apply { this.customerId = customerId } + + /** The company name of the customer/buyer */ + fun customerName(customerName: String?) = customerName(JsonField.ofNullable(customerName)) + + /** Alias for calling [Builder.customerName] with `customerName.orElse(null)`. */ + fun customerName(customerName: Optional) = customerName(customerName.getOrNull()) + + /** + * Sets [Builder.customerName] to an arbitrary JSON value. + * + * You should usually call [Builder.customerName] with a well-typed [String] value instead. + * This method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun customerName(customerName: JsonField) = apply { + this.customerName = customerName + } + + /** Customer tax ID. For Belgium this is the VAT number. Must include the country prefix */ + fun customerTaxId(customerTaxId: String?) = + customerTaxId(JsonField.ofNullable(customerTaxId)) + + /** Alias for calling [Builder.customerTaxId] with `customerTaxId.orElse(null)`. */ + fun customerTaxId(customerTaxId: Optional) = + customerTaxId(customerTaxId.getOrNull()) + + /** + * Sets [Builder.customerTaxId] to an arbitrary JSON value. + * + * You should usually call [Builder.customerTaxId] with a well-typed [String] value instead. + * This method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun customerTaxId(customerTaxId: JsonField) = apply { + this.customerTaxId = customerTaxId + } + + /** The direction of the document: INBOUND (purchases) or OUTBOUND (sales) */ + fun direction(direction: DocumentDirection) = direction(JsonField.of(direction)) + + /** + * Sets [Builder.direction] to an arbitrary JSON value. + * + * You should usually call [Builder.direction] with a well-typed [DocumentDirection] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun direction(direction: JsonField) = apply { + this.direction = direction + } + + /** The type of document: INVOICE, CREDIT_NOTE, or DEBIT_NOTE */ + fun documentType(documentType: DocumentType) = documentType(JsonField.of(documentType)) + + /** + * Sets [Builder.documentType] to an arbitrary JSON value. + * + * You should usually call [Builder.documentType] with a well-typed [DocumentType] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun documentType(documentType: JsonField) = apply { + this.documentType = documentType + } + + /** The date when payment is due */ + fun dueDate(dueDate: LocalDate?) = dueDate(JsonField.ofNullable(dueDate)) + + /** Alias for calling [Builder.dueDate] with `dueDate.orElse(null)`. */ + fun dueDate(dueDate: Optional) = dueDate(dueDate.getOrNull()) + + /** + * Sets [Builder.dueDate] to an arbitrary JSON value. + * + * You should usually call [Builder.dueDate] with a well-typed [LocalDate] value instead. + * This method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun dueDate(dueDate: JsonField) = apply { this.dueDate = dueDate } + + /** The date when the invoice was issued */ + fun invoiceDate(invoiceDate: LocalDate?) = invoiceDate(JsonField.ofNullable(invoiceDate)) + + /** Alias for calling [Builder.invoiceDate] with `invoiceDate.orElse(null)`. */ + fun invoiceDate(invoiceDate: Optional) = invoiceDate(invoiceDate.getOrNull()) + + /** + * Sets [Builder.invoiceDate] to an arbitrary JSON value. + * + * You should usually call [Builder.invoiceDate] with a well-typed [LocalDate] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun invoiceDate(invoiceDate: JsonField) = apply { + this.invoiceDate = invoiceDate + } + + /** The unique invoice identifier/number */ + fun invoiceId(invoiceId: String?) = invoiceId(JsonField.ofNullable(invoiceId)) + + /** Alias for calling [Builder.invoiceId] with `invoiceId.orElse(null)`. */ + fun invoiceId(invoiceId: Optional) = invoiceId(invoiceId.getOrNull()) + + /** + * Sets [Builder.invoiceId] to an arbitrary JSON value. + * + * You should usually call [Builder.invoiceId] with a well-typed [String] value instead. + * This method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun invoiceId(invoiceId: JsonField) = apply { this.invoiceId = invoiceId } + + /** + * The total amount of the invoice including tax (invoice_total = subtotal + total_tax + + * total_discount). Must be positive and rounded to maximum 2 decimals + */ + fun invoiceTotal(invoiceTotal: String?) = invoiceTotal(JsonField.ofNullable(invoiceTotal)) + + /** Alias for calling [Builder.invoiceTotal] with `invoiceTotal.orElse(null)`. */ + fun invoiceTotal(invoiceTotal: Optional) = invoiceTotal(invoiceTotal.getOrNull()) + + /** + * Sets [Builder.invoiceTotal] to an arbitrary JSON value. + * + * You should usually call [Builder.invoiceTotal] with a well-typed [String] value instead. + * This method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun invoiceTotal(invoiceTotal: JsonField) = apply { + this.invoiceTotal = invoiceTotal + } + + /** At least one line item is required */ + fun items(items: List) = items(JsonField.of(items)) + + /** + * Sets [Builder.items] to an arbitrary JSON value. + * + * You should usually call [Builder.items] with a well-typed `List` value instead. + * This method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun items(items: JsonField>) = apply { + this.items = items.map { it.toMutableList() } + } + + /** + * Adds a single [Item] to [items]. + * + * @throws IllegalStateException if the field was previously set to a non-list. + */ + fun addItem(item: Item) = apply { + items = + (items ?: JsonField.of(mutableListOf())).also { checkKnown("items", it).add(item) } + } + + /** Additional notes or comments for the invoice */ + fun note(note: String?) = note(JsonField.ofNullable(note)) + + /** Alias for calling [Builder.note] with `note.orElse(null)`. */ + fun note(note: Optional) = note(note.getOrNull()) + + /** + * Sets [Builder.note] to an arbitrary JSON value. + * + * You should usually call [Builder.note] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun note(note: JsonField) = apply { this.note = note } + + fun paymentDetails(paymentDetails: List?) = + paymentDetails(JsonField.ofNullable(paymentDetails)) + + /** Alias for calling [Builder.paymentDetails] with `paymentDetails.orElse(null)`. */ + fun paymentDetails(paymentDetails: Optional>) = + paymentDetails(paymentDetails.getOrNull()) + + /** + * Sets [Builder.paymentDetails] to an arbitrary JSON value. + * + * You should usually call [Builder.paymentDetails] with a well-typed + * `List` value instead. This method is primarily for setting the field + * to an undocumented or not yet supported value. + */ + fun paymentDetails(paymentDetails: JsonField>) = apply { + this.paymentDetails = paymentDetails.map { it.toMutableList() } + } + + /** + * Adds a single [PaymentDetailCreate] to [paymentDetails]. + * + * @throws IllegalStateException if the field was previously set to a non-list. + */ + fun addPaymentDetail(paymentDetail: PaymentDetailCreate) = apply { + paymentDetails = + (paymentDetails ?: JsonField.of(mutableListOf())).also { + checkKnown("paymentDetails", it).add(paymentDetail) + } + } + + /** The payment terms (e.g., 'Net 30', 'Due on receipt', '2/10 Net 30') */ + fun paymentTerm(paymentTerm: String?) = paymentTerm(JsonField.ofNullable(paymentTerm)) + + /** Alias for calling [Builder.paymentTerm] with `paymentTerm.orElse(null)`. */ + fun paymentTerm(paymentTerm: Optional) = paymentTerm(paymentTerm.getOrNull()) + + /** + * Sets [Builder.paymentTerm] to an arbitrary JSON value. + * + * You should usually call [Builder.paymentTerm] with a well-typed [String] value instead. + * This method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun paymentTerm(paymentTerm: JsonField) = apply { this.paymentTerm = paymentTerm } + + /** The purchase order reference number */ + fun purchaseOrder(purchaseOrder: String?) = + purchaseOrder(JsonField.ofNullable(purchaseOrder)) + + /** Alias for calling [Builder.purchaseOrder] with `purchaseOrder.orElse(null)`. */ + fun purchaseOrder(purchaseOrder: Optional) = + purchaseOrder(purchaseOrder.getOrNull()) + + /** + * Sets [Builder.purchaseOrder] to an arbitrary JSON value. + * + * You should usually call [Builder.purchaseOrder] with a well-typed [String] value instead. + * This method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun purchaseOrder(purchaseOrder: JsonField) = apply { + this.purchaseOrder = purchaseOrder + } + + /** The address where payment should be sent or remitted to */ + fun remittanceAddress(remittanceAddress: String?) = + remittanceAddress(JsonField.ofNullable(remittanceAddress)) + + /** Alias for calling [Builder.remittanceAddress] with `remittanceAddress.orElse(null)`. */ + fun remittanceAddress(remittanceAddress: Optional) = + remittanceAddress(remittanceAddress.getOrNull()) + + /** + * Sets [Builder.remittanceAddress] to an arbitrary JSON value. + * + * You should usually call [Builder.remittanceAddress] with a well-typed [String] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun remittanceAddress(remittanceAddress: JsonField) = apply { + this.remittanceAddress = remittanceAddress + } + + /** The recipient name at the remittance address */ + fun remittanceAddressRecipient(remittanceAddressRecipient: String?) = + remittanceAddressRecipient(JsonField.ofNullable(remittanceAddressRecipient)) + + /** + * Alias for calling [Builder.remittanceAddressRecipient] with + * `remittanceAddressRecipient.orElse(null)`. + */ + fun remittanceAddressRecipient(remittanceAddressRecipient: Optional) = + remittanceAddressRecipient(remittanceAddressRecipient.getOrNull()) + + /** + * Sets [Builder.remittanceAddressRecipient] to an arbitrary JSON value. + * + * You should usually call [Builder.remittanceAddressRecipient] with a well-typed [String] + * value instead. This method is primarily for setting the field to an undocumented or not + * yet supported value. + */ + fun remittanceAddressRecipient(remittanceAddressRecipient: JsonField) = apply { + this.remittanceAddressRecipient = remittanceAddressRecipient + } + + /** The address where services were performed or goods were delivered */ + fun serviceAddress(serviceAddress: String?) = + serviceAddress(JsonField.ofNullable(serviceAddress)) + + /** Alias for calling [Builder.serviceAddress] with `serviceAddress.orElse(null)`. */ + fun serviceAddress(serviceAddress: Optional) = + serviceAddress(serviceAddress.getOrNull()) + + /** + * Sets [Builder.serviceAddress] to an arbitrary JSON value. + * + * You should usually call [Builder.serviceAddress] with a well-typed [String] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun serviceAddress(serviceAddress: JsonField) = apply { + this.serviceAddress = serviceAddress + } + + /** The recipient name at the service address */ + fun serviceAddressRecipient(serviceAddressRecipient: String?) = + serviceAddressRecipient(JsonField.ofNullable(serviceAddressRecipient)) + + /** + * Alias for calling [Builder.serviceAddressRecipient] with + * `serviceAddressRecipient.orElse(null)`. + */ + fun serviceAddressRecipient(serviceAddressRecipient: Optional) = + serviceAddressRecipient(serviceAddressRecipient.getOrNull()) + + /** + * Sets [Builder.serviceAddressRecipient] to an arbitrary JSON value. + * + * You should usually call [Builder.serviceAddressRecipient] with a well-typed [String] + * value instead. This method is primarily for setting the field to an undocumented or not + * yet supported value. + */ + fun serviceAddressRecipient(serviceAddressRecipient: JsonField) = apply { + this.serviceAddressRecipient = serviceAddressRecipient + } + + /** The end date of the service period or delivery period */ + fun serviceEndDate(serviceEndDate: LocalDate?) = + serviceEndDate(JsonField.ofNullable(serviceEndDate)) + + /** Alias for calling [Builder.serviceEndDate] with `serviceEndDate.orElse(null)`. */ + fun serviceEndDate(serviceEndDate: Optional) = + serviceEndDate(serviceEndDate.getOrNull()) + + /** + * Sets [Builder.serviceEndDate] to an arbitrary JSON value. + * + * You should usually call [Builder.serviceEndDate] with a well-typed [LocalDate] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun serviceEndDate(serviceEndDate: JsonField) = apply { + this.serviceEndDate = serviceEndDate + } + + /** The start date of the service period or delivery period */ + fun serviceStartDate(serviceStartDate: LocalDate?) = + serviceStartDate(JsonField.ofNullable(serviceStartDate)) + + /** Alias for calling [Builder.serviceStartDate] with `serviceStartDate.orElse(null)`. */ + fun serviceStartDate(serviceStartDate: Optional) = + serviceStartDate(serviceStartDate.getOrNull()) + + /** + * Sets [Builder.serviceStartDate] to an arbitrary JSON value. + * + * You should usually call [Builder.serviceStartDate] with a well-typed [LocalDate] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun serviceStartDate(serviceStartDate: JsonField) = apply { + this.serviceStartDate = serviceStartDate + } + + /** The shipping/delivery address */ + fun shippingAddress(shippingAddress: String?) = + shippingAddress(JsonField.ofNullable(shippingAddress)) + + /** Alias for calling [Builder.shippingAddress] with `shippingAddress.orElse(null)`. */ + fun shippingAddress(shippingAddress: Optional) = + shippingAddress(shippingAddress.getOrNull()) + + /** + * Sets [Builder.shippingAddress] to an arbitrary JSON value. + * + * You should usually call [Builder.shippingAddress] with a well-typed [String] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun shippingAddress(shippingAddress: JsonField) = apply { + this.shippingAddress = shippingAddress + } + + /** The recipient name at the shipping address */ + fun shippingAddressRecipient(shippingAddressRecipient: String?) = + shippingAddressRecipient(JsonField.ofNullable(shippingAddressRecipient)) + + /** + * Alias for calling [Builder.shippingAddressRecipient] with + * `shippingAddressRecipient.orElse(null)`. + */ + fun shippingAddressRecipient(shippingAddressRecipient: Optional) = + shippingAddressRecipient(shippingAddressRecipient.getOrNull()) + + /** + * Sets [Builder.shippingAddressRecipient] to an arbitrary JSON value. + * + * You should usually call [Builder.shippingAddressRecipient] with a well-typed [String] + * value instead. This method is primarily for setting the field to an undocumented or not + * yet supported value. + */ + fun shippingAddressRecipient(shippingAddressRecipient: JsonField) = apply { + this.shippingAddressRecipient = shippingAddressRecipient + } + + /** The current state of the document: DRAFT, TRANSIT, FAILED, SENT, or RECEIVED */ + fun state(state: DocumentState) = state(JsonField.of(state)) + + /** + * Sets [Builder.state] to an arbitrary JSON value. + * + * You should usually call [Builder.state] with a well-typed [DocumentState] value instead. + * This method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun state(state: JsonField) = apply { this.state = state } + + /** + * The taxable base of the invoice. Should be the sum of all line items - allowances (for + * example commercial discounts) + charges with impact on VAT. Must be positive and rounded + * to maximum 2 decimals + */ + fun subtotal(subtotal: String?) = subtotal(JsonField.ofNullable(subtotal)) + + /** Alias for calling [Builder.subtotal] with `subtotal.orElse(null)`. */ + fun subtotal(subtotal: Optional) = subtotal(subtotal.getOrNull()) + + /** + * Sets [Builder.subtotal] to an arbitrary JSON value. + * + * You should usually call [Builder.subtotal] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun subtotal(subtotal: JsonField) = apply { this.subtotal = subtotal } + + /** Whether the PDF was successfully converted into a compliant e-invoice */ + fun success(success: Boolean) = success(JsonField.of(success)) + + /** + * Sets [Builder.success] to an arbitrary JSON value. + * + * You should usually call [Builder.success] with a well-typed [Boolean] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun success(success: JsonField) = apply { this.success = success } + + /** + * Tax category code of the invoice (e.g., S for standard rate, Z for zero rate, E for + * exempt) + */ + fun taxCode(taxCode: TaxCode) = taxCode(JsonField.of(taxCode)) + + /** + * Sets [Builder.taxCode] to an arbitrary JSON value. + * + * You should usually call [Builder.taxCode] with a well-typed [TaxCode] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun taxCode(taxCode: JsonField) = apply { this.taxCode = taxCode } + + fun taxDetails(taxDetails: List?) = taxDetails(JsonField.ofNullable(taxDetails)) + + /** Alias for calling [Builder.taxDetails] with `taxDetails.orElse(null)`. */ + fun taxDetails(taxDetails: Optional>) = taxDetails(taxDetails.getOrNull()) + + /** + * Sets [Builder.taxDetails] to an arbitrary JSON value. + * + * You should usually call [Builder.taxDetails] with a well-typed `List` value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun taxDetails(taxDetails: JsonField>) = apply { + this.taxDetails = taxDetails.map { it.toMutableList() } + } + + /** + * Adds a single [TaxDetail] to [taxDetails]. + * + * @throws IllegalStateException if the field was previously set to a non-list. + */ + fun addTaxDetail(taxDetail: TaxDetail) = apply { + taxDetails = + (taxDetails ?: JsonField.of(mutableListOf())).also { + checkKnown("taxDetails", it).add(taxDetail) + } + } + + /** + * The net financial discount/charge of the invoice (non-VAT charges minus non-VAT + * allowances). Can be positive (net charge), negative (net discount), or zero. Must be + * rounded to maximum 2 decimals + */ + fun totalDiscount(totalDiscount: String?) = + totalDiscount(JsonField.ofNullable(totalDiscount)) + + /** Alias for calling [Builder.totalDiscount] with `totalDiscount.orElse(null)`. */ + fun totalDiscount(totalDiscount: Optional) = + totalDiscount(totalDiscount.getOrNull()) + + /** + * Sets [Builder.totalDiscount] to an arbitrary JSON value. + * + * You should usually call [Builder.totalDiscount] with a well-typed [String] value instead. + * This method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun totalDiscount(totalDiscount: JsonField) = apply { + this.totalDiscount = totalDiscount + } + + /** + * The total tax amount of the invoice. Must be positive and rounded to maximum 2 decimals + */ + fun totalTax(totalTax: String?) = totalTax(JsonField.ofNullable(totalTax)) + + /** Alias for calling [Builder.totalTax] with `totalTax.orElse(null)`. */ + fun totalTax(totalTax: Optional) = totalTax(totalTax.getOrNull()) + + /** + * Sets [Builder.totalTax] to an arbitrary JSON value. + * + * You should usually call [Builder.totalTax] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun totalTax(totalTax: JsonField) = apply { this.totalTax = totalTax } + + /** The UBL document as an XML string */ + fun ublDocument(ublDocument: String?) = ublDocument(JsonField.ofNullable(ublDocument)) + + /** Alias for calling [Builder.ublDocument] with `ublDocument.orElse(null)`. */ + fun ublDocument(ublDocument: Optional) = ublDocument(ublDocument.getOrNull()) + + /** + * Sets [Builder.ublDocument] to an arbitrary JSON value. + * + * You should usually call [Builder.ublDocument] with a well-typed [String] value instead. + * This method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun ublDocument(ublDocument: JsonField) = apply { this.ublDocument = ublDocument } + + /** + * VATEX code list for VAT exemption reasons + * + * Agency: CEF Identifier: vatex + */ + fun vatex(vatex: Vatex?) = vatex(JsonField.ofNullable(vatex)) + + /** Alias for calling [Builder.vatex] with `vatex.orElse(null)`. */ + fun vatex(vatex: Optional) = vatex(vatex.getOrNull()) + + /** + * Sets [Builder.vatex] to an arbitrary JSON value. + * + * You should usually call [Builder.vatex] with a well-typed [Vatex] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun vatex(vatex: JsonField) = apply { this.vatex = vatex } + + /** Textual explanation for VAT exemption */ + fun vatexNote(vatexNote: String?) = vatexNote(JsonField.ofNullable(vatexNote)) + + /** Alias for calling [Builder.vatexNote] with `vatexNote.orElse(null)`. */ + fun vatexNote(vatexNote: Optional) = vatexNote(vatexNote.getOrNull()) + + /** + * Sets [Builder.vatexNote] to an arbitrary JSON value. + * + * You should usually call [Builder.vatexNote] with a well-typed [String] value instead. + * This method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun vatexNote(vatexNote: JsonField) = apply { this.vatexNote = vatexNote } + + /** The address of the vendor/seller */ + fun vendorAddress(vendorAddress: String?) = + vendorAddress(JsonField.ofNullable(vendorAddress)) + + /** Alias for calling [Builder.vendorAddress] with `vendorAddress.orElse(null)`. */ + fun vendorAddress(vendorAddress: Optional) = + vendorAddress(vendorAddress.getOrNull()) + + /** + * Sets [Builder.vendorAddress] to an arbitrary JSON value. + * + * You should usually call [Builder.vendorAddress] with a well-typed [String] value instead. + * This method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun vendorAddress(vendorAddress: JsonField) = apply { + this.vendorAddress = vendorAddress + } + + /** The recipient name at the vendor address */ + fun vendorAddressRecipient(vendorAddressRecipient: String?) = + vendorAddressRecipient(JsonField.ofNullable(vendorAddressRecipient)) + + /** + * Alias for calling [Builder.vendorAddressRecipient] with + * `vendorAddressRecipient.orElse(null)`. + */ + fun vendorAddressRecipient(vendorAddressRecipient: Optional) = + vendorAddressRecipient(vendorAddressRecipient.getOrNull()) + + /** + * Sets [Builder.vendorAddressRecipient] to an arbitrary JSON value. + * + * You should usually call [Builder.vendorAddressRecipient] with a well-typed [String] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun vendorAddressRecipient(vendorAddressRecipient: JsonField) = apply { + this.vendorAddressRecipient = vendorAddressRecipient + } + + /** + * Vendor company ID. For Belgium this is the CBE number or their EUID (European Unique + * Identifier) number. In the Netherlands this is the KVK number. + */ + fun vendorCompanyId(vendorCompanyId: String?) = + vendorCompanyId(JsonField.ofNullable(vendorCompanyId)) + + /** Alias for calling [Builder.vendorCompanyId] with `vendorCompanyId.orElse(null)`. */ + fun vendorCompanyId(vendorCompanyId: Optional) = + vendorCompanyId(vendorCompanyId.getOrNull()) + + /** + * Sets [Builder.vendorCompanyId] to an arbitrary JSON value. + * + * You should usually call [Builder.vendorCompanyId] with a well-typed [String] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun vendorCompanyId(vendorCompanyId: JsonField) = apply { + this.vendorCompanyId = vendorCompanyId + } + + /** The email address of the vendor */ + fun vendorEmail(vendorEmail: String?) = vendorEmail(JsonField.ofNullable(vendorEmail)) + + /** Alias for calling [Builder.vendorEmail] with `vendorEmail.orElse(null)`. */ + fun vendorEmail(vendorEmail: Optional) = vendorEmail(vendorEmail.getOrNull()) + + /** + * Sets [Builder.vendorEmail] to an arbitrary JSON value. + * + * You should usually call [Builder.vendorEmail] with a well-typed [String] value instead. + * This method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun vendorEmail(vendorEmail: JsonField) = apply { this.vendorEmail = vendorEmail } + + /** The name of the vendor/seller/supplier */ + fun vendorName(vendorName: String?) = vendorName(JsonField.ofNullable(vendorName)) + + /** Alias for calling [Builder.vendorName] with `vendorName.orElse(null)`. */ + fun vendorName(vendorName: Optional) = vendorName(vendorName.getOrNull()) + + /** + * Sets [Builder.vendorName] to an arbitrary JSON value. + * + * You should usually call [Builder.vendorName] with a well-typed [String] value instead. + * This method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun vendorName(vendorName: JsonField) = apply { this.vendorName = vendorName } + + /** Vendor tax ID. For Belgium this is the VAT number. Must include the country prefix */ + fun vendorTaxId(vendorTaxId: String?) = vendorTaxId(JsonField.ofNullable(vendorTaxId)) + + /** Alias for calling [Builder.vendorTaxId] with `vendorTaxId.orElse(null)`. */ + fun vendorTaxId(vendorTaxId: Optional) = vendorTaxId(vendorTaxId.getOrNull()) + + /** + * Sets [Builder.vendorTaxId] to an arbitrary JSON value. + * + * You should usually call [Builder.vendorTaxId] with a well-typed [String] value instead. + * This method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun vendorTaxId(vendorTaxId: JsonField) = apply { this.vendorTaxId = vendorTaxId } + + fun additionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.clear() + putAllAdditionalProperties(additionalProperties) + } + + fun putAdditionalProperty(key: String, value: JsonValue) = apply { + additionalProperties.put(key, value) + } + + fun putAllAdditionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.putAll(additionalProperties) + } + + fun removeAdditionalProperty(key: String) = apply { additionalProperties.remove(key) } + + fun removeAllAdditionalProperties(keys: Set) = apply { + keys.forEach(::removeAdditionalProperty) + } + + /** + * Returns an immutable instance of [DocumentCreateFromPdfResponse]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): DocumentCreateFromPdfResponse = + DocumentCreateFromPdfResponse( + (allowances ?: JsonMissing.of()).map { it.toImmutable() }, + amountDue, + (attachments ?: JsonMissing.of()).map { it.toImmutable() }, + billingAddress, + billingAddressRecipient, + (charges ?: JsonMissing.of()).map { it.toImmutable() }, + currency, + customerAddress, + customerAddressRecipient, + customerCompanyId, + customerEmail, + customerId, + customerName, + customerTaxId, + direction, + documentType, + dueDate, + invoiceDate, + invoiceId, + invoiceTotal, + (items ?: JsonMissing.of()).map { it.toImmutable() }, + note, + (paymentDetails ?: JsonMissing.of()).map { it.toImmutable() }, + paymentTerm, + purchaseOrder, + remittanceAddress, + remittanceAddressRecipient, + serviceAddress, + serviceAddressRecipient, + serviceEndDate, + serviceStartDate, + shippingAddress, + shippingAddressRecipient, + state, + subtotal, + success, + taxCode, + (taxDetails ?: JsonMissing.of()).map { it.toImmutable() }, + totalDiscount, + totalTax, + ublDocument, + vatex, + vatexNote, + vendorAddress, + vendorAddressRecipient, + vendorCompanyId, + vendorEmail, + vendorName, + vendorTaxId, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + fun validate(): DocumentCreateFromPdfResponse = apply { + if (validated) { + return@apply + } + + allowances().ifPresent { it.forEach { it.validate() } } + amountDue() + attachments().ifPresent { it.forEach { it.validate() } } + billingAddress() + billingAddressRecipient() + charges().ifPresent { it.forEach { it.validate() } } + currency().ifPresent { it.validate() } + customerAddress() + customerAddressRecipient() + customerCompanyId() + customerEmail() + customerId() + customerName() + customerTaxId() + direction().ifPresent { it.validate() } + documentType().ifPresent { it.validate() } + dueDate() + invoiceDate() + invoiceId() + invoiceTotal() + items().ifPresent { it.forEach { it.validate() } } + note() + paymentDetails().ifPresent { it.forEach { it.validate() } } + paymentTerm() + purchaseOrder() + remittanceAddress() + remittanceAddressRecipient() + serviceAddress() + serviceAddressRecipient() + serviceEndDate() + serviceStartDate() + shippingAddress() + shippingAddressRecipient() + state().ifPresent { it.validate() } + subtotal() + success() + taxCode().ifPresent { it.validate() } + taxDetails().ifPresent { it.forEach { it.validate() } } + totalDiscount() + totalTax() + ublDocument() + vatex().ifPresent { it.validate() } + vatexNote() + vendorAddress() + vendorAddressRecipient() + vendorCompanyId() + vendorEmail() + vendorName() + vendorTaxId() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: EInvoiceInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic + internal fun validity(): Int = + (allowances.asKnown().getOrNull()?.sumOf { it.validity().toInt() } ?: 0) + + (if (amountDue.asKnown().isPresent) 1 else 0) + + (attachments.asKnown().getOrNull()?.sumOf { it.validity().toInt() } ?: 0) + + (if (billingAddress.asKnown().isPresent) 1 else 0) + + (if (billingAddressRecipient.asKnown().isPresent) 1 else 0) + + (charges.asKnown().getOrNull()?.sumOf { it.validity().toInt() } ?: 0) + + (currency.asKnown().getOrNull()?.validity() ?: 0) + + (if (customerAddress.asKnown().isPresent) 1 else 0) + + (if (customerAddressRecipient.asKnown().isPresent) 1 else 0) + + (if (customerCompanyId.asKnown().isPresent) 1 else 0) + + (if (customerEmail.asKnown().isPresent) 1 else 0) + + (if (customerId.asKnown().isPresent) 1 else 0) + + (if (customerName.asKnown().isPresent) 1 else 0) + + (if (customerTaxId.asKnown().isPresent) 1 else 0) + + (direction.asKnown().getOrNull()?.validity() ?: 0) + + (documentType.asKnown().getOrNull()?.validity() ?: 0) + + (if (dueDate.asKnown().isPresent) 1 else 0) + + (if (invoiceDate.asKnown().isPresent) 1 else 0) + + (if (invoiceId.asKnown().isPresent) 1 else 0) + + (if (invoiceTotal.asKnown().isPresent) 1 else 0) + + (items.asKnown().getOrNull()?.sumOf { it.validity().toInt() } ?: 0) + + (if (note.asKnown().isPresent) 1 else 0) + + (paymentDetails.asKnown().getOrNull()?.sumOf { it.validity().toInt() } ?: 0) + + (if (paymentTerm.asKnown().isPresent) 1 else 0) + + (if (purchaseOrder.asKnown().isPresent) 1 else 0) + + (if (remittanceAddress.asKnown().isPresent) 1 else 0) + + (if (remittanceAddressRecipient.asKnown().isPresent) 1 else 0) + + (if (serviceAddress.asKnown().isPresent) 1 else 0) + + (if (serviceAddressRecipient.asKnown().isPresent) 1 else 0) + + (if (serviceEndDate.asKnown().isPresent) 1 else 0) + + (if (serviceStartDate.asKnown().isPresent) 1 else 0) + + (if (shippingAddress.asKnown().isPresent) 1 else 0) + + (if (shippingAddressRecipient.asKnown().isPresent) 1 else 0) + + (state.asKnown().getOrNull()?.validity() ?: 0) + + (if (subtotal.asKnown().isPresent) 1 else 0) + + (if (success.asKnown().isPresent) 1 else 0) + + (taxCode.asKnown().getOrNull()?.validity() ?: 0) + + (taxDetails.asKnown().getOrNull()?.sumOf { it.validity().toInt() } ?: 0) + + (if (totalDiscount.asKnown().isPresent) 1 else 0) + + (if (totalTax.asKnown().isPresent) 1 else 0) + + (if (ublDocument.asKnown().isPresent) 1 else 0) + + (vatex.asKnown().getOrNull()?.validity() ?: 0) + + (if (vatexNote.asKnown().isPresent) 1 else 0) + + (if (vendorAddress.asKnown().isPresent) 1 else 0) + + (if (vendorAddressRecipient.asKnown().isPresent) 1 else 0) + + (if (vendorCompanyId.asKnown().isPresent) 1 else 0) + + (if (vendorEmail.asKnown().isPresent) 1 else 0) + + (if (vendorName.asKnown().isPresent) 1 else 0) + + (if (vendorTaxId.asKnown().isPresent) 1 else 0) + + class Item + @JsonCreator(mode = JsonCreator.Mode.DISABLED) + private constructor( + private val allowances: JsonField>, + private val amount: JsonField, + private val charges: JsonField>, + private val date: JsonField, + private val description: JsonField, + private val productCode: JsonField, + private val quantity: JsonField, + private val tax: JsonField, + private val taxRate: JsonField, + private val unit: JsonField, + private val unitPrice: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("allowances") + @ExcludeMissing + allowances: JsonField> = JsonMissing.of(), + @JsonProperty("amount") @ExcludeMissing amount: JsonField = JsonMissing.of(), + @JsonProperty("charges") + @ExcludeMissing + charges: JsonField> = JsonMissing.of(), + @JsonProperty("date") @ExcludeMissing date: JsonField = JsonMissing.of(), + @JsonProperty("description") + @ExcludeMissing + description: JsonField = JsonMissing.of(), + @JsonProperty("product_code") + @ExcludeMissing + productCode: JsonField = JsonMissing.of(), + @JsonProperty("quantity") + @ExcludeMissing + quantity: JsonField = JsonMissing.of(), + @JsonProperty("tax") @ExcludeMissing tax: JsonField = JsonMissing.of(), + @JsonProperty("tax_rate") @ExcludeMissing taxRate: JsonField = JsonMissing.of(), + @JsonProperty("unit") + @ExcludeMissing + unit: JsonField = JsonMissing.of(), + @JsonProperty("unit_price") + @ExcludeMissing + unitPrice: JsonField = JsonMissing.of(), + ) : this( + allowances, + amount, + charges, + date, + description, + productCode, + quantity, + tax, + taxRate, + unit, + unitPrice, + mutableMapOf(), + ) + + /** + * The allowances of the line item. + * + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun allowances(): Optional> = allowances.getOptional("allowances") + + /** + * The invoice line net amount (BT-131), exclusive of VAT, inclusive of line level + * allowances and charges. Calculated as: ((unit_price / price_base_quantity) * quantity) - + * allowances + charges. Must be rounded to maximum 2 decimals. Can be negative for credit + * notes or corrections. + * + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun amount(): Optional = amount.getOptional("amount") + + /** + * The charges of the line item. + * + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun charges(): Optional> = charges.getOptional("charges") + + /** + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun date(): Optional = date.getOptional("date") + + /** + * The description of the line item. + * + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun description(): Optional = description.getOptional("description") + + /** + * The product code of the line item. + * + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun productCode(): Optional = productCode.getOptional("product_code") + + /** + * The quantity of items (goods or services) that is the subject of the line item. Must be + * rounded to maximum 4 decimals. Can be negative for credit notes or corrections. + * + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun quantity(): Optional = quantity.getOptional("quantity") + + /** + * The total VAT amount for the line item. Must be rounded to maximum 2 decimals. Can be + * negative for credit notes or corrections. + * + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun tax(): Optional = tax.getOptional("tax") + + /** + * The VAT rate of the line item expressed as percentage with 2 decimals + * + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun taxRate(): Optional = taxRate.getOptional("tax_rate") + + /** + * Unit of Measure Codes from UNECERec20 used in Peppol BIS Billing 3.0. + * + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun unit(): Optional = unit.getOptional("unit") + + /** + * The item net price (BT-146). The price of an item, exclusive of VAT, after subtracting + * item price discount. Must be rounded to maximum 4 decimals + * + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun unitPrice(): Optional = unitPrice.getOptional("unit_price") + + /** + * Returns the raw JSON value of [allowances]. + * + * Unlike [allowances], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("allowances") + @ExcludeMissing + fun _allowances(): JsonField> = allowances + + /** + * Returns the raw JSON value of [amount]. + * + * Unlike [amount], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("amount") @ExcludeMissing fun _amount(): JsonField = amount + + /** + * Returns the raw JSON value of [charges]. + * + * Unlike [charges], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("charges") @ExcludeMissing fun _charges(): JsonField> = charges + + /** + * Returns the raw JSON value of [date]. + * + * Unlike [date], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("date") @ExcludeMissing fun _date(): JsonField = date + + /** + * Returns the raw JSON value of [description]. + * + * Unlike [description], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("description") + @ExcludeMissing + fun _description(): JsonField = description + + /** + * Returns the raw JSON value of [productCode]. + * + * Unlike [productCode], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("product_code") + @ExcludeMissing + fun _productCode(): JsonField = productCode + + /** + * Returns the raw JSON value of [quantity]. + * + * Unlike [quantity], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("quantity") @ExcludeMissing fun _quantity(): JsonField = quantity + + /** + * Returns the raw JSON value of [tax]. + * + * Unlike [tax], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("tax") @ExcludeMissing fun _tax(): JsonField = tax + + /** + * Returns the raw JSON value of [taxRate]. + * + * Unlike [taxRate], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("tax_rate") @ExcludeMissing fun _taxRate(): JsonField = taxRate + + /** + * Returns the raw JSON value of [unit]. + * + * Unlike [unit], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("unit") @ExcludeMissing fun _unit(): JsonField = unit + + /** + * Returns the raw JSON value of [unitPrice]. + * + * Unlike [unitPrice], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("unit_price") @ExcludeMissing fun _unitPrice(): JsonField = unitPrice + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** Returns a mutable builder for constructing an instance of [Item]. */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [Item]. */ + class Builder internal constructor() { + + private var allowances: JsonField>? = null + private var amount: JsonField = JsonMissing.of() + private var charges: JsonField>? = null + private var date: JsonField = JsonMissing.of() + private var description: JsonField = JsonMissing.of() + private var productCode: JsonField = JsonMissing.of() + private var quantity: JsonField = JsonMissing.of() + private var tax: JsonField = JsonMissing.of() + private var taxRate: JsonField = JsonMissing.of() + private var unit: JsonField = JsonMissing.of() + private var unitPrice: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(item: Item) = apply { + allowances = item.allowances.map { it.toMutableList() } + amount = item.amount + charges = item.charges.map { it.toMutableList() } + date = item.date + description = item.description + productCode = item.productCode + quantity = item.quantity + tax = item.tax + taxRate = item.taxRate + unit = item.unit + unitPrice = item.unitPrice + additionalProperties = item.additionalProperties.toMutableMap() + } + + /** The allowances of the line item. */ + fun allowances(allowances: List?) = + allowances(JsonField.ofNullable(allowances)) + + /** Alias for calling [Builder.allowances] with `allowances.orElse(null)`. */ + fun allowances(allowances: Optional>) = + allowances(allowances.getOrNull()) + + /** + * Sets [Builder.allowances] to an arbitrary JSON value. + * + * You should usually call [Builder.allowances] with a well-typed `List` + * value instead. This method is primarily for setting the field to an undocumented or + * not yet supported value. + */ + fun allowances(allowances: JsonField>) = apply { + this.allowances = allowances.map { it.toMutableList() } + } + + /** + * Adds a single [Allowance] to [allowances]. + * + * @throws IllegalStateException if the field was previously set to a non-list. + */ + fun addAllowance(allowance: Allowance) = apply { + allowances = + (allowances ?: JsonField.of(mutableListOf())).also { + checkKnown("allowances", it).add(allowance) + } + } + + /** + * The invoice line net amount (BT-131), exclusive of VAT, inclusive of line level + * allowances and charges. Calculated as: ((unit_price / price_base_quantity) * + * quantity) - allowances + charges. Must be rounded to maximum 2 decimals. Can be + * negative for credit notes or corrections. + */ + fun amount(amount: String?) = amount(JsonField.ofNullable(amount)) + + /** Alias for calling [Builder.amount] with `amount.orElse(null)`. */ + fun amount(amount: Optional) = amount(amount.getOrNull()) + + /** + * Sets [Builder.amount] to an arbitrary JSON value. + * + * You should usually call [Builder.amount] with a well-typed [String] value instead. + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun amount(amount: JsonField) = apply { this.amount = amount } + + /** The charges of the line item. */ + fun charges(charges: List?) = charges(JsonField.ofNullable(charges)) + + /** Alias for calling [Builder.charges] with `charges.orElse(null)`. */ + fun charges(charges: Optional>) = charges(charges.getOrNull()) + + /** + * Sets [Builder.charges] to an arbitrary JSON value. + * + * You should usually call [Builder.charges] with a well-typed `List` value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun charges(charges: JsonField>) = apply { + this.charges = charges.map { it.toMutableList() } + } + + /** + * Adds a single [Charge] to [charges]. + * + * @throws IllegalStateException if the field was previously set to a non-list. + */ + fun addCharge(charge: Charge) = apply { + charges = + (charges ?: JsonField.of(mutableListOf())).also { + checkKnown("charges", it).add(charge) + } + } + + fun date(date: Void?) = date(JsonField.ofNullable(date)) + + /** Alias for calling [Builder.date] with `date.orElse(null)`. */ + fun date(date: Optional) = date(date.getOrNull()) + + /** + * Sets [Builder.date] to an arbitrary JSON value. + * + * You should usually call [Builder.date] with a well-typed [Void] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun date(date: JsonField) = apply { this.date = date } + + /** The description of the line item. */ + fun description(description: String?) = description(JsonField.ofNullable(description)) + + /** Alias for calling [Builder.description] with `description.orElse(null)`. */ + fun description(description: Optional) = description(description.getOrNull()) + + /** + * Sets [Builder.description] to an arbitrary JSON value. + * + * You should usually call [Builder.description] with a well-typed [String] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun description(description: JsonField) = apply { + this.description = description + } + + /** The product code of the line item. */ + fun productCode(productCode: String?) = productCode(JsonField.ofNullable(productCode)) + + /** Alias for calling [Builder.productCode] with `productCode.orElse(null)`. */ + fun productCode(productCode: Optional) = productCode(productCode.getOrNull()) + + /** + * Sets [Builder.productCode] to an arbitrary JSON value. + * + * You should usually call [Builder.productCode] with a well-typed [String] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun productCode(productCode: JsonField) = apply { + this.productCode = productCode + } + + /** + * The quantity of items (goods or services) that is the subject of the line item. Must + * be rounded to maximum 4 decimals. Can be negative for credit notes or corrections. + */ + fun quantity(quantity: String?) = quantity(JsonField.ofNullable(quantity)) + + /** Alias for calling [Builder.quantity] with `quantity.orElse(null)`. */ + fun quantity(quantity: Optional) = quantity(quantity.getOrNull()) + + /** + * Sets [Builder.quantity] to an arbitrary JSON value. + * + * You should usually call [Builder.quantity] with a well-typed [String] value instead. + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun quantity(quantity: JsonField) = apply { this.quantity = quantity } + + /** + * The total VAT amount for the line item. Must be rounded to maximum 2 decimals. Can be + * negative for credit notes or corrections. + */ + fun tax(tax: String?) = tax(JsonField.ofNullable(tax)) + + /** Alias for calling [Builder.tax] with `tax.orElse(null)`. */ + fun tax(tax: Optional) = tax(tax.getOrNull()) + + /** + * Sets [Builder.tax] to an arbitrary JSON value. + * + * You should usually call [Builder.tax] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun tax(tax: JsonField) = apply { this.tax = tax } + + /** The VAT rate of the line item expressed as percentage with 2 decimals */ + fun taxRate(taxRate: String?) = taxRate(JsonField.ofNullable(taxRate)) + + /** Alias for calling [Builder.taxRate] with `taxRate.orElse(null)`. */ + fun taxRate(taxRate: Optional) = taxRate(taxRate.getOrNull()) + + /** + * Sets [Builder.taxRate] to an arbitrary JSON value. + * + * You should usually call [Builder.taxRate] with a well-typed [String] value instead. + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun taxRate(taxRate: JsonField) = apply { this.taxRate = taxRate } + + /** Unit of Measure Codes from UNECERec20 used in Peppol BIS Billing 3.0. */ + fun unit(unit: UnitOfMeasureCode?) = unit(JsonField.ofNullable(unit)) + + /** Alias for calling [Builder.unit] with `unit.orElse(null)`. */ + fun unit(unit: Optional) = unit(unit.getOrNull()) + + /** + * Sets [Builder.unit] to an arbitrary JSON value. + * + * You should usually call [Builder.unit] with a well-typed [UnitOfMeasureCode] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun unit(unit: JsonField) = apply { this.unit = unit } + + /** + * The item net price (BT-146). The price of an item, exclusive of VAT, after + * subtracting item price discount. Must be rounded to maximum 4 decimals + */ + fun unitPrice(unitPrice: String?) = unitPrice(JsonField.ofNullable(unitPrice)) + + /** Alias for calling [Builder.unitPrice] with `unitPrice.orElse(null)`. */ + fun unitPrice(unitPrice: Optional) = unitPrice(unitPrice.getOrNull()) + + /** + * Sets [Builder.unitPrice] to an arbitrary JSON value. + * + * You should usually call [Builder.unitPrice] with a well-typed [String] value instead. + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun unitPrice(unitPrice: JsonField) = apply { this.unitPrice = unitPrice } + + fun additionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.clear() + putAllAdditionalProperties(additionalProperties) + } + + fun putAdditionalProperty(key: String, value: JsonValue) = apply { + additionalProperties.put(key, value) + } + + fun putAllAdditionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.putAll(additionalProperties) + } + + fun removeAdditionalProperty(key: String) = apply { additionalProperties.remove(key) } + + fun removeAllAdditionalProperties(keys: Set) = apply { + keys.forEach(::removeAdditionalProperty) + } + + /** + * Returns an immutable instance of [Item]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): Item = + Item( + (allowances ?: JsonMissing.of()).map { it.toImmutable() }, + amount, + (charges ?: JsonMissing.of()).map { it.toImmutable() }, + date, + description, + productCode, + quantity, + tax, + taxRate, + unit, + unitPrice, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + fun validate(): Item = apply { + if (validated) { + return@apply + } + + allowances().ifPresent { it.forEach { it.validate() } } + amount() + charges().ifPresent { it.forEach { it.validate() } } + date() + description() + productCode() + quantity() + tax() + taxRate() + unit().ifPresent { it.validate() } + unitPrice() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: EInvoiceInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic + internal fun validity(): Int = + (allowances.asKnown().getOrNull()?.sumOf { it.validity().toInt() } ?: 0) + + (if (amount.asKnown().isPresent) 1 else 0) + + (charges.asKnown().getOrNull()?.sumOf { it.validity().toInt() } ?: 0) + + (if (date.asKnown().isPresent) 1 else 0) + + (if (description.asKnown().isPresent) 1 else 0) + + (if (productCode.asKnown().isPresent) 1 else 0) + + (if (quantity.asKnown().isPresent) 1 else 0) + + (if (tax.asKnown().isPresent) 1 else 0) + + (if (taxRate.asKnown().isPresent) 1 else 0) + + (unit.asKnown().getOrNull()?.validity() ?: 0) + + (if (unitPrice.asKnown().isPresent) 1 else 0) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Item && + allowances == other.allowances && + amount == other.amount && + charges == other.charges && + date == other.date && + description == other.description && + productCode == other.productCode && + quantity == other.quantity && + tax == other.tax && + taxRate == other.taxRate && + unit == other.unit && + unitPrice == other.unitPrice && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash( + allowances, + amount, + charges, + date, + description, + productCode, + quantity, + tax, + taxRate, + unit, + unitPrice, + additionalProperties, + ) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "Item{allowances=$allowances, amount=$amount, charges=$charges, date=$date, description=$description, productCode=$productCode, quantity=$quantity, tax=$tax, taxRate=$taxRate, unit=$unit, unitPrice=$unitPrice, additionalProperties=$additionalProperties}" + } + + /** + * Tax category code of the invoice (e.g., S for standard rate, Z for zero rate, E for exempt) + */ + class TaxCode @JsonCreator private constructor(private val value: JsonField) : Enum { + + /** + * Returns this class instance's raw value. + * + * This is usually only useful if this instance was deserialized from data that doesn't + * match any known member, and you want to know that value. For example, if the SDK is on an + * older version than the API, then the API may respond with new members that the SDK is + * unaware of. + */ + @com.fasterxml.jackson.annotation.JsonValue fun _value(): JsonField = value + + companion object { + + @JvmField val AE = of("AE") + + @JvmField val E = of("E") + + @JvmField val S = of("S") + + @JvmField val Z = of("Z") + + @JvmField val G = of("G") + + @JvmField val O = of("O") + + @JvmField val K = of("K") + + @JvmField val L = of("L") + + @JvmField val M = of("M") + + @JvmField val B = of("B") + + @JvmStatic fun of(value: String) = TaxCode(JsonField.of(value)) + } + + /** An enum containing [TaxCode]'s known values. */ + enum class Known { + AE, + E, + S, + Z, + G, + O, + K, + L, + M, + B, + } + + /** + * An enum containing [TaxCode]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [TaxCode] can contain an unknown value in a couple of cases: + * - It was deserialized from data that doesn't match any known member. For example, if the + * SDK is on an older version than the API, then the API may respond with new members that + * the SDK is unaware of. + * - It was constructed with an arbitrary value using the [of] method. + */ + enum class Value { + AE, + E, + S, + Z, + G, + O, + K, + L, + M, + B, + /** An enum member indicating that [TaxCode] was instantiated with an unknown value. */ + _UNKNOWN, + } + + /** + * Returns an enum member corresponding to this class instance's value, or [Value._UNKNOWN] + * if the class was instantiated with an unknown value. + * + * Use the [known] method instead if you're certain the value is always known or if you want + * to throw for the unknown case. + */ + fun value(): Value = + when (this) { + AE -> Value.AE + E -> Value.E + S -> Value.S + Z -> Value.Z + G -> Value.G + O -> Value.O + K -> Value.K + L -> Value.L + M -> Value.M + B -> Value.B + else -> Value._UNKNOWN + } + + /** + * Returns an enum member corresponding to this class instance's value. + * + * Use the [value] method instead if you're uncertain the value is always known and don't + * want to throw for the unknown case. + * + * @throws EInvoiceInvalidDataException if this class instance's value is a not a known + * member. + */ + fun known(): Known = + when (this) { + AE -> Known.AE + E -> Known.E + S -> Known.S + Z -> Known.Z + G -> Known.G + O -> Known.O + K -> Known.K + L -> Known.L + M -> Known.M + B -> Known.B + else -> throw EInvoiceInvalidDataException("Unknown TaxCode: $value") + } + + /** + * Returns this class instance's primitive wire representation. + * + * This differs from the [toString] method because that method is primarily for debugging + * and generally doesn't throw. + * + * @throws EInvoiceInvalidDataException if this class instance's value does not have the + * expected primitive type. + */ + fun asString(): String = + _value().asString().orElseThrow { + EInvoiceInvalidDataException("Value is not a String") + } + + private var validated: Boolean = false + + fun validate(): TaxCode = apply { + if (validated) { + return@apply + } + + known() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: EInvoiceInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic internal fun validity(): Int = if (value() == Value._UNKNOWN) 0 else 1 + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is TaxCode && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + class TaxDetail + @JsonCreator(mode = JsonCreator.Mode.DISABLED) + private constructor( + private val amount: JsonField, + private val rate: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("amount") @ExcludeMissing amount: JsonField = JsonMissing.of(), + @JsonProperty("rate") @ExcludeMissing rate: JsonField = JsonMissing.of(), + ) : this(amount, rate, mutableMapOf()) + + /** + * The tax amount for this tax category. Must be rounded to maximum 2 decimals + * + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun amount(): Optional = amount.getOptional("amount") + + /** + * The tax rate as a percentage (e.g., '21.00', '6.00', '0.00') + * + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun rate(): Optional = rate.getOptional("rate") + + /** + * Returns the raw JSON value of [amount]. + * + * Unlike [amount], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("amount") @ExcludeMissing fun _amount(): JsonField = amount + + /** + * Returns the raw JSON value of [rate]. + * + * Unlike [rate], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("rate") @ExcludeMissing fun _rate(): JsonField = rate + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** Returns a mutable builder for constructing an instance of [TaxDetail]. */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [TaxDetail]. */ + class Builder internal constructor() { + + private var amount: JsonField = JsonMissing.of() + private var rate: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(taxDetail: TaxDetail) = apply { + amount = taxDetail.amount + rate = taxDetail.rate + additionalProperties = taxDetail.additionalProperties.toMutableMap() + } + + /** The tax amount for this tax category. Must be rounded to maximum 2 decimals */ + fun amount(amount: String?) = amount(JsonField.ofNullable(amount)) + + /** Alias for calling [Builder.amount] with `amount.orElse(null)`. */ + fun amount(amount: Optional) = amount(amount.getOrNull()) + + /** + * Sets [Builder.amount] to an arbitrary JSON value. + * + * You should usually call [Builder.amount] with a well-typed [String] value instead. + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun amount(amount: JsonField) = apply { this.amount = amount } + + /** The tax rate as a percentage (e.g., '21.00', '6.00', '0.00') */ + fun rate(rate: String?) = rate(JsonField.ofNullable(rate)) + + /** Alias for calling [Builder.rate] with `rate.orElse(null)`. */ + fun rate(rate: Optional) = rate(rate.getOrNull()) + + /** + * Sets [Builder.rate] to an arbitrary JSON value. + * + * You should usually call [Builder.rate] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun rate(rate: JsonField) = apply { this.rate = rate } + + fun additionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.clear() + putAllAdditionalProperties(additionalProperties) + } + + fun putAdditionalProperty(key: String, value: JsonValue) = apply { + additionalProperties.put(key, value) + } + + fun putAllAdditionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.putAll(additionalProperties) + } + + fun removeAdditionalProperty(key: String) = apply { additionalProperties.remove(key) } + + fun removeAllAdditionalProperties(keys: Set) = apply { + keys.forEach(::removeAdditionalProperty) + } + + /** + * Returns an immutable instance of [TaxDetail]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): TaxDetail = TaxDetail(amount, rate, additionalProperties.toMutableMap()) + } + + private var validated: Boolean = false + + fun validate(): TaxDetail = apply { + if (validated) { + return@apply + } + + amount() + rate() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: EInvoiceInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic + internal fun validity(): Int = + (if (amount.asKnown().isPresent) 1 else 0) + (if (rate.asKnown().isPresent) 1 else 0) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is TaxDetail && + amount == other.amount && + rate == other.rate && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { Objects.hash(amount, rate, additionalProperties) } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "TaxDetail{amount=$amount, rate=$rate, additionalProperties=$additionalProperties}" + } + + /** + * VATEX code list for VAT exemption reasons + * + * Agency: CEF Identifier: vatex + */ + class Vatex @JsonCreator private constructor(private val value: JsonField) : Enum { + + /** + * Returns this class instance's raw value. + * + * This is usually only useful if this instance was deserialized from data that doesn't + * match any known member, and you want to know that value. For example, if the SDK is on an + * older version than the API, then the API may respond with new members that the SDK is + * unaware of. + */ + @com.fasterxml.jackson.annotation.JsonValue fun _value(): JsonField = value + + companion object { + + @JvmField val VATEX_EU_79_C = of("VATEX-EU-79-C") + + @JvmField val VATEX_EU_132 = of("VATEX-EU-132") + + @JvmField val VATEX_EU_132_1_A = of("VATEX-EU-132-1A") + + @JvmField val VATEX_EU_132_1_B = of("VATEX-EU-132-1B") + + @JvmField val VATEX_EU_132_1_C = of("VATEX-EU-132-1C") + + @JvmField val VATEX_EU_132_1_D = of("VATEX-EU-132-1D") + + @JvmField val VATEX_EU_132_1_E = of("VATEX-EU-132-1E") + + @JvmField val VATEX_EU_132_1_F = of("VATEX-EU-132-1F") + + @JvmField val VATEX_EU_132_1_G = of("VATEX-EU-132-1G") + + @JvmField val VATEX_EU_132_1_H = of("VATEX-EU-132-1H") + + @JvmField val VATEX_EU_132_1_I = of("VATEX-EU-132-1I") + + @JvmField val VATEX_EU_132_1_J = of("VATEX-EU-132-1J") + + @JvmField val VATEX_EU_132_1_K = of("VATEX-EU-132-1K") + + @JvmField val VATEX_EU_132_1_L = of("VATEX-EU-132-1L") + + @JvmField val VATEX_EU_132_1_M = of("VATEX-EU-132-1M") + + @JvmField val VATEX_EU_132_1_N = of("VATEX-EU-132-1N") + + @JvmField val VATEX_EU_132_1_O = of("VATEX-EU-132-1O") + + @JvmField val VATEX_EU_132_1_P = of("VATEX-EU-132-1P") + + @JvmField val VATEX_EU_132_1_Q = of("VATEX-EU-132-1Q") + + @JvmField val VATEX_EU_143 = of("VATEX-EU-143") + + @JvmField val VATEX_EU_143_1_A = of("VATEX-EU-143-1A") + + @JvmField val VATEX_EU_143_1_B = of("VATEX-EU-143-1B") + + @JvmField val VATEX_EU_143_1_C = of("VATEX-EU-143-1C") + + @JvmField val VATEX_EU_143_1_D = of("VATEX-EU-143-1D") + + @JvmField val VATEX_EU_143_1_E = of("VATEX-EU-143-1E") + + @JvmField val VATEX_EU_143_1_F = of("VATEX-EU-143-1F") + + @JvmField val VATEX_EU_143_1_FA = of("VATEX-EU-143-1FA") + + @JvmField val VATEX_EU_143_1_G = of("VATEX-EU-143-1G") + + @JvmField val VATEX_EU_143_1_H = of("VATEX-EU-143-1H") + + @JvmField val VATEX_EU_143_1_I = of("VATEX-EU-143-1I") + + @JvmField val VATEX_EU_143_1_J = of("VATEX-EU-143-1J") + + @JvmField val VATEX_EU_143_1_K = of("VATEX-EU-143-1K") + + @JvmField val VATEX_EU_143_1_L = of("VATEX-EU-143-1L") + + @JvmField val VATEX_EU_144 = of("VATEX-EU-144") + + @JvmField val VATEX_EU_146_1_E = of("VATEX-EU-146-1E") + + @JvmField val VATEX_EU_148 = of("VATEX-EU-148") + + @JvmField val VATEX_EU_148_A = of("VATEX-EU-148-A") + + @JvmField val VATEX_EU_148_B = of("VATEX-EU-148-B") + + @JvmField val VATEX_EU_148_C = of("VATEX-EU-148-C") + + @JvmField val VATEX_EU_148_D = of("VATEX-EU-148-D") + + @JvmField val VATEX_EU_148_E = of("VATEX-EU-148-E") + + @JvmField val VATEX_EU_148_F = of("VATEX-EU-148-F") + + @JvmField val VATEX_EU_148_G = of("VATEX-EU-148-G") + + @JvmField val VATEX_EU_151 = of("VATEX-EU-151") + + @JvmField val VATEX_EU_151_1_A = of("VATEX-EU-151-1A") + + @JvmField val VATEX_EU_151_1_AA = of("VATEX-EU-151-1AA") + + @JvmField val VATEX_EU_151_1_B = of("VATEX-EU-151-1B") + + @JvmField val VATEX_EU_151_1_C = of("VATEX-EU-151-1C") + + @JvmField val VATEX_EU_151_1_D = of("VATEX-EU-151-1D") + + @JvmField val VATEX_EU_151_1_E = of("VATEX-EU-151-1E") + + @JvmField val VATEX_EU_159 = of("VATEX-EU-159") + + @JvmField val VATEX_EU_309 = of("VATEX-EU-309") + + @JvmField val VATEX_EU_AE = of("VATEX-EU-AE") + + @JvmField val VATEX_EU_D = of("VATEX-EU-D") + + @JvmField val VATEX_EU_F = of("VATEX-EU-F") + + @JvmField val VATEX_EU_G = of("VATEX-EU-G") + + @JvmField val VATEX_EU_I = of("VATEX-EU-I") + + @JvmField val VATEX_EU_IC = of("VATEX-EU-IC") + + @JvmField val VATEX_EU_O = of("VATEX-EU-O") + + @JvmField val VATEX_EU_J = of("VATEX-EU-J") + + @JvmField val VATEX_FR_FRANCHISE = of("VATEX-FR-FRANCHISE") + + @JvmField val VATEX_FR_CNWVAT = of("VATEX-FR-CNWVAT") + + @JvmStatic fun of(value: String) = Vatex(JsonField.of(value)) + } + + /** An enum containing [Vatex]'s known values. */ + enum class Known { + VATEX_EU_79_C, + VATEX_EU_132, + VATEX_EU_132_1_A, + VATEX_EU_132_1_B, + VATEX_EU_132_1_C, + VATEX_EU_132_1_D, + VATEX_EU_132_1_E, + VATEX_EU_132_1_F, + VATEX_EU_132_1_G, + VATEX_EU_132_1_H, + VATEX_EU_132_1_I, + VATEX_EU_132_1_J, + VATEX_EU_132_1_K, + VATEX_EU_132_1_L, + VATEX_EU_132_1_M, + VATEX_EU_132_1_N, + VATEX_EU_132_1_O, + VATEX_EU_132_1_P, + VATEX_EU_132_1_Q, + VATEX_EU_143, + VATEX_EU_143_1_A, + VATEX_EU_143_1_B, + VATEX_EU_143_1_C, + VATEX_EU_143_1_D, + VATEX_EU_143_1_E, + VATEX_EU_143_1_F, + VATEX_EU_143_1_FA, + VATEX_EU_143_1_G, + VATEX_EU_143_1_H, + VATEX_EU_143_1_I, + VATEX_EU_143_1_J, + VATEX_EU_143_1_K, + VATEX_EU_143_1_L, + VATEX_EU_144, + VATEX_EU_146_1_E, + VATEX_EU_148, + VATEX_EU_148_A, + VATEX_EU_148_B, + VATEX_EU_148_C, + VATEX_EU_148_D, + VATEX_EU_148_E, + VATEX_EU_148_F, + VATEX_EU_148_G, + VATEX_EU_151, + VATEX_EU_151_1_A, + VATEX_EU_151_1_AA, + VATEX_EU_151_1_B, + VATEX_EU_151_1_C, + VATEX_EU_151_1_D, + VATEX_EU_151_1_E, + VATEX_EU_159, + VATEX_EU_309, + VATEX_EU_AE, + VATEX_EU_D, + VATEX_EU_F, + VATEX_EU_G, + VATEX_EU_I, + VATEX_EU_IC, + VATEX_EU_O, + VATEX_EU_J, + VATEX_FR_FRANCHISE, + VATEX_FR_CNWVAT, + } + + /** + * An enum containing [Vatex]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [Vatex] can contain an unknown value in a couple of cases: + * - It was deserialized from data that doesn't match any known member. For example, if the + * SDK is on an older version than the API, then the API may respond with new members that + * the SDK is unaware of. + * - It was constructed with an arbitrary value using the [of] method. + */ + enum class Value { + VATEX_EU_79_C, + VATEX_EU_132, + VATEX_EU_132_1_A, + VATEX_EU_132_1_B, + VATEX_EU_132_1_C, + VATEX_EU_132_1_D, + VATEX_EU_132_1_E, + VATEX_EU_132_1_F, + VATEX_EU_132_1_G, + VATEX_EU_132_1_H, + VATEX_EU_132_1_I, + VATEX_EU_132_1_J, + VATEX_EU_132_1_K, + VATEX_EU_132_1_L, + VATEX_EU_132_1_M, + VATEX_EU_132_1_N, + VATEX_EU_132_1_O, + VATEX_EU_132_1_P, + VATEX_EU_132_1_Q, + VATEX_EU_143, + VATEX_EU_143_1_A, + VATEX_EU_143_1_B, + VATEX_EU_143_1_C, + VATEX_EU_143_1_D, + VATEX_EU_143_1_E, + VATEX_EU_143_1_F, + VATEX_EU_143_1_FA, + VATEX_EU_143_1_G, + VATEX_EU_143_1_H, + VATEX_EU_143_1_I, + VATEX_EU_143_1_J, + VATEX_EU_143_1_K, + VATEX_EU_143_1_L, + VATEX_EU_144, + VATEX_EU_146_1_E, + VATEX_EU_148, + VATEX_EU_148_A, + VATEX_EU_148_B, + VATEX_EU_148_C, + VATEX_EU_148_D, + VATEX_EU_148_E, + VATEX_EU_148_F, + VATEX_EU_148_G, + VATEX_EU_151, + VATEX_EU_151_1_A, + VATEX_EU_151_1_AA, + VATEX_EU_151_1_B, + VATEX_EU_151_1_C, + VATEX_EU_151_1_D, + VATEX_EU_151_1_E, + VATEX_EU_159, + VATEX_EU_309, + VATEX_EU_AE, + VATEX_EU_D, + VATEX_EU_F, + VATEX_EU_G, + VATEX_EU_I, + VATEX_EU_IC, + VATEX_EU_O, + VATEX_EU_J, + VATEX_FR_FRANCHISE, + VATEX_FR_CNWVAT, + /** An enum member indicating that [Vatex] was instantiated with an unknown value. */ + _UNKNOWN, + } + + /** + * Returns an enum member corresponding to this class instance's value, or [Value._UNKNOWN] + * if the class was instantiated with an unknown value. + * + * Use the [known] method instead if you're certain the value is always known or if you want + * to throw for the unknown case. + */ + fun value(): Value = + when (this) { + VATEX_EU_79_C -> Value.VATEX_EU_79_C + VATEX_EU_132 -> Value.VATEX_EU_132 + VATEX_EU_132_1_A -> Value.VATEX_EU_132_1_A + VATEX_EU_132_1_B -> Value.VATEX_EU_132_1_B + VATEX_EU_132_1_C -> Value.VATEX_EU_132_1_C + VATEX_EU_132_1_D -> Value.VATEX_EU_132_1_D + VATEX_EU_132_1_E -> Value.VATEX_EU_132_1_E + VATEX_EU_132_1_F -> Value.VATEX_EU_132_1_F + VATEX_EU_132_1_G -> Value.VATEX_EU_132_1_G + VATEX_EU_132_1_H -> Value.VATEX_EU_132_1_H + VATEX_EU_132_1_I -> Value.VATEX_EU_132_1_I + VATEX_EU_132_1_J -> Value.VATEX_EU_132_1_J + VATEX_EU_132_1_K -> Value.VATEX_EU_132_1_K + VATEX_EU_132_1_L -> Value.VATEX_EU_132_1_L + VATEX_EU_132_1_M -> Value.VATEX_EU_132_1_M + VATEX_EU_132_1_N -> Value.VATEX_EU_132_1_N + VATEX_EU_132_1_O -> Value.VATEX_EU_132_1_O + VATEX_EU_132_1_P -> Value.VATEX_EU_132_1_P + VATEX_EU_132_1_Q -> Value.VATEX_EU_132_1_Q + VATEX_EU_143 -> Value.VATEX_EU_143 + VATEX_EU_143_1_A -> Value.VATEX_EU_143_1_A + VATEX_EU_143_1_B -> Value.VATEX_EU_143_1_B + VATEX_EU_143_1_C -> Value.VATEX_EU_143_1_C + VATEX_EU_143_1_D -> Value.VATEX_EU_143_1_D + VATEX_EU_143_1_E -> Value.VATEX_EU_143_1_E + VATEX_EU_143_1_F -> Value.VATEX_EU_143_1_F + VATEX_EU_143_1_FA -> Value.VATEX_EU_143_1_FA + VATEX_EU_143_1_G -> Value.VATEX_EU_143_1_G + VATEX_EU_143_1_H -> Value.VATEX_EU_143_1_H + VATEX_EU_143_1_I -> Value.VATEX_EU_143_1_I + VATEX_EU_143_1_J -> Value.VATEX_EU_143_1_J + VATEX_EU_143_1_K -> Value.VATEX_EU_143_1_K + VATEX_EU_143_1_L -> Value.VATEX_EU_143_1_L + VATEX_EU_144 -> Value.VATEX_EU_144 + VATEX_EU_146_1_E -> Value.VATEX_EU_146_1_E + VATEX_EU_148 -> Value.VATEX_EU_148 + VATEX_EU_148_A -> Value.VATEX_EU_148_A + VATEX_EU_148_B -> Value.VATEX_EU_148_B + VATEX_EU_148_C -> Value.VATEX_EU_148_C + VATEX_EU_148_D -> Value.VATEX_EU_148_D + VATEX_EU_148_E -> Value.VATEX_EU_148_E + VATEX_EU_148_F -> Value.VATEX_EU_148_F + VATEX_EU_148_G -> Value.VATEX_EU_148_G + VATEX_EU_151 -> Value.VATEX_EU_151 + VATEX_EU_151_1_A -> Value.VATEX_EU_151_1_A + VATEX_EU_151_1_AA -> Value.VATEX_EU_151_1_AA + VATEX_EU_151_1_B -> Value.VATEX_EU_151_1_B + VATEX_EU_151_1_C -> Value.VATEX_EU_151_1_C + VATEX_EU_151_1_D -> Value.VATEX_EU_151_1_D + VATEX_EU_151_1_E -> Value.VATEX_EU_151_1_E + VATEX_EU_159 -> Value.VATEX_EU_159 + VATEX_EU_309 -> Value.VATEX_EU_309 + VATEX_EU_AE -> Value.VATEX_EU_AE + VATEX_EU_D -> Value.VATEX_EU_D + VATEX_EU_F -> Value.VATEX_EU_F + VATEX_EU_G -> Value.VATEX_EU_G + VATEX_EU_I -> Value.VATEX_EU_I + VATEX_EU_IC -> Value.VATEX_EU_IC + VATEX_EU_O -> Value.VATEX_EU_O + VATEX_EU_J -> Value.VATEX_EU_J + VATEX_FR_FRANCHISE -> Value.VATEX_FR_FRANCHISE + VATEX_FR_CNWVAT -> Value.VATEX_FR_CNWVAT + else -> Value._UNKNOWN + } + + /** + * Returns an enum member corresponding to this class instance's value. + * + * Use the [value] method instead if you're uncertain the value is always known and don't + * want to throw for the unknown case. + * + * @throws EInvoiceInvalidDataException if this class instance's value is a not a known + * member. + */ + fun known(): Known = + when (this) { + VATEX_EU_79_C -> Known.VATEX_EU_79_C + VATEX_EU_132 -> Known.VATEX_EU_132 + VATEX_EU_132_1_A -> Known.VATEX_EU_132_1_A + VATEX_EU_132_1_B -> Known.VATEX_EU_132_1_B + VATEX_EU_132_1_C -> Known.VATEX_EU_132_1_C + VATEX_EU_132_1_D -> Known.VATEX_EU_132_1_D + VATEX_EU_132_1_E -> Known.VATEX_EU_132_1_E + VATEX_EU_132_1_F -> Known.VATEX_EU_132_1_F + VATEX_EU_132_1_G -> Known.VATEX_EU_132_1_G + VATEX_EU_132_1_H -> Known.VATEX_EU_132_1_H + VATEX_EU_132_1_I -> Known.VATEX_EU_132_1_I + VATEX_EU_132_1_J -> Known.VATEX_EU_132_1_J + VATEX_EU_132_1_K -> Known.VATEX_EU_132_1_K + VATEX_EU_132_1_L -> Known.VATEX_EU_132_1_L + VATEX_EU_132_1_M -> Known.VATEX_EU_132_1_M + VATEX_EU_132_1_N -> Known.VATEX_EU_132_1_N + VATEX_EU_132_1_O -> Known.VATEX_EU_132_1_O + VATEX_EU_132_1_P -> Known.VATEX_EU_132_1_P + VATEX_EU_132_1_Q -> Known.VATEX_EU_132_1_Q + VATEX_EU_143 -> Known.VATEX_EU_143 + VATEX_EU_143_1_A -> Known.VATEX_EU_143_1_A + VATEX_EU_143_1_B -> Known.VATEX_EU_143_1_B + VATEX_EU_143_1_C -> Known.VATEX_EU_143_1_C + VATEX_EU_143_1_D -> Known.VATEX_EU_143_1_D + VATEX_EU_143_1_E -> Known.VATEX_EU_143_1_E + VATEX_EU_143_1_F -> Known.VATEX_EU_143_1_F + VATEX_EU_143_1_FA -> Known.VATEX_EU_143_1_FA + VATEX_EU_143_1_G -> Known.VATEX_EU_143_1_G + VATEX_EU_143_1_H -> Known.VATEX_EU_143_1_H + VATEX_EU_143_1_I -> Known.VATEX_EU_143_1_I + VATEX_EU_143_1_J -> Known.VATEX_EU_143_1_J + VATEX_EU_143_1_K -> Known.VATEX_EU_143_1_K + VATEX_EU_143_1_L -> Known.VATEX_EU_143_1_L + VATEX_EU_144 -> Known.VATEX_EU_144 + VATEX_EU_146_1_E -> Known.VATEX_EU_146_1_E + VATEX_EU_148 -> Known.VATEX_EU_148 + VATEX_EU_148_A -> Known.VATEX_EU_148_A + VATEX_EU_148_B -> Known.VATEX_EU_148_B + VATEX_EU_148_C -> Known.VATEX_EU_148_C + VATEX_EU_148_D -> Known.VATEX_EU_148_D + VATEX_EU_148_E -> Known.VATEX_EU_148_E + VATEX_EU_148_F -> Known.VATEX_EU_148_F + VATEX_EU_148_G -> Known.VATEX_EU_148_G + VATEX_EU_151 -> Known.VATEX_EU_151 + VATEX_EU_151_1_A -> Known.VATEX_EU_151_1_A + VATEX_EU_151_1_AA -> Known.VATEX_EU_151_1_AA + VATEX_EU_151_1_B -> Known.VATEX_EU_151_1_B + VATEX_EU_151_1_C -> Known.VATEX_EU_151_1_C + VATEX_EU_151_1_D -> Known.VATEX_EU_151_1_D + VATEX_EU_151_1_E -> Known.VATEX_EU_151_1_E + VATEX_EU_159 -> Known.VATEX_EU_159 + VATEX_EU_309 -> Known.VATEX_EU_309 + VATEX_EU_AE -> Known.VATEX_EU_AE + VATEX_EU_D -> Known.VATEX_EU_D + VATEX_EU_F -> Known.VATEX_EU_F + VATEX_EU_G -> Known.VATEX_EU_G + VATEX_EU_I -> Known.VATEX_EU_I + VATEX_EU_IC -> Known.VATEX_EU_IC + VATEX_EU_O -> Known.VATEX_EU_O + VATEX_EU_J -> Known.VATEX_EU_J + VATEX_FR_FRANCHISE -> Known.VATEX_FR_FRANCHISE + VATEX_FR_CNWVAT -> Known.VATEX_FR_CNWVAT + else -> throw EInvoiceInvalidDataException("Unknown Vatex: $value") + } + + /** + * Returns this class instance's primitive wire representation. + * + * This differs from the [toString] method because that method is primarily for debugging + * and generally doesn't throw. + * + * @throws EInvoiceInvalidDataException if this class instance's value does not have the + * expected primitive type. + */ + fun asString(): String = + _value().asString().orElseThrow { + EInvoiceInvalidDataException("Value is not a String") + } + + private var validated: Boolean = false + + fun validate(): Vatex = apply { + if (validated) { + return@apply + } + + known() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: EInvoiceInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic internal fun validity(): Int = if (value() == Value._UNKNOWN) 0 else 1 + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Vatex && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is DocumentCreateFromPdfResponse && + allowances == other.allowances && + amountDue == other.amountDue && + attachments == other.attachments && + billingAddress == other.billingAddress && + billingAddressRecipient == other.billingAddressRecipient && + charges == other.charges && + currency == other.currency && + customerAddress == other.customerAddress && + customerAddressRecipient == other.customerAddressRecipient && + customerCompanyId == other.customerCompanyId && + customerEmail == other.customerEmail && + customerId == other.customerId && + customerName == other.customerName && + customerTaxId == other.customerTaxId && + direction == other.direction && + documentType == other.documentType && + dueDate == other.dueDate && + invoiceDate == other.invoiceDate && + invoiceId == other.invoiceId && + invoiceTotal == other.invoiceTotal && + items == other.items && + note == other.note && + paymentDetails == other.paymentDetails && + paymentTerm == other.paymentTerm && + purchaseOrder == other.purchaseOrder && + remittanceAddress == other.remittanceAddress && + remittanceAddressRecipient == other.remittanceAddressRecipient && + serviceAddress == other.serviceAddress && + serviceAddressRecipient == other.serviceAddressRecipient && + serviceEndDate == other.serviceEndDate && + serviceStartDate == other.serviceStartDate && + shippingAddress == other.shippingAddress && + shippingAddressRecipient == other.shippingAddressRecipient && + state == other.state && + subtotal == other.subtotal && + success == other.success && + taxCode == other.taxCode && + taxDetails == other.taxDetails && + totalDiscount == other.totalDiscount && + totalTax == other.totalTax && + ublDocument == other.ublDocument && + vatex == other.vatex && + vatexNote == other.vatexNote && + vendorAddress == other.vendorAddress && + vendorAddressRecipient == other.vendorAddressRecipient && + vendorCompanyId == other.vendorCompanyId && + vendorEmail == other.vendorEmail && + vendorName == other.vendorName && + vendorTaxId == other.vendorTaxId && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash( + allowances, + amountDue, + attachments, + billingAddress, + billingAddressRecipient, + charges, + currency, + customerAddress, + customerAddressRecipient, + customerCompanyId, + customerEmail, + customerId, + customerName, + customerTaxId, + direction, + documentType, + dueDate, + invoiceDate, + invoiceId, + invoiceTotal, + items, + note, + paymentDetails, + paymentTerm, + purchaseOrder, + remittanceAddress, + remittanceAddressRecipient, + serviceAddress, + serviceAddressRecipient, + serviceEndDate, + serviceStartDate, + shippingAddress, + shippingAddressRecipient, + state, + subtotal, + success, + taxCode, + taxDetails, + totalDiscount, + totalTax, + ublDocument, + vatex, + vatexNote, + vendorAddress, + vendorAddressRecipient, + vendorCompanyId, + vendorEmail, + vendorName, + vendorTaxId, + additionalProperties, + ) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "DocumentCreateFromPdfResponse{allowances=$allowances, amountDue=$amountDue, attachments=$attachments, billingAddress=$billingAddress, billingAddressRecipient=$billingAddressRecipient, charges=$charges, currency=$currency, customerAddress=$customerAddress, customerAddressRecipient=$customerAddressRecipient, customerCompanyId=$customerCompanyId, customerEmail=$customerEmail, customerId=$customerId, customerName=$customerName, customerTaxId=$customerTaxId, direction=$direction, documentType=$documentType, dueDate=$dueDate, invoiceDate=$invoiceDate, invoiceId=$invoiceId, invoiceTotal=$invoiceTotal, items=$items, note=$note, paymentDetails=$paymentDetails, paymentTerm=$paymentTerm, purchaseOrder=$purchaseOrder, remittanceAddress=$remittanceAddress, remittanceAddressRecipient=$remittanceAddressRecipient, serviceAddress=$serviceAddress, serviceAddressRecipient=$serviceAddressRecipient, serviceEndDate=$serviceEndDate, serviceStartDate=$serviceStartDate, shippingAddress=$shippingAddress, shippingAddressRecipient=$shippingAddressRecipient, state=$state, subtotal=$subtotal, success=$success, taxCode=$taxCode, taxDetails=$taxDetails, totalDiscount=$totalDiscount, totalTax=$totalTax, ublDocument=$ublDocument, vatex=$vatex, vatexNote=$vatexNote, vendorAddress=$vendorAddress, vendorAddressRecipient=$vendorAddressRecipient, vendorCompanyId=$vendorCompanyId, vendorEmail=$vendorEmail, vendorName=$vendorName, vendorTaxId=$vendorTaxId, additionalProperties=$additionalProperties}" +} diff --git a/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/models/documents/DocumentCreateParams.kt b/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/models/documents/DocumentCreateParams.kt index 2c4d977..e8cf143 100644 --- a/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/models/documents/DocumentCreateParams.kt +++ b/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/models/documents/DocumentCreateParams.kt @@ -8,15 +8,24 @@ import com.e_invoice.api.core.checkRequired import com.e_invoice.api.core.http.Headers import com.e_invoice.api.core.http.QueryParams import java.util.Objects +import java.util.Optional +import kotlin.jvm.optionals.getOrNull /** Create a new invoice or credit note */ class DocumentCreateParams private constructor( + private val constructPdf: Boolean?, private val documentCreate: DocumentCreate, private val additionalHeaders: Headers, private val additionalQueryParams: QueryParams, ) : Params { + /** + * If true, generate a constructed PDF from the document and include it both as document + * attachment and embedded in the UBL. + */ + fun constructPdf(): Optional = Optional.ofNullable(constructPdf) + fun documentCreate(): DocumentCreate = documentCreate fun _additionalBodyProperties(): Map = documentCreate._additionalProperties() @@ -45,17 +54,35 @@ private constructor( /** A builder for [DocumentCreateParams]. */ class Builder internal constructor() { + private var constructPdf: Boolean? = null private var documentCreate: DocumentCreate? = null private var additionalHeaders: Headers.Builder = Headers.builder() private var additionalQueryParams: QueryParams.Builder = QueryParams.builder() @JvmSynthetic internal fun from(documentCreateParams: DocumentCreateParams) = apply { + constructPdf = documentCreateParams.constructPdf documentCreate = documentCreateParams.documentCreate additionalHeaders = documentCreateParams.additionalHeaders.toBuilder() additionalQueryParams = documentCreateParams.additionalQueryParams.toBuilder() } + /** + * If true, generate a constructed PDF from the document and include it both as document + * attachment and embedded in the UBL. + */ + fun constructPdf(constructPdf: Boolean?) = apply { this.constructPdf = constructPdf } + + /** + * Alias for [Builder.constructPdf]. + * + * This unboxed primitive overload exists for backwards compatibility. + */ + fun constructPdf(constructPdf: Boolean) = constructPdf(constructPdf as Boolean?) + + /** Alias for calling [Builder.constructPdf] with `constructPdf.orElse(null)`. */ + fun constructPdf(constructPdf: Optional) = constructPdf(constructPdf.getOrNull()) + fun documentCreate(documentCreate: DocumentCreate) = apply { this.documentCreate = documentCreate } @@ -172,6 +199,7 @@ private constructor( */ fun build(): DocumentCreateParams = DocumentCreateParams( + constructPdf, checkRequired("documentCreate", documentCreate), additionalHeaders.build(), additionalQueryParams.build(), @@ -182,7 +210,13 @@ private constructor( override fun _headers(): Headers = additionalHeaders - override fun _queryParams(): QueryParams = additionalQueryParams + override fun _queryParams(): QueryParams = + QueryParams.builder() + .apply { + constructPdf?.let { put("construct_pdf", it.toString()) } + putAll(additionalQueryParams) + } + .build() override fun equals(other: Any?): Boolean { if (this === other) { @@ -190,14 +224,15 @@ private constructor( } return other is DocumentCreateParams && + constructPdf == other.constructPdf && documentCreate == other.documentCreate && additionalHeaders == other.additionalHeaders && additionalQueryParams == other.additionalQueryParams } override fun hashCode(): Int = - Objects.hash(documentCreate, additionalHeaders, additionalQueryParams) + Objects.hash(constructPdf, documentCreate, additionalHeaders, additionalQueryParams) override fun toString() = - "DocumentCreateParams{documentCreate=$documentCreate, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams}" + "DocumentCreateParams{constructPdf=$constructPdf, documentCreate=$documentCreate, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams}" } diff --git a/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/models/documents/DocumentResponse.kt b/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/models/documents/DocumentResponse.kt index f266b64..ee70256 100644 --- a/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/models/documents/DocumentResponse.kt +++ b/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/models/documents/DocumentResponse.kt @@ -2,6 +2,7 @@ package com.e_invoice.api.models.documents +import com.e_invoice.api.core.Enum import com.e_invoice.api.core.ExcludeMissing import com.e_invoice.api.core.JsonField import com.e_invoice.api.core.JsonMissing @@ -17,6 +18,7 @@ import com.fasterxml.jackson.annotation.JsonAnySetter import com.fasterxml.jackson.annotation.JsonCreator import com.fasterxml.jackson.annotation.JsonProperty import java.time.LocalDate +import java.time.OffsetDateTime import java.util.Collections import java.util.Objects import java.util.Optional @@ -26,13 +28,17 @@ class DocumentResponse @JsonCreator(mode = JsonCreator.Mode.DISABLED) private constructor( private val id: JsonField, + private val createdAt: JsonField, + private val allowances: JsonField>, private val amountDue: JsonField, private val attachments: JsonField>, private val billingAddress: JsonField, private val billingAddressRecipient: JsonField, + private val charges: JsonField>, private val currency: JsonField, private val customerAddress: JsonField, private val customerAddressRecipient: JsonField, + private val customerCompanyId: JsonField, private val customerEmail: JsonField, private val customerId: JsonField, private val customerName: JsonField, @@ -47,7 +53,6 @@ private constructor( private val note: JsonField, private val paymentDetails: JsonField>, private val paymentTerm: JsonField, - private val previousUnpaidBalance: JsonField, private val purchaseOrder: JsonField, private val remittanceAddress: JsonField, private val remittanceAddressRecipient: JsonField, @@ -59,11 +64,15 @@ private constructor( private val shippingAddressRecipient: JsonField, private val state: JsonField, private val subtotal: JsonField, + private val taxCode: JsonField, private val taxDetails: JsonField>, private val totalDiscount: JsonField, private val totalTax: JsonField, + private val vatex: JsonField, + private val vatexNote: JsonField, private val vendorAddress: JsonField, private val vendorAddressRecipient: JsonField, + private val vendorCompanyId: JsonField, private val vendorEmail: JsonField, private val vendorName: JsonField, private val vendorTaxId: JsonField, @@ -73,6 +82,12 @@ private constructor( @JsonCreator private constructor( @JsonProperty("id") @ExcludeMissing id: JsonField = JsonMissing.of(), + @JsonProperty("created_at") + @ExcludeMissing + createdAt: JsonField = JsonMissing.of(), + @JsonProperty("allowances") + @ExcludeMissing + allowances: JsonField> = JsonMissing.of(), @JsonProperty("amount_due") @ExcludeMissing amountDue: JsonField = JsonMissing.of(), @JsonProperty("attachments") @ExcludeMissing @@ -83,6 +98,9 @@ private constructor( @JsonProperty("billing_address_recipient") @ExcludeMissing billingAddressRecipient: JsonField = JsonMissing.of(), + @JsonProperty("charges") + @ExcludeMissing + charges: JsonField> = JsonMissing.of(), @JsonProperty("currency") @ExcludeMissing currency: JsonField = JsonMissing.of(), @@ -92,6 +110,9 @@ private constructor( @JsonProperty("customer_address_recipient") @ExcludeMissing customerAddressRecipient: JsonField = JsonMissing.of(), + @JsonProperty("customer_company_id") + @ExcludeMissing + customerCompanyId: JsonField = JsonMissing.of(), @JsonProperty("customer_email") @ExcludeMissing customerEmail: JsonField = JsonMissing.of(), @@ -126,9 +147,6 @@ private constructor( @JsonProperty("payment_term") @ExcludeMissing paymentTerm: JsonField = JsonMissing.of(), - @JsonProperty("previous_unpaid_balance") - @ExcludeMissing - previousUnpaidBalance: JsonField = JsonMissing.of(), @JsonProperty("purchase_order") @ExcludeMissing purchaseOrder: JsonField = JsonMissing.of(), @@ -158,6 +176,7 @@ private constructor( shippingAddressRecipient: JsonField = JsonMissing.of(), @JsonProperty("state") @ExcludeMissing state: JsonField = JsonMissing.of(), @JsonProperty("subtotal") @ExcludeMissing subtotal: JsonField = JsonMissing.of(), + @JsonProperty("tax_code") @ExcludeMissing taxCode: JsonField = JsonMissing.of(), @JsonProperty("tax_details") @ExcludeMissing taxDetails: JsonField> = JsonMissing.of(), @@ -165,12 +184,17 @@ private constructor( @ExcludeMissing totalDiscount: JsonField = JsonMissing.of(), @JsonProperty("total_tax") @ExcludeMissing totalTax: JsonField = JsonMissing.of(), + @JsonProperty("vatex") @ExcludeMissing vatex: JsonField = JsonMissing.of(), + @JsonProperty("vatex_note") @ExcludeMissing vatexNote: JsonField = JsonMissing.of(), @JsonProperty("vendor_address") @ExcludeMissing vendorAddress: JsonField = JsonMissing.of(), @JsonProperty("vendor_address_recipient") @ExcludeMissing vendorAddressRecipient: JsonField = JsonMissing.of(), + @JsonProperty("vendor_company_id") + @ExcludeMissing + vendorCompanyId: JsonField = JsonMissing.of(), @JsonProperty("vendor_email") @ExcludeMissing vendorEmail: JsonField = JsonMissing.of(), @@ -182,13 +206,17 @@ private constructor( vendorTaxId: JsonField = JsonMissing.of(), ) : this( id, + createdAt, + allowances, amountDue, attachments, billingAddress, billingAddressRecipient, + charges, currency, customerAddress, customerAddressRecipient, + customerCompanyId, customerEmail, customerId, customerName, @@ -203,7 +231,6 @@ private constructor( note, paymentDetails, paymentTerm, - previousUnpaidBalance, purchaseOrder, remittanceAddress, remittanceAddressRecipient, @@ -215,11 +242,15 @@ private constructor( shippingAddressRecipient, state, subtotal, + taxCode, taxDetails, totalDiscount, totalTax, + vatex, + vatexNote, vendorAddress, vendorAddressRecipient, + vendorCompanyId, vendorEmail, vendorName, vendorTaxId, @@ -233,6 +264,20 @@ private constructor( fun id(): String = id.getRequired("id") /** + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun createdAt(): OffsetDateTime = createdAt.getRequired("created_at") + + /** + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun allowances(): Optional> = allowances.getOptional("allowances") + + /** + * The amount due for payment. Must be positive and rounded to maximum 2 decimals + * * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the * server responded with an unexpected value). */ @@ -245,12 +290,16 @@ private constructor( fun attachments(): Optional> = attachments.getOptional("attachments") /** + * The billing address (if different from customer address) + * * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the * server responded with an unexpected value). */ fun billingAddress(): Optional = billingAddress.getOptional("billing_address") /** + * The recipient name at the billing address + * * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the * server responded with an unexpected value). */ @@ -258,7 +307,13 @@ private constructor( billingAddressRecipient.getOptional("billing_address_recipient") /** - * Currency of the invoice + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun charges(): Optional> = charges.getOptional("charges") + + /** + * Currency of the invoice (ISO 4217 currency code) * * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the * server responded with an unexpected value). @@ -266,12 +321,16 @@ private constructor( fun currency(): Optional = currency.getOptional("currency") /** + * The address of the customer/buyer + * * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the * server responded with an unexpected value). */ fun customerAddress(): Optional = customerAddress.getOptional("customer_address") /** + * The recipient name at the customer address + * * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the * server responded with an unexpected value). */ @@ -279,60 +338,90 @@ private constructor( customerAddressRecipient.getOptional("customer_address_recipient") /** + * Customer company ID. For Belgium this is the CBE number or their EUID (European Unique + * Identifier) number. In the Netherlands this is the KVK number. + * + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun customerCompanyId(): Optional = customerCompanyId.getOptional("customer_company_id") + + /** + * The email address of the customer + * * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the * server responded with an unexpected value). */ fun customerEmail(): Optional = customerEmail.getOptional("customer_email") /** + * The unique identifier for the customer in your system + * * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the * server responded with an unexpected value). */ fun customerId(): Optional = customerId.getOptional("customer_id") /** + * The company name of the customer/buyer + * * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the * server responded with an unexpected value). */ fun customerName(): Optional = customerName.getOptional("customer_name") /** + * Customer tax ID. For Belgium this is the VAT number. Must include the country prefix + * * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the * server responded with an unexpected value). */ fun customerTaxId(): Optional = customerTaxId.getOptional("customer_tax_id") /** + * The direction of the document: INBOUND (purchases) or OUTBOUND (sales) + * * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the * server responded with an unexpected value). */ fun direction(): Optional = direction.getOptional("direction") /** + * The type of document: INVOICE, CREDIT_NOTE, or DEBIT_NOTE + * * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the * server responded with an unexpected value). */ fun documentType(): Optional = documentType.getOptional("document_type") /** + * The date when payment is due + * * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the * server responded with an unexpected value). */ fun dueDate(): Optional = dueDate.getOptional("due_date") /** + * The date when the invoice was issued + * * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the * server responded with an unexpected value). */ fun invoiceDate(): Optional = invoiceDate.getOptional("invoice_date") /** + * The unique invoice identifier/number + * * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the * server responded with an unexpected value). */ fun invoiceId(): Optional = invoiceId.getOptional("invoice_id") /** + * The total amount of the invoice including tax (invoice_total = subtotal + total_tax + + * total_discount). Must be positive and rounded to maximum 2 decimals + * * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the * server responded with an unexpected value). */ @@ -345,6 +434,8 @@ private constructor( fun items(): Optional> = items.getOptional("items") /** + * Additional notes or comments for the invoice + * * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the * server responded with an unexpected value). */ @@ -358,31 +449,32 @@ private constructor( paymentDetails.getOptional("payment_details") /** + * The payment terms (e.g., 'Net 30', 'Due on receipt', '2/10 Net 30') + * * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the * server responded with an unexpected value). */ fun paymentTerm(): Optional = paymentTerm.getOptional("payment_term") /** - * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the - * server responded with an unexpected value). - */ - fun previousUnpaidBalance(): Optional = - previousUnpaidBalance.getOptional("previous_unpaid_balance") - - /** + * The purchase order reference number + * * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the * server responded with an unexpected value). */ fun purchaseOrder(): Optional = purchaseOrder.getOptional("purchase_order") /** + * The address where payment should be sent or remitted to + * * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the * server responded with an unexpected value). */ fun remittanceAddress(): Optional = remittanceAddress.getOptional("remittance_address") /** + * The recipient name at the remittance address + * * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the * server responded with an unexpected value). */ @@ -390,12 +482,16 @@ private constructor( remittanceAddressRecipient.getOptional("remittance_address_recipient") /** + * The address where services were performed or goods were delivered + * * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the * server responded with an unexpected value). */ fun serviceAddress(): Optional = serviceAddress.getOptional("service_address") /** + * The recipient name at the service address + * * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the * server responded with an unexpected value). */ @@ -403,24 +499,32 @@ private constructor( serviceAddressRecipient.getOptional("service_address_recipient") /** + * The end date of the service period or delivery period + * * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the * server responded with an unexpected value). */ fun serviceEndDate(): Optional = serviceEndDate.getOptional("service_end_date") /** + * The start date of the service period or delivery period + * * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the * server responded with an unexpected value). */ fun serviceStartDate(): Optional = serviceStartDate.getOptional("service_start_date") /** + * The shipping/delivery address + * * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the * server responded with an unexpected value). */ fun shippingAddress(): Optional = shippingAddress.getOptional("shipping_address") /** + * The recipient name at the shipping address + * * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the * server responded with an unexpected value). */ @@ -428,17 +532,31 @@ private constructor( shippingAddressRecipient.getOptional("shipping_address_recipient") /** + * The current state of the document: DRAFT, TRANSIT, FAILED, SENT, or RECEIVED + * * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the * server responded with an unexpected value). */ fun state(): Optional = state.getOptional("state") /** + * The taxable base of the invoice. Should be the sum of all line items - allowances (for + * example commercial discounts) + charges with impact on VAT. Must be positive and rounded to + * maximum 2 decimals + * * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the * server responded with an unexpected value). */ fun subtotal(): Optional = subtotal.getOptional("subtotal") + /** + * Tax category code of the invoice (e.g., S for standard rate, Z for zero rate, E for exempt) + * + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun taxCode(): Optional = taxCode.getOptional("tax_code") + /** * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the * server responded with an unexpected value). @@ -446,24 +564,52 @@ private constructor( fun taxDetails(): Optional> = taxDetails.getOptional("tax_details") /** + * The net financial discount/charge of the invoice (non-VAT charges minus non-VAT allowances). + * Can be positive (net charge), negative (net discount), or zero. Must be rounded to maximum 2 + * decimals + * * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the * server responded with an unexpected value). */ fun totalDiscount(): Optional = totalDiscount.getOptional("total_discount") /** + * The total tax amount of the invoice. Must be positive and rounded to maximum 2 decimals + * * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the * server responded with an unexpected value). */ fun totalTax(): Optional = totalTax.getOptional("total_tax") /** + * VATEX code list for VAT exemption reasons + * + * Agency: CEF Identifier: vatex + * + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun vatex(): Optional = vatex.getOptional("vatex") + + /** + * Textual explanation for VAT exemption + * + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun vatexNote(): Optional = vatexNote.getOptional("vatex_note") + + /** + * The address of the vendor/seller + * * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the * server responded with an unexpected value). */ fun vendorAddress(): Optional = vendorAddress.getOptional("vendor_address") /** + * The recipient name at the vendor address + * * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the * server responded with an unexpected value). */ @@ -471,18 +617,33 @@ private constructor( vendorAddressRecipient.getOptional("vendor_address_recipient") /** + * Vendor company ID. For Belgium this is the CBE number or their EUID (European Unique + * Identifier) number. In the Netherlands this is the KVK number. + * + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun vendorCompanyId(): Optional = vendorCompanyId.getOptional("vendor_company_id") + + /** + * The email address of the vendor + * * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the * server responded with an unexpected value). */ fun vendorEmail(): Optional = vendorEmail.getOptional("vendor_email") /** + * The name of the vendor/seller/supplier + * * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the * server responded with an unexpected value). */ fun vendorName(): Optional = vendorName.getOptional("vendor_name") /** + * Vendor tax ID. For Belgium this is the VAT number. Must include the country prefix + * * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the * server responded with an unexpected value). */ @@ -495,6 +656,24 @@ private constructor( */ @JsonProperty("id") @ExcludeMissing fun _id(): JsonField = id + /** + * Returns the raw JSON value of [createdAt]. + * + * Unlike [createdAt], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("created_at") + @ExcludeMissing + fun _createdAt(): JsonField = createdAt + + /** + * Returns the raw JSON value of [allowances]. + * + * Unlike [allowances], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("allowances") + @ExcludeMissing + fun _allowances(): JsonField> = allowances + /** * Returns the raw JSON value of [amountDue]. * @@ -530,6 +709,13 @@ private constructor( @ExcludeMissing fun _billingAddressRecipient(): JsonField = billingAddressRecipient + /** + * Returns the raw JSON value of [charges]. + * + * Unlike [charges], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("charges") @ExcludeMissing fun _charges(): JsonField> = charges + /** * Returns the raw JSON value of [currency]. * @@ -556,6 +742,16 @@ private constructor( @ExcludeMissing fun _customerAddressRecipient(): JsonField = customerAddressRecipient + /** + * Returns the raw JSON value of [customerCompanyId]. + * + * Unlike [customerCompanyId], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("customer_company_id") + @ExcludeMissing + fun _customerCompanyId(): JsonField = customerCompanyId + /** * Returns the raw JSON value of [customerEmail]. * @@ -672,16 +868,6 @@ private constructor( @ExcludeMissing fun _paymentTerm(): JsonField = paymentTerm - /** - * Returns the raw JSON value of [previousUnpaidBalance]. - * - * Unlike [previousUnpaidBalance], this method doesn't throw if the JSON field has an unexpected - * type. - */ - @JsonProperty("previous_unpaid_balance") - @ExcludeMissing - fun _previousUnpaidBalance(): JsonField = previousUnpaidBalance - /** * Returns the raw JSON value of [purchaseOrder]. * @@ -782,6 +968,13 @@ private constructor( */ @JsonProperty("subtotal") @ExcludeMissing fun _subtotal(): JsonField = subtotal + /** + * Returns the raw JSON value of [taxCode]. + * + * Unlike [taxCode], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("tax_code") @ExcludeMissing fun _taxCode(): JsonField = taxCode + /** * Returns the raw JSON value of [taxDetails]. * @@ -807,6 +1000,20 @@ private constructor( */ @JsonProperty("total_tax") @ExcludeMissing fun _totalTax(): JsonField = totalTax + /** + * Returns the raw JSON value of [vatex]. + * + * Unlike [vatex], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("vatex") @ExcludeMissing fun _vatex(): JsonField = vatex + + /** + * Returns the raw JSON value of [vatexNote]. + * + * Unlike [vatexNote], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("vatex_note") @ExcludeMissing fun _vatexNote(): JsonField = vatexNote + /** * Returns the raw JSON value of [vendorAddress]. * @@ -826,6 +1033,15 @@ private constructor( @ExcludeMissing fun _vendorAddressRecipient(): JsonField = vendorAddressRecipient + /** + * Returns the raw JSON value of [vendorCompanyId]. + * + * Unlike [vendorCompanyId], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("vendor_company_id") + @ExcludeMissing + fun _vendorCompanyId(): JsonField = vendorCompanyId + /** * Returns the raw JSON value of [vendorEmail]. * @@ -871,6 +1087,7 @@ private constructor( * The following fields are required: * ```java * .id() + * .createdAt() * ``` */ @JvmStatic fun builder() = Builder() @@ -880,13 +1097,17 @@ private constructor( class Builder internal constructor() { private var id: JsonField? = null + private var createdAt: JsonField? = null + private var allowances: JsonField>? = null private var amountDue: JsonField = JsonMissing.of() private var attachments: JsonField>? = null private var billingAddress: JsonField = JsonMissing.of() private var billingAddressRecipient: JsonField = JsonMissing.of() + private var charges: JsonField>? = null private var currency: JsonField = JsonMissing.of() private var customerAddress: JsonField = JsonMissing.of() private var customerAddressRecipient: JsonField = JsonMissing.of() + private var customerCompanyId: JsonField = JsonMissing.of() private var customerEmail: JsonField = JsonMissing.of() private var customerId: JsonField = JsonMissing.of() private var customerName: JsonField = JsonMissing.of() @@ -901,7 +1122,6 @@ private constructor( private var note: JsonField = JsonMissing.of() private var paymentDetails: JsonField>? = null private var paymentTerm: JsonField = JsonMissing.of() - private var previousUnpaidBalance: JsonField = JsonMissing.of() private var purchaseOrder: JsonField = JsonMissing.of() private var remittanceAddress: JsonField = JsonMissing.of() private var remittanceAddressRecipient: JsonField = JsonMissing.of() @@ -913,11 +1133,15 @@ private constructor( private var shippingAddressRecipient: JsonField = JsonMissing.of() private var state: JsonField = JsonMissing.of() private var subtotal: JsonField = JsonMissing.of() + private var taxCode: JsonField = JsonMissing.of() private var taxDetails: JsonField>? = null private var totalDiscount: JsonField = JsonMissing.of() private var totalTax: JsonField = JsonMissing.of() + private var vatex: JsonField = JsonMissing.of() + private var vatexNote: JsonField = JsonMissing.of() private var vendorAddress: JsonField = JsonMissing.of() private var vendorAddressRecipient: JsonField = JsonMissing.of() + private var vendorCompanyId: JsonField = JsonMissing.of() private var vendorEmail: JsonField = JsonMissing.of() private var vendorName: JsonField = JsonMissing.of() private var vendorTaxId: JsonField = JsonMissing.of() @@ -926,13 +1150,17 @@ private constructor( @JvmSynthetic internal fun from(documentResponse: DocumentResponse) = apply { id = documentResponse.id + createdAt = documentResponse.createdAt + allowances = documentResponse.allowances.map { it.toMutableList() } amountDue = documentResponse.amountDue attachments = documentResponse.attachments.map { it.toMutableList() } billingAddress = documentResponse.billingAddress billingAddressRecipient = documentResponse.billingAddressRecipient + charges = documentResponse.charges.map { it.toMutableList() } currency = documentResponse.currency customerAddress = documentResponse.customerAddress customerAddressRecipient = documentResponse.customerAddressRecipient + customerCompanyId = documentResponse.customerCompanyId customerEmail = documentResponse.customerEmail customerId = documentResponse.customerId customerName = documentResponse.customerName @@ -947,7 +1175,6 @@ private constructor( note = documentResponse.note paymentDetails = documentResponse.paymentDetails.map { it.toMutableList() } paymentTerm = documentResponse.paymentTerm - previousUnpaidBalance = documentResponse.previousUnpaidBalance purchaseOrder = documentResponse.purchaseOrder remittanceAddress = documentResponse.remittanceAddress remittanceAddressRecipient = documentResponse.remittanceAddressRecipient @@ -959,11 +1186,15 @@ private constructor( shippingAddressRecipient = documentResponse.shippingAddressRecipient state = documentResponse.state subtotal = documentResponse.subtotal + taxCode = documentResponse.taxCode taxDetails = documentResponse.taxDetails.map { it.toMutableList() } totalDiscount = documentResponse.totalDiscount totalTax = documentResponse.totalTax + vatex = documentResponse.vatex + vatexNote = documentResponse.vatexNote vendorAddress = documentResponse.vendorAddress vendorAddressRecipient = documentResponse.vendorAddressRecipient + vendorCompanyId = documentResponse.vendorCompanyId vendorEmail = documentResponse.vendorEmail vendorName = documentResponse.vendorName vendorTaxId = documentResponse.vendorTaxId @@ -980,6 +1211,46 @@ private constructor( */ fun id(id: JsonField) = apply { this.id = id } + fun createdAt(createdAt: OffsetDateTime) = createdAt(JsonField.of(createdAt)) + + /** + * Sets [Builder.createdAt] to an arbitrary JSON value. + * + * You should usually call [Builder.createdAt] with a well-typed [OffsetDateTime] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun createdAt(createdAt: JsonField) = apply { this.createdAt = createdAt } + + fun allowances(allowances: List?) = allowances(JsonField.ofNullable(allowances)) + + /** Alias for calling [Builder.allowances] with `allowances.orElse(null)`. */ + fun allowances(allowances: Optional>) = allowances(allowances.getOrNull()) + + /** + * Sets [Builder.allowances] to an arbitrary JSON value. + * + * You should usually call [Builder.allowances] with a well-typed `List` value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun allowances(allowances: JsonField>) = apply { + this.allowances = allowances.map { it.toMutableList() } + } + + /** + * Adds a single [Allowance] to [allowances]. + * + * @throws IllegalStateException if the field was previously set to a non-list. + */ + fun addAllowance(allowance: Allowance) = apply { + allowances = + (allowances ?: JsonField.of(mutableListOf())).also { + checkKnown("allowances", it).add(allowance) + } + } + + /** The amount due for payment. Must be positive and rounded to maximum 2 decimals */ fun amountDue(amountDue: String?) = amountDue(JsonField.ofNullable(amountDue)) /** Alias for calling [Builder.amountDue] with `amountDue.orElse(null)`. */ @@ -994,8 +1265,12 @@ private constructor( */ fun amountDue(amountDue: JsonField) = apply { this.amountDue = amountDue } - fun attachments(attachments: List) = - attachments(JsonField.of(attachments)) + fun attachments(attachments: List?) = + attachments(JsonField.ofNullable(attachments)) + + /** Alias for calling [Builder.attachments] with `attachments.orElse(null)`. */ + fun attachments(attachments: Optional>) = + attachments(attachments.getOrNull()) /** * Sets [Builder.attachments] to an arbitrary JSON value. @@ -1020,6 +1295,7 @@ private constructor( } } + /** The billing address (if different from customer address) */ fun billingAddress(billingAddress: String?) = billingAddress(JsonField.ofNullable(billingAddress)) @@ -1038,6 +1314,7 @@ private constructor( this.billingAddress = billingAddress } + /** The recipient name at the billing address */ fun billingAddressRecipient(billingAddressRecipient: String?) = billingAddressRecipient(JsonField.ofNullable(billingAddressRecipient)) @@ -1059,7 +1336,35 @@ private constructor( this.billingAddressRecipient = billingAddressRecipient } - /** Currency of the invoice */ + fun charges(charges: List?) = charges(JsonField.ofNullable(charges)) + + /** Alias for calling [Builder.charges] with `charges.orElse(null)`. */ + fun charges(charges: Optional>) = charges(charges.getOrNull()) + + /** + * Sets [Builder.charges] to an arbitrary JSON value. + * + * You should usually call [Builder.charges] with a well-typed `List` value instead. + * This method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun charges(charges: JsonField>) = apply { + this.charges = charges.map { it.toMutableList() } + } + + /** + * Adds a single [Charge] to [charges]. + * + * @throws IllegalStateException if the field was previously set to a non-list. + */ + fun addCharge(charge: Charge) = apply { + charges = + (charges ?: JsonField.of(mutableListOf())).also { + checkKnown("charges", it).add(charge) + } + } + + /** Currency of the invoice (ISO 4217 currency code) */ fun currency(currency: CurrencyCode) = currency(JsonField.of(currency)) /** @@ -1071,6 +1376,7 @@ private constructor( */ fun currency(currency: JsonField) = apply { this.currency = currency } + /** The address of the customer/buyer */ fun customerAddress(customerAddress: String?) = customerAddress(JsonField.ofNullable(customerAddress)) @@ -1089,6 +1395,7 @@ private constructor( this.customerAddress = customerAddress } + /** The recipient name at the customer address */ fun customerAddressRecipient(customerAddressRecipient: String?) = customerAddressRecipient(JsonField.ofNullable(customerAddressRecipient)) @@ -1110,6 +1417,29 @@ private constructor( this.customerAddressRecipient = customerAddressRecipient } + /** + * Customer company ID. For Belgium this is the CBE number or their EUID (European Unique + * Identifier) number. In the Netherlands this is the KVK number. + */ + fun customerCompanyId(customerCompanyId: String?) = + customerCompanyId(JsonField.ofNullable(customerCompanyId)) + + /** Alias for calling [Builder.customerCompanyId] with `customerCompanyId.orElse(null)`. */ + fun customerCompanyId(customerCompanyId: Optional) = + customerCompanyId(customerCompanyId.getOrNull()) + + /** + * Sets [Builder.customerCompanyId] to an arbitrary JSON value. + * + * You should usually call [Builder.customerCompanyId] with a well-typed [String] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun customerCompanyId(customerCompanyId: JsonField) = apply { + this.customerCompanyId = customerCompanyId + } + + /** The email address of the customer */ fun customerEmail(customerEmail: String?) = customerEmail(JsonField.ofNullable(customerEmail)) @@ -1128,6 +1458,7 @@ private constructor( this.customerEmail = customerEmail } + /** The unique identifier for the customer in your system */ fun customerId(customerId: String?) = customerId(JsonField.ofNullable(customerId)) /** Alias for calling [Builder.customerId] with `customerId.orElse(null)`. */ @@ -1142,6 +1473,7 @@ private constructor( */ fun customerId(customerId: JsonField) = apply { this.customerId = customerId } + /** The company name of the customer/buyer */ fun customerName(customerName: String?) = customerName(JsonField.ofNullable(customerName)) /** Alias for calling [Builder.customerName] with `customerName.orElse(null)`. */ @@ -1158,6 +1490,7 @@ private constructor( this.customerName = customerName } + /** Customer tax ID. For Belgium this is the VAT number. Must include the country prefix */ fun customerTaxId(customerTaxId: String?) = customerTaxId(JsonField.ofNullable(customerTaxId)) @@ -1176,6 +1509,7 @@ private constructor( this.customerTaxId = customerTaxId } + /** The direction of the document: INBOUND (purchases) or OUTBOUND (sales) */ fun direction(direction: DocumentDirection) = direction(JsonField.of(direction)) /** @@ -1189,6 +1523,7 @@ private constructor( this.direction = direction } + /** The type of document: INVOICE, CREDIT_NOTE, or DEBIT_NOTE */ fun documentType(documentType: DocumentType) = documentType(JsonField.of(documentType)) /** @@ -1202,6 +1537,7 @@ private constructor( this.documentType = documentType } + /** The date when payment is due */ fun dueDate(dueDate: LocalDate?) = dueDate(JsonField.ofNullable(dueDate)) /** Alias for calling [Builder.dueDate] with `dueDate.orElse(null)`. */ @@ -1216,6 +1552,7 @@ private constructor( */ fun dueDate(dueDate: JsonField) = apply { this.dueDate = dueDate } + /** The date when the invoice was issued */ fun invoiceDate(invoiceDate: LocalDate?) = invoiceDate(JsonField.ofNullable(invoiceDate)) /** Alias for calling [Builder.invoiceDate] with `invoiceDate.orElse(null)`. */ @@ -1232,6 +1569,7 @@ private constructor( this.invoiceDate = invoiceDate } + /** The unique invoice identifier/number */ fun invoiceId(invoiceId: String?) = invoiceId(JsonField.ofNullable(invoiceId)) /** Alias for calling [Builder.invoiceId] with `invoiceId.orElse(null)`. */ @@ -1246,6 +1584,10 @@ private constructor( */ fun invoiceId(invoiceId: JsonField) = apply { this.invoiceId = invoiceId } + /** + * The total amount of the invoice including tax (invoice_total = subtotal + total_tax + + * total_discount). Must be positive and rounded to maximum 2 decimals + */ fun invoiceTotal(invoiceTotal: String?) = invoiceTotal(JsonField.ofNullable(invoiceTotal)) /** Alias for calling [Builder.invoiceTotal] with `invoiceTotal.orElse(null)`. */ @@ -1262,7 +1604,10 @@ private constructor( this.invoiceTotal = invoiceTotal } - fun items(items: List) = items(JsonField.of(items)) + fun items(items: List?) = items(JsonField.ofNullable(items)) + + /** Alias for calling [Builder.items] with `items.orElse(null)`. */ + fun items(items: Optional>) = items(items.getOrNull()) /** * Sets [Builder.items] to an arbitrary JSON value. @@ -1285,6 +1630,7 @@ private constructor( (items ?: JsonField.of(mutableListOf())).also { checkKnown("items", it).add(item) } } + /** Additional notes or comments for the invoice */ fun note(note: String?) = note(JsonField.ofNullable(note)) /** Alias for calling [Builder.note] with `note.orElse(null)`. */ @@ -1298,8 +1644,12 @@ private constructor( */ fun note(note: JsonField) = apply { this.note = note } - fun paymentDetails(paymentDetails: List) = - paymentDetails(JsonField.of(paymentDetails)) + fun paymentDetails(paymentDetails: List?) = + paymentDetails(JsonField.ofNullable(paymentDetails)) + + /** Alias for calling [Builder.paymentDetails] with `paymentDetails.orElse(null)`. */ + fun paymentDetails(paymentDetails: Optional>) = + paymentDetails(paymentDetails.getOrNull()) /** * Sets [Builder.paymentDetails] to an arbitrary JSON value. @@ -1324,6 +1674,7 @@ private constructor( } } + /** The payment terms (e.g., 'Net 30', 'Due on receipt', '2/10 Net 30') */ fun paymentTerm(paymentTerm: String?) = paymentTerm(JsonField.ofNullable(paymentTerm)) /** Alias for calling [Builder.paymentTerm] with `paymentTerm.orElse(null)`. */ @@ -1338,27 +1689,7 @@ private constructor( */ fun paymentTerm(paymentTerm: JsonField) = apply { this.paymentTerm = paymentTerm } - fun previousUnpaidBalance(previousUnpaidBalance: String?) = - previousUnpaidBalance(JsonField.ofNullable(previousUnpaidBalance)) - - /** - * Alias for calling [Builder.previousUnpaidBalance] with - * `previousUnpaidBalance.orElse(null)`. - */ - fun previousUnpaidBalance(previousUnpaidBalance: Optional) = - previousUnpaidBalance(previousUnpaidBalance.getOrNull()) - - /** - * Sets [Builder.previousUnpaidBalance] to an arbitrary JSON value. - * - * You should usually call [Builder.previousUnpaidBalance] with a well-typed [String] value - * instead. This method is primarily for setting the field to an undocumented or not yet - * supported value. - */ - fun previousUnpaidBalance(previousUnpaidBalance: JsonField) = apply { - this.previousUnpaidBalance = previousUnpaidBalance - } - + /** The purchase order reference number */ fun purchaseOrder(purchaseOrder: String?) = purchaseOrder(JsonField.ofNullable(purchaseOrder)) @@ -1377,6 +1708,7 @@ private constructor( this.purchaseOrder = purchaseOrder } + /** The address where payment should be sent or remitted to */ fun remittanceAddress(remittanceAddress: String?) = remittanceAddress(JsonField.ofNullable(remittanceAddress)) @@ -1395,6 +1727,7 @@ private constructor( this.remittanceAddress = remittanceAddress } + /** The recipient name at the remittance address */ fun remittanceAddressRecipient(remittanceAddressRecipient: String?) = remittanceAddressRecipient(JsonField.ofNullable(remittanceAddressRecipient)) @@ -1416,6 +1749,7 @@ private constructor( this.remittanceAddressRecipient = remittanceAddressRecipient } + /** The address where services were performed or goods were delivered */ fun serviceAddress(serviceAddress: String?) = serviceAddress(JsonField.ofNullable(serviceAddress)) @@ -1434,6 +1768,7 @@ private constructor( this.serviceAddress = serviceAddress } + /** The recipient name at the service address */ fun serviceAddressRecipient(serviceAddressRecipient: String?) = serviceAddressRecipient(JsonField.ofNullable(serviceAddressRecipient)) @@ -1455,6 +1790,7 @@ private constructor( this.serviceAddressRecipient = serviceAddressRecipient } + /** The end date of the service period or delivery period */ fun serviceEndDate(serviceEndDate: LocalDate?) = serviceEndDate(JsonField.ofNullable(serviceEndDate)) @@ -1473,6 +1809,7 @@ private constructor( this.serviceEndDate = serviceEndDate } + /** The start date of the service period or delivery period */ fun serviceStartDate(serviceStartDate: LocalDate?) = serviceStartDate(JsonField.ofNullable(serviceStartDate)) @@ -1491,6 +1828,7 @@ private constructor( this.serviceStartDate = serviceStartDate } + /** The shipping/delivery address */ fun shippingAddress(shippingAddress: String?) = shippingAddress(JsonField.ofNullable(shippingAddress)) @@ -1509,6 +1847,7 @@ private constructor( this.shippingAddress = shippingAddress } + /** The recipient name at the shipping address */ fun shippingAddressRecipient(shippingAddressRecipient: String?) = shippingAddressRecipient(JsonField.ofNullable(shippingAddressRecipient)) @@ -1530,6 +1869,7 @@ private constructor( this.shippingAddressRecipient = shippingAddressRecipient } + /** The current state of the document: DRAFT, TRANSIT, FAILED, SENT, or RECEIVED */ fun state(state: DocumentState) = state(JsonField.of(state)) /** @@ -1541,6 +1881,11 @@ private constructor( */ fun state(state: JsonField) = apply { this.state = state } + /** + * The taxable base of the invoice. Should be the sum of all line items - allowances (for + * example commercial discounts) + charges with impact on VAT. Must be positive and rounded + * to maximum 2 decimals + */ fun subtotal(subtotal: String?) = subtotal(JsonField.ofNullable(subtotal)) /** Alias for calling [Builder.subtotal] with `subtotal.orElse(null)`. */ @@ -1554,7 +1899,24 @@ private constructor( */ fun subtotal(subtotal: JsonField) = apply { this.subtotal = subtotal } - fun taxDetails(taxDetails: List) = taxDetails(JsonField.of(taxDetails)) + /** + * Tax category code of the invoice (e.g., S for standard rate, Z for zero rate, E for + * exempt) + */ + fun taxCode(taxCode: TaxCode) = taxCode(JsonField.of(taxCode)) + + /** + * Sets [Builder.taxCode] to an arbitrary JSON value. + * + * You should usually call [Builder.taxCode] with a well-typed [TaxCode] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun taxCode(taxCode: JsonField) = apply { this.taxCode = taxCode } + + fun taxDetails(taxDetails: List?) = taxDetails(JsonField.ofNullable(taxDetails)) + + /** Alias for calling [Builder.taxDetails] with `taxDetails.orElse(null)`. */ + fun taxDetails(taxDetails: Optional>) = taxDetails(taxDetails.getOrNull()) /** * Sets [Builder.taxDetails] to an arbitrary JSON value. @@ -1579,6 +1941,11 @@ private constructor( } } + /** + * The net financial discount/charge of the invoice (non-VAT charges minus non-VAT + * allowances). Can be positive (net charge), negative (net discount), or zero. Must be + * rounded to maximum 2 decimals + */ fun totalDiscount(totalDiscount: String?) = totalDiscount(JsonField.ofNullable(totalDiscount)) @@ -1597,6 +1964,9 @@ private constructor( this.totalDiscount = totalDiscount } + /** + * The total tax amount of the invoice. Must be positive and rounded to maximum 2 decimals + */ fun totalTax(totalTax: String?) = totalTax(JsonField.ofNullable(totalTax)) /** Alias for calling [Builder.totalTax] with `totalTax.orElse(null)`. */ @@ -1610,6 +1980,40 @@ private constructor( */ fun totalTax(totalTax: JsonField) = apply { this.totalTax = totalTax } + /** + * VATEX code list for VAT exemption reasons + * + * Agency: CEF Identifier: vatex + */ + fun vatex(vatex: Vatex?) = vatex(JsonField.ofNullable(vatex)) + + /** Alias for calling [Builder.vatex] with `vatex.orElse(null)`. */ + fun vatex(vatex: Optional) = vatex(vatex.getOrNull()) + + /** + * Sets [Builder.vatex] to an arbitrary JSON value. + * + * You should usually call [Builder.vatex] with a well-typed [Vatex] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun vatex(vatex: JsonField) = apply { this.vatex = vatex } + + /** Textual explanation for VAT exemption */ + fun vatexNote(vatexNote: String?) = vatexNote(JsonField.ofNullable(vatexNote)) + + /** Alias for calling [Builder.vatexNote] with `vatexNote.orElse(null)`. */ + fun vatexNote(vatexNote: Optional) = vatexNote(vatexNote.getOrNull()) + + /** + * Sets [Builder.vatexNote] to an arbitrary JSON value. + * + * You should usually call [Builder.vatexNote] with a well-typed [String] value instead. + * This method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun vatexNote(vatexNote: JsonField) = apply { this.vatexNote = vatexNote } + + /** The address of the vendor/seller */ fun vendorAddress(vendorAddress: String?) = vendorAddress(JsonField.ofNullable(vendorAddress)) @@ -1628,6 +2032,7 @@ private constructor( this.vendorAddress = vendorAddress } + /** The recipient name at the vendor address */ fun vendorAddressRecipient(vendorAddressRecipient: String?) = vendorAddressRecipient(JsonField.ofNullable(vendorAddressRecipient)) @@ -1649,6 +2054,29 @@ private constructor( this.vendorAddressRecipient = vendorAddressRecipient } + /** + * Vendor company ID. For Belgium this is the CBE number or their EUID (European Unique + * Identifier) number. In the Netherlands this is the KVK number. + */ + fun vendorCompanyId(vendorCompanyId: String?) = + vendorCompanyId(JsonField.ofNullable(vendorCompanyId)) + + /** Alias for calling [Builder.vendorCompanyId] with `vendorCompanyId.orElse(null)`. */ + fun vendorCompanyId(vendorCompanyId: Optional) = + vendorCompanyId(vendorCompanyId.getOrNull()) + + /** + * Sets [Builder.vendorCompanyId] to an arbitrary JSON value. + * + * You should usually call [Builder.vendorCompanyId] with a well-typed [String] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun vendorCompanyId(vendorCompanyId: JsonField) = apply { + this.vendorCompanyId = vendorCompanyId + } + + /** The email address of the vendor */ fun vendorEmail(vendorEmail: String?) = vendorEmail(JsonField.ofNullable(vendorEmail)) /** Alias for calling [Builder.vendorEmail] with `vendorEmail.orElse(null)`. */ @@ -1663,6 +2091,7 @@ private constructor( */ fun vendorEmail(vendorEmail: JsonField) = apply { this.vendorEmail = vendorEmail } + /** The name of the vendor/seller/supplier */ fun vendorName(vendorName: String?) = vendorName(JsonField.ofNullable(vendorName)) /** Alias for calling [Builder.vendorName] with `vendorName.orElse(null)`. */ @@ -1677,6 +2106,7 @@ private constructor( */ fun vendorName(vendorName: JsonField) = apply { this.vendorName = vendorName } + /** Vendor tax ID. For Belgium this is the VAT number. Must include the country prefix */ fun vendorTaxId(vendorTaxId: String?) = vendorTaxId(JsonField.ofNullable(vendorTaxId)) /** Alias for calling [Builder.vendorTaxId] with `vendorTaxId.orElse(null)`. */ @@ -1718,6 +2148,7 @@ private constructor( * The following fields are required: * ```java * .id() + * .createdAt() * ``` * * @throws IllegalStateException if any required field is unset. @@ -1725,13 +2156,17 @@ private constructor( fun build(): DocumentResponse = DocumentResponse( checkRequired("id", id), + checkRequired("createdAt", createdAt), + (allowances ?: JsonMissing.of()).map { it.toImmutable() }, amountDue, (attachments ?: JsonMissing.of()).map { it.toImmutable() }, billingAddress, billingAddressRecipient, + (charges ?: JsonMissing.of()).map { it.toImmutable() }, currency, customerAddress, customerAddressRecipient, + customerCompanyId, customerEmail, customerId, customerName, @@ -1746,7 +2181,6 @@ private constructor( note, (paymentDetails ?: JsonMissing.of()).map { it.toImmutable() }, paymentTerm, - previousUnpaidBalance, purchaseOrder, remittanceAddress, remittanceAddressRecipient, @@ -1758,11 +2192,15 @@ private constructor( shippingAddressRecipient, state, subtotal, + taxCode, (taxDetails ?: JsonMissing.of()).map { it.toImmutable() }, totalDiscount, totalTax, + vatex, + vatexNote, vendorAddress, vendorAddressRecipient, + vendorCompanyId, vendorEmail, vendorName, vendorTaxId, @@ -1778,13 +2216,17 @@ private constructor( } id() + createdAt() + allowances().ifPresent { it.forEach { it.validate() } } amountDue() attachments().ifPresent { it.forEach { it.validate() } } billingAddress() billingAddressRecipient() + charges().ifPresent { it.forEach { it.validate() } } currency().ifPresent { it.validate() } customerAddress() customerAddressRecipient() + customerCompanyId() customerEmail() customerId() customerName() @@ -1799,7 +2241,6 @@ private constructor( note() paymentDetails().ifPresent { it.forEach { it.validate() } } paymentTerm() - previousUnpaidBalance() purchaseOrder() remittanceAddress() remittanceAddressRecipient() @@ -1811,11 +2252,15 @@ private constructor( shippingAddressRecipient() state().ifPresent { it.validate() } subtotal() + taxCode().ifPresent { it.validate() } taxDetails().ifPresent { it.forEach { it.validate() } } totalDiscount() totalTax() + vatex().ifPresent { it.validate() } + vatexNote() vendorAddress() vendorAddressRecipient() + vendorCompanyId() vendorEmail() vendorName() vendorTaxId() @@ -1838,13 +2283,17 @@ private constructor( @JvmSynthetic internal fun validity(): Int = (if (id.asKnown().isPresent) 1 else 0) + + (if (createdAt.asKnown().isPresent) 1 else 0) + + (allowances.asKnown().getOrNull()?.sumOf { it.validity().toInt() } ?: 0) + (if (amountDue.asKnown().isPresent) 1 else 0) + (attachments.asKnown().getOrNull()?.sumOf { it.validity().toInt() } ?: 0) + (if (billingAddress.asKnown().isPresent) 1 else 0) + (if (billingAddressRecipient.asKnown().isPresent) 1 else 0) + + (charges.asKnown().getOrNull()?.sumOf { it.validity().toInt() } ?: 0) + (currency.asKnown().getOrNull()?.validity() ?: 0) + (if (customerAddress.asKnown().isPresent) 1 else 0) + (if (customerAddressRecipient.asKnown().isPresent) 1 else 0) + + (if (customerCompanyId.asKnown().isPresent) 1 else 0) + (if (customerEmail.asKnown().isPresent) 1 else 0) + (if (customerId.asKnown().isPresent) 1 else 0) + (if (customerName.asKnown().isPresent) 1 else 0) + @@ -1859,7 +2308,6 @@ private constructor( (if (note.asKnown().isPresent) 1 else 0) + (paymentDetails.asKnown().getOrNull()?.sumOf { it.validity().toInt() } ?: 0) + (if (paymentTerm.asKnown().isPresent) 1 else 0) + - (if (previousUnpaidBalance.asKnown().isPresent) 1 else 0) + (if (purchaseOrder.asKnown().isPresent) 1 else 0) + (if (remittanceAddress.asKnown().isPresent) 1 else 0) + (if (remittanceAddressRecipient.asKnown().isPresent) 1 else 0) + @@ -1871,37 +2319,2700 @@ private constructor( (if (shippingAddressRecipient.asKnown().isPresent) 1 else 0) + (state.asKnown().getOrNull()?.validity() ?: 0) + (if (subtotal.asKnown().isPresent) 1 else 0) + + (taxCode.asKnown().getOrNull()?.validity() ?: 0) + (taxDetails.asKnown().getOrNull()?.sumOf { it.validity().toInt() } ?: 0) + (if (totalDiscount.asKnown().isPresent) 1 else 0) + (if (totalTax.asKnown().isPresent) 1 else 0) + + (vatex.asKnown().getOrNull()?.validity() ?: 0) + + (if (vatexNote.asKnown().isPresent) 1 else 0) + (if (vendorAddress.asKnown().isPresent) 1 else 0) + (if (vendorAddressRecipient.asKnown().isPresent) 1 else 0) + + (if (vendorCompanyId.asKnown().isPresent) 1 else 0) + (if (vendorEmail.asKnown().isPresent) 1 else 0) + (if (vendorName.asKnown().isPresent) 1 else 0) + (if (vendorTaxId.asKnown().isPresent) 1 else 0) - class Item + class Allowance @JsonCreator(mode = JsonCreator.Mode.DISABLED) private constructor( private val amount: JsonField, - private val date: JsonField, - private val description: JsonField, - private val productCode: JsonField, - private val quantity: JsonField, - private val tax: JsonField, + private val baseAmount: JsonField, + private val multiplierFactor: JsonField, + private val reason: JsonField, + private val reasonCode: JsonField, + private val taxCode: JsonField, private val taxRate: JsonField, - private val unit: JsonField, - private val unitPrice: JsonField, private val additionalProperties: MutableMap, ) { @JsonCreator private constructor( @JsonProperty("amount") @ExcludeMissing amount: JsonField = JsonMissing.of(), - @JsonProperty("date") @ExcludeMissing date: JsonField = JsonMissing.of(), - @JsonProperty("description") + @JsonProperty("base_amount") @ExcludeMissing - description: JsonField = JsonMissing.of(), + baseAmount: JsonField = JsonMissing.of(), + @JsonProperty("multiplier_factor") + @ExcludeMissing + multiplierFactor: JsonField = JsonMissing.of(), + @JsonProperty("reason") @ExcludeMissing reason: JsonField = JsonMissing.of(), + @JsonProperty("reason_code") + @ExcludeMissing + reasonCode: JsonField = JsonMissing.of(), + @JsonProperty("tax_code") + @ExcludeMissing + taxCode: JsonField = JsonMissing.of(), + @JsonProperty("tax_rate") @ExcludeMissing taxRate: JsonField = JsonMissing.of(), + ) : this( + amount, + baseAmount, + multiplierFactor, + reason, + reasonCode, + taxCode, + taxRate, + mutableMapOf(), + ) + + /** + * The allowance amount, without VAT. Must be rounded to maximum 2 decimals + * + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun amount(): Optional = amount.getOptional("amount") + + /** + * The base amount that may be used, in conjunction with the allowance percentage, to + * calculate the allowance amount. Must be rounded to maximum 2 decimals + * + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun baseAmount(): Optional = baseAmount.getOptional("base_amount") + + /** + * The percentage that may be used, in conjunction with the allowance base amount, to + * calculate the allowance amount. To state 20%, use value 20. Must be rounded to maximum 2 + * decimals + * + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun multiplierFactor(): Optional = multiplierFactor.getOptional("multiplier_factor") + + /** + * The reason for the allowance + * + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun reason(): Optional = reason.getOptional("reason") + + /** + * Allowance reason codes for invoice discounts and charges + * + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun reasonCode(): Optional = reasonCode.getOptional("reason_code") + + /** + * The VAT category code that applies to the allowance + * + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun taxCode(): Optional = taxCode.getOptional("tax_code") + + /** + * The VAT rate, represented as percentage that applies to the allowance. Must be rounded to + * maximum 2 decimals + * + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun taxRate(): Optional = taxRate.getOptional("tax_rate") + + /** + * Returns the raw JSON value of [amount]. + * + * Unlike [amount], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("amount") @ExcludeMissing fun _amount(): JsonField = amount + + /** + * Returns the raw JSON value of [baseAmount]. + * + * Unlike [baseAmount], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("base_amount") + @ExcludeMissing + fun _baseAmount(): JsonField = baseAmount + + /** + * Returns the raw JSON value of [multiplierFactor]. + * + * Unlike [multiplierFactor], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("multiplier_factor") + @ExcludeMissing + fun _multiplierFactor(): JsonField = multiplierFactor + + /** + * Returns the raw JSON value of [reason]. + * + * Unlike [reason], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("reason") @ExcludeMissing fun _reason(): JsonField = reason + + /** + * Returns the raw JSON value of [reasonCode]. + * + * Unlike [reasonCode], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("reason_code") + @ExcludeMissing + fun _reasonCode(): JsonField = reasonCode + + /** + * Returns the raw JSON value of [taxCode]. + * + * Unlike [taxCode], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("tax_code") @ExcludeMissing fun _taxCode(): JsonField = taxCode + + /** + * Returns the raw JSON value of [taxRate]. + * + * Unlike [taxRate], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("tax_rate") @ExcludeMissing fun _taxRate(): JsonField = taxRate + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** Returns a mutable builder for constructing an instance of [Allowance]. */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [Allowance]. */ + class Builder internal constructor() { + + private var amount: JsonField = JsonMissing.of() + private var baseAmount: JsonField = JsonMissing.of() + private var multiplierFactor: JsonField = JsonMissing.of() + private var reason: JsonField = JsonMissing.of() + private var reasonCode: JsonField = JsonMissing.of() + private var taxCode: JsonField = JsonMissing.of() + private var taxRate: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(allowance: Allowance) = apply { + amount = allowance.amount + baseAmount = allowance.baseAmount + multiplierFactor = allowance.multiplierFactor + reason = allowance.reason + reasonCode = allowance.reasonCode + taxCode = allowance.taxCode + taxRate = allowance.taxRate + additionalProperties = allowance.additionalProperties.toMutableMap() + } + + /** The allowance amount, without VAT. Must be rounded to maximum 2 decimals */ + fun amount(amount: String?) = amount(JsonField.ofNullable(amount)) + + /** Alias for calling [Builder.amount] with `amount.orElse(null)`. */ + fun amount(amount: Optional) = amount(amount.getOrNull()) + + /** + * Sets [Builder.amount] to an arbitrary JSON value. + * + * You should usually call [Builder.amount] with a well-typed [String] value instead. + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun amount(amount: JsonField) = apply { this.amount = amount } + + /** + * The base amount that may be used, in conjunction with the allowance percentage, to + * calculate the allowance amount. Must be rounded to maximum 2 decimals + */ + fun baseAmount(baseAmount: String?) = baseAmount(JsonField.ofNullable(baseAmount)) + + /** Alias for calling [Builder.baseAmount] with `baseAmount.orElse(null)`. */ + fun baseAmount(baseAmount: Optional) = baseAmount(baseAmount.getOrNull()) + + /** + * Sets [Builder.baseAmount] to an arbitrary JSON value. + * + * You should usually call [Builder.baseAmount] with a well-typed [String] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun baseAmount(baseAmount: JsonField) = apply { this.baseAmount = baseAmount } + + /** + * The percentage that may be used, in conjunction with the allowance base amount, to + * calculate the allowance amount. To state 20%, use value 20. Must be rounded to + * maximum 2 decimals + */ + fun multiplierFactor(multiplierFactor: String?) = + multiplierFactor(JsonField.ofNullable(multiplierFactor)) + + /** + * Alias for calling [Builder.multiplierFactor] with `multiplierFactor.orElse(null)`. + */ + fun multiplierFactor(multiplierFactor: Optional) = + multiplierFactor(multiplierFactor.getOrNull()) + + /** + * Sets [Builder.multiplierFactor] to an arbitrary JSON value. + * + * You should usually call [Builder.multiplierFactor] with a well-typed [String] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun multiplierFactor(multiplierFactor: JsonField) = apply { + this.multiplierFactor = multiplierFactor + } + + /** The reason for the allowance */ + fun reason(reason: String?) = reason(JsonField.ofNullable(reason)) + + /** Alias for calling [Builder.reason] with `reason.orElse(null)`. */ + fun reason(reason: Optional) = reason(reason.getOrNull()) + + /** + * Sets [Builder.reason] to an arbitrary JSON value. + * + * You should usually call [Builder.reason] with a well-typed [String] value instead. + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun reason(reason: JsonField) = apply { this.reason = reason } + + /** Allowance reason codes for invoice discounts and charges */ + fun reasonCode(reasonCode: ReasonCode?) = reasonCode(JsonField.ofNullable(reasonCode)) + + /** Alias for calling [Builder.reasonCode] with `reasonCode.orElse(null)`. */ + fun reasonCode(reasonCode: Optional) = reasonCode(reasonCode.getOrNull()) + + /** + * Sets [Builder.reasonCode] to an arbitrary JSON value. + * + * You should usually call [Builder.reasonCode] with a well-typed [ReasonCode] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun reasonCode(reasonCode: JsonField) = apply { + this.reasonCode = reasonCode + } + + /** The VAT category code that applies to the allowance */ + fun taxCode(taxCode: TaxCode) = taxCode(JsonField.of(taxCode)) + + /** + * Sets [Builder.taxCode] to an arbitrary JSON value. + * + * You should usually call [Builder.taxCode] with a well-typed [TaxCode] value instead. + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun taxCode(taxCode: JsonField) = apply { this.taxCode = taxCode } + + /** + * The VAT rate, represented as percentage that applies to the allowance. Must be + * rounded to maximum 2 decimals + */ + fun taxRate(taxRate: String?) = taxRate(JsonField.ofNullable(taxRate)) + + /** Alias for calling [Builder.taxRate] with `taxRate.orElse(null)`. */ + fun taxRate(taxRate: Optional) = taxRate(taxRate.getOrNull()) + + /** + * Sets [Builder.taxRate] to an arbitrary JSON value. + * + * You should usually call [Builder.taxRate] with a well-typed [String] value instead. + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun taxRate(taxRate: JsonField) = apply { this.taxRate = taxRate } + + fun additionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.clear() + putAllAdditionalProperties(additionalProperties) + } + + fun putAdditionalProperty(key: String, value: JsonValue) = apply { + additionalProperties.put(key, value) + } + + fun putAllAdditionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.putAll(additionalProperties) + } + + fun removeAdditionalProperty(key: String) = apply { additionalProperties.remove(key) } + + fun removeAllAdditionalProperties(keys: Set) = apply { + keys.forEach(::removeAdditionalProperty) + } + + /** + * Returns an immutable instance of [Allowance]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): Allowance = + Allowance( + amount, + baseAmount, + multiplierFactor, + reason, + reasonCode, + taxCode, + taxRate, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + fun validate(): Allowance = apply { + if (validated) { + return@apply + } + + amount() + baseAmount() + multiplierFactor() + reason() + reasonCode().ifPresent { it.validate() } + taxCode().ifPresent { it.validate() } + taxRate() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: EInvoiceInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic + internal fun validity(): Int = + (if (amount.asKnown().isPresent) 1 else 0) + + (if (baseAmount.asKnown().isPresent) 1 else 0) + + (if (multiplierFactor.asKnown().isPresent) 1 else 0) + + (if (reason.asKnown().isPresent) 1 else 0) + + (reasonCode.asKnown().getOrNull()?.validity() ?: 0) + + (taxCode.asKnown().getOrNull()?.validity() ?: 0) + + (if (taxRate.asKnown().isPresent) 1 else 0) + + /** Allowance reason codes for invoice discounts and charges */ + class ReasonCode @JsonCreator private constructor(private val value: JsonField) : + Enum { + + /** + * Returns this class instance's raw value. + * + * This is usually only useful if this instance was deserialized from data that doesn't + * match any known member, and you want to know that value. For example, if the SDK is + * on an older version than the API, then the API may respond with new members that the + * SDK is unaware of. + */ + @com.fasterxml.jackson.annotation.JsonValue fun _value(): JsonField = value + + companion object { + + @JvmField val _41 = of("41") + + @JvmField val _42 = of("42") + + @JvmField val _60 = of("60") + + @JvmField val _62 = of("62") + + @JvmField val _63 = of("63") + + @JvmField val _64 = of("64") + + @JvmField val _65 = of("65") + + @JvmField val _66 = of("66") + + @JvmField val _67 = of("67") + + @JvmField val _68 = of("68") + + @JvmField val _70 = of("70") + + @JvmField val _71 = of("71") + + @JvmField val _88 = of("88") + + @JvmField val _95 = of("95") + + @JvmField val _100 = of("100") + + @JvmField val _102 = of("102") + + @JvmField val _103 = of("103") + + @JvmField val _104 = of("104") + + @JvmField val _105 = of("105") + + @JvmStatic fun of(value: String) = ReasonCode(JsonField.of(value)) + } + + /** An enum containing [ReasonCode]'s known values. */ + enum class Known { + _41, + _42, + _60, + _62, + _63, + _64, + _65, + _66, + _67, + _68, + _70, + _71, + _88, + _95, + _100, + _102, + _103, + _104, + _105, + } + + /** + * An enum containing [ReasonCode]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [ReasonCode] can contain an unknown value in a couple of cases: + * - It was deserialized from data that doesn't match any known member. For example, if + * the SDK is on an older version than the API, then the API may respond with new + * members that the SDK is unaware of. + * - It was constructed with an arbitrary value using the [of] method. + */ + enum class Value { + _41, + _42, + _60, + _62, + _63, + _64, + _65, + _66, + _67, + _68, + _70, + _71, + _88, + _95, + _100, + _102, + _103, + _104, + _105, + /** + * An enum member indicating that [ReasonCode] was instantiated with an unknown + * value. + */ + _UNKNOWN, + } + + /** + * Returns an enum member corresponding to this class instance's value, or + * [Value._UNKNOWN] if the class was instantiated with an unknown value. + * + * Use the [known] method instead if you're certain the value is always known or if you + * want to throw for the unknown case. + */ + fun value(): Value = + when (this) { + _41 -> Value._41 + _42 -> Value._42 + _60 -> Value._60 + _62 -> Value._62 + _63 -> Value._63 + _64 -> Value._64 + _65 -> Value._65 + _66 -> Value._66 + _67 -> Value._67 + _68 -> Value._68 + _70 -> Value._70 + _71 -> Value._71 + _88 -> Value._88 + _95 -> Value._95 + _100 -> Value._100 + _102 -> Value._102 + _103 -> Value._103 + _104 -> Value._104 + _105 -> Value._105 + else -> Value._UNKNOWN + } + + /** + * Returns an enum member corresponding to this class instance's value. + * + * Use the [value] method instead if you're uncertain the value is always known and + * don't want to throw for the unknown case. + * + * @throws EInvoiceInvalidDataException if this class instance's value is a not a known + * member. + */ + fun known(): Known = + when (this) { + _41 -> Known._41 + _42 -> Known._42 + _60 -> Known._60 + _62 -> Known._62 + _63 -> Known._63 + _64 -> Known._64 + _65 -> Known._65 + _66 -> Known._66 + _67 -> Known._67 + _68 -> Known._68 + _70 -> Known._70 + _71 -> Known._71 + _88 -> Known._88 + _95 -> Known._95 + _100 -> Known._100 + _102 -> Known._102 + _103 -> Known._103 + _104 -> Known._104 + _105 -> Known._105 + else -> throw EInvoiceInvalidDataException("Unknown ReasonCode: $value") + } + + /** + * Returns this class instance's primitive wire representation. + * + * This differs from the [toString] method because that method is primarily for + * debugging and generally doesn't throw. + * + * @throws EInvoiceInvalidDataException if this class instance's value does not have the + * expected primitive type. + */ + fun asString(): String = + _value().asString().orElseThrow { + EInvoiceInvalidDataException("Value is not a String") + } + + private var validated: Boolean = false + + fun validate(): ReasonCode = apply { + if (validated) { + return@apply + } + + known() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: EInvoiceInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic internal fun validity(): Int = if (value() == Value._UNKNOWN) 0 else 1 + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is ReasonCode && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + /** The VAT category code that applies to the allowance */ + class TaxCode @JsonCreator private constructor(private val value: JsonField) : + Enum { + + /** + * Returns this class instance's raw value. + * + * This is usually only useful if this instance was deserialized from data that doesn't + * match any known member, and you want to know that value. For example, if the SDK is + * on an older version than the API, then the API may respond with new members that the + * SDK is unaware of. + */ + @com.fasterxml.jackson.annotation.JsonValue fun _value(): JsonField = value + + companion object { + + @JvmField val AE = of("AE") + + @JvmField val E = of("E") + + @JvmField val S = of("S") + + @JvmField val Z = of("Z") + + @JvmField val G = of("G") + + @JvmField val O = of("O") + + @JvmField val K = of("K") + + @JvmField val L = of("L") + + @JvmField val M = of("M") + + @JvmField val B = of("B") + + @JvmStatic fun of(value: String) = TaxCode(JsonField.of(value)) + } + + /** An enum containing [TaxCode]'s known values. */ + enum class Known { + AE, + E, + S, + Z, + G, + O, + K, + L, + M, + B, + } + + /** + * An enum containing [TaxCode]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [TaxCode] can contain an unknown value in a couple of cases: + * - It was deserialized from data that doesn't match any known member. For example, if + * the SDK is on an older version than the API, then the API may respond with new + * members that the SDK is unaware of. + * - It was constructed with an arbitrary value using the [of] method. + */ + enum class Value { + AE, + E, + S, + Z, + G, + O, + K, + L, + M, + B, + /** + * An enum member indicating that [TaxCode] was instantiated with an unknown value. + */ + _UNKNOWN, + } + + /** + * Returns an enum member corresponding to this class instance's value, or + * [Value._UNKNOWN] if the class was instantiated with an unknown value. + * + * Use the [known] method instead if you're certain the value is always known or if you + * want to throw for the unknown case. + */ + fun value(): Value = + when (this) { + AE -> Value.AE + E -> Value.E + S -> Value.S + Z -> Value.Z + G -> Value.G + O -> Value.O + K -> Value.K + L -> Value.L + M -> Value.M + B -> Value.B + else -> Value._UNKNOWN + } + + /** + * Returns an enum member corresponding to this class instance's value. + * + * Use the [value] method instead if you're uncertain the value is always known and + * don't want to throw for the unknown case. + * + * @throws EInvoiceInvalidDataException if this class instance's value is a not a known + * member. + */ + fun known(): Known = + when (this) { + AE -> Known.AE + E -> Known.E + S -> Known.S + Z -> Known.Z + G -> Known.G + O -> Known.O + K -> Known.K + L -> Known.L + M -> Known.M + B -> Known.B + else -> throw EInvoiceInvalidDataException("Unknown TaxCode: $value") + } + + /** + * Returns this class instance's primitive wire representation. + * + * This differs from the [toString] method because that method is primarily for + * debugging and generally doesn't throw. + * + * @throws EInvoiceInvalidDataException if this class instance's value does not have the + * expected primitive type. + */ + fun asString(): String = + _value().asString().orElseThrow { + EInvoiceInvalidDataException("Value is not a String") + } + + private var validated: Boolean = false + + fun validate(): TaxCode = apply { + if (validated) { + return@apply + } + + known() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: EInvoiceInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic internal fun validity(): Int = if (value() == Value._UNKNOWN) 0 else 1 + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is TaxCode && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Allowance && + amount == other.amount && + baseAmount == other.baseAmount && + multiplierFactor == other.multiplierFactor && + reason == other.reason && + reasonCode == other.reasonCode && + taxCode == other.taxCode && + taxRate == other.taxRate && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash( + amount, + baseAmount, + multiplierFactor, + reason, + reasonCode, + taxCode, + taxRate, + additionalProperties, + ) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "Allowance{amount=$amount, baseAmount=$baseAmount, multiplierFactor=$multiplierFactor, reason=$reason, reasonCode=$reasonCode, taxCode=$taxCode, taxRate=$taxRate, additionalProperties=$additionalProperties}" + } + + class Charge + @JsonCreator(mode = JsonCreator.Mode.DISABLED) + private constructor( + private val amount: JsonField, + private val baseAmount: JsonField, + private val multiplierFactor: JsonField, + private val reason: JsonField, + private val reasonCode: JsonField, + private val taxCode: JsonField, + private val taxRate: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("amount") @ExcludeMissing amount: JsonField = JsonMissing.of(), + @JsonProperty("base_amount") + @ExcludeMissing + baseAmount: JsonField = JsonMissing.of(), + @JsonProperty("multiplier_factor") + @ExcludeMissing + multiplierFactor: JsonField = JsonMissing.of(), + @JsonProperty("reason") @ExcludeMissing reason: JsonField = JsonMissing.of(), + @JsonProperty("reason_code") + @ExcludeMissing + reasonCode: JsonField = JsonMissing.of(), + @JsonProperty("tax_code") + @ExcludeMissing + taxCode: JsonField = JsonMissing.of(), + @JsonProperty("tax_rate") @ExcludeMissing taxRate: JsonField = JsonMissing.of(), + ) : this( + amount, + baseAmount, + multiplierFactor, + reason, + reasonCode, + taxCode, + taxRate, + mutableMapOf(), + ) + + /** + * The charge amount, without VAT. Must be rounded to maximum 2 decimals + * + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun amount(): Optional = amount.getOptional("amount") + + /** + * The base amount that may be used, in conjunction with the charge percentage, to calculate + * the charge amount. Must be rounded to maximum 2 decimals + * + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun baseAmount(): Optional = baseAmount.getOptional("base_amount") + + /** + * The percentage that may be used, in conjunction with the charge base amount, to calculate + * the charge amount. To state 20%, use value 20 + * + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun multiplierFactor(): Optional = multiplierFactor.getOptional("multiplier_factor") + + /** + * The reason for the charge + * + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun reason(): Optional = reason.getOptional("reason") + + /** + * Charge reason codes for invoice charges and fees + * + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun reasonCode(): Optional = reasonCode.getOptional("reason_code") + + /** + * Duty or tax or fee category codes (Subset of UNCL5305) + * + * Agency: UN/CEFACT Version: D.16B Subset: OpenPEPPOL + * + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun taxCode(): Optional = taxCode.getOptional("tax_code") + + /** + * The VAT rate, represented as percentage that applies to the charge + * + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun taxRate(): Optional = taxRate.getOptional("tax_rate") + + /** + * Returns the raw JSON value of [amount]. + * + * Unlike [amount], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("amount") @ExcludeMissing fun _amount(): JsonField = amount + + /** + * Returns the raw JSON value of [baseAmount]. + * + * Unlike [baseAmount], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("base_amount") + @ExcludeMissing + fun _baseAmount(): JsonField = baseAmount + + /** + * Returns the raw JSON value of [multiplierFactor]. + * + * Unlike [multiplierFactor], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("multiplier_factor") + @ExcludeMissing + fun _multiplierFactor(): JsonField = multiplierFactor + + /** + * Returns the raw JSON value of [reason]. + * + * Unlike [reason], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("reason") @ExcludeMissing fun _reason(): JsonField = reason + + /** + * Returns the raw JSON value of [reasonCode]. + * + * Unlike [reasonCode], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("reason_code") + @ExcludeMissing + fun _reasonCode(): JsonField = reasonCode + + /** + * Returns the raw JSON value of [taxCode]. + * + * Unlike [taxCode], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("tax_code") @ExcludeMissing fun _taxCode(): JsonField = taxCode + + /** + * Returns the raw JSON value of [taxRate]. + * + * Unlike [taxRate], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("tax_rate") @ExcludeMissing fun _taxRate(): JsonField = taxRate + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** Returns a mutable builder for constructing an instance of [Charge]. */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [Charge]. */ + class Builder internal constructor() { + + private var amount: JsonField = JsonMissing.of() + private var baseAmount: JsonField = JsonMissing.of() + private var multiplierFactor: JsonField = JsonMissing.of() + private var reason: JsonField = JsonMissing.of() + private var reasonCode: JsonField = JsonMissing.of() + private var taxCode: JsonField = JsonMissing.of() + private var taxRate: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(charge: Charge) = apply { + amount = charge.amount + baseAmount = charge.baseAmount + multiplierFactor = charge.multiplierFactor + reason = charge.reason + reasonCode = charge.reasonCode + taxCode = charge.taxCode + taxRate = charge.taxRate + additionalProperties = charge.additionalProperties.toMutableMap() + } + + /** The charge amount, without VAT. Must be rounded to maximum 2 decimals */ + fun amount(amount: String?) = amount(JsonField.ofNullable(amount)) + + /** Alias for calling [Builder.amount] with `amount.orElse(null)`. */ + fun amount(amount: Optional) = amount(amount.getOrNull()) + + /** + * Sets [Builder.amount] to an arbitrary JSON value. + * + * You should usually call [Builder.amount] with a well-typed [String] value instead. + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun amount(amount: JsonField) = apply { this.amount = amount } + + /** + * The base amount that may be used, in conjunction with the charge percentage, to + * calculate the charge amount. Must be rounded to maximum 2 decimals + */ + fun baseAmount(baseAmount: String?) = baseAmount(JsonField.ofNullable(baseAmount)) + + /** Alias for calling [Builder.baseAmount] with `baseAmount.orElse(null)`. */ + fun baseAmount(baseAmount: Optional) = baseAmount(baseAmount.getOrNull()) + + /** + * Sets [Builder.baseAmount] to an arbitrary JSON value. + * + * You should usually call [Builder.baseAmount] with a well-typed [String] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun baseAmount(baseAmount: JsonField) = apply { this.baseAmount = baseAmount } + + /** + * The percentage that may be used, in conjunction with the charge base amount, to + * calculate the charge amount. To state 20%, use value 20 + */ + fun multiplierFactor(multiplierFactor: String?) = + multiplierFactor(JsonField.ofNullable(multiplierFactor)) + + /** + * Alias for calling [Builder.multiplierFactor] with `multiplierFactor.orElse(null)`. + */ + fun multiplierFactor(multiplierFactor: Optional) = + multiplierFactor(multiplierFactor.getOrNull()) + + /** + * Sets [Builder.multiplierFactor] to an arbitrary JSON value. + * + * You should usually call [Builder.multiplierFactor] with a well-typed [String] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun multiplierFactor(multiplierFactor: JsonField) = apply { + this.multiplierFactor = multiplierFactor + } + + /** The reason for the charge */ + fun reason(reason: String?) = reason(JsonField.ofNullable(reason)) + + /** Alias for calling [Builder.reason] with `reason.orElse(null)`. */ + fun reason(reason: Optional) = reason(reason.getOrNull()) + + /** + * Sets [Builder.reason] to an arbitrary JSON value. + * + * You should usually call [Builder.reason] with a well-typed [String] value instead. + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun reason(reason: JsonField) = apply { this.reason = reason } + + /** Charge reason codes for invoice charges and fees */ + fun reasonCode(reasonCode: ReasonCode?) = reasonCode(JsonField.ofNullable(reasonCode)) + + /** Alias for calling [Builder.reasonCode] with `reasonCode.orElse(null)`. */ + fun reasonCode(reasonCode: Optional) = reasonCode(reasonCode.getOrNull()) + + /** + * Sets [Builder.reasonCode] to an arbitrary JSON value. + * + * You should usually call [Builder.reasonCode] with a well-typed [ReasonCode] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun reasonCode(reasonCode: JsonField) = apply { + this.reasonCode = reasonCode + } + + /** + * Duty or tax or fee category codes (Subset of UNCL5305) + * + * Agency: UN/CEFACT Version: D.16B Subset: OpenPEPPOL + */ + fun taxCode(taxCode: TaxCode?) = taxCode(JsonField.ofNullable(taxCode)) + + /** Alias for calling [Builder.taxCode] with `taxCode.orElse(null)`. */ + fun taxCode(taxCode: Optional) = taxCode(taxCode.getOrNull()) + + /** + * Sets [Builder.taxCode] to an arbitrary JSON value. + * + * You should usually call [Builder.taxCode] with a well-typed [TaxCode] value instead. + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun taxCode(taxCode: JsonField) = apply { this.taxCode = taxCode } + + /** The VAT rate, represented as percentage that applies to the charge */ + fun taxRate(taxRate: String?) = taxRate(JsonField.ofNullable(taxRate)) + + /** Alias for calling [Builder.taxRate] with `taxRate.orElse(null)`. */ + fun taxRate(taxRate: Optional) = taxRate(taxRate.getOrNull()) + + /** + * Sets [Builder.taxRate] to an arbitrary JSON value. + * + * You should usually call [Builder.taxRate] with a well-typed [String] value instead. + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun taxRate(taxRate: JsonField) = apply { this.taxRate = taxRate } + + fun additionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.clear() + putAllAdditionalProperties(additionalProperties) + } + + fun putAdditionalProperty(key: String, value: JsonValue) = apply { + additionalProperties.put(key, value) + } + + fun putAllAdditionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.putAll(additionalProperties) + } + + fun removeAdditionalProperty(key: String) = apply { additionalProperties.remove(key) } + + fun removeAllAdditionalProperties(keys: Set) = apply { + keys.forEach(::removeAdditionalProperty) + } + + /** + * Returns an immutable instance of [Charge]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): Charge = + Charge( + amount, + baseAmount, + multiplierFactor, + reason, + reasonCode, + taxCode, + taxRate, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + fun validate(): Charge = apply { + if (validated) { + return@apply + } + + amount() + baseAmount() + multiplierFactor() + reason() + reasonCode().ifPresent { it.validate() } + taxCode().ifPresent { it.validate() } + taxRate() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: EInvoiceInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic + internal fun validity(): Int = + (if (amount.asKnown().isPresent) 1 else 0) + + (if (baseAmount.asKnown().isPresent) 1 else 0) + + (if (multiplierFactor.asKnown().isPresent) 1 else 0) + + (if (reason.asKnown().isPresent) 1 else 0) + + (reasonCode.asKnown().getOrNull()?.validity() ?: 0) + + (taxCode.asKnown().getOrNull()?.validity() ?: 0) + + (if (taxRate.asKnown().isPresent) 1 else 0) + + /** Charge reason codes for invoice charges and fees */ + class ReasonCode @JsonCreator private constructor(private val value: JsonField) : + Enum { + + /** + * Returns this class instance's raw value. + * + * This is usually only useful if this instance was deserialized from data that doesn't + * match any known member, and you want to know that value. For example, if the SDK is + * on an older version than the API, then the API may respond with new members that the + * SDK is unaware of. + */ + @com.fasterxml.jackson.annotation.JsonValue fun _value(): JsonField = value + + companion object { + + @JvmField val AA = of("AA") + + @JvmField val AAA = of("AAA") + + @JvmField val AAC = of("AAC") + + @JvmField val AAD = of("AAD") + + @JvmField val AAE = of("AAE") + + @JvmField val AAF = of("AAF") + + @JvmField val AAH = of("AAH") + + @JvmField val AAI = of("AAI") + + @JvmField val AAS = of("AAS") + + @JvmField val AAT = of("AAT") + + @JvmField val AAV = of("AAV") + + @JvmField val AAY = of("AAY") + + @JvmField val AAZ = of("AAZ") + + @JvmField val ABA = of("ABA") + + @JvmField val ABB = of("ABB") + + @JvmField val ABC = of("ABC") + + @JvmField val ABD = of("ABD") + + @JvmField val ABF = of("ABF") + + @JvmField val ABK = of("ABK") + + @JvmField val ABL = of("ABL") + + @JvmField val ABN = of("ABN") + + @JvmField val ABR = of("ABR") + + @JvmField val ABS = of("ABS") + + @JvmField val ABT = of("ABT") + + @JvmField val ABU = of("ABU") + + @JvmField val ACF = of("ACF") + + @JvmField val ACG = of("ACG") + + @JvmField val ACH = of("ACH") + + @JvmField val ACI = of("ACI") + + @JvmField val ACJ = of("ACJ") + + @JvmField val ACK = of("ACK") + + @JvmField val ACL = of("ACL") + + @JvmField val ACM = of("ACM") + + @JvmField val ACS = of("ACS") + + @JvmField val ADC = of("ADC") + + @JvmField val ADE = of("ADE") + + @JvmField val ADJ = of("ADJ") + + @JvmField val ADK = of("ADK") + + @JvmField val ADL = of("ADL") + + @JvmField val ADM = of("ADM") + + @JvmField val ADN = of("ADN") + + @JvmField val ADO = of("ADO") + + @JvmField val ADP = of("ADP") + + @JvmField val ADQ = of("ADQ") + + @JvmField val ADR = of("ADR") + + @JvmField val ADT = of("ADT") + + @JvmField val ADW = of("ADW") + + @JvmField val ADY = of("ADY") + + @JvmField val ADZ = of("ADZ") + + @JvmField val AEA = of("AEA") + + @JvmField val AEB = of("AEB") + + @JvmField val AEC = of("AEC") + + @JvmField val AED = of("AED") + + @JvmField val AEF = of("AEF") + + @JvmField val AEH = of("AEH") + + @JvmField val AEI = of("AEI") + + @JvmField val AEJ = of("AEJ") + + @JvmField val AEK = of("AEK") + + @JvmField val AEL = of("AEL") + + @JvmField val AEM = of("AEM") + + @JvmField val AEN = of("AEN") + + @JvmField val AEO = of("AEO") + + @JvmField val AEP = of("AEP") + + @JvmField val AES = of("AES") + + @JvmField val AET = of("AET") + + @JvmField val AEU = of("AEU") + + @JvmField val AEV = of("AEV") + + @JvmField val AEW = of("AEW") + + @JvmField val AEX = of("AEX") + + @JvmField val AEY = of("AEY") + + @JvmField val AEZ = of("AEZ") + + @JvmField val AJ = of("AJ") + + @JvmField val AU = of("AU") + + @JvmField val CA = of("CA") + + @JvmField val CAB = of("CAB") + + @JvmField val CAD = of("CAD") + + @JvmField val CAE = of("CAE") + + @JvmField val CAF = of("CAF") + + @JvmField val CAI = of("CAI") + + @JvmField val CAJ = of("CAJ") + + @JvmField val CAK = of("CAK") + + @JvmField val CAL = of("CAL") + + @JvmField val CAM = of("CAM") + + @JvmField val CAN = of("CAN") + + @JvmField val CAO = of("CAO") + + @JvmField val CAP = of("CAP") + + @JvmField val CAQ = of("CAQ") + + @JvmField val CAR = of("CAR") + + @JvmField val CAS = of("CAS") + + @JvmField val CAT = of("CAT") + + @JvmField val CAU = of("CAU") + + @JvmField val CAV = of("CAV") + + @JvmField val CAW = of("CAW") + + @JvmField val CAX = of("CAX") + + @JvmField val CAY = of("CAY") + + @JvmField val CAZ = of("CAZ") + + @JvmField val CD = of("CD") + + @JvmField val CG = of("CG") + + @JvmField val CS = of("CS") + + @JvmField val CT = of("CT") + + @JvmField val DAB = of("DAB") + + @JvmField val DAC = of("DAC") + + @JvmField val DAD = of("DAD") + + @JvmField val DAF = of("DAF") + + @JvmField val DAG = of("DAG") + + @JvmField val DAH = of("DAH") + + @JvmField val DAI = of("DAI") + + @JvmField val DAJ = of("DAJ") + + @JvmField val DAK = of("DAK") + + @JvmField val DAL = of("DAL") + + @JvmField val DAM = of("DAM") + + @JvmField val DAN = of("DAN") + + @JvmField val DAO = of("DAO") + + @JvmField val DAP = of("DAP") + + @JvmField val DAQ = of("DAQ") + + @JvmField val DL = of("DL") + + @JvmField val EG = of("EG") + + @JvmField val EP = of("EP") + + @JvmField val ER = of("ER") + + @JvmField val FAA = of("FAA") + + @JvmField val FAB = of("FAB") + + @JvmField val FAC = of("FAC") + + @JvmField val FC = of("FC") + + @JvmField val FH = of("FH") + + @JvmField val FI = of("FI") + + @JvmField val GAA = of("GAA") + + @JvmField val HAA = of("HAA") + + @JvmField val HD = of("HD") + + @JvmField val HH = of("HH") + + @JvmField val IAA = of("IAA") + + @JvmField val IAB = of("IAB") + + @JvmField val ID = of("ID") + + @JvmField val IF = of("IF") + + @JvmField val IR = of("IR") + + @JvmField val IS = of("IS") + + @JvmField val KO = of("KO") + + @JvmField val L1 = of("L1") + + @JvmField val LA = of("LA") + + @JvmField val LAA = of("LAA") + + @JvmField val LAB = of("LAB") + + @JvmField val LF = of("LF") + + @JvmField val MAE = of("MAE") + + @JvmField val MI = of("MI") + + @JvmField val ML = of("ML") + + @JvmField val NAA = of("NAA") + + @JvmField val OA = of("OA") + + @JvmField val PA = of("PA") + + @JvmField val PAA = of("PAA") + + @JvmField val PC = of("PC") + + @JvmField val PL = of("PL") + + @JvmField val PRV = of("PRV") + + @JvmField val RAB = of("RAB") + + @JvmField val RAC = of("RAC") + + @JvmField val RAD = of("RAD") + + @JvmField val RAF = of("RAF") + + @JvmField val RE = of("RE") + + @JvmField val RF = of("RF") + + @JvmField val RH = of("RH") + + @JvmField val RV = of("RV") + + @JvmField val SA = of("SA") + + @JvmField val SAA = of("SAA") + + @JvmField val SAD = of("SAD") + + @JvmField val SAE = of("SAE") + + @JvmField val SAI = of("SAI") + + @JvmField val SG = of("SG") + + @JvmField val SH = of("SH") + + @JvmField val SM = of("SM") + + @JvmField val SU = of("SU") + + @JvmField val TAB = of("TAB") + + @JvmField val TAC = of("TAC") + + @JvmField val TT = of("TT") + + @JvmField val TV = of("TV") + + @JvmField val V1 = of("V1") + + @JvmField val V2 = of("V2") + + @JvmField val WH = of("WH") + + @JvmField val XAA = of("XAA") + + @JvmField val YY = of("YY") + + @JvmField val ZZZ = of("ZZZ") + + @JvmStatic fun of(value: String) = ReasonCode(JsonField.of(value)) + } + + /** An enum containing [ReasonCode]'s known values. */ + enum class Known { + AA, + AAA, + AAC, + AAD, + AAE, + AAF, + AAH, + AAI, + AAS, + AAT, + AAV, + AAY, + AAZ, + ABA, + ABB, + ABC, + ABD, + ABF, + ABK, + ABL, + ABN, + ABR, + ABS, + ABT, + ABU, + ACF, + ACG, + ACH, + ACI, + ACJ, + ACK, + ACL, + ACM, + ACS, + ADC, + ADE, + ADJ, + ADK, + ADL, + ADM, + ADN, + ADO, + ADP, + ADQ, + ADR, + ADT, + ADW, + ADY, + ADZ, + AEA, + AEB, + AEC, + AED, + AEF, + AEH, + AEI, + AEJ, + AEK, + AEL, + AEM, + AEN, + AEO, + AEP, + AES, + AET, + AEU, + AEV, + AEW, + AEX, + AEY, + AEZ, + AJ, + AU, + CA, + CAB, + CAD, + CAE, + CAF, + CAI, + CAJ, + CAK, + CAL, + CAM, + CAN, + CAO, + CAP, + CAQ, + CAR, + CAS, + CAT, + CAU, + CAV, + CAW, + CAX, + CAY, + CAZ, + CD, + CG, + CS, + CT, + DAB, + DAC, + DAD, + DAF, + DAG, + DAH, + DAI, + DAJ, + DAK, + DAL, + DAM, + DAN, + DAO, + DAP, + DAQ, + DL, + EG, + EP, + ER, + FAA, + FAB, + FAC, + FC, + FH, + FI, + GAA, + HAA, + HD, + HH, + IAA, + IAB, + ID, + IF, + IR, + IS, + KO, + L1, + LA, + LAA, + LAB, + LF, + MAE, + MI, + ML, + NAA, + OA, + PA, + PAA, + PC, + PL, + PRV, + RAB, + RAC, + RAD, + RAF, + RE, + RF, + RH, + RV, + SA, + SAA, + SAD, + SAE, + SAI, + SG, + SH, + SM, + SU, + TAB, + TAC, + TT, + TV, + V1, + V2, + WH, + XAA, + YY, + ZZZ, + } + + /** + * An enum containing [ReasonCode]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [ReasonCode] can contain an unknown value in a couple of cases: + * - It was deserialized from data that doesn't match any known member. For example, if + * the SDK is on an older version than the API, then the API may respond with new + * members that the SDK is unaware of. + * - It was constructed with an arbitrary value using the [of] method. + */ + enum class Value { + AA, + AAA, + AAC, + AAD, + AAE, + AAF, + AAH, + AAI, + AAS, + AAT, + AAV, + AAY, + AAZ, + ABA, + ABB, + ABC, + ABD, + ABF, + ABK, + ABL, + ABN, + ABR, + ABS, + ABT, + ABU, + ACF, + ACG, + ACH, + ACI, + ACJ, + ACK, + ACL, + ACM, + ACS, + ADC, + ADE, + ADJ, + ADK, + ADL, + ADM, + ADN, + ADO, + ADP, + ADQ, + ADR, + ADT, + ADW, + ADY, + ADZ, + AEA, + AEB, + AEC, + AED, + AEF, + AEH, + AEI, + AEJ, + AEK, + AEL, + AEM, + AEN, + AEO, + AEP, + AES, + AET, + AEU, + AEV, + AEW, + AEX, + AEY, + AEZ, + AJ, + AU, + CA, + CAB, + CAD, + CAE, + CAF, + CAI, + CAJ, + CAK, + CAL, + CAM, + CAN, + CAO, + CAP, + CAQ, + CAR, + CAS, + CAT, + CAU, + CAV, + CAW, + CAX, + CAY, + CAZ, + CD, + CG, + CS, + CT, + DAB, + DAC, + DAD, + DAF, + DAG, + DAH, + DAI, + DAJ, + DAK, + DAL, + DAM, + DAN, + DAO, + DAP, + DAQ, + DL, + EG, + EP, + ER, + FAA, + FAB, + FAC, + FC, + FH, + FI, + GAA, + HAA, + HD, + HH, + IAA, + IAB, + ID, + IF, + IR, + IS, + KO, + L1, + LA, + LAA, + LAB, + LF, + MAE, + MI, + ML, + NAA, + OA, + PA, + PAA, + PC, + PL, + PRV, + RAB, + RAC, + RAD, + RAF, + RE, + RF, + RH, + RV, + SA, + SAA, + SAD, + SAE, + SAI, + SG, + SH, + SM, + SU, + TAB, + TAC, + TT, + TV, + V1, + V2, + WH, + XAA, + YY, + ZZZ, + /** + * An enum member indicating that [ReasonCode] was instantiated with an unknown + * value. + */ + _UNKNOWN, + } + + /** + * Returns an enum member corresponding to this class instance's value, or + * [Value._UNKNOWN] if the class was instantiated with an unknown value. + * + * Use the [known] method instead if you're certain the value is always known or if you + * want to throw for the unknown case. + */ + fun value(): Value = + when (this) { + AA -> Value.AA + AAA -> Value.AAA + AAC -> Value.AAC + AAD -> Value.AAD + AAE -> Value.AAE + AAF -> Value.AAF + AAH -> Value.AAH + AAI -> Value.AAI + AAS -> Value.AAS + AAT -> Value.AAT + AAV -> Value.AAV + AAY -> Value.AAY + AAZ -> Value.AAZ + ABA -> Value.ABA + ABB -> Value.ABB + ABC -> Value.ABC + ABD -> Value.ABD + ABF -> Value.ABF + ABK -> Value.ABK + ABL -> Value.ABL + ABN -> Value.ABN + ABR -> Value.ABR + ABS -> Value.ABS + ABT -> Value.ABT + ABU -> Value.ABU + ACF -> Value.ACF + ACG -> Value.ACG + ACH -> Value.ACH + ACI -> Value.ACI + ACJ -> Value.ACJ + ACK -> Value.ACK + ACL -> Value.ACL + ACM -> Value.ACM + ACS -> Value.ACS + ADC -> Value.ADC + ADE -> Value.ADE + ADJ -> Value.ADJ + ADK -> Value.ADK + ADL -> Value.ADL + ADM -> Value.ADM + ADN -> Value.ADN + ADO -> Value.ADO + ADP -> Value.ADP + ADQ -> Value.ADQ + ADR -> Value.ADR + ADT -> Value.ADT + ADW -> Value.ADW + ADY -> Value.ADY + ADZ -> Value.ADZ + AEA -> Value.AEA + AEB -> Value.AEB + AEC -> Value.AEC + AED -> Value.AED + AEF -> Value.AEF + AEH -> Value.AEH + AEI -> Value.AEI + AEJ -> Value.AEJ + AEK -> Value.AEK + AEL -> Value.AEL + AEM -> Value.AEM + AEN -> Value.AEN + AEO -> Value.AEO + AEP -> Value.AEP + AES -> Value.AES + AET -> Value.AET + AEU -> Value.AEU + AEV -> Value.AEV + AEW -> Value.AEW + AEX -> Value.AEX + AEY -> Value.AEY + AEZ -> Value.AEZ + AJ -> Value.AJ + AU -> Value.AU + CA -> Value.CA + CAB -> Value.CAB + CAD -> Value.CAD + CAE -> Value.CAE + CAF -> Value.CAF + CAI -> Value.CAI + CAJ -> Value.CAJ + CAK -> Value.CAK + CAL -> Value.CAL + CAM -> Value.CAM + CAN -> Value.CAN + CAO -> Value.CAO + CAP -> Value.CAP + CAQ -> Value.CAQ + CAR -> Value.CAR + CAS -> Value.CAS + CAT -> Value.CAT + CAU -> Value.CAU + CAV -> Value.CAV + CAW -> Value.CAW + CAX -> Value.CAX + CAY -> Value.CAY + CAZ -> Value.CAZ + CD -> Value.CD + CG -> Value.CG + CS -> Value.CS + CT -> Value.CT + DAB -> Value.DAB + DAC -> Value.DAC + DAD -> Value.DAD + DAF -> Value.DAF + DAG -> Value.DAG + DAH -> Value.DAH + DAI -> Value.DAI + DAJ -> Value.DAJ + DAK -> Value.DAK + DAL -> Value.DAL + DAM -> Value.DAM + DAN -> Value.DAN + DAO -> Value.DAO + DAP -> Value.DAP + DAQ -> Value.DAQ + DL -> Value.DL + EG -> Value.EG + EP -> Value.EP + ER -> Value.ER + FAA -> Value.FAA + FAB -> Value.FAB + FAC -> Value.FAC + FC -> Value.FC + FH -> Value.FH + FI -> Value.FI + GAA -> Value.GAA + HAA -> Value.HAA + HD -> Value.HD + HH -> Value.HH + IAA -> Value.IAA + IAB -> Value.IAB + ID -> Value.ID + IF -> Value.IF + IR -> Value.IR + IS -> Value.IS + KO -> Value.KO + L1 -> Value.L1 + LA -> Value.LA + LAA -> Value.LAA + LAB -> Value.LAB + LF -> Value.LF + MAE -> Value.MAE + MI -> Value.MI + ML -> Value.ML + NAA -> Value.NAA + OA -> Value.OA + PA -> Value.PA + PAA -> Value.PAA + PC -> Value.PC + PL -> Value.PL + PRV -> Value.PRV + RAB -> Value.RAB + RAC -> Value.RAC + RAD -> Value.RAD + RAF -> Value.RAF + RE -> Value.RE + RF -> Value.RF + RH -> Value.RH + RV -> Value.RV + SA -> Value.SA + SAA -> Value.SAA + SAD -> Value.SAD + SAE -> Value.SAE + SAI -> Value.SAI + SG -> Value.SG + SH -> Value.SH + SM -> Value.SM + SU -> Value.SU + TAB -> Value.TAB + TAC -> Value.TAC + TT -> Value.TT + TV -> Value.TV + V1 -> Value.V1 + V2 -> Value.V2 + WH -> Value.WH + XAA -> Value.XAA + YY -> Value.YY + ZZZ -> Value.ZZZ + else -> Value._UNKNOWN + } + + /** + * Returns an enum member corresponding to this class instance's value. + * + * Use the [value] method instead if you're uncertain the value is always known and + * don't want to throw for the unknown case. + * + * @throws EInvoiceInvalidDataException if this class instance's value is a not a known + * member. + */ + fun known(): Known = + when (this) { + AA -> Known.AA + AAA -> Known.AAA + AAC -> Known.AAC + AAD -> Known.AAD + AAE -> Known.AAE + AAF -> Known.AAF + AAH -> Known.AAH + AAI -> Known.AAI + AAS -> Known.AAS + AAT -> Known.AAT + AAV -> Known.AAV + AAY -> Known.AAY + AAZ -> Known.AAZ + ABA -> Known.ABA + ABB -> Known.ABB + ABC -> Known.ABC + ABD -> Known.ABD + ABF -> Known.ABF + ABK -> Known.ABK + ABL -> Known.ABL + ABN -> Known.ABN + ABR -> Known.ABR + ABS -> Known.ABS + ABT -> Known.ABT + ABU -> Known.ABU + ACF -> Known.ACF + ACG -> Known.ACG + ACH -> Known.ACH + ACI -> Known.ACI + ACJ -> Known.ACJ + ACK -> Known.ACK + ACL -> Known.ACL + ACM -> Known.ACM + ACS -> Known.ACS + ADC -> Known.ADC + ADE -> Known.ADE + ADJ -> Known.ADJ + ADK -> Known.ADK + ADL -> Known.ADL + ADM -> Known.ADM + ADN -> Known.ADN + ADO -> Known.ADO + ADP -> Known.ADP + ADQ -> Known.ADQ + ADR -> Known.ADR + ADT -> Known.ADT + ADW -> Known.ADW + ADY -> Known.ADY + ADZ -> Known.ADZ + AEA -> Known.AEA + AEB -> Known.AEB + AEC -> Known.AEC + AED -> Known.AED + AEF -> Known.AEF + AEH -> Known.AEH + AEI -> Known.AEI + AEJ -> Known.AEJ + AEK -> Known.AEK + AEL -> Known.AEL + AEM -> Known.AEM + AEN -> Known.AEN + AEO -> Known.AEO + AEP -> Known.AEP + AES -> Known.AES + AET -> Known.AET + AEU -> Known.AEU + AEV -> Known.AEV + AEW -> Known.AEW + AEX -> Known.AEX + AEY -> Known.AEY + AEZ -> Known.AEZ + AJ -> Known.AJ + AU -> Known.AU + CA -> Known.CA + CAB -> Known.CAB + CAD -> Known.CAD + CAE -> Known.CAE + CAF -> Known.CAF + CAI -> Known.CAI + CAJ -> Known.CAJ + CAK -> Known.CAK + CAL -> Known.CAL + CAM -> Known.CAM + CAN -> Known.CAN + CAO -> Known.CAO + CAP -> Known.CAP + CAQ -> Known.CAQ + CAR -> Known.CAR + CAS -> Known.CAS + CAT -> Known.CAT + CAU -> Known.CAU + CAV -> Known.CAV + CAW -> Known.CAW + CAX -> Known.CAX + CAY -> Known.CAY + CAZ -> Known.CAZ + CD -> Known.CD + CG -> Known.CG + CS -> Known.CS + CT -> Known.CT + DAB -> Known.DAB + DAC -> Known.DAC + DAD -> Known.DAD + DAF -> Known.DAF + DAG -> Known.DAG + DAH -> Known.DAH + DAI -> Known.DAI + DAJ -> Known.DAJ + DAK -> Known.DAK + DAL -> Known.DAL + DAM -> Known.DAM + DAN -> Known.DAN + DAO -> Known.DAO + DAP -> Known.DAP + DAQ -> Known.DAQ + DL -> Known.DL + EG -> Known.EG + EP -> Known.EP + ER -> Known.ER + FAA -> Known.FAA + FAB -> Known.FAB + FAC -> Known.FAC + FC -> Known.FC + FH -> Known.FH + FI -> Known.FI + GAA -> Known.GAA + HAA -> Known.HAA + HD -> Known.HD + HH -> Known.HH + IAA -> Known.IAA + IAB -> Known.IAB + ID -> Known.ID + IF -> Known.IF + IR -> Known.IR + IS -> Known.IS + KO -> Known.KO + L1 -> Known.L1 + LA -> Known.LA + LAA -> Known.LAA + LAB -> Known.LAB + LF -> Known.LF + MAE -> Known.MAE + MI -> Known.MI + ML -> Known.ML + NAA -> Known.NAA + OA -> Known.OA + PA -> Known.PA + PAA -> Known.PAA + PC -> Known.PC + PL -> Known.PL + PRV -> Known.PRV + RAB -> Known.RAB + RAC -> Known.RAC + RAD -> Known.RAD + RAF -> Known.RAF + RE -> Known.RE + RF -> Known.RF + RH -> Known.RH + RV -> Known.RV + SA -> Known.SA + SAA -> Known.SAA + SAD -> Known.SAD + SAE -> Known.SAE + SAI -> Known.SAI + SG -> Known.SG + SH -> Known.SH + SM -> Known.SM + SU -> Known.SU + TAB -> Known.TAB + TAC -> Known.TAC + TT -> Known.TT + TV -> Known.TV + V1 -> Known.V1 + V2 -> Known.V2 + WH -> Known.WH + XAA -> Known.XAA + YY -> Known.YY + ZZZ -> Known.ZZZ + else -> throw EInvoiceInvalidDataException("Unknown ReasonCode: $value") + } + + /** + * Returns this class instance's primitive wire representation. + * + * This differs from the [toString] method because that method is primarily for + * debugging and generally doesn't throw. + * + * @throws EInvoiceInvalidDataException if this class instance's value does not have the + * expected primitive type. + */ + fun asString(): String = + _value().asString().orElseThrow { + EInvoiceInvalidDataException("Value is not a String") + } + + private var validated: Boolean = false + + fun validate(): ReasonCode = apply { + if (validated) { + return@apply + } + + known() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: EInvoiceInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic internal fun validity(): Int = if (value() == Value._UNKNOWN) 0 else 1 + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is ReasonCode && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + /** + * Duty or tax or fee category codes (Subset of UNCL5305) + * + * Agency: UN/CEFACT Version: D.16B Subset: OpenPEPPOL + */ + class TaxCode @JsonCreator private constructor(private val value: JsonField) : + Enum { + + /** + * Returns this class instance's raw value. + * + * This is usually only useful if this instance was deserialized from data that doesn't + * match any known member, and you want to know that value. For example, if the SDK is + * on an older version than the API, then the API may respond with new members that the + * SDK is unaware of. + */ + @com.fasterxml.jackson.annotation.JsonValue fun _value(): JsonField = value + + companion object { + + @JvmField val AE = of("AE") + + @JvmField val E = of("E") + + @JvmField val S = of("S") + + @JvmField val Z = of("Z") + + @JvmField val G = of("G") + + @JvmField val O = of("O") + + @JvmField val K = of("K") + + @JvmField val L = of("L") + + @JvmField val M = of("M") + + @JvmField val B = of("B") + + @JvmStatic fun of(value: String) = TaxCode(JsonField.of(value)) + } + + /** An enum containing [TaxCode]'s known values. */ + enum class Known { + AE, + E, + S, + Z, + G, + O, + K, + L, + M, + B, + } + + /** + * An enum containing [TaxCode]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [TaxCode] can contain an unknown value in a couple of cases: + * - It was deserialized from data that doesn't match any known member. For example, if + * the SDK is on an older version than the API, then the API may respond with new + * members that the SDK is unaware of. + * - It was constructed with an arbitrary value using the [of] method. + */ + enum class Value { + AE, + E, + S, + Z, + G, + O, + K, + L, + M, + B, + /** + * An enum member indicating that [TaxCode] was instantiated with an unknown value. + */ + _UNKNOWN, + } + + /** + * Returns an enum member corresponding to this class instance's value, or + * [Value._UNKNOWN] if the class was instantiated with an unknown value. + * + * Use the [known] method instead if you're certain the value is always known or if you + * want to throw for the unknown case. + */ + fun value(): Value = + when (this) { + AE -> Value.AE + E -> Value.E + S -> Value.S + Z -> Value.Z + G -> Value.G + O -> Value.O + K -> Value.K + L -> Value.L + M -> Value.M + B -> Value.B + else -> Value._UNKNOWN + } + + /** + * Returns an enum member corresponding to this class instance's value. + * + * Use the [value] method instead if you're uncertain the value is always known and + * don't want to throw for the unknown case. + * + * @throws EInvoiceInvalidDataException if this class instance's value is a not a known + * member. + */ + fun known(): Known = + when (this) { + AE -> Known.AE + E -> Known.E + S -> Known.S + Z -> Known.Z + G -> Known.G + O -> Known.O + K -> Known.K + L -> Known.L + M -> Known.M + B -> Known.B + else -> throw EInvoiceInvalidDataException("Unknown TaxCode: $value") + } + + /** + * Returns this class instance's primitive wire representation. + * + * This differs from the [toString] method because that method is primarily for + * debugging and generally doesn't throw. + * + * @throws EInvoiceInvalidDataException if this class instance's value does not have the + * expected primitive type. + */ + fun asString(): String = + _value().asString().orElseThrow { + EInvoiceInvalidDataException("Value is not a String") + } + + private var validated: Boolean = false + + fun validate(): TaxCode = apply { + if (validated) { + return@apply + } + + known() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: EInvoiceInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic internal fun validity(): Int = if (value() == Value._UNKNOWN) 0 else 1 + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is TaxCode && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Charge && + amount == other.amount && + baseAmount == other.baseAmount && + multiplierFactor == other.multiplierFactor && + reason == other.reason && + reasonCode == other.reasonCode && + taxCode == other.taxCode && + taxRate == other.taxRate && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash( + amount, + baseAmount, + multiplierFactor, + reason, + reasonCode, + taxCode, + taxRate, + additionalProperties, + ) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "Charge{amount=$amount, baseAmount=$baseAmount, multiplierFactor=$multiplierFactor, reason=$reason, reasonCode=$reasonCode, taxCode=$taxCode, taxRate=$taxRate, additionalProperties=$additionalProperties}" + } + + class Item + @JsonCreator(mode = JsonCreator.Mode.DISABLED) + private constructor( + private val allowances: JsonField>, + private val amount: JsonField, + private val charges: JsonField>, + private val date: JsonField, + private val description: JsonField, + private val productCode: JsonField, + private val quantity: JsonField, + private val tax: JsonField, + private val taxRate: JsonField, + private val unit: JsonField, + private val unitPrice: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("allowances") + @ExcludeMissing + allowances: JsonField> = JsonMissing.of(), + @JsonProperty("amount") @ExcludeMissing amount: JsonField = JsonMissing.of(), + @JsonProperty("charges") + @ExcludeMissing + charges: JsonField> = JsonMissing.of(), + @JsonProperty("date") @ExcludeMissing date: JsonField = JsonMissing.of(), + @JsonProperty("description") + @ExcludeMissing + description: JsonField = JsonMissing.of(), @JsonProperty("product_code") @ExcludeMissing productCode: JsonField = JsonMissing.of(), @@ -1917,7 +5028,9 @@ private constructor( @ExcludeMissing unitPrice: JsonField = JsonMissing.of(), ) : this( + allowances, amount, + charges, date, description, productCode, @@ -1930,11 +5043,32 @@ private constructor( ) /** + * The allowances of the line item. + * + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun allowances(): Optional> = allowances.getOptional("allowances") + + /** + * The invoice line net amount (BT-131), exclusive of VAT, inclusive of line level + * allowances and charges. Calculated as: ((unit_price / price_base_quantity) * quantity) - + * allowances + charges. Must be rounded to maximum 2 decimals. Can be negative for credit + * notes or corrections. + * * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if * the server responded with an unexpected value). */ fun amount(): Optional = amount.getOptional("amount") + /** + * The charges of the line item. + * + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun charges(): Optional> = charges.getOptional("charges") + /** * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if * the server responded with an unexpected value). @@ -1942,30 +5076,42 @@ private constructor( fun date(): Optional = date.getOptional("date") /** + * The description of the line item. + * * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if * the server responded with an unexpected value). */ fun description(): Optional = description.getOptional("description") /** + * The product code of the line item. + * * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if * the server responded with an unexpected value). */ fun productCode(): Optional = productCode.getOptional("product_code") /** + * The quantity of items (goods or services) that is the subject of the line item. Must be + * rounded to maximum 4 decimals. Can be negative for credit notes or corrections. + * * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if * the server responded with an unexpected value). */ fun quantity(): Optional = quantity.getOptional("quantity") /** + * The total VAT amount for the line item. Must be rounded to maximum 2 decimals. Can be + * negative for credit notes or corrections. + * * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if * the server responded with an unexpected value). */ fun tax(): Optional = tax.getOptional("tax") /** + * The VAT rate of the line item expressed as percentage with 2 decimals + * * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if * the server responded with an unexpected value). */ @@ -1980,17 +5126,36 @@ private constructor( fun unit(): Optional = unit.getOptional("unit") /** + * The item net price (BT-146). The price of an item, exclusive of VAT, after subtracting + * item price discount. Must be rounded to maximum 4 decimals + * * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if * the server responded with an unexpected value). */ fun unitPrice(): Optional = unitPrice.getOptional("unit_price") + /** + * Returns the raw JSON value of [allowances]. + * + * Unlike [allowances], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("allowances") + @ExcludeMissing + fun _allowances(): JsonField> = allowances + /** * Returns the raw JSON value of [amount]. * - * Unlike [amount], this method doesn't throw if the JSON field has an unexpected type. + * Unlike [amount], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("amount") @ExcludeMissing fun _amount(): JsonField = amount + + /** + * Returns the raw JSON value of [charges]. + * + * Unlike [charges], this method doesn't throw if the JSON field has an unexpected type. */ - @JsonProperty("amount") @ExcludeMissing fun _amount(): JsonField = amount + @JsonProperty("charges") @ExcludeMissing fun _charges(): JsonField> = charges /** * Returns the raw JSON value of [date]. @@ -2073,7 +5238,9 @@ private constructor( /** A builder for [Item]. */ class Builder internal constructor() { + private var allowances: JsonField>? = null private var amount: JsonField = JsonMissing.of() + private var charges: JsonField>? = null private var date: JsonField = JsonMissing.of() private var description: JsonField = JsonMissing.of() private var productCode: JsonField = JsonMissing.of() @@ -2086,7 +5253,9 @@ private constructor( @JvmSynthetic internal fun from(item: Item) = apply { + allowances = item.allowances.map { it.toMutableList() } amount = item.amount + charges = item.charges.map { it.toMutableList() } date = item.date description = item.description productCode = item.productCode @@ -2098,6 +5267,43 @@ private constructor( additionalProperties = item.additionalProperties.toMutableMap() } + /** The allowances of the line item. */ + fun allowances(allowances: List?) = + allowances(JsonField.ofNullable(allowances)) + + /** Alias for calling [Builder.allowances] with `allowances.orElse(null)`. */ + fun allowances(allowances: Optional>) = + allowances(allowances.getOrNull()) + + /** + * Sets [Builder.allowances] to an arbitrary JSON value. + * + * You should usually call [Builder.allowances] with a well-typed `List` + * value instead. This method is primarily for setting the field to an undocumented or + * not yet supported value. + */ + fun allowances(allowances: JsonField>) = apply { + this.allowances = allowances.map { it.toMutableList() } + } + + /** + * Adds a single [Allowance] to [allowances]. + * + * @throws IllegalStateException if the field was previously set to a non-list. + */ + fun addAllowance(allowance: Allowance) = apply { + allowances = + (allowances ?: JsonField.of(mutableListOf())).also { + checkKnown("allowances", it).add(allowance) + } + } + + /** + * The invoice line net amount (BT-131), exclusive of VAT, inclusive of line level + * allowances and charges. Calculated as: ((unit_price / price_base_quantity) * + * quantity) - allowances + charges. Must be rounded to maximum 2 decimals. Can be + * negative for credit notes or corrections. + */ fun amount(amount: String?) = amount(JsonField.ofNullable(amount)) /** Alias for calling [Builder.amount] with `amount.orElse(null)`. */ @@ -2112,6 +5318,35 @@ private constructor( */ fun amount(amount: JsonField) = apply { this.amount = amount } + /** The charges of the line item. */ + fun charges(charges: List?) = charges(JsonField.ofNullable(charges)) + + /** Alias for calling [Builder.charges] with `charges.orElse(null)`. */ + fun charges(charges: Optional>) = charges(charges.getOrNull()) + + /** + * Sets [Builder.charges] to an arbitrary JSON value. + * + * You should usually call [Builder.charges] with a well-typed `List` value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun charges(charges: JsonField>) = apply { + this.charges = charges.map { it.toMutableList() } + } + + /** + * Adds a single [Charge] to [charges]. + * + * @throws IllegalStateException if the field was previously set to a non-list. + */ + fun addCharge(charge: Charge) = apply { + charges = + (charges ?: JsonField.of(mutableListOf())).also { + checkKnown("charges", it).add(charge) + } + } + fun date(date: Void?) = date(JsonField.ofNullable(date)) /** Alias for calling [Builder.date] with `date.orElse(null)`. */ @@ -2126,6 +5361,7 @@ private constructor( */ fun date(date: JsonField) = apply { this.date = date } + /** The description of the line item. */ fun description(description: String?) = description(JsonField.ofNullable(description)) /** Alias for calling [Builder.description] with `description.orElse(null)`. */ @@ -2142,6 +5378,7 @@ private constructor( this.description = description } + /** The product code of the line item. */ fun productCode(productCode: String?) = productCode(JsonField.ofNullable(productCode)) /** Alias for calling [Builder.productCode] with `productCode.orElse(null)`. */ @@ -2158,6 +5395,10 @@ private constructor( this.productCode = productCode } + /** + * The quantity of items (goods or services) that is the subject of the line item. Must + * be rounded to maximum 4 decimals. Can be negative for credit notes or corrections. + */ fun quantity(quantity: String?) = quantity(JsonField.ofNullable(quantity)) /** Alias for calling [Builder.quantity] with `quantity.orElse(null)`. */ @@ -2172,6 +5413,10 @@ private constructor( */ fun quantity(quantity: JsonField) = apply { this.quantity = quantity } + /** + * The total VAT amount for the line item. Must be rounded to maximum 2 decimals. Can be + * negative for credit notes or corrections. + */ fun tax(tax: String?) = tax(JsonField.ofNullable(tax)) /** Alias for calling [Builder.tax] with `tax.orElse(null)`. */ @@ -2186,6 +5431,7 @@ private constructor( */ fun tax(tax: JsonField) = apply { this.tax = tax } + /** The VAT rate of the line item expressed as percentage with 2 decimals */ fun taxRate(taxRate: String?) = taxRate(JsonField.ofNullable(taxRate)) /** Alias for calling [Builder.taxRate] with `taxRate.orElse(null)`. */ @@ -2215,6 +5461,10 @@ private constructor( */ fun unit(unit: JsonField) = apply { this.unit = unit } + /** + * The item net price (BT-146). The price of an item, exclusive of VAT, after + * subtracting item price discount. Must be rounded to maximum 4 decimals + */ fun unitPrice(unitPrice: String?) = unitPrice(JsonField.ofNullable(unitPrice)) /** Alias for calling [Builder.unitPrice] with `unitPrice.orElse(null)`. */ @@ -2255,7 +5505,9 @@ private constructor( */ fun build(): Item = Item( + (allowances ?: JsonMissing.of()).map { it.toImmutable() }, amount, + (charges ?: JsonMissing.of()).map { it.toImmutable() }, date, description, productCode, @@ -2275,7 +5527,9 @@ private constructor( return@apply } + allowances().ifPresent { it.forEach { it.validate() } } amount() + charges().ifPresent { it.forEach { it.validate() } } date() description() productCode() @@ -2303,7 +5557,9 @@ private constructor( */ @JvmSynthetic internal fun validity(): Int = - (if (amount.asKnown().isPresent) 1 else 0) + + (allowances.asKnown().getOrNull()?.sumOf { it.validity().toInt() } ?: 0) + + (if (amount.asKnown().isPresent) 1 else 0) + + (charges.asKnown().getOrNull()?.sumOf { it.validity().toInt() } ?: 0) + (if (date.asKnown().isPresent) 1 else 0) + (if (description.asKnown().isPresent) 1 else 0) + (if (productCode.asKnown().isPresent) 1 else 0) + @@ -2319,7 +5575,9 @@ private constructor( } return other is Item && + allowances == other.allowances && amount == other.amount && + charges == other.charges && date == other.date && description == other.description && productCode == other.productCode && @@ -2333,7 +5591,9 @@ private constructor( private val hashCode: Int by lazy { Objects.hash( + allowances, amount, + charges, date, description, productCode, @@ -2349,7 +5609,7 @@ private constructor( override fun hashCode(): Int = hashCode override fun toString() = - "Item{amount=$amount, date=$date, description=$description, productCode=$productCode, quantity=$quantity, tax=$tax, taxRate=$taxRate, unit=$unit, unitPrice=$unitPrice, additionalProperties=$additionalProperties}" + "Item{allowances=$allowances, amount=$amount, charges=$charges, date=$date, description=$description, productCode=$productCode, quantity=$quantity, tax=$tax, taxRate=$taxRate, unit=$unit, unitPrice=$unitPrice, additionalProperties=$additionalProperties}" } class PaymentDetail @@ -2375,6 +5635,8 @@ private constructor( ) : this(bankAccountNumber, iban, paymentReference, swift, mutableMapOf()) /** + * Bank account number (for non-IBAN accounts) + * * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if * the server responded with an unexpected value). */ @@ -2382,18 +5644,25 @@ private constructor( bankAccountNumber.getOptional("bank_account_number") /** + * International Bank Account Number for payment transfers + * * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if * the server responded with an unexpected value). */ fun iban(): Optional = iban.getOptional("iban") /** + * Structured payment reference or communication (e.g., structured communication for Belgian + * bank transfers) + * * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if * the server responded with an unexpected value). */ fun paymentReference(): Optional = paymentReference.getOptional("payment_reference") /** + * SWIFT/BIC code of the bank + * * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if * the server responded with an unexpected value). */ @@ -2469,6 +5738,7 @@ private constructor( additionalProperties = paymentDetail.additionalProperties.toMutableMap() } + /** Bank account number (for non-IBAN accounts) */ fun bankAccountNumber(bankAccountNumber: String?) = bankAccountNumber(JsonField.ofNullable(bankAccountNumber)) @@ -2489,6 +5759,7 @@ private constructor( this.bankAccountNumber = bankAccountNumber } + /** International Bank Account Number for payment transfers */ fun iban(iban: String?) = iban(JsonField.ofNullable(iban)) /** Alias for calling [Builder.iban] with `iban.orElse(null)`. */ @@ -2503,6 +5774,10 @@ private constructor( */ fun iban(iban: JsonField) = apply { this.iban = iban } + /** + * Structured payment reference or communication (e.g., structured communication for + * Belgian bank transfers) + */ fun paymentReference(paymentReference: String?) = paymentReference(JsonField.ofNullable(paymentReference)) @@ -2523,6 +5798,7 @@ private constructor( this.paymentReference = paymentReference } + /** SWIFT/BIC code of the bank */ fun swift(swift: String?) = swift(JsonField.ofNullable(swift)) /** Alias for calling [Builder.swift] with `swift.orElse(null)`. */ @@ -2629,6 +5905,184 @@ private constructor( "PaymentDetail{bankAccountNumber=$bankAccountNumber, iban=$iban, paymentReference=$paymentReference, swift=$swift, additionalProperties=$additionalProperties}" } + /** + * Tax category code of the invoice (e.g., S for standard rate, Z for zero rate, E for exempt) + */ + class TaxCode @JsonCreator private constructor(private val value: JsonField) : Enum { + + /** + * Returns this class instance's raw value. + * + * This is usually only useful if this instance was deserialized from data that doesn't + * match any known member, and you want to know that value. For example, if the SDK is on an + * older version than the API, then the API may respond with new members that the SDK is + * unaware of. + */ + @com.fasterxml.jackson.annotation.JsonValue fun _value(): JsonField = value + + companion object { + + @JvmField val AE = of("AE") + + @JvmField val E = of("E") + + @JvmField val S = of("S") + + @JvmField val Z = of("Z") + + @JvmField val G = of("G") + + @JvmField val O = of("O") + + @JvmField val K = of("K") + + @JvmField val L = of("L") + + @JvmField val M = of("M") + + @JvmField val B = of("B") + + @JvmStatic fun of(value: String) = TaxCode(JsonField.of(value)) + } + + /** An enum containing [TaxCode]'s known values. */ + enum class Known { + AE, + E, + S, + Z, + G, + O, + K, + L, + M, + B, + } + + /** + * An enum containing [TaxCode]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [TaxCode] can contain an unknown value in a couple of cases: + * - It was deserialized from data that doesn't match any known member. For example, if the + * SDK is on an older version than the API, then the API may respond with new members that + * the SDK is unaware of. + * - It was constructed with an arbitrary value using the [of] method. + */ + enum class Value { + AE, + E, + S, + Z, + G, + O, + K, + L, + M, + B, + /** An enum member indicating that [TaxCode] was instantiated with an unknown value. */ + _UNKNOWN, + } + + /** + * Returns an enum member corresponding to this class instance's value, or [Value._UNKNOWN] + * if the class was instantiated with an unknown value. + * + * Use the [known] method instead if you're certain the value is always known or if you want + * to throw for the unknown case. + */ + fun value(): Value = + when (this) { + AE -> Value.AE + E -> Value.E + S -> Value.S + Z -> Value.Z + G -> Value.G + O -> Value.O + K -> Value.K + L -> Value.L + M -> Value.M + B -> Value.B + else -> Value._UNKNOWN + } + + /** + * Returns an enum member corresponding to this class instance's value. + * + * Use the [value] method instead if you're uncertain the value is always known and don't + * want to throw for the unknown case. + * + * @throws EInvoiceInvalidDataException if this class instance's value is a not a known + * member. + */ + fun known(): Known = + when (this) { + AE -> Known.AE + E -> Known.E + S -> Known.S + Z -> Known.Z + G -> Known.G + O -> Known.O + K -> Known.K + L -> Known.L + M -> Known.M + B -> Known.B + else -> throw EInvoiceInvalidDataException("Unknown TaxCode: $value") + } + + /** + * Returns this class instance's primitive wire representation. + * + * This differs from the [toString] method because that method is primarily for debugging + * and generally doesn't throw. + * + * @throws EInvoiceInvalidDataException if this class instance's value does not have the + * expected primitive type. + */ + fun asString(): String = + _value().asString().orElseThrow { + EInvoiceInvalidDataException("Value is not a String") + } + + private var validated: Boolean = false + + fun validate(): TaxCode = apply { + if (validated) { + return@apply + } + + known() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: EInvoiceInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic internal fun validity(): Int = if (value() == Value._UNKNOWN) 0 else 1 + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is TaxCode && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + class TaxDetail @JsonCreator(mode = JsonCreator.Mode.DISABLED) private constructor( @@ -2644,12 +6098,16 @@ private constructor( ) : this(amount, rate, mutableMapOf()) /** + * The tax amount for this tax category. Must be rounded to maximum 2 decimals + * * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if * the server responded with an unexpected value). */ fun amount(): Optional = amount.getOptional("amount") /** + * The tax rate as a percentage (e.g., '21.00', '6.00', '0.00') + * * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if * the server responded with an unexpected value). */ @@ -2701,6 +6159,7 @@ private constructor( additionalProperties = taxDetail.additionalProperties.toMutableMap() } + /** The tax amount for this tax category. Must be rounded to maximum 2 decimals */ fun amount(amount: String?) = amount(JsonField.ofNullable(amount)) /** Alias for calling [Builder.amount] with `amount.orElse(null)`. */ @@ -2715,6 +6174,7 @@ private constructor( */ fun amount(amount: JsonField) = apply { this.amount = amount } + /** The tax rate as a percentage (e.g., '21.00', '6.00', '0.00') */ fun rate(rate: String?) = rate(JsonField.ofNullable(rate)) /** Alias for calling [Builder.rate] with `rate.orElse(null)`. */ @@ -2805,6 +6265,498 @@ private constructor( "TaxDetail{amount=$amount, rate=$rate, additionalProperties=$additionalProperties}" } + /** + * VATEX code list for VAT exemption reasons + * + * Agency: CEF Identifier: vatex + */ + class Vatex @JsonCreator private constructor(private val value: JsonField) : Enum { + + /** + * Returns this class instance's raw value. + * + * This is usually only useful if this instance was deserialized from data that doesn't + * match any known member, and you want to know that value. For example, if the SDK is on an + * older version than the API, then the API may respond with new members that the SDK is + * unaware of. + */ + @com.fasterxml.jackson.annotation.JsonValue fun _value(): JsonField = value + + companion object { + + @JvmField val VATEX_EU_79_C = of("VATEX-EU-79-C") + + @JvmField val VATEX_EU_132 = of("VATEX-EU-132") + + @JvmField val VATEX_EU_132_1_A = of("VATEX-EU-132-1A") + + @JvmField val VATEX_EU_132_1_B = of("VATEX-EU-132-1B") + + @JvmField val VATEX_EU_132_1_C = of("VATEX-EU-132-1C") + + @JvmField val VATEX_EU_132_1_D = of("VATEX-EU-132-1D") + + @JvmField val VATEX_EU_132_1_E = of("VATEX-EU-132-1E") + + @JvmField val VATEX_EU_132_1_F = of("VATEX-EU-132-1F") + + @JvmField val VATEX_EU_132_1_G = of("VATEX-EU-132-1G") + + @JvmField val VATEX_EU_132_1_H = of("VATEX-EU-132-1H") + + @JvmField val VATEX_EU_132_1_I = of("VATEX-EU-132-1I") + + @JvmField val VATEX_EU_132_1_J = of("VATEX-EU-132-1J") + + @JvmField val VATEX_EU_132_1_K = of("VATEX-EU-132-1K") + + @JvmField val VATEX_EU_132_1_L = of("VATEX-EU-132-1L") + + @JvmField val VATEX_EU_132_1_M = of("VATEX-EU-132-1M") + + @JvmField val VATEX_EU_132_1_N = of("VATEX-EU-132-1N") + + @JvmField val VATEX_EU_132_1_O = of("VATEX-EU-132-1O") + + @JvmField val VATEX_EU_132_1_P = of("VATEX-EU-132-1P") + + @JvmField val VATEX_EU_132_1_Q = of("VATEX-EU-132-1Q") + + @JvmField val VATEX_EU_143 = of("VATEX-EU-143") + + @JvmField val VATEX_EU_143_1_A = of("VATEX-EU-143-1A") + + @JvmField val VATEX_EU_143_1_B = of("VATEX-EU-143-1B") + + @JvmField val VATEX_EU_143_1_C = of("VATEX-EU-143-1C") + + @JvmField val VATEX_EU_143_1_D = of("VATEX-EU-143-1D") + + @JvmField val VATEX_EU_143_1_E = of("VATEX-EU-143-1E") + + @JvmField val VATEX_EU_143_1_F = of("VATEX-EU-143-1F") + + @JvmField val VATEX_EU_143_1_FA = of("VATEX-EU-143-1FA") + + @JvmField val VATEX_EU_143_1_G = of("VATEX-EU-143-1G") + + @JvmField val VATEX_EU_143_1_H = of("VATEX-EU-143-1H") + + @JvmField val VATEX_EU_143_1_I = of("VATEX-EU-143-1I") + + @JvmField val VATEX_EU_143_1_J = of("VATEX-EU-143-1J") + + @JvmField val VATEX_EU_143_1_K = of("VATEX-EU-143-1K") + + @JvmField val VATEX_EU_143_1_L = of("VATEX-EU-143-1L") + + @JvmField val VATEX_EU_144 = of("VATEX-EU-144") + + @JvmField val VATEX_EU_146_1_E = of("VATEX-EU-146-1E") + + @JvmField val VATEX_EU_148 = of("VATEX-EU-148") + + @JvmField val VATEX_EU_148_A = of("VATEX-EU-148-A") + + @JvmField val VATEX_EU_148_B = of("VATEX-EU-148-B") + + @JvmField val VATEX_EU_148_C = of("VATEX-EU-148-C") + + @JvmField val VATEX_EU_148_D = of("VATEX-EU-148-D") + + @JvmField val VATEX_EU_148_E = of("VATEX-EU-148-E") + + @JvmField val VATEX_EU_148_F = of("VATEX-EU-148-F") + + @JvmField val VATEX_EU_148_G = of("VATEX-EU-148-G") + + @JvmField val VATEX_EU_151 = of("VATEX-EU-151") + + @JvmField val VATEX_EU_151_1_A = of("VATEX-EU-151-1A") + + @JvmField val VATEX_EU_151_1_AA = of("VATEX-EU-151-1AA") + + @JvmField val VATEX_EU_151_1_B = of("VATEX-EU-151-1B") + + @JvmField val VATEX_EU_151_1_C = of("VATEX-EU-151-1C") + + @JvmField val VATEX_EU_151_1_D = of("VATEX-EU-151-1D") + + @JvmField val VATEX_EU_151_1_E = of("VATEX-EU-151-1E") + + @JvmField val VATEX_EU_159 = of("VATEX-EU-159") + + @JvmField val VATEX_EU_309 = of("VATEX-EU-309") + + @JvmField val VATEX_EU_AE = of("VATEX-EU-AE") + + @JvmField val VATEX_EU_D = of("VATEX-EU-D") + + @JvmField val VATEX_EU_F = of("VATEX-EU-F") + + @JvmField val VATEX_EU_G = of("VATEX-EU-G") + + @JvmField val VATEX_EU_I = of("VATEX-EU-I") + + @JvmField val VATEX_EU_IC = of("VATEX-EU-IC") + + @JvmField val VATEX_EU_O = of("VATEX-EU-O") + + @JvmField val VATEX_EU_J = of("VATEX-EU-J") + + @JvmField val VATEX_FR_FRANCHISE = of("VATEX-FR-FRANCHISE") + + @JvmField val VATEX_FR_CNWVAT = of("VATEX-FR-CNWVAT") + + @JvmStatic fun of(value: String) = Vatex(JsonField.of(value)) + } + + /** An enum containing [Vatex]'s known values. */ + enum class Known { + VATEX_EU_79_C, + VATEX_EU_132, + VATEX_EU_132_1_A, + VATEX_EU_132_1_B, + VATEX_EU_132_1_C, + VATEX_EU_132_1_D, + VATEX_EU_132_1_E, + VATEX_EU_132_1_F, + VATEX_EU_132_1_G, + VATEX_EU_132_1_H, + VATEX_EU_132_1_I, + VATEX_EU_132_1_J, + VATEX_EU_132_1_K, + VATEX_EU_132_1_L, + VATEX_EU_132_1_M, + VATEX_EU_132_1_N, + VATEX_EU_132_1_O, + VATEX_EU_132_1_P, + VATEX_EU_132_1_Q, + VATEX_EU_143, + VATEX_EU_143_1_A, + VATEX_EU_143_1_B, + VATEX_EU_143_1_C, + VATEX_EU_143_1_D, + VATEX_EU_143_1_E, + VATEX_EU_143_1_F, + VATEX_EU_143_1_FA, + VATEX_EU_143_1_G, + VATEX_EU_143_1_H, + VATEX_EU_143_1_I, + VATEX_EU_143_1_J, + VATEX_EU_143_1_K, + VATEX_EU_143_1_L, + VATEX_EU_144, + VATEX_EU_146_1_E, + VATEX_EU_148, + VATEX_EU_148_A, + VATEX_EU_148_B, + VATEX_EU_148_C, + VATEX_EU_148_D, + VATEX_EU_148_E, + VATEX_EU_148_F, + VATEX_EU_148_G, + VATEX_EU_151, + VATEX_EU_151_1_A, + VATEX_EU_151_1_AA, + VATEX_EU_151_1_B, + VATEX_EU_151_1_C, + VATEX_EU_151_1_D, + VATEX_EU_151_1_E, + VATEX_EU_159, + VATEX_EU_309, + VATEX_EU_AE, + VATEX_EU_D, + VATEX_EU_F, + VATEX_EU_G, + VATEX_EU_I, + VATEX_EU_IC, + VATEX_EU_O, + VATEX_EU_J, + VATEX_FR_FRANCHISE, + VATEX_FR_CNWVAT, + } + + /** + * An enum containing [Vatex]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [Vatex] can contain an unknown value in a couple of cases: + * - It was deserialized from data that doesn't match any known member. For example, if the + * SDK is on an older version than the API, then the API may respond with new members that + * the SDK is unaware of. + * - It was constructed with an arbitrary value using the [of] method. + */ + enum class Value { + VATEX_EU_79_C, + VATEX_EU_132, + VATEX_EU_132_1_A, + VATEX_EU_132_1_B, + VATEX_EU_132_1_C, + VATEX_EU_132_1_D, + VATEX_EU_132_1_E, + VATEX_EU_132_1_F, + VATEX_EU_132_1_G, + VATEX_EU_132_1_H, + VATEX_EU_132_1_I, + VATEX_EU_132_1_J, + VATEX_EU_132_1_K, + VATEX_EU_132_1_L, + VATEX_EU_132_1_M, + VATEX_EU_132_1_N, + VATEX_EU_132_1_O, + VATEX_EU_132_1_P, + VATEX_EU_132_1_Q, + VATEX_EU_143, + VATEX_EU_143_1_A, + VATEX_EU_143_1_B, + VATEX_EU_143_1_C, + VATEX_EU_143_1_D, + VATEX_EU_143_1_E, + VATEX_EU_143_1_F, + VATEX_EU_143_1_FA, + VATEX_EU_143_1_G, + VATEX_EU_143_1_H, + VATEX_EU_143_1_I, + VATEX_EU_143_1_J, + VATEX_EU_143_1_K, + VATEX_EU_143_1_L, + VATEX_EU_144, + VATEX_EU_146_1_E, + VATEX_EU_148, + VATEX_EU_148_A, + VATEX_EU_148_B, + VATEX_EU_148_C, + VATEX_EU_148_D, + VATEX_EU_148_E, + VATEX_EU_148_F, + VATEX_EU_148_G, + VATEX_EU_151, + VATEX_EU_151_1_A, + VATEX_EU_151_1_AA, + VATEX_EU_151_1_B, + VATEX_EU_151_1_C, + VATEX_EU_151_1_D, + VATEX_EU_151_1_E, + VATEX_EU_159, + VATEX_EU_309, + VATEX_EU_AE, + VATEX_EU_D, + VATEX_EU_F, + VATEX_EU_G, + VATEX_EU_I, + VATEX_EU_IC, + VATEX_EU_O, + VATEX_EU_J, + VATEX_FR_FRANCHISE, + VATEX_FR_CNWVAT, + /** An enum member indicating that [Vatex] was instantiated with an unknown value. */ + _UNKNOWN, + } + + /** + * Returns an enum member corresponding to this class instance's value, or [Value._UNKNOWN] + * if the class was instantiated with an unknown value. + * + * Use the [known] method instead if you're certain the value is always known or if you want + * to throw for the unknown case. + */ + fun value(): Value = + when (this) { + VATEX_EU_79_C -> Value.VATEX_EU_79_C + VATEX_EU_132 -> Value.VATEX_EU_132 + VATEX_EU_132_1_A -> Value.VATEX_EU_132_1_A + VATEX_EU_132_1_B -> Value.VATEX_EU_132_1_B + VATEX_EU_132_1_C -> Value.VATEX_EU_132_1_C + VATEX_EU_132_1_D -> Value.VATEX_EU_132_1_D + VATEX_EU_132_1_E -> Value.VATEX_EU_132_1_E + VATEX_EU_132_1_F -> Value.VATEX_EU_132_1_F + VATEX_EU_132_1_G -> Value.VATEX_EU_132_1_G + VATEX_EU_132_1_H -> Value.VATEX_EU_132_1_H + VATEX_EU_132_1_I -> Value.VATEX_EU_132_1_I + VATEX_EU_132_1_J -> Value.VATEX_EU_132_1_J + VATEX_EU_132_1_K -> Value.VATEX_EU_132_1_K + VATEX_EU_132_1_L -> Value.VATEX_EU_132_1_L + VATEX_EU_132_1_M -> Value.VATEX_EU_132_1_M + VATEX_EU_132_1_N -> Value.VATEX_EU_132_1_N + VATEX_EU_132_1_O -> Value.VATEX_EU_132_1_O + VATEX_EU_132_1_P -> Value.VATEX_EU_132_1_P + VATEX_EU_132_1_Q -> Value.VATEX_EU_132_1_Q + VATEX_EU_143 -> Value.VATEX_EU_143 + VATEX_EU_143_1_A -> Value.VATEX_EU_143_1_A + VATEX_EU_143_1_B -> Value.VATEX_EU_143_1_B + VATEX_EU_143_1_C -> Value.VATEX_EU_143_1_C + VATEX_EU_143_1_D -> Value.VATEX_EU_143_1_D + VATEX_EU_143_1_E -> Value.VATEX_EU_143_1_E + VATEX_EU_143_1_F -> Value.VATEX_EU_143_1_F + VATEX_EU_143_1_FA -> Value.VATEX_EU_143_1_FA + VATEX_EU_143_1_G -> Value.VATEX_EU_143_1_G + VATEX_EU_143_1_H -> Value.VATEX_EU_143_1_H + VATEX_EU_143_1_I -> Value.VATEX_EU_143_1_I + VATEX_EU_143_1_J -> Value.VATEX_EU_143_1_J + VATEX_EU_143_1_K -> Value.VATEX_EU_143_1_K + VATEX_EU_143_1_L -> Value.VATEX_EU_143_1_L + VATEX_EU_144 -> Value.VATEX_EU_144 + VATEX_EU_146_1_E -> Value.VATEX_EU_146_1_E + VATEX_EU_148 -> Value.VATEX_EU_148 + VATEX_EU_148_A -> Value.VATEX_EU_148_A + VATEX_EU_148_B -> Value.VATEX_EU_148_B + VATEX_EU_148_C -> Value.VATEX_EU_148_C + VATEX_EU_148_D -> Value.VATEX_EU_148_D + VATEX_EU_148_E -> Value.VATEX_EU_148_E + VATEX_EU_148_F -> Value.VATEX_EU_148_F + VATEX_EU_148_G -> Value.VATEX_EU_148_G + VATEX_EU_151 -> Value.VATEX_EU_151 + VATEX_EU_151_1_A -> Value.VATEX_EU_151_1_A + VATEX_EU_151_1_AA -> Value.VATEX_EU_151_1_AA + VATEX_EU_151_1_B -> Value.VATEX_EU_151_1_B + VATEX_EU_151_1_C -> Value.VATEX_EU_151_1_C + VATEX_EU_151_1_D -> Value.VATEX_EU_151_1_D + VATEX_EU_151_1_E -> Value.VATEX_EU_151_1_E + VATEX_EU_159 -> Value.VATEX_EU_159 + VATEX_EU_309 -> Value.VATEX_EU_309 + VATEX_EU_AE -> Value.VATEX_EU_AE + VATEX_EU_D -> Value.VATEX_EU_D + VATEX_EU_F -> Value.VATEX_EU_F + VATEX_EU_G -> Value.VATEX_EU_G + VATEX_EU_I -> Value.VATEX_EU_I + VATEX_EU_IC -> Value.VATEX_EU_IC + VATEX_EU_O -> Value.VATEX_EU_O + VATEX_EU_J -> Value.VATEX_EU_J + VATEX_FR_FRANCHISE -> Value.VATEX_FR_FRANCHISE + VATEX_FR_CNWVAT -> Value.VATEX_FR_CNWVAT + else -> Value._UNKNOWN + } + + /** + * Returns an enum member corresponding to this class instance's value. + * + * Use the [value] method instead if you're uncertain the value is always known and don't + * want to throw for the unknown case. + * + * @throws EInvoiceInvalidDataException if this class instance's value is a not a known + * member. + */ + fun known(): Known = + when (this) { + VATEX_EU_79_C -> Known.VATEX_EU_79_C + VATEX_EU_132 -> Known.VATEX_EU_132 + VATEX_EU_132_1_A -> Known.VATEX_EU_132_1_A + VATEX_EU_132_1_B -> Known.VATEX_EU_132_1_B + VATEX_EU_132_1_C -> Known.VATEX_EU_132_1_C + VATEX_EU_132_1_D -> Known.VATEX_EU_132_1_D + VATEX_EU_132_1_E -> Known.VATEX_EU_132_1_E + VATEX_EU_132_1_F -> Known.VATEX_EU_132_1_F + VATEX_EU_132_1_G -> Known.VATEX_EU_132_1_G + VATEX_EU_132_1_H -> Known.VATEX_EU_132_1_H + VATEX_EU_132_1_I -> Known.VATEX_EU_132_1_I + VATEX_EU_132_1_J -> Known.VATEX_EU_132_1_J + VATEX_EU_132_1_K -> Known.VATEX_EU_132_1_K + VATEX_EU_132_1_L -> Known.VATEX_EU_132_1_L + VATEX_EU_132_1_M -> Known.VATEX_EU_132_1_M + VATEX_EU_132_1_N -> Known.VATEX_EU_132_1_N + VATEX_EU_132_1_O -> Known.VATEX_EU_132_1_O + VATEX_EU_132_1_P -> Known.VATEX_EU_132_1_P + VATEX_EU_132_1_Q -> Known.VATEX_EU_132_1_Q + VATEX_EU_143 -> Known.VATEX_EU_143 + VATEX_EU_143_1_A -> Known.VATEX_EU_143_1_A + VATEX_EU_143_1_B -> Known.VATEX_EU_143_1_B + VATEX_EU_143_1_C -> Known.VATEX_EU_143_1_C + VATEX_EU_143_1_D -> Known.VATEX_EU_143_1_D + VATEX_EU_143_1_E -> Known.VATEX_EU_143_1_E + VATEX_EU_143_1_F -> Known.VATEX_EU_143_1_F + VATEX_EU_143_1_FA -> Known.VATEX_EU_143_1_FA + VATEX_EU_143_1_G -> Known.VATEX_EU_143_1_G + VATEX_EU_143_1_H -> Known.VATEX_EU_143_1_H + VATEX_EU_143_1_I -> Known.VATEX_EU_143_1_I + VATEX_EU_143_1_J -> Known.VATEX_EU_143_1_J + VATEX_EU_143_1_K -> Known.VATEX_EU_143_1_K + VATEX_EU_143_1_L -> Known.VATEX_EU_143_1_L + VATEX_EU_144 -> Known.VATEX_EU_144 + VATEX_EU_146_1_E -> Known.VATEX_EU_146_1_E + VATEX_EU_148 -> Known.VATEX_EU_148 + VATEX_EU_148_A -> Known.VATEX_EU_148_A + VATEX_EU_148_B -> Known.VATEX_EU_148_B + VATEX_EU_148_C -> Known.VATEX_EU_148_C + VATEX_EU_148_D -> Known.VATEX_EU_148_D + VATEX_EU_148_E -> Known.VATEX_EU_148_E + VATEX_EU_148_F -> Known.VATEX_EU_148_F + VATEX_EU_148_G -> Known.VATEX_EU_148_G + VATEX_EU_151 -> Known.VATEX_EU_151 + VATEX_EU_151_1_A -> Known.VATEX_EU_151_1_A + VATEX_EU_151_1_AA -> Known.VATEX_EU_151_1_AA + VATEX_EU_151_1_B -> Known.VATEX_EU_151_1_B + VATEX_EU_151_1_C -> Known.VATEX_EU_151_1_C + VATEX_EU_151_1_D -> Known.VATEX_EU_151_1_D + VATEX_EU_151_1_E -> Known.VATEX_EU_151_1_E + VATEX_EU_159 -> Known.VATEX_EU_159 + VATEX_EU_309 -> Known.VATEX_EU_309 + VATEX_EU_AE -> Known.VATEX_EU_AE + VATEX_EU_D -> Known.VATEX_EU_D + VATEX_EU_F -> Known.VATEX_EU_F + VATEX_EU_G -> Known.VATEX_EU_G + VATEX_EU_I -> Known.VATEX_EU_I + VATEX_EU_IC -> Known.VATEX_EU_IC + VATEX_EU_O -> Known.VATEX_EU_O + VATEX_EU_J -> Known.VATEX_EU_J + VATEX_FR_FRANCHISE -> Known.VATEX_FR_FRANCHISE + VATEX_FR_CNWVAT -> Known.VATEX_FR_CNWVAT + else -> throw EInvoiceInvalidDataException("Unknown Vatex: $value") + } + + /** + * Returns this class instance's primitive wire representation. + * + * This differs from the [toString] method because that method is primarily for debugging + * and generally doesn't throw. + * + * @throws EInvoiceInvalidDataException if this class instance's value does not have the + * expected primitive type. + */ + fun asString(): String = + _value().asString().orElseThrow { + EInvoiceInvalidDataException("Value is not a String") + } + + private var validated: Boolean = false + + fun validate(): Vatex = apply { + if (validated) { + return@apply + } + + known() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: EInvoiceInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic internal fun validity(): Int = if (value() == Value._UNKNOWN) 0 else 1 + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Vatex && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + override fun equals(other: Any?): Boolean { if (this === other) { return true @@ -2812,13 +6764,17 @@ private constructor( return other is DocumentResponse && id == other.id && + createdAt == other.createdAt && + allowances == other.allowances && amountDue == other.amountDue && attachments == other.attachments && billingAddress == other.billingAddress && billingAddressRecipient == other.billingAddressRecipient && + charges == other.charges && currency == other.currency && customerAddress == other.customerAddress && customerAddressRecipient == other.customerAddressRecipient && + customerCompanyId == other.customerCompanyId && customerEmail == other.customerEmail && customerId == other.customerId && customerName == other.customerName && @@ -2833,7 +6789,6 @@ private constructor( note == other.note && paymentDetails == other.paymentDetails && paymentTerm == other.paymentTerm && - previousUnpaidBalance == other.previousUnpaidBalance && purchaseOrder == other.purchaseOrder && remittanceAddress == other.remittanceAddress && remittanceAddressRecipient == other.remittanceAddressRecipient && @@ -2845,11 +6800,15 @@ private constructor( shippingAddressRecipient == other.shippingAddressRecipient && state == other.state && subtotal == other.subtotal && + taxCode == other.taxCode && taxDetails == other.taxDetails && totalDiscount == other.totalDiscount && totalTax == other.totalTax && + vatex == other.vatex && + vatexNote == other.vatexNote && vendorAddress == other.vendorAddress && vendorAddressRecipient == other.vendorAddressRecipient && + vendorCompanyId == other.vendorCompanyId && vendorEmail == other.vendorEmail && vendorName == other.vendorName && vendorTaxId == other.vendorTaxId && @@ -2859,13 +6818,17 @@ private constructor( private val hashCode: Int by lazy { Objects.hash( id, + createdAt, + allowances, amountDue, attachments, billingAddress, billingAddressRecipient, + charges, currency, customerAddress, customerAddressRecipient, + customerCompanyId, customerEmail, customerId, customerName, @@ -2880,7 +6843,6 @@ private constructor( note, paymentDetails, paymentTerm, - previousUnpaidBalance, purchaseOrder, remittanceAddress, remittanceAddressRecipient, @@ -2892,11 +6854,15 @@ private constructor( shippingAddressRecipient, state, subtotal, + taxCode, taxDetails, totalDiscount, totalTax, + vatex, + vatexNote, vendorAddress, vendorAddressRecipient, + vendorCompanyId, vendorEmail, vendorName, vendorTaxId, @@ -2907,5 +6873,5 @@ private constructor( override fun hashCode(): Int = hashCode override fun toString() = - "DocumentResponse{id=$id, amountDue=$amountDue, attachments=$attachments, billingAddress=$billingAddress, billingAddressRecipient=$billingAddressRecipient, currency=$currency, customerAddress=$customerAddress, customerAddressRecipient=$customerAddressRecipient, customerEmail=$customerEmail, customerId=$customerId, customerName=$customerName, customerTaxId=$customerTaxId, direction=$direction, documentType=$documentType, dueDate=$dueDate, invoiceDate=$invoiceDate, invoiceId=$invoiceId, invoiceTotal=$invoiceTotal, items=$items, note=$note, paymentDetails=$paymentDetails, paymentTerm=$paymentTerm, previousUnpaidBalance=$previousUnpaidBalance, purchaseOrder=$purchaseOrder, remittanceAddress=$remittanceAddress, remittanceAddressRecipient=$remittanceAddressRecipient, serviceAddress=$serviceAddress, serviceAddressRecipient=$serviceAddressRecipient, serviceEndDate=$serviceEndDate, serviceStartDate=$serviceStartDate, shippingAddress=$shippingAddress, shippingAddressRecipient=$shippingAddressRecipient, state=$state, subtotal=$subtotal, taxDetails=$taxDetails, totalDiscount=$totalDiscount, totalTax=$totalTax, vendorAddress=$vendorAddress, vendorAddressRecipient=$vendorAddressRecipient, vendorEmail=$vendorEmail, vendorName=$vendorName, vendorTaxId=$vendorTaxId, additionalProperties=$additionalProperties}" + "DocumentResponse{id=$id, createdAt=$createdAt, allowances=$allowances, amountDue=$amountDue, attachments=$attachments, billingAddress=$billingAddress, billingAddressRecipient=$billingAddressRecipient, charges=$charges, currency=$currency, customerAddress=$customerAddress, customerAddressRecipient=$customerAddressRecipient, customerCompanyId=$customerCompanyId, customerEmail=$customerEmail, customerId=$customerId, customerName=$customerName, customerTaxId=$customerTaxId, direction=$direction, documentType=$documentType, dueDate=$dueDate, invoiceDate=$invoiceDate, invoiceId=$invoiceId, invoiceTotal=$invoiceTotal, items=$items, note=$note, paymentDetails=$paymentDetails, paymentTerm=$paymentTerm, purchaseOrder=$purchaseOrder, remittanceAddress=$remittanceAddress, remittanceAddressRecipient=$remittanceAddressRecipient, serviceAddress=$serviceAddress, serviceAddressRecipient=$serviceAddressRecipient, serviceEndDate=$serviceEndDate, serviceStartDate=$serviceStartDate, shippingAddress=$shippingAddress, shippingAddressRecipient=$shippingAddressRecipient, state=$state, subtotal=$subtotal, taxCode=$taxCode, taxDetails=$taxDetails, totalDiscount=$totalDiscount, totalTax=$totalTax, vatex=$vatex, vatexNote=$vatexNote, vendorAddress=$vendorAddress, vendorAddressRecipient=$vendorAddressRecipient, vendorCompanyId=$vendorCompanyId, vendorEmail=$vendorEmail, vendorName=$vendorName, vendorTaxId=$vendorTaxId, additionalProperties=$additionalProperties}" } diff --git a/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/models/documents/DocumentSendParams.kt b/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/models/documents/DocumentSendParams.kt index f20b196..8c80d37 100644 --- a/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/models/documents/DocumentSendParams.kt +++ b/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/models/documents/DocumentSendParams.kt @@ -11,7 +11,13 @@ import java.util.Objects import java.util.Optional import kotlin.jvm.optionals.getOrNull -/** Send an invoice or credit note via Peppol */ +/** + * Send an invoice or credit note via Peppol. By default, the sender and receiver Peppol IDs are + * derived from the company (tax) IDs in the document, regardless of whether the document was + * created from a UBL with a different endpoint ID. To explicitly set the sender or receiver Peppol + * ID, provide them via the query parameters (sender_peppol_scheme, sender_peppol_id, + * receiver_peppol_scheme, receiver_peppol_id). + */ class DocumentSendParams private constructor( private val documentId: String?, diff --git a/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/models/documents/DocumentType.kt b/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/models/documents/DocumentType.kt index 4e8edd5..cb1613a 100644 --- a/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/models/documents/DocumentType.kt +++ b/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/models/documents/DocumentType.kt @@ -26,6 +26,10 @@ class DocumentType @JsonCreator private constructor(private val value: JsonField @JvmField val DEBIT_NOTE = of("DEBIT_NOTE") + @JvmField val SELFBILLING_INVOICE = of("SELFBILLING_INVOICE") + + @JvmField val SELFBILLING_CREDIT_NOTE = of("SELFBILLING_CREDIT_NOTE") + @JvmStatic fun of(value: String) = DocumentType(JsonField.of(value)) } @@ -34,6 +38,8 @@ class DocumentType @JsonCreator private constructor(private val value: JsonField INVOICE, CREDIT_NOTE, DEBIT_NOTE, + SELFBILLING_INVOICE, + SELFBILLING_CREDIT_NOTE, } /** @@ -49,6 +55,8 @@ class DocumentType @JsonCreator private constructor(private val value: JsonField INVOICE, CREDIT_NOTE, DEBIT_NOTE, + SELFBILLING_INVOICE, + SELFBILLING_CREDIT_NOTE, /** An enum member indicating that [DocumentType] was instantiated with an unknown value. */ _UNKNOWN, } @@ -65,6 +73,8 @@ class DocumentType @JsonCreator private constructor(private val value: JsonField INVOICE -> Value.INVOICE CREDIT_NOTE -> Value.CREDIT_NOTE DEBIT_NOTE -> Value.DEBIT_NOTE + SELFBILLING_INVOICE -> Value.SELFBILLING_INVOICE + SELFBILLING_CREDIT_NOTE -> Value.SELFBILLING_CREDIT_NOTE else -> Value._UNKNOWN } @@ -81,6 +91,8 @@ class DocumentType @JsonCreator private constructor(private val value: JsonField INVOICE -> Known.INVOICE CREDIT_NOTE -> Known.CREDIT_NOTE DEBIT_NOTE -> Known.DEBIT_NOTE + SELFBILLING_INVOICE -> Known.SELFBILLING_INVOICE + SELFBILLING_CREDIT_NOTE -> Known.SELFBILLING_CREDIT_NOTE else -> throw EInvoiceInvalidDataException("Unknown DocumentType: $value") } diff --git a/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/models/documents/DocumentValidateParams.kt b/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/models/documents/DocumentValidateParams.kt new file mode 100644 index 0000000..303db15 --- /dev/null +++ b/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/models/documents/DocumentValidateParams.kt @@ -0,0 +1,230 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.e_invoice.api.models.documents + +import com.e_invoice.api.core.JsonValue +import com.e_invoice.api.core.Params +import com.e_invoice.api.core.http.Headers +import com.e_invoice.api.core.http.QueryParams +import com.e_invoice.api.core.toImmutable +import java.util.Objects +import java.util.Optional +import kotlin.jvm.optionals.getOrNull + +/** Validate a UBL document according to Peppol BIS Billing 3.0 */ +class DocumentValidateParams +private constructor( + private val documentId: String?, + private val additionalHeaders: Headers, + private val additionalQueryParams: QueryParams, + private val additionalBodyProperties: Map, +) : Params { + + fun documentId(): Optional = Optional.ofNullable(documentId) + + /** Additional body properties to send with the request. */ + fun _additionalBodyProperties(): Map = additionalBodyProperties + + /** Additional headers to send with the request. */ + fun _additionalHeaders(): Headers = additionalHeaders + + /** Additional query param to send with the request. */ + fun _additionalQueryParams(): QueryParams = additionalQueryParams + + fun toBuilder() = Builder().from(this) + + companion object { + + @JvmStatic fun none(): DocumentValidateParams = builder().build() + + /** Returns a mutable builder for constructing an instance of [DocumentValidateParams]. */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [DocumentValidateParams]. */ + class Builder internal constructor() { + + private var documentId: String? = null + private var additionalHeaders: Headers.Builder = Headers.builder() + private var additionalQueryParams: QueryParams.Builder = QueryParams.builder() + private var additionalBodyProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(documentValidateParams: DocumentValidateParams) = apply { + documentId = documentValidateParams.documentId + additionalHeaders = documentValidateParams.additionalHeaders.toBuilder() + additionalQueryParams = documentValidateParams.additionalQueryParams.toBuilder() + additionalBodyProperties = + documentValidateParams.additionalBodyProperties.toMutableMap() + } + + fun documentId(documentId: String?) = apply { this.documentId = documentId } + + /** Alias for calling [Builder.documentId] with `documentId.orElse(null)`. */ + fun documentId(documentId: Optional) = documentId(documentId.getOrNull()) + + fun additionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun additionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun putAdditionalHeader(name: String, value: String) = apply { + additionalHeaders.put(name, value) + } + + fun putAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.put(name, values) + } + + fun putAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun putAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun replaceAdditionalHeaders(name: String, value: String) = apply { + additionalHeaders.replace(name, value) + } + + fun replaceAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.replace(name, values) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun removeAdditionalHeaders(name: String) = apply { additionalHeaders.remove(name) } + + fun removeAllAdditionalHeaders(names: Set) = apply { + additionalHeaders.removeAll(names) + } + + fun additionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun additionalQueryParams(additionalQueryParams: Map>) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun putAdditionalQueryParam(key: String, value: String) = apply { + additionalQueryParams.put(key, value) + } + + fun putAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.put(key, values) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun replaceAdditionalQueryParams(key: String, value: String) = apply { + additionalQueryParams.replace(key, value) + } + + fun replaceAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.replace(key, values) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun removeAdditionalQueryParams(key: String) = apply { additionalQueryParams.remove(key) } + + fun removeAllAdditionalQueryParams(keys: Set) = apply { + additionalQueryParams.removeAll(keys) + } + + fun additionalBodyProperties(additionalBodyProperties: Map) = apply { + this.additionalBodyProperties.clear() + putAllAdditionalBodyProperties(additionalBodyProperties) + } + + fun putAdditionalBodyProperty(key: String, value: JsonValue) = apply { + additionalBodyProperties.put(key, value) + } + + fun putAllAdditionalBodyProperties(additionalBodyProperties: Map) = + apply { + this.additionalBodyProperties.putAll(additionalBodyProperties) + } + + fun removeAdditionalBodyProperty(key: String) = apply { + additionalBodyProperties.remove(key) + } + + fun removeAllAdditionalBodyProperties(keys: Set) = apply { + keys.forEach(::removeAdditionalBodyProperty) + } + + /** + * Returns an immutable instance of [DocumentValidateParams]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): DocumentValidateParams = + DocumentValidateParams( + documentId, + additionalHeaders.build(), + additionalQueryParams.build(), + additionalBodyProperties.toImmutable(), + ) + } + + fun _body(): Optional> = + Optional.ofNullable(additionalBodyProperties.ifEmpty { null }) + + fun _pathParam(index: Int): String = + when (index) { + 0 -> documentId ?: "" + else -> "" + } + + override fun _headers(): Headers = additionalHeaders + + override fun _queryParams(): QueryParams = additionalQueryParams + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is DocumentValidateParams && + documentId == other.documentId && + additionalHeaders == other.additionalHeaders && + additionalQueryParams == other.additionalQueryParams && + additionalBodyProperties == other.additionalBodyProperties + } + + override fun hashCode(): Int = + Objects.hash(documentId, additionalHeaders, additionalQueryParams, additionalBodyProperties) + + override fun toString() = + "DocumentValidateParams{documentId=$documentId, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams, additionalBodyProperties=$additionalBodyProperties}" +} diff --git a/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/models/documents/PaymentDetailCreate.kt b/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/models/documents/PaymentDetailCreate.kt index 87d6adb..d22e20f 100644 --- a/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/models/documents/PaymentDetailCreate.kt +++ b/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/models/documents/PaymentDetailCreate.kt @@ -39,24 +39,33 @@ private constructor( ) : this(bankAccountNumber, iban, paymentReference, swift, mutableMapOf()) /** + * Bank account number (for non-IBAN accounts) + * * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the * server responded with an unexpected value). */ fun bankAccountNumber(): Optional = bankAccountNumber.getOptional("bank_account_number") /** + * International Bank Account Number for payment transfers + * * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the * server responded with an unexpected value). */ fun iban(): Optional = iban.getOptional("iban") /** + * Structured payment reference or communication (e.g., structured communication for Belgian + * bank transfers) + * * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the * server responded with an unexpected value). */ fun paymentReference(): Optional = paymentReference.getOptional("payment_reference") /** + * SWIFT/BIC code of the bank + * * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the * server responded with an unexpected value). */ @@ -132,6 +141,7 @@ private constructor( additionalProperties = paymentDetailCreate.additionalProperties.toMutableMap() } + /** Bank account number (for non-IBAN accounts) */ fun bankAccountNumber(bankAccountNumber: String?) = bankAccountNumber(JsonField.ofNullable(bankAccountNumber)) @@ -150,6 +160,7 @@ private constructor( this.bankAccountNumber = bankAccountNumber } + /** International Bank Account Number for payment transfers */ fun iban(iban: String?) = iban(JsonField.ofNullable(iban)) /** Alias for calling [Builder.iban] with `iban.orElse(null)`. */ @@ -163,6 +174,10 @@ private constructor( */ fun iban(iban: JsonField) = apply { this.iban = iban } + /** + * Structured payment reference or communication (e.g., structured communication for Belgian + * bank transfers) + */ fun paymentReference(paymentReference: String?) = paymentReference(JsonField.ofNullable(paymentReference)) @@ -181,6 +196,7 @@ private constructor( this.paymentReference = paymentReference } + /** SWIFT/BIC code of the bank */ fun swift(swift: String?) = swift(JsonField.ofNullable(swift)) /** Alias for calling [Builder.swift] with `swift.orElse(null)`. */ diff --git a/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/models/documents/UnitOfMeasureCode.kt b/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/models/documents/UnitOfMeasureCode.kt index e58cd7d..362bb6a 100644 --- a/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/models/documents/UnitOfMeasureCode.kt +++ b/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/models/documents/UnitOfMeasureCode.kt @@ -792,8 +792,6 @@ class UnitOfMeasureCode @JsonCreator private constructor(private val value: Json @JvmField val C61 = of("C61") - @JvmField val C62 = of("C62") - @JvmField val C63 = of("C63") @JvmField val C64 = of("C64") @@ -960,8 +958,6 @@ class UnitOfMeasureCode @JsonCreator private constructor(private val value: Json @JvmField val ONZ = of("ONZ") - @JvmField val PCE = of("PCE") - @JvmField val LBR = of("LBR") @JvmField val QT = of("QT") @@ -2082,8 +2078,12 @@ class UnitOfMeasureCode @JsonCreator private constructor(private val value: Json @JvmField val NAR = of("NAR") + @JvmField val C62 = of("C62") + @JvmField val LTR = of("LTR") + @JvmField val H87 = of("H87") + @JvmStatic fun of(value: String) = UnitOfMeasureCode(JsonField.of(value)) } @@ -2474,7 +2474,6 @@ class UnitOfMeasureCode @JsonCreator private constructor(private val value: Json C59, C60, C61, - C62, C63, C64, C65, @@ -2558,7 +2557,6 @@ class UnitOfMeasureCode @JsonCreator private constructor(private val value: Json MIN, MON, ONZ, - PCE, LBR, QT, SEC, @@ -3119,7 +3117,9 @@ class UnitOfMeasureCode @JsonCreator private constructor(private val value: Json XZZ, ZZ, NAR, + C62, LTR, + H87, } /** @@ -3517,7 +3517,6 @@ class UnitOfMeasureCode @JsonCreator private constructor(private val value: Json C59, C60, C61, - C62, C63, C64, C65, @@ -3601,7 +3600,6 @@ class UnitOfMeasureCode @JsonCreator private constructor(private val value: Json MIN, MON, ONZ, - PCE, LBR, QT, SEC, @@ -4162,7 +4160,9 @@ class UnitOfMeasureCode @JsonCreator private constructor(private val value: Json XZZ, ZZ, NAR, + C62, LTR, + H87, /** * An enum member indicating that [UnitOfMeasureCode] was instantiated with an unknown * value. @@ -4564,7 +4564,6 @@ class UnitOfMeasureCode @JsonCreator private constructor(private val value: Json C59 -> Value.C59 C60 -> Value.C60 C61 -> Value.C61 - C62 -> Value.C62 C63 -> Value.C63 C64 -> Value.C64 C65 -> Value.C65 @@ -4648,7 +4647,6 @@ class UnitOfMeasureCode @JsonCreator private constructor(private val value: Json MIN -> Value.MIN MON -> Value.MON ONZ -> Value.ONZ - PCE -> Value.PCE LBR -> Value.LBR QT -> Value.QT SEC -> Value.SEC @@ -5209,7 +5207,9 @@ class UnitOfMeasureCode @JsonCreator private constructor(private val value: Json XZZ -> Value.XZZ ZZ -> Value.ZZ NAR -> Value.NAR + C62 -> Value.C62 LTR -> Value.LTR + H87 -> Value.H87 else -> Value._UNKNOWN } @@ -5608,7 +5608,6 @@ class UnitOfMeasureCode @JsonCreator private constructor(private val value: Json C59 -> Known.C59 C60 -> Known.C60 C61 -> Known.C61 - C62 -> Known.C62 C63 -> Known.C63 C64 -> Known.C64 C65 -> Known.C65 @@ -5692,7 +5691,6 @@ class UnitOfMeasureCode @JsonCreator private constructor(private val value: Json MIN -> Known.MIN MON -> Known.MON ONZ -> Known.ONZ - PCE -> Known.PCE LBR -> Known.LBR QT -> Known.QT SEC -> Known.SEC @@ -6253,7 +6251,9 @@ class UnitOfMeasureCode @JsonCreator private constructor(private val value: Json XZZ -> Known.XZZ ZZ -> Known.ZZ NAR -> Known.NAR + C62 -> Known.C62 LTR -> Known.LTR + H87 -> Known.H87 else -> throw EInvoiceInvalidDataException("Unknown UnitOfMeasureCode: $value") } diff --git a/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/models/documents/attachments/AttachmentAddParams.kt b/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/models/documents/attachments/AttachmentAddParams.kt index 9dc465e..b64d645 100644 --- a/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/models/documents/attachments/AttachmentAddParams.kt +++ b/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/models/documents/attachments/AttachmentAddParams.kt @@ -23,7 +23,12 @@ import kotlin.io.path.inputStream import kotlin.io.path.name import kotlin.jvm.optionals.getOrNull -/** Add a new attachment to an invoice or credit note */ +/** + * Add one or more attachments to an invoice. Be careful: the attachments ARE NOT ADDED to the UBL! + * They are only stored in our database and can be downloaded later. To add attachments to the UBL, + * you need to add the attachment(s) via POST /api/documents + */ +@Deprecated("deprecated") class AttachmentAddParams private constructor( private val documentId: String?, diff --git a/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/models/documents/ubl/UblCreateFromUblParams.kt b/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/models/documents/ubl/UblCreateFromUblParams.kt new file mode 100644 index 0000000..fc29fbe --- /dev/null +++ b/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/models/documents/ubl/UblCreateFromUblParams.kt @@ -0,0 +1,415 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.e_invoice.api.models.documents.ubl + +import com.e_invoice.api.core.ExcludeMissing +import com.e_invoice.api.core.JsonValue +import com.e_invoice.api.core.MultipartField +import com.e_invoice.api.core.Params +import com.e_invoice.api.core.checkRequired +import com.e_invoice.api.core.http.Headers +import com.e_invoice.api.core.http.QueryParams +import com.e_invoice.api.core.toImmutable +import com.e_invoice.api.errors.EInvoiceInvalidDataException +import com.fasterxml.jackson.annotation.JsonAnyGetter +import com.fasterxml.jackson.annotation.JsonAnySetter +import com.fasterxml.jackson.annotation.JsonProperty +import java.io.InputStream +import java.nio.file.Path +import java.util.Collections +import java.util.Objects +import kotlin.io.path.inputStream +import kotlin.io.path.name + +/** Create a new invoice or credit note from a UBL file */ +class UblCreateFromUblParams +private constructor( + private val body: Body, + private val additionalHeaders: Headers, + private val additionalQueryParams: QueryParams, +) : Params { + + /** + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun file(): InputStream = body.file() + + /** + * Returns the raw multipart value of [file]. + * + * Unlike [file], this method doesn't throw if the multipart field has an unexpected type. + */ + fun _file(): MultipartField = body._file() + + fun _additionalBodyProperties(): Map = body._additionalProperties() + + /** Additional headers to send with the request. */ + fun _additionalHeaders(): Headers = additionalHeaders + + /** Additional query param to send with the request. */ + fun _additionalQueryParams(): QueryParams = additionalQueryParams + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of [UblCreateFromUblParams]. + * + * The following fields are required: + * ```java + * .file() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [UblCreateFromUblParams]. */ + class Builder internal constructor() { + + private var body: Body.Builder = Body.builder() + private var additionalHeaders: Headers.Builder = Headers.builder() + private var additionalQueryParams: QueryParams.Builder = QueryParams.builder() + + @JvmSynthetic + internal fun from(ublCreateFromUblParams: UblCreateFromUblParams) = apply { + body = ublCreateFromUblParams.body.toBuilder() + additionalHeaders = ublCreateFromUblParams.additionalHeaders.toBuilder() + additionalQueryParams = ublCreateFromUblParams.additionalQueryParams.toBuilder() + } + + /** + * Sets the entire request body. + * + * This is generally only useful if you are already constructing the body separately. + * Otherwise, it's more convenient to use the top-level setters instead: + * - [file] + */ + fun body(body: Body) = apply { this.body = body.toBuilder() } + + fun file(file: InputStream) = apply { body.file(file) } + + /** + * Sets [Builder.file] to an arbitrary multipart value. + * + * You should usually call [Builder.file] with a well-typed [InputStream] value instead. + * This method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun file(file: MultipartField) = apply { body.file(file) } + + fun file(file: ByteArray) = apply { body.file(file) } + + fun file(path: Path) = apply { body.file(path) } + + fun additionalBodyProperties(additionalBodyProperties: Map) = apply { + body.additionalProperties(additionalBodyProperties) + } + + fun putAdditionalBodyProperty(key: String, value: JsonValue) = apply { + body.putAdditionalProperty(key, value) + } + + fun putAllAdditionalBodyProperties(additionalBodyProperties: Map) = + apply { + body.putAllAdditionalProperties(additionalBodyProperties) + } + + fun removeAdditionalBodyProperty(key: String) = apply { body.removeAdditionalProperty(key) } + + fun removeAllAdditionalBodyProperties(keys: Set) = apply { + body.removeAllAdditionalProperties(keys) + } + + fun additionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun additionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun putAdditionalHeader(name: String, value: String) = apply { + additionalHeaders.put(name, value) + } + + fun putAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.put(name, values) + } + + fun putAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun putAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun replaceAdditionalHeaders(name: String, value: String) = apply { + additionalHeaders.replace(name, value) + } + + fun replaceAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.replace(name, values) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun removeAdditionalHeaders(name: String) = apply { additionalHeaders.remove(name) } + + fun removeAllAdditionalHeaders(names: Set) = apply { + additionalHeaders.removeAll(names) + } + + fun additionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun additionalQueryParams(additionalQueryParams: Map>) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun putAdditionalQueryParam(key: String, value: String) = apply { + additionalQueryParams.put(key, value) + } + + fun putAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.put(key, values) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun replaceAdditionalQueryParams(key: String, value: String) = apply { + additionalQueryParams.replace(key, value) + } + + fun replaceAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.replace(key, values) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun removeAdditionalQueryParams(key: String) = apply { additionalQueryParams.remove(key) } + + fun removeAllAdditionalQueryParams(keys: Set) = apply { + additionalQueryParams.removeAll(keys) + } + + /** + * Returns an immutable instance of [UblCreateFromUblParams]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .file() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): UblCreateFromUblParams = + UblCreateFromUblParams( + body.build(), + additionalHeaders.build(), + additionalQueryParams.build(), + ) + } + + fun _body(): Map> = + (mapOf("file" to _file()) + + _additionalBodyProperties().mapValues { (_, value) -> MultipartField.of(value) }) + .toImmutable() + + override fun _headers(): Headers = additionalHeaders + + override fun _queryParams(): QueryParams = additionalQueryParams + + class Body + private constructor( + private val file: MultipartField, + private val additionalProperties: MutableMap, + ) { + + /** + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun file(): InputStream = file.value.getRequired("file") + + /** + * Returns the raw multipart value of [file]. + * + * Unlike [file], this method doesn't throw if the multipart field has an unexpected type. + */ + @JsonProperty("file") @ExcludeMissing fun _file(): MultipartField = file + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of [Body]. + * + * The following fields are required: + * ```java + * .file() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [Body]. */ + class Builder internal constructor() { + + private var file: MultipartField? = null + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(body: Body) = apply { + file = body.file + additionalProperties = body.additionalProperties.toMutableMap() + } + + fun file(file: InputStream) = file(MultipartField.of(file)) + + /** + * Sets [Builder.file] to an arbitrary multipart value. + * + * You should usually call [Builder.file] with a well-typed [InputStream] value instead. + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun file(file: MultipartField) = apply { this.file = file } + + fun file(file: ByteArray) = file(file.inputStream()) + + fun file(path: Path) = + file( + MultipartField.builder() + .value(path.inputStream()) + .filename(path.name) + .build() + ) + + fun additionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.clear() + putAllAdditionalProperties(additionalProperties) + } + + fun putAdditionalProperty(key: String, value: JsonValue) = apply { + additionalProperties.put(key, value) + } + + fun putAllAdditionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.putAll(additionalProperties) + } + + fun removeAdditionalProperty(key: String) = apply { additionalProperties.remove(key) } + + fun removeAllAdditionalProperties(keys: Set) = apply { + keys.forEach(::removeAdditionalProperty) + } + + /** + * Returns an immutable instance of [Body]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .file() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): Body = + Body(checkRequired("file", file), additionalProperties.toMutableMap()) + } + + private var validated: Boolean = false + + fun validate(): Body = apply { + if (validated) { + return@apply + } + + file() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: EInvoiceInvalidDataException) { + false + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Body && + file == other.file && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { Objects.hash(file, additionalProperties) } + + override fun hashCode(): Int = hashCode + + override fun toString() = "Body{file=$file, additionalProperties=$additionalProperties}" + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is UblCreateFromUblParams && + body == other.body && + additionalHeaders == other.additionalHeaders && + additionalQueryParams == other.additionalQueryParams + } + + override fun hashCode(): Int = Objects.hash(body, additionalHeaders, additionalQueryParams) + + override fun toString() = + "UblCreateFromUblParams{body=$body, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams}" +} diff --git a/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/models/inbox/InboxListCreditNotesPage.kt b/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/models/inbox/InboxListCreditNotesPage.kt index be65901..b8cfb3f 100644 --- a/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/models/inbox/InboxListCreditNotesPage.kt +++ b/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/models/inbox/InboxListCreditNotesPage.kt @@ -55,8 +55,8 @@ private constructor( } val pageNumber = page().getOrDefault(1) - val pageCount = total().getOrDefault(Long.MAX_VALUE) - return pageNumber < pageCount + val pageCount = total().getOrNull() + return pageCount == null || pageNumber < pageCount } fun nextPageParams(): InboxListCreditNotesParams { diff --git a/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/models/inbox/InboxListCreditNotesPageAsync.kt b/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/models/inbox/InboxListCreditNotesPageAsync.kt index b38b74c..193f7c5 100644 --- a/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/models/inbox/InboxListCreditNotesPageAsync.kt +++ b/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/models/inbox/InboxListCreditNotesPageAsync.kt @@ -58,8 +58,8 @@ private constructor( } val pageNumber = page().getOrDefault(1) - val pageCount = total().getOrDefault(Long.MAX_VALUE) - return pageNumber < pageCount + val pageCount = total().getOrNull() + return pageCount == null || pageNumber < pageCount } fun nextPageParams(): InboxListCreditNotesParams { diff --git a/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/models/inbox/InboxListCreditNotesParams.kt b/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/models/inbox/InboxListCreditNotesParams.kt index 03f6bda..4891f17 100644 --- a/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/models/inbox/InboxListCreditNotesParams.kt +++ b/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/models/inbox/InboxListCreditNotesParams.kt @@ -2,9 +2,13 @@ package com.e_invoice.api.models.inbox +import com.e_invoice.api.core.Enum +import com.e_invoice.api.core.JsonField import com.e_invoice.api.core.Params import com.e_invoice.api.core.http.Headers import com.e_invoice.api.core.http.QueryParams +import com.e_invoice.api.errors.EInvoiceInvalidDataException +import com.fasterxml.jackson.annotation.JsonCreator import java.util.Objects import java.util.Optional import kotlin.jvm.optionals.getOrNull @@ -14,6 +18,8 @@ class InboxListCreditNotesParams private constructor( private val page: Long?, private val pageSize: Long?, + private val sortBy: SortBy?, + private val sortOrder: SortOrder?, private val additionalHeaders: Headers, private val additionalQueryParams: QueryParams, ) : Params { @@ -24,6 +30,12 @@ private constructor( /** Number of items per page */ fun pageSize(): Optional = Optional.ofNullable(pageSize) + /** Field to sort by */ + fun sortBy(): Optional = Optional.ofNullable(sortBy) + + /** Sort direction (asc/desc) */ + fun sortOrder(): Optional = Optional.ofNullable(sortOrder) + /** Additional headers to send with the request. */ fun _additionalHeaders(): Headers = additionalHeaders @@ -47,6 +59,8 @@ private constructor( private var page: Long? = null private var pageSize: Long? = null + private var sortBy: SortBy? = null + private var sortOrder: SortOrder? = null private var additionalHeaders: Headers.Builder = Headers.builder() private var additionalQueryParams: QueryParams.Builder = QueryParams.builder() @@ -54,6 +68,8 @@ private constructor( internal fun from(inboxListCreditNotesParams: InboxListCreditNotesParams) = apply { page = inboxListCreditNotesParams.page pageSize = inboxListCreditNotesParams.pageSize + sortBy = inboxListCreditNotesParams.sortBy + sortOrder = inboxListCreditNotesParams.sortOrder additionalHeaders = inboxListCreditNotesParams.additionalHeaders.toBuilder() additionalQueryParams = inboxListCreditNotesParams.additionalQueryParams.toBuilder() } @@ -84,6 +100,18 @@ private constructor( /** Alias for calling [Builder.pageSize] with `pageSize.orElse(null)`. */ fun pageSize(pageSize: Optional) = pageSize(pageSize.getOrNull()) + /** Field to sort by */ + fun sortBy(sortBy: SortBy?) = apply { this.sortBy = sortBy } + + /** Alias for calling [Builder.sortBy] with `sortBy.orElse(null)`. */ + fun sortBy(sortBy: Optional) = sortBy(sortBy.getOrNull()) + + /** Sort direction (asc/desc) */ + fun sortOrder(sortOrder: SortOrder?) = apply { this.sortOrder = sortOrder } + + /** Alias for calling [Builder.sortOrder] with `sortOrder.orElse(null)`. */ + fun sortOrder(sortOrder: Optional) = sortOrder(sortOrder.getOrNull()) + fun additionalHeaders(additionalHeaders: Headers) = apply { this.additionalHeaders.clear() putAllAdditionalHeaders(additionalHeaders) @@ -191,6 +219,8 @@ private constructor( InboxListCreditNotesParams( page, pageSize, + sortBy, + sortOrder, additionalHeaders.build(), additionalQueryParams.build(), ) @@ -203,10 +233,300 @@ private constructor( .apply { page?.let { put("page", it.toString()) } pageSize?.let { put("page_size", it.toString()) } + sortBy?.let { put("sort_by", it.toString()) } + sortOrder?.let { put("sort_order", it.toString()) } putAll(additionalQueryParams) } .build() + /** Field to sort by */ + class SortBy @JsonCreator private constructor(private val value: JsonField) : Enum { + + /** + * Returns this class instance's raw value. + * + * This is usually only useful if this instance was deserialized from data that doesn't + * match any known member, and you want to know that value. For example, if the SDK is on an + * older version than the API, then the API may respond with new members that the SDK is + * unaware of. + */ + @com.fasterxml.jackson.annotation.JsonValue fun _value(): JsonField = value + + companion object { + + @JvmField val CREATED_AT = of("created_at") + + @JvmField val INVOICE_DATE = of("invoice_date") + + @JvmField val DUE_DATE = of("due_date") + + @JvmField val INVOICE_TOTAL = of("invoice_total") + + @JvmField val CUSTOMER_NAME = of("customer_name") + + @JvmField val VENDOR_NAME = of("vendor_name") + + @JvmField val INVOICE_ID = of("invoice_id") + + @JvmStatic fun of(value: String) = SortBy(JsonField.of(value)) + } + + /** An enum containing [SortBy]'s known values. */ + enum class Known { + CREATED_AT, + INVOICE_DATE, + DUE_DATE, + INVOICE_TOTAL, + CUSTOMER_NAME, + VENDOR_NAME, + INVOICE_ID, + } + + /** + * An enum containing [SortBy]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [SortBy] can contain an unknown value in a couple of cases: + * - It was deserialized from data that doesn't match any known member. For example, if the + * SDK is on an older version than the API, then the API may respond with new members that + * the SDK is unaware of. + * - It was constructed with an arbitrary value using the [of] method. + */ + enum class Value { + CREATED_AT, + INVOICE_DATE, + DUE_DATE, + INVOICE_TOTAL, + CUSTOMER_NAME, + VENDOR_NAME, + INVOICE_ID, + /** An enum member indicating that [SortBy] was instantiated with an unknown value. */ + _UNKNOWN, + } + + /** + * Returns an enum member corresponding to this class instance's value, or [Value._UNKNOWN] + * if the class was instantiated with an unknown value. + * + * Use the [known] method instead if you're certain the value is always known or if you want + * to throw for the unknown case. + */ + fun value(): Value = + when (this) { + CREATED_AT -> Value.CREATED_AT + INVOICE_DATE -> Value.INVOICE_DATE + DUE_DATE -> Value.DUE_DATE + INVOICE_TOTAL -> Value.INVOICE_TOTAL + CUSTOMER_NAME -> Value.CUSTOMER_NAME + VENDOR_NAME -> Value.VENDOR_NAME + INVOICE_ID -> Value.INVOICE_ID + else -> Value._UNKNOWN + } + + /** + * Returns an enum member corresponding to this class instance's value. + * + * Use the [value] method instead if you're uncertain the value is always known and don't + * want to throw for the unknown case. + * + * @throws EInvoiceInvalidDataException if this class instance's value is a not a known + * member. + */ + fun known(): Known = + when (this) { + CREATED_AT -> Known.CREATED_AT + INVOICE_DATE -> Known.INVOICE_DATE + DUE_DATE -> Known.DUE_DATE + INVOICE_TOTAL -> Known.INVOICE_TOTAL + CUSTOMER_NAME -> Known.CUSTOMER_NAME + VENDOR_NAME -> Known.VENDOR_NAME + INVOICE_ID -> Known.INVOICE_ID + else -> throw EInvoiceInvalidDataException("Unknown SortBy: $value") + } + + /** + * Returns this class instance's primitive wire representation. + * + * This differs from the [toString] method because that method is primarily for debugging + * and generally doesn't throw. + * + * @throws EInvoiceInvalidDataException if this class instance's value does not have the + * expected primitive type. + */ + fun asString(): String = + _value().asString().orElseThrow { + EInvoiceInvalidDataException("Value is not a String") + } + + private var validated: Boolean = false + + fun validate(): SortBy = apply { + if (validated) { + return@apply + } + + known() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: EInvoiceInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic internal fun validity(): Int = if (value() == Value._UNKNOWN) 0 else 1 + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is SortBy && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + /** Sort direction (asc/desc) */ + class SortOrder @JsonCreator private constructor(private val value: JsonField) : Enum { + + /** + * Returns this class instance's raw value. + * + * This is usually only useful if this instance was deserialized from data that doesn't + * match any known member, and you want to know that value. For example, if the SDK is on an + * older version than the API, then the API may respond with new members that the SDK is + * unaware of. + */ + @com.fasterxml.jackson.annotation.JsonValue fun _value(): JsonField = value + + companion object { + + @JvmField val ASC = of("asc") + + @JvmField val DESC = of("desc") + + @JvmStatic fun of(value: String) = SortOrder(JsonField.of(value)) + } + + /** An enum containing [SortOrder]'s known values. */ + enum class Known { + ASC, + DESC, + } + + /** + * An enum containing [SortOrder]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [SortOrder] can contain an unknown value in a couple of cases: + * - It was deserialized from data that doesn't match any known member. For example, if the + * SDK is on an older version than the API, then the API may respond with new members that + * the SDK is unaware of. + * - It was constructed with an arbitrary value using the [of] method. + */ + enum class Value { + ASC, + DESC, + /** + * An enum member indicating that [SortOrder] was instantiated with an unknown value. + */ + _UNKNOWN, + } + + /** + * Returns an enum member corresponding to this class instance's value, or [Value._UNKNOWN] + * if the class was instantiated with an unknown value. + * + * Use the [known] method instead if you're certain the value is always known or if you want + * to throw for the unknown case. + */ + fun value(): Value = + when (this) { + ASC -> Value.ASC + DESC -> Value.DESC + else -> Value._UNKNOWN + } + + /** + * Returns an enum member corresponding to this class instance's value. + * + * Use the [value] method instead if you're uncertain the value is always known and don't + * want to throw for the unknown case. + * + * @throws EInvoiceInvalidDataException if this class instance's value is a not a known + * member. + */ + fun known(): Known = + when (this) { + ASC -> Known.ASC + DESC -> Known.DESC + else -> throw EInvoiceInvalidDataException("Unknown SortOrder: $value") + } + + /** + * Returns this class instance's primitive wire representation. + * + * This differs from the [toString] method because that method is primarily for debugging + * and generally doesn't throw. + * + * @throws EInvoiceInvalidDataException if this class instance's value does not have the + * expected primitive type. + */ + fun asString(): String = + _value().asString().orElseThrow { + EInvoiceInvalidDataException("Value is not a String") + } + + private var validated: Boolean = false + + fun validate(): SortOrder = apply { + if (validated) { + return@apply + } + + known() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: EInvoiceInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic internal fun validity(): Int = if (value() == Value._UNKNOWN) 0 else 1 + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is SortOrder && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + override fun equals(other: Any?): Boolean { if (this === other) { return true @@ -215,13 +535,15 @@ private constructor( return other is InboxListCreditNotesParams && page == other.page && pageSize == other.pageSize && + sortBy == other.sortBy && + sortOrder == other.sortOrder && additionalHeaders == other.additionalHeaders && additionalQueryParams == other.additionalQueryParams } override fun hashCode(): Int = - Objects.hash(page, pageSize, additionalHeaders, additionalQueryParams) + Objects.hash(page, pageSize, sortBy, sortOrder, additionalHeaders, additionalQueryParams) override fun toString() = - "InboxListCreditNotesParams{page=$page, pageSize=$pageSize, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams}" + "InboxListCreditNotesParams{page=$page, pageSize=$pageSize, sortBy=$sortBy, sortOrder=$sortOrder, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams}" } diff --git a/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/models/inbox/InboxListInvoicesPage.kt b/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/models/inbox/InboxListInvoicesPage.kt index ab7be57..4036b02 100644 --- a/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/models/inbox/InboxListInvoicesPage.kt +++ b/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/models/inbox/InboxListInvoicesPage.kt @@ -55,8 +55,8 @@ private constructor( } val pageNumber = page().getOrDefault(1) - val pageCount = total().getOrDefault(Long.MAX_VALUE) - return pageNumber < pageCount + val pageCount = total().getOrNull() + return pageCount == null || pageNumber < pageCount } fun nextPageParams(): InboxListInvoicesParams { diff --git a/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/models/inbox/InboxListInvoicesPageAsync.kt b/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/models/inbox/InboxListInvoicesPageAsync.kt index e7e6a10..a68631d 100644 --- a/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/models/inbox/InboxListInvoicesPageAsync.kt +++ b/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/models/inbox/InboxListInvoicesPageAsync.kt @@ -58,8 +58,8 @@ private constructor( } val pageNumber = page().getOrDefault(1) - val pageCount = total().getOrDefault(Long.MAX_VALUE) - return pageNumber < pageCount + val pageCount = total().getOrNull() + return pageCount == null || pageNumber < pageCount } fun nextPageParams(): InboxListInvoicesParams { diff --git a/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/models/inbox/InboxListInvoicesParams.kt b/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/models/inbox/InboxListInvoicesParams.kt index 6114365..6c806d6 100644 --- a/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/models/inbox/InboxListInvoicesParams.kt +++ b/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/models/inbox/InboxListInvoicesParams.kt @@ -2,9 +2,13 @@ package com.e_invoice.api.models.inbox +import com.e_invoice.api.core.Enum +import com.e_invoice.api.core.JsonField import com.e_invoice.api.core.Params import com.e_invoice.api.core.http.Headers import com.e_invoice.api.core.http.QueryParams +import com.e_invoice.api.errors.EInvoiceInvalidDataException +import com.fasterxml.jackson.annotation.JsonCreator import java.util.Objects import java.util.Optional import kotlin.jvm.optionals.getOrNull @@ -14,6 +18,8 @@ class InboxListInvoicesParams private constructor( private val page: Long?, private val pageSize: Long?, + private val sortBy: SortBy?, + private val sortOrder: SortOrder?, private val additionalHeaders: Headers, private val additionalQueryParams: QueryParams, ) : Params { @@ -24,6 +30,12 @@ private constructor( /** Number of items per page */ fun pageSize(): Optional = Optional.ofNullable(pageSize) + /** Field to sort by */ + fun sortBy(): Optional = Optional.ofNullable(sortBy) + + /** Sort direction (asc/desc) */ + fun sortOrder(): Optional = Optional.ofNullable(sortOrder) + /** Additional headers to send with the request. */ fun _additionalHeaders(): Headers = additionalHeaders @@ -45,6 +57,8 @@ private constructor( private var page: Long? = null private var pageSize: Long? = null + private var sortBy: SortBy? = null + private var sortOrder: SortOrder? = null private var additionalHeaders: Headers.Builder = Headers.builder() private var additionalQueryParams: QueryParams.Builder = QueryParams.builder() @@ -52,6 +66,8 @@ private constructor( internal fun from(inboxListInvoicesParams: InboxListInvoicesParams) = apply { page = inboxListInvoicesParams.page pageSize = inboxListInvoicesParams.pageSize + sortBy = inboxListInvoicesParams.sortBy + sortOrder = inboxListInvoicesParams.sortOrder additionalHeaders = inboxListInvoicesParams.additionalHeaders.toBuilder() additionalQueryParams = inboxListInvoicesParams.additionalQueryParams.toBuilder() } @@ -82,6 +98,18 @@ private constructor( /** Alias for calling [Builder.pageSize] with `pageSize.orElse(null)`. */ fun pageSize(pageSize: Optional) = pageSize(pageSize.getOrNull()) + /** Field to sort by */ + fun sortBy(sortBy: SortBy?) = apply { this.sortBy = sortBy } + + /** Alias for calling [Builder.sortBy] with `sortBy.orElse(null)`. */ + fun sortBy(sortBy: Optional) = sortBy(sortBy.getOrNull()) + + /** Sort direction (asc/desc) */ + fun sortOrder(sortOrder: SortOrder?) = apply { this.sortOrder = sortOrder } + + /** Alias for calling [Builder.sortOrder] with `sortOrder.orElse(null)`. */ + fun sortOrder(sortOrder: Optional) = sortOrder(sortOrder.getOrNull()) + fun additionalHeaders(additionalHeaders: Headers) = apply { this.additionalHeaders.clear() putAllAdditionalHeaders(additionalHeaders) @@ -189,6 +217,8 @@ private constructor( InboxListInvoicesParams( page, pageSize, + sortBy, + sortOrder, additionalHeaders.build(), additionalQueryParams.build(), ) @@ -201,10 +231,300 @@ private constructor( .apply { page?.let { put("page", it.toString()) } pageSize?.let { put("page_size", it.toString()) } + sortBy?.let { put("sort_by", it.toString()) } + sortOrder?.let { put("sort_order", it.toString()) } putAll(additionalQueryParams) } .build() + /** Field to sort by */ + class SortBy @JsonCreator private constructor(private val value: JsonField) : Enum { + + /** + * Returns this class instance's raw value. + * + * This is usually only useful if this instance was deserialized from data that doesn't + * match any known member, and you want to know that value. For example, if the SDK is on an + * older version than the API, then the API may respond with new members that the SDK is + * unaware of. + */ + @com.fasterxml.jackson.annotation.JsonValue fun _value(): JsonField = value + + companion object { + + @JvmField val CREATED_AT = of("created_at") + + @JvmField val INVOICE_DATE = of("invoice_date") + + @JvmField val DUE_DATE = of("due_date") + + @JvmField val INVOICE_TOTAL = of("invoice_total") + + @JvmField val CUSTOMER_NAME = of("customer_name") + + @JvmField val VENDOR_NAME = of("vendor_name") + + @JvmField val INVOICE_ID = of("invoice_id") + + @JvmStatic fun of(value: String) = SortBy(JsonField.of(value)) + } + + /** An enum containing [SortBy]'s known values. */ + enum class Known { + CREATED_AT, + INVOICE_DATE, + DUE_DATE, + INVOICE_TOTAL, + CUSTOMER_NAME, + VENDOR_NAME, + INVOICE_ID, + } + + /** + * An enum containing [SortBy]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [SortBy] can contain an unknown value in a couple of cases: + * - It was deserialized from data that doesn't match any known member. For example, if the + * SDK is on an older version than the API, then the API may respond with new members that + * the SDK is unaware of. + * - It was constructed with an arbitrary value using the [of] method. + */ + enum class Value { + CREATED_AT, + INVOICE_DATE, + DUE_DATE, + INVOICE_TOTAL, + CUSTOMER_NAME, + VENDOR_NAME, + INVOICE_ID, + /** An enum member indicating that [SortBy] was instantiated with an unknown value. */ + _UNKNOWN, + } + + /** + * Returns an enum member corresponding to this class instance's value, or [Value._UNKNOWN] + * if the class was instantiated with an unknown value. + * + * Use the [known] method instead if you're certain the value is always known or if you want + * to throw for the unknown case. + */ + fun value(): Value = + when (this) { + CREATED_AT -> Value.CREATED_AT + INVOICE_DATE -> Value.INVOICE_DATE + DUE_DATE -> Value.DUE_DATE + INVOICE_TOTAL -> Value.INVOICE_TOTAL + CUSTOMER_NAME -> Value.CUSTOMER_NAME + VENDOR_NAME -> Value.VENDOR_NAME + INVOICE_ID -> Value.INVOICE_ID + else -> Value._UNKNOWN + } + + /** + * Returns an enum member corresponding to this class instance's value. + * + * Use the [value] method instead if you're uncertain the value is always known and don't + * want to throw for the unknown case. + * + * @throws EInvoiceInvalidDataException if this class instance's value is a not a known + * member. + */ + fun known(): Known = + when (this) { + CREATED_AT -> Known.CREATED_AT + INVOICE_DATE -> Known.INVOICE_DATE + DUE_DATE -> Known.DUE_DATE + INVOICE_TOTAL -> Known.INVOICE_TOTAL + CUSTOMER_NAME -> Known.CUSTOMER_NAME + VENDOR_NAME -> Known.VENDOR_NAME + INVOICE_ID -> Known.INVOICE_ID + else -> throw EInvoiceInvalidDataException("Unknown SortBy: $value") + } + + /** + * Returns this class instance's primitive wire representation. + * + * This differs from the [toString] method because that method is primarily for debugging + * and generally doesn't throw. + * + * @throws EInvoiceInvalidDataException if this class instance's value does not have the + * expected primitive type. + */ + fun asString(): String = + _value().asString().orElseThrow { + EInvoiceInvalidDataException("Value is not a String") + } + + private var validated: Boolean = false + + fun validate(): SortBy = apply { + if (validated) { + return@apply + } + + known() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: EInvoiceInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic internal fun validity(): Int = if (value() == Value._UNKNOWN) 0 else 1 + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is SortBy && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + /** Sort direction (asc/desc) */ + class SortOrder @JsonCreator private constructor(private val value: JsonField) : Enum { + + /** + * Returns this class instance's raw value. + * + * This is usually only useful if this instance was deserialized from data that doesn't + * match any known member, and you want to know that value. For example, if the SDK is on an + * older version than the API, then the API may respond with new members that the SDK is + * unaware of. + */ + @com.fasterxml.jackson.annotation.JsonValue fun _value(): JsonField = value + + companion object { + + @JvmField val ASC = of("asc") + + @JvmField val DESC = of("desc") + + @JvmStatic fun of(value: String) = SortOrder(JsonField.of(value)) + } + + /** An enum containing [SortOrder]'s known values. */ + enum class Known { + ASC, + DESC, + } + + /** + * An enum containing [SortOrder]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [SortOrder] can contain an unknown value in a couple of cases: + * - It was deserialized from data that doesn't match any known member. For example, if the + * SDK is on an older version than the API, then the API may respond with new members that + * the SDK is unaware of. + * - It was constructed with an arbitrary value using the [of] method. + */ + enum class Value { + ASC, + DESC, + /** + * An enum member indicating that [SortOrder] was instantiated with an unknown value. + */ + _UNKNOWN, + } + + /** + * Returns an enum member corresponding to this class instance's value, or [Value._UNKNOWN] + * if the class was instantiated with an unknown value. + * + * Use the [known] method instead if you're certain the value is always known or if you want + * to throw for the unknown case. + */ + fun value(): Value = + when (this) { + ASC -> Value.ASC + DESC -> Value.DESC + else -> Value._UNKNOWN + } + + /** + * Returns an enum member corresponding to this class instance's value. + * + * Use the [value] method instead if you're uncertain the value is always known and don't + * want to throw for the unknown case. + * + * @throws EInvoiceInvalidDataException if this class instance's value is a not a known + * member. + */ + fun known(): Known = + when (this) { + ASC -> Known.ASC + DESC -> Known.DESC + else -> throw EInvoiceInvalidDataException("Unknown SortOrder: $value") + } + + /** + * Returns this class instance's primitive wire representation. + * + * This differs from the [toString] method because that method is primarily for debugging + * and generally doesn't throw. + * + * @throws EInvoiceInvalidDataException if this class instance's value does not have the + * expected primitive type. + */ + fun asString(): String = + _value().asString().orElseThrow { + EInvoiceInvalidDataException("Value is not a String") + } + + private var validated: Boolean = false + + fun validate(): SortOrder = apply { + if (validated) { + return@apply + } + + known() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: EInvoiceInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic internal fun validity(): Int = if (value() == Value._UNKNOWN) 0 else 1 + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is SortOrder && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + override fun equals(other: Any?): Boolean { if (this === other) { return true @@ -213,13 +533,15 @@ private constructor( return other is InboxListInvoicesParams && page == other.page && pageSize == other.pageSize && + sortBy == other.sortBy && + sortOrder == other.sortOrder && additionalHeaders == other.additionalHeaders && additionalQueryParams == other.additionalQueryParams } override fun hashCode(): Int = - Objects.hash(page, pageSize, additionalHeaders, additionalQueryParams) + Objects.hash(page, pageSize, sortBy, sortOrder, additionalHeaders, additionalQueryParams) override fun toString() = - "InboxListInvoicesParams{page=$page, pageSize=$pageSize, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams}" + "InboxListInvoicesParams{page=$page, pageSize=$pageSize, sortBy=$sortBy, sortOrder=$sortOrder, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams}" } diff --git a/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/models/inbox/InboxListPage.kt b/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/models/inbox/InboxListPage.kt index a3118c4..2117818 100644 --- a/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/models/inbox/InboxListPage.kt +++ b/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/models/inbox/InboxListPage.kt @@ -55,8 +55,8 @@ private constructor( } val pageNumber = page().getOrDefault(1) - val pageCount = total().getOrDefault(Long.MAX_VALUE) - return pageNumber < pageCount + val pageCount = total().getOrNull() + return pageCount == null || pageNumber < pageCount } fun nextPageParams(): InboxListParams { diff --git a/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/models/inbox/InboxListPageAsync.kt b/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/models/inbox/InboxListPageAsync.kt index d83775d..4be7c5b 100644 --- a/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/models/inbox/InboxListPageAsync.kt +++ b/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/models/inbox/InboxListPageAsync.kt @@ -58,8 +58,8 @@ private constructor( } val pageNumber = page().getOrDefault(1) - val pageCount = total().getOrDefault(Long.MAX_VALUE) - return pageNumber < pageCount + val pageCount = total().getOrNull() + return pageCount == null || pageNumber < pageCount } fun nextPageParams(): InboxListParams { diff --git a/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/models/inbox/InboxListParams.kt b/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/models/inbox/InboxListParams.kt index 4b06da2..63839bd 100644 --- a/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/models/inbox/InboxListParams.kt +++ b/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/models/inbox/InboxListParams.kt @@ -2,10 +2,14 @@ package com.e_invoice.api.models.inbox +import com.e_invoice.api.core.Enum +import com.e_invoice.api.core.JsonField import com.e_invoice.api.core.Params import com.e_invoice.api.core.http.Headers import com.e_invoice.api.core.http.QueryParams +import com.e_invoice.api.errors.EInvoiceInvalidDataException import com.e_invoice.api.models.documents.DocumentType +import com.fasterxml.jackson.annotation.JsonCreator import java.time.OffsetDateTime import java.time.format.DateTimeFormatter import java.util.Objects @@ -24,7 +28,8 @@ private constructor( private val pageSize: Long?, private val search: String?, private val sender: String?, - private val state: DocumentState?, + private val sortBy: SortBy?, + private val sortOrder: SortOrder?, private val type: DocumentType?, private val additionalHeaders: Headers, private val additionalQueryParams: QueryParams, @@ -45,13 +50,16 @@ private constructor( /** Search in invoice number, seller/buyer names */ fun search(): Optional = Optional.ofNullable(search) - /** Filter by sender ID */ + /** Filter by sender (vendor_name, vendor_email, vendor_tax_id, vendor_company_id) */ fun sender(): Optional = Optional.ofNullable(sender) - /** Filter by document state */ - fun state(): Optional = Optional.ofNullable(state) + /** Field to sort by */ + fun sortBy(): Optional = Optional.ofNullable(sortBy) - /** Filter by document type */ + /** Sort direction (asc/desc) */ + fun sortOrder(): Optional = Optional.ofNullable(sortOrder) + + /** Filter by document type. If not provided, returns all types. */ fun type(): Optional = Optional.ofNullable(type) /** Additional headers to send with the request. */ @@ -79,7 +87,8 @@ private constructor( private var pageSize: Long? = null private var search: String? = null private var sender: String? = null - private var state: DocumentState? = null + private var sortBy: SortBy? = null + private var sortOrder: SortOrder? = null private var type: DocumentType? = null private var additionalHeaders: Headers.Builder = Headers.builder() private var additionalQueryParams: QueryParams.Builder = QueryParams.builder() @@ -92,7 +101,8 @@ private constructor( pageSize = inboxListParams.pageSize search = inboxListParams.search sender = inboxListParams.sender - state = inboxListParams.state + sortBy = inboxListParams.sortBy + sortOrder = inboxListParams.sortOrder type = inboxListParams.type additionalHeaders = inboxListParams.additionalHeaders.toBuilder() additionalQueryParams = inboxListParams.additionalQueryParams.toBuilder() @@ -142,19 +152,25 @@ private constructor( /** Alias for calling [Builder.search] with `search.orElse(null)`. */ fun search(search: Optional) = search(search.getOrNull()) - /** Filter by sender ID */ + /** Filter by sender (vendor_name, vendor_email, vendor_tax_id, vendor_company_id) */ fun sender(sender: String?) = apply { this.sender = sender } /** Alias for calling [Builder.sender] with `sender.orElse(null)`. */ fun sender(sender: Optional) = sender(sender.getOrNull()) - /** Filter by document state */ - fun state(state: DocumentState?) = apply { this.state = state } + /** Field to sort by */ + fun sortBy(sortBy: SortBy?) = apply { this.sortBy = sortBy } + + /** Alias for calling [Builder.sortBy] with `sortBy.orElse(null)`. */ + fun sortBy(sortBy: Optional) = sortBy(sortBy.getOrNull()) - /** Alias for calling [Builder.state] with `state.orElse(null)`. */ - fun state(state: Optional) = state(state.getOrNull()) + /** Sort direction (asc/desc) */ + fun sortOrder(sortOrder: SortOrder?) = apply { this.sortOrder = sortOrder } - /** Filter by document type */ + /** Alias for calling [Builder.sortOrder] with `sortOrder.orElse(null)`. */ + fun sortOrder(sortOrder: Optional) = sortOrder(sortOrder.getOrNull()) + + /** Filter by document type. If not provided, returns all types. */ fun type(type: DocumentType?) = apply { this.type = type } /** Alias for calling [Builder.type] with `type.orElse(null)`. */ @@ -271,7 +287,8 @@ private constructor( pageSize, search, sender, - state, + sortBy, + sortOrder, type, additionalHeaders.build(), additionalQueryParams.build(), @@ -291,12 +308,301 @@ private constructor( pageSize?.let { put("page_size", it.toString()) } search?.let { put("search", it) } sender?.let { put("sender", it) } - state?.let { put("state", it.toString()) } + sortBy?.let { put("sort_by", it.toString()) } + sortOrder?.let { put("sort_order", it.toString()) } type?.let { put("type", it.toString()) } putAll(additionalQueryParams) } .build() + /** Field to sort by */ + class SortBy @JsonCreator private constructor(private val value: JsonField) : Enum { + + /** + * Returns this class instance's raw value. + * + * This is usually only useful if this instance was deserialized from data that doesn't + * match any known member, and you want to know that value. For example, if the SDK is on an + * older version than the API, then the API may respond with new members that the SDK is + * unaware of. + */ + @com.fasterxml.jackson.annotation.JsonValue fun _value(): JsonField = value + + companion object { + + @JvmField val CREATED_AT = of("created_at") + + @JvmField val INVOICE_DATE = of("invoice_date") + + @JvmField val DUE_DATE = of("due_date") + + @JvmField val INVOICE_TOTAL = of("invoice_total") + + @JvmField val CUSTOMER_NAME = of("customer_name") + + @JvmField val VENDOR_NAME = of("vendor_name") + + @JvmField val INVOICE_ID = of("invoice_id") + + @JvmStatic fun of(value: String) = SortBy(JsonField.of(value)) + } + + /** An enum containing [SortBy]'s known values. */ + enum class Known { + CREATED_AT, + INVOICE_DATE, + DUE_DATE, + INVOICE_TOTAL, + CUSTOMER_NAME, + VENDOR_NAME, + INVOICE_ID, + } + + /** + * An enum containing [SortBy]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [SortBy] can contain an unknown value in a couple of cases: + * - It was deserialized from data that doesn't match any known member. For example, if the + * SDK is on an older version than the API, then the API may respond with new members that + * the SDK is unaware of. + * - It was constructed with an arbitrary value using the [of] method. + */ + enum class Value { + CREATED_AT, + INVOICE_DATE, + DUE_DATE, + INVOICE_TOTAL, + CUSTOMER_NAME, + VENDOR_NAME, + INVOICE_ID, + /** An enum member indicating that [SortBy] was instantiated with an unknown value. */ + _UNKNOWN, + } + + /** + * Returns an enum member corresponding to this class instance's value, or [Value._UNKNOWN] + * if the class was instantiated with an unknown value. + * + * Use the [known] method instead if you're certain the value is always known or if you want + * to throw for the unknown case. + */ + fun value(): Value = + when (this) { + CREATED_AT -> Value.CREATED_AT + INVOICE_DATE -> Value.INVOICE_DATE + DUE_DATE -> Value.DUE_DATE + INVOICE_TOTAL -> Value.INVOICE_TOTAL + CUSTOMER_NAME -> Value.CUSTOMER_NAME + VENDOR_NAME -> Value.VENDOR_NAME + INVOICE_ID -> Value.INVOICE_ID + else -> Value._UNKNOWN + } + + /** + * Returns an enum member corresponding to this class instance's value. + * + * Use the [value] method instead if you're uncertain the value is always known and don't + * want to throw for the unknown case. + * + * @throws EInvoiceInvalidDataException if this class instance's value is a not a known + * member. + */ + fun known(): Known = + when (this) { + CREATED_AT -> Known.CREATED_AT + INVOICE_DATE -> Known.INVOICE_DATE + DUE_DATE -> Known.DUE_DATE + INVOICE_TOTAL -> Known.INVOICE_TOTAL + CUSTOMER_NAME -> Known.CUSTOMER_NAME + VENDOR_NAME -> Known.VENDOR_NAME + INVOICE_ID -> Known.INVOICE_ID + else -> throw EInvoiceInvalidDataException("Unknown SortBy: $value") + } + + /** + * Returns this class instance's primitive wire representation. + * + * This differs from the [toString] method because that method is primarily for debugging + * and generally doesn't throw. + * + * @throws EInvoiceInvalidDataException if this class instance's value does not have the + * expected primitive type. + */ + fun asString(): String = + _value().asString().orElseThrow { + EInvoiceInvalidDataException("Value is not a String") + } + + private var validated: Boolean = false + + fun validate(): SortBy = apply { + if (validated) { + return@apply + } + + known() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: EInvoiceInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic internal fun validity(): Int = if (value() == Value._UNKNOWN) 0 else 1 + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is SortBy && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + /** Sort direction (asc/desc) */ + class SortOrder @JsonCreator private constructor(private val value: JsonField) : Enum { + + /** + * Returns this class instance's raw value. + * + * This is usually only useful if this instance was deserialized from data that doesn't + * match any known member, and you want to know that value. For example, if the SDK is on an + * older version than the API, then the API may respond with new members that the SDK is + * unaware of. + */ + @com.fasterxml.jackson.annotation.JsonValue fun _value(): JsonField = value + + companion object { + + @JvmField val ASC = of("asc") + + @JvmField val DESC = of("desc") + + @JvmStatic fun of(value: String) = SortOrder(JsonField.of(value)) + } + + /** An enum containing [SortOrder]'s known values. */ + enum class Known { + ASC, + DESC, + } + + /** + * An enum containing [SortOrder]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [SortOrder] can contain an unknown value in a couple of cases: + * - It was deserialized from data that doesn't match any known member. For example, if the + * SDK is on an older version than the API, then the API may respond with new members that + * the SDK is unaware of. + * - It was constructed with an arbitrary value using the [of] method. + */ + enum class Value { + ASC, + DESC, + /** + * An enum member indicating that [SortOrder] was instantiated with an unknown value. + */ + _UNKNOWN, + } + + /** + * Returns an enum member corresponding to this class instance's value, or [Value._UNKNOWN] + * if the class was instantiated with an unknown value. + * + * Use the [known] method instead if you're certain the value is always known or if you want + * to throw for the unknown case. + */ + fun value(): Value = + when (this) { + ASC -> Value.ASC + DESC -> Value.DESC + else -> Value._UNKNOWN + } + + /** + * Returns an enum member corresponding to this class instance's value. + * + * Use the [value] method instead if you're uncertain the value is always known and don't + * want to throw for the unknown case. + * + * @throws EInvoiceInvalidDataException if this class instance's value is a not a known + * member. + */ + fun known(): Known = + when (this) { + ASC -> Known.ASC + DESC -> Known.DESC + else -> throw EInvoiceInvalidDataException("Unknown SortOrder: $value") + } + + /** + * Returns this class instance's primitive wire representation. + * + * This differs from the [toString] method because that method is primarily for debugging + * and generally doesn't throw. + * + * @throws EInvoiceInvalidDataException if this class instance's value does not have the + * expected primitive type. + */ + fun asString(): String = + _value().asString().orElseThrow { + EInvoiceInvalidDataException("Value is not a String") + } + + private var validated: Boolean = false + + fun validate(): SortOrder = apply { + if (validated) { + return@apply + } + + known() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: EInvoiceInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic internal fun validity(): Int = if (value() == Value._UNKNOWN) 0 else 1 + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is SortOrder && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + override fun equals(other: Any?): Boolean { if (this === other) { return true @@ -309,7 +615,8 @@ private constructor( pageSize == other.pageSize && search == other.search && sender == other.sender && - state == other.state && + sortBy == other.sortBy && + sortOrder == other.sortOrder && type == other.type && additionalHeaders == other.additionalHeaders && additionalQueryParams == other.additionalQueryParams @@ -323,12 +630,13 @@ private constructor( pageSize, search, sender, - state, + sortBy, + sortOrder, type, additionalHeaders, additionalQueryParams, ) override fun toString() = - "InboxListParams{dateFrom=$dateFrom, dateTo=$dateTo, page=$page, pageSize=$pageSize, search=$search, sender=$sender, state=$state, type=$type, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams}" + "InboxListParams{dateFrom=$dateFrom, dateTo=$dateTo, page=$page, pageSize=$pageSize, search=$search, sender=$sender, sortBy=$sortBy, sortOrder=$sortOrder, type=$type, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams}" } diff --git a/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/models/inbox/PaginatedDocumentResponse.kt b/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/models/inbox/PaginatedDocumentResponse.kt index 1eefc67..236e300 100644 --- a/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/models/inbox/PaginatedDocumentResponse.kt +++ b/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/models/inbox/PaginatedDocumentResponse.kt @@ -22,6 +22,7 @@ import kotlin.jvm.optionals.getOrNull class PaginatedDocumentResponse @JsonCreator(mode = JsonCreator.Mode.DISABLED) private constructor( + private val hasNextPage: JsonField, private val items: JsonField>, private val page: JsonField, private val pageSize: JsonField, @@ -32,6 +33,9 @@ private constructor( @JsonCreator private constructor( + @JsonProperty("has_next_page") + @ExcludeMissing + hasNextPage: JsonField = JsonMissing.of(), @JsonProperty("items") @ExcludeMissing items: JsonField> = JsonMissing.of(), @@ -39,7 +43,13 @@ private constructor( @JsonProperty("page_size") @ExcludeMissing pageSize: JsonField = JsonMissing.of(), @JsonProperty("pages") @ExcludeMissing pages: JsonField = JsonMissing.of(), @JsonProperty("total") @ExcludeMissing total: JsonField = JsonMissing.of(), - ) : this(items, page, pageSize, pages, total, mutableMapOf()) + ) : this(hasNextPage, items, page, pageSize, pages, total, mutableMapOf()) + + /** + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun hasNextPage(): Boolean = hasNextPage.getRequired("has_next_page") /** * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type or is @@ -71,6 +81,15 @@ private constructor( */ fun total(): Long = total.getRequired("total") + /** + * Returns the raw JSON value of [hasNextPage]. + * + * Unlike [hasNextPage], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("has_next_page") + @ExcludeMissing + fun _hasNextPage(): JsonField = hasNextPage + /** * Returns the raw JSON value of [items]. * @@ -125,6 +144,7 @@ private constructor( * * The following fields are required: * ```java + * .hasNextPage() * .items() * .page() * .pageSize() @@ -138,6 +158,7 @@ private constructor( /** A builder for [PaginatedDocumentResponse]. */ class Builder internal constructor() { + private var hasNextPage: JsonField? = null private var items: JsonField>? = null private var page: JsonField? = null private var pageSize: JsonField? = null @@ -147,6 +168,7 @@ private constructor( @JvmSynthetic internal fun from(paginatedDocumentResponse: PaginatedDocumentResponse) = apply { + hasNextPage = paginatedDocumentResponse.hasNextPage items = paginatedDocumentResponse.items.map { it.toMutableList() } page = paginatedDocumentResponse.page pageSize = paginatedDocumentResponse.pageSize @@ -155,6 +177,17 @@ private constructor( additionalProperties = paginatedDocumentResponse.additionalProperties.toMutableMap() } + fun hasNextPage(hasNextPage: Boolean) = hasNextPage(JsonField.of(hasNextPage)) + + /** + * Sets [Builder.hasNextPage] to an arbitrary JSON value. + * + * You should usually call [Builder.hasNextPage] with a well-typed [Boolean] value instead. + * This method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun hasNextPage(hasNextPage: JsonField) = apply { this.hasNextPage = hasNextPage } + fun items(items: List) = items(JsonField.of(items)) /** @@ -244,6 +277,7 @@ private constructor( * * The following fields are required: * ```java + * .hasNextPage() * .items() * .page() * .pageSize() @@ -255,6 +289,7 @@ private constructor( */ fun build(): PaginatedDocumentResponse = PaginatedDocumentResponse( + checkRequired("hasNextPage", hasNextPage), checkRequired("items", items).map { it.toImmutable() }, checkRequired("page", page), checkRequired("pageSize", pageSize), @@ -271,6 +306,7 @@ private constructor( return@apply } + hasNextPage() items().forEach { it.validate() } page() pageSize() @@ -294,7 +330,8 @@ private constructor( */ @JvmSynthetic internal fun validity(): Int = - (items.asKnown().getOrNull()?.sumOf { it.validity().toInt() } ?: 0) + + (if (hasNextPage.asKnown().isPresent) 1 else 0) + + (items.asKnown().getOrNull()?.sumOf { it.validity().toInt() } ?: 0) + (if (page.asKnown().isPresent) 1 else 0) + (if (pageSize.asKnown().isPresent) 1 else 0) + (if (pages.asKnown().isPresent) 1 else 0) + @@ -306,6 +343,7 @@ private constructor( } return other is PaginatedDocumentResponse && + hasNextPage == other.hasNextPage && items == other.items && page == other.page && pageSize == other.pageSize && @@ -315,11 +353,11 @@ private constructor( } private val hashCode: Int by lazy { - Objects.hash(items, page, pageSize, pages, total, additionalProperties) + Objects.hash(hasNextPage, items, page, pageSize, pages, total, additionalProperties) } override fun hashCode(): Int = hashCode override fun toString() = - "PaginatedDocumentResponse{items=$items, page=$page, pageSize=$pageSize, pages=$pages, total=$total, additionalProperties=$additionalProperties}" + "PaginatedDocumentResponse{hasNextPage=$hasNextPage, items=$items, page=$page, pageSize=$pageSize, pages=$pages, total=$total, additionalProperties=$additionalProperties}" } diff --git a/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/models/lookup/LookupRetrieveResponse.kt b/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/models/lookup/LookupRetrieveResponse.kt index 0c9449a..91abeb9 100644 --- a/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/models/lookup/LookupRetrieveResponse.kt +++ b/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/models/lookup/LookupRetrieveResponse.kt @@ -1121,6 +1121,8 @@ private constructor( private val smlHostname: JsonField, private val status: JsonField, private val error: JsonField, + private val lookupMethod: JsonField, + private val smpHostname: JsonField, private val additionalProperties: MutableMap, ) { @@ -1134,7 +1136,13 @@ private constructor( smlHostname: JsonField = JsonMissing.of(), @JsonProperty("status") @ExcludeMissing status: JsonField = JsonMissing.of(), @JsonProperty("error") @ExcludeMissing error: JsonField = JsonMissing.of(), - ) : this(dnsRecords, smlHostname, status, error, mutableMapOf()) + @JsonProperty("lookupMethod") + @ExcludeMissing + lookupMethod: JsonField = JsonMissing.of(), + @JsonProperty("smpHostname") + @ExcludeMissing + smpHostname: JsonField = JsonMissing.of(), + ) : this(dnsRecords, smlHostname, status, error, lookupMethod, smpHostname, mutableMapOf()) /** * List of DNS records found for the Peppol participant @@ -1168,6 +1176,22 @@ private constructor( */ fun error(): Optional = error.getOptional("error") + /** + * DNS lookup method used: 'naptr' (new spec) or 'busdox' (legacy) + * + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun lookupMethod(): Optional = lookupMethod.getOptional("lookupMethod") + + /** + * Hostname of the SMP (Service Metadata Publisher) discovered via DNS + * + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun smpHostname(): Optional = smpHostname.getOptional("smpHostname") + /** * Returns the raw JSON value of [dnsRecords]. * @@ -1200,6 +1224,25 @@ private constructor( */ @JsonProperty("error") @ExcludeMissing fun _error(): JsonField = error + /** + * Returns the raw JSON value of [lookupMethod]. + * + * Unlike [lookupMethod], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("lookupMethod") + @ExcludeMissing + fun _lookupMethod(): JsonField = lookupMethod + + /** + * Returns the raw JSON value of [smpHostname]. + * + * Unlike [smpHostname], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("smpHostname") + @ExcludeMissing + fun _smpHostname(): JsonField = smpHostname + @JsonAnySetter private fun putAdditionalProperty(key: String, value: JsonValue) { additionalProperties.put(key, value) @@ -1234,6 +1277,8 @@ private constructor( private var smlHostname: JsonField? = null private var status: JsonField? = null private var error: JsonField = JsonMissing.of() + private var lookupMethod: JsonField = JsonMissing.of() + private var smpHostname: JsonField = JsonMissing.of() private var additionalProperties: MutableMap = mutableMapOf() @JvmSynthetic @@ -1242,6 +1287,8 @@ private constructor( smlHostname = dnsInfo.smlHostname status = dnsInfo.status error = dnsInfo.error + lookupMethod = dnsInfo.lookupMethod + smpHostname = dnsInfo.smpHostname additionalProperties = dnsInfo.additionalProperties.toMutableMap() } @@ -1312,6 +1359,42 @@ private constructor( */ fun error(error: JsonField) = apply { this.error = error } + /** DNS lookup method used: 'naptr' (new spec) or 'busdox' (legacy) */ + fun lookupMethod(lookupMethod: String?) = + lookupMethod(JsonField.ofNullable(lookupMethod)) + + /** Alias for calling [Builder.lookupMethod] with `lookupMethod.orElse(null)`. */ + fun lookupMethod(lookupMethod: Optional) = + lookupMethod(lookupMethod.getOrNull()) + + /** + * Sets [Builder.lookupMethod] to an arbitrary JSON value. + * + * You should usually call [Builder.lookupMethod] with a well-typed [String] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun lookupMethod(lookupMethod: JsonField) = apply { + this.lookupMethod = lookupMethod + } + + /** Hostname of the SMP (Service Metadata Publisher) discovered via DNS */ + fun smpHostname(smpHostname: String?) = smpHostname(JsonField.ofNullable(smpHostname)) + + /** Alias for calling [Builder.smpHostname] with `smpHostname.orElse(null)`. */ + fun smpHostname(smpHostname: Optional) = smpHostname(smpHostname.getOrNull()) + + /** + * Sets [Builder.smpHostname] to an arbitrary JSON value. + * + * You should usually call [Builder.smpHostname] with a well-typed [String] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun smpHostname(smpHostname: JsonField) = apply { + this.smpHostname = smpHostname + } + fun additionalProperties(additionalProperties: Map) = apply { this.additionalProperties.clear() putAllAdditionalProperties(additionalProperties) @@ -1351,6 +1434,8 @@ private constructor( checkRequired("smlHostname", smlHostname), checkRequired("status", status), error, + lookupMethod, + smpHostname, additionalProperties.toMutableMap(), ) } @@ -1366,6 +1451,8 @@ private constructor( smlHostname() status() error() + lookupMethod() + smpHostname() validated = true } @@ -1388,7 +1475,9 @@ private constructor( (dnsRecords.asKnown().getOrNull()?.sumOf { it.validity().toInt() } ?: 0) + (if (smlHostname.asKnown().isPresent) 1 else 0) + (if (status.asKnown().isPresent) 1 else 0) + - (if (error.asKnown().isPresent) 1 else 0) + (if (error.asKnown().isPresent) 1 else 0) + + (if (lookupMethod.asKnown().isPresent) 1 else 0) + + (if (smpHostname.asKnown().isPresent) 1 else 0) /** DNS record information for a Peppol participant. */ class DnsRecord @@ -1561,17 +1650,27 @@ private constructor( smlHostname == other.smlHostname && status == other.status && error == other.error && + lookupMethod == other.lookupMethod && + smpHostname == other.smpHostname && additionalProperties == other.additionalProperties } private val hashCode: Int by lazy { - Objects.hash(dnsRecords, smlHostname, status, error, additionalProperties) + Objects.hash( + dnsRecords, + smlHostname, + status, + error, + lookupMethod, + smpHostname, + additionalProperties, + ) } override fun hashCode(): Int = hashCode override fun toString() = - "DnsInfo{dnsRecords=$dnsRecords, smlHostname=$smlHostname, status=$status, error=$error, additionalProperties=$additionalProperties}" + "DnsInfo{dnsRecords=$dnsRecords, smlHostname=$smlHostname, status=$status, error=$error, lookupMethod=$lookupMethod, smpHostname=$smpHostname, additionalProperties=$additionalProperties}" } /** Metadata about the query that was performed */ diff --git a/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/models/me/MeRetrieveParams.kt b/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/models/me/MeRetrieveParams.kt new file mode 100644 index 0000000..fde28c1 --- /dev/null +++ b/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/models/me/MeRetrieveParams.kt @@ -0,0 +1,170 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.e_invoice.api.models.me + +import com.e_invoice.api.core.Params +import com.e_invoice.api.core.http.Headers +import com.e_invoice.api.core.http.QueryParams +import java.util.Objects + +/** Retrieve information about your account. */ +class MeRetrieveParams +private constructor( + private val additionalHeaders: Headers, + private val additionalQueryParams: QueryParams, +) : Params { + + /** Additional headers to send with the request. */ + fun _additionalHeaders(): Headers = additionalHeaders + + /** Additional query param to send with the request. */ + fun _additionalQueryParams(): QueryParams = additionalQueryParams + + fun toBuilder() = Builder().from(this) + + companion object { + + @JvmStatic fun none(): MeRetrieveParams = builder().build() + + /** Returns a mutable builder for constructing an instance of [MeRetrieveParams]. */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [MeRetrieveParams]. */ + class Builder internal constructor() { + + private var additionalHeaders: Headers.Builder = Headers.builder() + private var additionalQueryParams: QueryParams.Builder = QueryParams.builder() + + @JvmSynthetic + internal fun from(meRetrieveParams: MeRetrieveParams) = apply { + additionalHeaders = meRetrieveParams.additionalHeaders.toBuilder() + additionalQueryParams = meRetrieveParams.additionalQueryParams.toBuilder() + } + + fun additionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun additionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun putAdditionalHeader(name: String, value: String) = apply { + additionalHeaders.put(name, value) + } + + fun putAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.put(name, values) + } + + fun putAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun putAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun replaceAdditionalHeaders(name: String, value: String) = apply { + additionalHeaders.replace(name, value) + } + + fun replaceAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.replace(name, values) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun removeAdditionalHeaders(name: String) = apply { additionalHeaders.remove(name) } + + fun removeAllAdditionalHeaders(names: Set) = apply { + additionalHeaders.removeAll(names) + } + + fun additionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun additionalQueryParams(additionalQueryParams: Map>) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun putAdditionalQueryParam(key: String, value: String) = apply { + additionalQueryParams.put(key, value) + } + + fun putAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.put(key, values) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun replaceAdditionalQueryParams(key: String, value: String) = apply { + additionalQueryParams.replace(key, value) + } + + fun replaceAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.replace(key, values) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun removeAdditionalQueryParams(key: String) = apply { additionalQueryParams.remove(key) } + + fun removeAllAdditionalQueryParams(keys: Set) = apply { + additionalQueryParams.removeAll(keys) + } + + /** + * Returns an immutable instance of [MeRetrieveParams]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): MeRetrieveParams = + MeRetrieveParams(additionalHeaders.build(), additionalQueryParams.build()) + } + + override fun _headers(): Headers = additionalHeaders + + override fun _queryParams(): QueryParams = additionalQueryParams + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is MeRetrieveParams && + additionalHeaders == other.additionalHeaders && + additionalQueryParams == other.additionalQueryParams + } + + override fun hashCode(): Int = Objects.hash(additionalHeaders, additionalQueryParams) + + override fun toString() = + "MeRetrieveParams{additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams}" +} diff --git a/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/models/me/MeRetrieveResponse.kt b/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/models/me/MeRetrieveResponse.kt new file mode 100644 index 0000000..91e13de --- /dev/null +++ b/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/models/me/MeRetrieveResponse.kt @@ -0,0 +1,1077 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.e_invoice.api.models.me + +import com.e_invoice.api.core.Enum +import com.e_invoice.api.core.ExcludeMissing +import com.e_invoice.api.core.JsonField +import com.e_invoice.api.core.JsonMissing +import com.e_invoice.api.core.JsonValue +import com.e_invoice.api.core.checkKnown +import com.e_invoice.api.core.checkRequired +import com.e_invoice.api.core.toImmutable +import com.e_invoice.api.errors.EInvoiceInvalidDataException +import com.fasterxml.jackson.annotation.JsonAnyGetter +import com.fasterxml.jackson.annotation.JsonAnySetter +import com.fasterxml.jackson.annotation.JsonCreator +import com.fasterxml.jackson.annotation.JsonProperty +import java.time.OffsetDateTime +import java.util.Collections +import java.util.Objects +import java.util.Optional +import kotlin.jvm.optionals.getOrNull + +class MeRetrieveResponse +@JsonCreator(mode = JsonCreator.Mode.DISABLED) +private constructor( + private val name: JsonField, + private val bccRecipientEmail: JsonField, + private val companyAddress: JsonField, + private val companyCity: JsonField, + private val companyCountry: JsonField, + private val companyEmail: JsonField, + private val companyName: JsonField, + private val companyNumber: JsonField, + private val companyTaxId: JsonField, + private val companyZip: JsonField, + private val creditBalance: JsonField, + private val description: JsonField, + private val ibans: JsonField>, + private val peppolIds: JsonField>, + private val plan: JsonField, + private val smpRegistration: JsonField, + private val smpRegistrationDate: JsonField, + private val additionalProperties: MutableMap, +) { + + @JsonCreator + private constructor( + @JsonProperty("name") @ExcludeMissing name: JsonField = JsonMissing.of(), + @JsonProperty("bcc_recipient_email") + @ExcludeMissing + bccRecipientEmail: JsonField = JsonMissing.of(), + @JsonProperty("company_address") + @ExcludeMissing + companyAddress: JsonField = JsonMissing.of(), + @JsonProperty("company_city") + @ExcludeMissing + companyCity: JsonField = JsonMissing.of(), + @JsonProperty("company_country") + @ExcludeMissing + companyCountry: JsonField = JsonMissing.of(), + @JsonProperty("company_email") + @ExcludeMissing + companyEmail: JsonField = JsonMissing.of(), + @JsonProperty("company_name") + @ExcludeMissing + companyName: JsonField = JsonMissing.of(), + @JsonProperty("company_number") + @ExcludeMissing + companyNumber: JsonField = JsonMissing.of(), + @JsonProperty("company_tax_id") + @ExcludeMissing + companyTaxId: JsonField = JsonMissing.of(), + @JsonProperty("company_zip") + @ExcludeMissing + companyZip: JsonField = JsonMissing.of(), + @JsonProperty("credit_balance") + @ExcludeMissing + creditBalance: JsonField = JsonMissing.of(), + @JsonProperty("description") + @ExcludeMissing + description: JsonField = JsonMissing.of(), + @JsonProperty("ibans") @ExcludeMissing ibans: JsonField> = JsonMissing.of(), + @JsonProperty("peppol_ids") + @ExcludeMissing + peppolIds: JsonField> = JsonMissing.of(), + @JsonProperty("plan") @ExcludeMissing plan: JsonField = JsonMissing.of(), + @JsonProperty("smp_registration") + @ExcludeMissing + smpRegistration: JsonField = JsonMissing.of(), + @JsonProperty("smp_registration_date") + @ExcludeMissing + smpRegistrationDate: JsonField = JsonMissing.of(), + ) : this( + name, + bccRecipientEmail, + companyAddress, + companyCity, + companyCountry, + companyEmail, + companyName, + companyNumber, + companyTaxId, + companyZip, + creditBalance, + description, + ibans, + peppolIds, + plan, + smpRegistration, + smpRegistrationDate, + mutableMapOf(), + ) + + /** + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun name(): String = name.getRequired("name") + + /** + * BCC recipient email to deliver documents + * + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun bccRecipientEmail(): Optional = bccRecipientEmail.getOptional("bcc_recipient_email") + + /** + * Address of the company. Must be in the form of `Street Name Street Number` + * + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun companyAddress(): Optional = companyAddress.getOptional("company_address") + + /** + * City of the company + * + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun companyCity(): Optional = companyCity.getOptional("company_city") + + /** + * Country of the company + * + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun companyCountry(): Optional = companyCountry.getOptional("company_country") + + /** + * Email of the company + * + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun companyEmail(): Optional = companyEmail.getOptional("company_email") + + /** + * Name of the company. Must include the company type. For example: `BV`, `NV`, `CVBA`, `VOF` + * + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun companyName(): Optional = companyName.getOptional("company_name") + + /** + * Company number. For Belgium this is the CBE number or their EUID (European Unique Identifier) + * number + * + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun companyNumber(): Optional = companyNumber.getOptional("company_number") + + /** + * Company tax ID. For Belgium this is the VAT number. Must include the country prefix + * + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun companyTaxId(): Optional = companyTaxId.getOptional("company_tax_id") + + /** + * Zip code of the company + * + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun companyZip(): Optional = companyZip.getOptional("company_zip") + + /** + * Credit balance of the tenant + * + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun creditBalance(): Optional = creditBalance.getOptional("credit_balance") + + /** + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun description(): Optional = description.getOptional("description") + + /** + * IBANs of the tenant + * + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun ibans(): Optional> = ibans.getOptional("ibans") + + /** + * Peppol IDs of the tenant + * + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun peppolIds(): Optional> = peppolIds.getOptional("peppol_ids") + + /** + * Plan of the tenant + * + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun plan(): Optional = plan.getOptional("plan") + + /** + * Whether the tenant is registered on our SMP + * + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun smpRegistration(): Optional = smpRegistration.getOptional("smp_registration") + + /** + * Date when the tenant was registered on SMP + * + * @throws EInvoiceInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun smpRegistrationDate(): Optional = + smpRegistrationDate.getOptional("smp_registration_date") + + /** + * Returns the raw JSON value of [name]. + * + * Unlike [name], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("name") @ExcludeMissing fun _name(): JsonField = name + + /** + * Returns the raw JSON value of [bccRecipientEmail]. + * + * Unlike [bccRecipientEmail], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("bcc_recipient_email") + @ExcludeMissing + fun _bccRecipientEmail(): JsonField = bccRecipientEmail + + /** + * Returns the raw JSON value of [companyAddress]. + * + * Unlike [companyAddress], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("company_address") + @ExcludeMissing + fun _companyAddress(): JsonField = companyAddress + + /** + * Returns the raw JSON value of [companyCity]. + * + * Unlike [companyCity], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("company_city") + @ExcludeMissing + fun _companyCity(): JsonField = companyCity + + /** + * Returns the raw JSON value of [companyCountry]. + * + * Unlike [companyCountry], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("company_country") + @ExcludeMissing + fun _companyCountry(): JsonField = companyCountry + + /** + * Returns the raw JSON value of [companyEmail]. + * + * Unlike [companyEmail], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("company_email") + @ExcludeMissing + fun _companyEmail(): JsonField = companyEmail + + /** + * Returns the raw JSON value of [companyName]. + * + * Unlike [companyName], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("company_name") + @ExcludeMissing + fun _companyName(): JsonField = companyName + + /** + * Returns the raw JSON value of [companyNumber]. + * + * Unlike [companyNumber], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("company_number") + @ExcludeMissing + fun _companyNumber(): JsonField = companyNumber + + /** + * Returns the raw JSON value of [companyTaxId]. + * + * Unlike [companyTaxId], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("company_tax_id") + @ExcludeMissing + fun _companyTaxId(): JsonField = companyTaxId + + /** + * Returns the raw JSON value of [companyZip]. + * + * Unlike [companyZip], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("company_zip") @ExcludeMissing fun _companyZip(): JsonField = companyZip + + /** + * Returns the raw JSON value of [creditBalance]. + * + * Unlike [creditBalance], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("credit_balance") + @ExcludeMissing + fun _creditBalance(): JsonField = creditBalance + + /** + * Returns the raw JSON value of [description]. + * + * Unlike [description], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("description") @ExcludeMissing fun _description(): JsonField = description + + /** + * Returns the raw JSON value of [ibans]. + * + * Unlike [ibans], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("ibans") @ExcludeMissing fun _ibans(): JsonField> = ibans + + /** + * Returns the raw JSON value of [peppolIds]. + * + * Unlike [peppolIds], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("peppol_ids") + @ExcludeMissing + fun _peppolIds(): JsonField> = peppolIds + + /** + * Returns the raw JSON value of [plan]. + * + * Unlike [plan], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("plan") @ExcludeMissing fun _plan(): JsonField = plan + + /** + * Returns the raw JSON value of [smpRegistration]. + * + * Unlike [smpRegistration], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("smp_registration") + @ExcludeMissing + fun _smpRegistration(): JsonField = smpRegistration + + /** + * Returns the raw JSON value of [smpRegistrationDate]. + * + * Unlike [smpRegistrationDate], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("smp_registration_date") + @ExcludeMissing + fun _smpRegistrationDate(): JsonField = smpRegistrationDate + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of [MeRetrieveResponse]. + * + * The following fields are required: + * ```java + * .name() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [MeRetrieveResponse]. */ + class Builder internal constructor() { + + private var name: JsonField? = null + private var bccRecipientEmail: JsonField = JsonMissing.of() + private var companyAddress: JsonField = JsonMissing.of() + private var companyCity: JsonField = JsonMissing.of() + private var companyCountry: JsonField = JsonMissing.of() + private var companyEmail: JsonField = JsonMissing.of() + private var companyName: JsonField = JsonMissing.of() + private var companyNumber: JsonField = JsonMissing.of() + private var companyTaxId: JsonField = JsonMissing.of() + private var companyZip: JsonField = JsonMissing.of() + private var creditBalance: JsonField = JsonMissing.of() + private var description: JsonField = JsonMissing.of() + private var ibans: JsonField>? = null + private var peppolIds: JsonField>? = null + private var plan: JsonField = JsonMissing.of() + private var smpRegistration: JsonField = JsonMissing.of() + private var smpRegistrationDate: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(meRetrieveResponse: MeRetrieveResponse) = apply { + name = meRetrieveResponse.name + bccRecipientEmail = meRetrieveResponse.bccRecipientEmail + companyAddress = meRetrieveResponse.companyAddress + companyCity = meRetrieveResponse.companyCity + companyCountry = meRetrieveResponse.companyCountry + companyEmail = meRetrieveResponse.companyEmail + companyName = meRetrieveResponse.companyName + companyNumber = meRetrieveResponse.companyNumber + companyTaxId = meRetrieveResponse.companyTaxId + companyZip = meRetrieveResponse.companyZip + creditBalance = meRetrieveResponse.creditBalance + description = meRetrieveResponse.description + ibans = meRetrieveResponse.ibans.map { it.toMutableList() } + peppolIds = meRetrieveResponse.peppolIds.map { it.toMutableList() } + plan = meRetrieveResponse.plan + smpRegistration = meRetrieveResponse.smpRegistration + smpRegistrationDate = meRetrieveResponse.smpRegistrationDate + additionalProperties = meRetrieveResponse.additionalProperties.toMutableMap() + } + + fun name(name: String) = name(JsonField.of(name)) + + /** + * Sets [Builder.name] to an arbitrary JSON value. + * + * You should usually call [Builder.name] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun name(name: JsonField) = apply { this.name = name } + + /** BCC recipient email to deliver documents */ + fun bccRecipientEmail(bccRecipientEmail: String?) = + bccRecipientEmail(JsonField.ofNullable(bccRecipientEmail)) + + /** Alias for calling [Builder.bccRecipientEmail] with `bccRecipientEmail.orElse(null)`. */ + fun bccRecipientEmail(bccRecipientEmail: Optional) = + bccRecipientEmail(bccRecipientEmail.getOrNull()) + + /** + * Sets [Builder.bccRecipientEmail] to an arbitrary JSON value. + * + * You should usually call [Builder.bccRecipientEmail] with a well-typed [String] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun bccRecipientEmail(bccRecipientEmail: JsonField) = apply { + this.bccRecipientEmail = bccRecipientEmail + } + + /** Address of the company. Must be in the form of `Street Name Street Number` */ + fun companyAddress(companyAddress: String?) = + companyAddress(JsonField.ofNullable(companyAddress)) + + /** Alias for calling [Builder.companyAddress] with `companyAddress.orElse(null)`. */ + fun companyAddress(companyAddress: Optional) = + companyAddress(companyAddress.getOrNull()) + + /** + * Sets [Builder.companyAddress] to an arbitrary JSON value. + * + * You should usually call [Builder.companyAddress] with a well-typed [String] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun companyAddress(companyAddress: JsonField) = apply { + this.companyAddress = companyAddress + } + + /** City of the company */ + fun companyCity(companyCity: String?) = companyCity(JsonField.ofNullable(companyCity)) + + /** Alias for calling [Builder.companyCity] with `companyCity.orElse(null)`. */ + fun companyCity(companyCity: Optional) = companyCity(companyCity.getOrNull()) + + /** + * Sets [Builder.companyCity] to an arbitrary JSON value. + * + * You should usually call [Builder.companyCity] with a well-typed [String] value instead. + * This method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun companyCity(companyCity: JsonField) = apply { this.companyCity = companyCity } + + /** Country of the company */ + fun companyCountry(companyCountry: String?) = + companyCountry(JsonField.ofNullable(companyCountry)) + + /** Alias for calling [Builder.companyCountry] with `companyCountry.orElse(null)`. */ + fun companyCountry(companyCountry: Optional) = + companyCountry(companyCountry.getOrNull()) + + /** + * Sets [Builder.companyCountry] to an arbitrary JSON value. + * + * You should usually call [Builder.companyCountry] with a well-typed [String] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun companyCountry(companyCountry: JsonField) = apply { + this.companyCountry = companyCountry + } + + /** Email of the company */ + fun companyEmail(companyEmail: String?) = companyEmail(JsonField.ofNullable(companyEmail)) + + /** Alias for calling [Builder.companyEmail] with `companyEmail.orElse(null)`. */ + fun companyEmail(companyEmail: Optional) = companyEmail(companyEmail.getOrNull()) + + /** + * Sets [Builder.companyEmail] to an arbitrary JSON value. + * + * You should usually call [Builder.companyEmail] with a well-typed [String] value instead. + * This method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun companyEmail(companyEmail: JsonField) = apply { + this.companyEmail = companyEmail + } + + /** + * Name of the company. Must include the company type. For example: `BV`, `NV`, `CVBA`, + * `VOF` + */ + fun companyName(companyName: String?) = companyName(JsonField.ofNullable(companyName)) + + /** Alias for calling [Builder.companyName] with `companyName.orElse(null)`. */ + fun companyName(companyName: Optional) = companyName(companyName.getOrNull()) + + /** + * Sets [Builder.companyName] to an arbitrary JSON value. + * + * You should usually call [Builder.companyName] with a well-typed [String] value instead. + * This method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun companyName(companyName: JsonField) = apply { this.companyName = companyName } + + /** + * Company number. For Belgium this is the CBE number or their EUID (European Unique + * Identifier) number + */ + fun companyNumber(companyNumber: String?) = + companyNumber(JsonField.ofNullable(companyNumber)) + + /** Alias for calling [Builder.companyNumber] with `companyNumber.orElse(null)`. */ + fun companyNumber(companyNumber: Optional) = + companyNumber(companyNumber.getOrNull()) + + /** + * Sets [Builder.companyNumber] to an arbitrary JSON value. + * + * You should usually call [Builder.companyNumber] with a well-typed [String] value instead. + * This method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun companyNumber(companyNumber: JsonField) = apply { + this.companyNumber = companyNumber + } + + /** Company tax ID. For Belgium this is the VAT number. Must include the country prefix */ + fun companyTaxId(companyTaxId: String?) = companyTaxId(JsonField.ofNullable(companyTaxId)) + + /** Alias for calling [Builder.companyTaxId] with `companyTaxId.orElse(null)`. */ + fun companyTaxId(companyTaxId: Optional) = companyTaxId(companyTaxId.getOrNull()) + + /** + * Sets [Builder.companyTaxId] to an arbitrary JSON value. + * + * You should usually call [Builder.companyTaxId] with a well-typed [String] value instead. + * This method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun companyTaxId(companyTaxId: JsonField) = apply { + this.companyTaxId = companyTaxId + } + + /** Zip code of the company */ + fun companyZip(companyZip: String?) = companyZip(JsonField.ofNullable(companyZip)) + + /** Alias for calling [Builder.companyZip] with `companyZip.orElse(null)`. */ + fun companyZip(companyZip: Optional) = companyZip(companyZip.getOrNull()) + + /** + * Sets [Builder.companyZip] to an arbitrary JSON value. + * + * You should usually call [Builder.companyZip] with a well-typed [String] value instead. + * This method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun companyZip(companyZip: JsonField) = apply { this.companyZip = companyZip } + + /** Credit balance of the tenant */ + fun creditBalance(creditBalance: Long) = creditBalance(JsonField.of(creditBalance)) + + /** + * Sets [Builder.creditBalance] to an arbitrary JSON value. + * + * You should usually call [Builder.creditBalance] with a well-typed [Long] value instead. + * This method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun creditBalance(creditBalance: JsonField) = apply { + this.creditBalance = creditBalance + } + + fun description(description: String?) = description(JsonField.ofNullable(description)) + + /** Alias for calling [Builder.description] with `description.orElse(null)`. */ + fun description(description: Optional) = description(description.getOrNull()) + + /** + * Sets [Builder.description] to an arbitrary JSON value. + * + * You should usually call [Builder.description] with a well-typed [String] value instead. + * This method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun description(description: JsonField) = apply { this.description = description } + + /** IBANs of the tenant */ + fun ibans(ibans: List?) = ibans(JsonField.ofNullable(ibans)) + + /** Alias for calling [Builder.ibans] with `ibans.orElse(null)`. */ + fun ibans(ibans: Optional>) = ibans(ibans.getOrNull()) + + /** + * Sets [Builder.ibans] to an arbitrary JSON value. + * + * You should usually call [Builder.ibans] with a well-typed `List` value instead. + * This method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun ibans(ibans: JsonField>) = apply { + this.ibans = ibans.map { it.toMutableList() } + } + + /** + * Adds a single [String] to [ibans]. + * + * @throws IllegalStateException if the field was previously set to a non-list. + */ + fun addIban(iban: String) = apply { + ibans = + (ibans ?: JsonField.of(mutableListOf())).also { checkKnown("ibans", it).add(iban) } + } + + /** Peppol IDs of the tenant */ + fun peppolIds(peppolIds: List?) = peppolIds(JsonField.ofNullable(peppolIds)) + + /** Alias for calling [Builder.peppolIds] with `peppolIds.orElse(null)`. */ + fun peppolIds(peppolIds: Optional>) = peppolIds(peppolIds.getOrNull()) + + /** + * Sets [Builder.peppolIds] to an arbitrary JSON value. + * + * You should usually call [Builder.peppolIds] with a well-typed `List` value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun peppolIds(peppolIds: JsonField>) = apply { + this.peppolIds = peppolIds.map { it.toMutableList() } + } + + /** + * Adds a single [String] to [peppolIds]. + * + * @throws IllegalStateException if the field was previously set to a non-list. + */ + fun addPeppolId(peppolId: String) = apply { + peppolIds = + (peppolIds ?: JsonField.of(mutableListOf())).also { + checkKnown("peppolIds", it).add(peppolId) + } + } + + /** Plan of the tenant */ + fun plan(plan: Plan) = plan(JsonField.of(plan)) + + /** + * Sets [Builder.plan] to an arbitrary JSON value. + * + * You should usually call [Builder.plan] with a well-typed [Plan] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun plan(plan: JsonField) = apply { this.plan = plan } + + /** Whether the tenant is registered on our SMP */ + fun smpRegistration(smpRegistration: Boolean?) = + smpRegistration(JsonField.ofNullable(smpRegistration)) + + /** + * Alias for [Builder.smpRegistration]. + * + * This unboxed primitive overload exists for backwards compatibility. + */ + fun smpRegistration(smpRegistration: Boolean) = smpRegistration(smpRegistration as Boolean?) + + /** Alias for calling [Builder.smpRegistration] with `smpRegistration.orElse(null)`. */ + fun smpRegistration(smpRegistration: Optional) = + smpRegistration(smpRegistration.getOrNull()) + + /** + * Sets [Builder.smpRegistration] to an arbitrary JSON value. + * + * You should usually call [Builder.smpRegistration] with a well-typed [Boolean] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun smpRegistration(smpRegistration: JsonField) = apply { + this.smpRegistration = smpRegistration + } + + /** Date when the tenant was registered on SMP */ + fun smpRegistrationDate(smpRegistrationDate: OffsetDateTime?) = + smpRegistrationDate(JsonField.ofNullable(smpRegistrationDate)) + + /** + * Alias for calling [Builder.smpRegistrationDate] with `smpRegistrationDate.orElse(null)`. + */ + fun smpRegistrationDate(smpRegistrationDate: Optional) = + smpRegistrationDate(smpRegistrationDate.getOrNull()) + + /** + * Sets [Builder.smpRegistrationDate] to an arbitrary JSON value. + * + * You should usually call [Builder.smpRegistrationDate] with a well-typed [OffsetDateTime] + * value instead. This method is primarily for setting the field to an undocumented or not + * yet supported value. + */ + fun smpRegistrationDate(smpRegistrationDate: JsonField) = apply { + this.smpRegistrationDate = smpRegistrationDate + } + + fun additionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.clear() + putAllAdditionalProperties(additionalProperties) + } + + fun putAdditionalProperty(key: String, value: JsonValue) = apply { + additionalProperties.put(key, value) + } + + fun putAllAdditionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.putAll(additionalProperties) + } + + fun removeAdditionalProperty(key: String) = apply { additionalProperties.remove(key) } + + fun removeAllAdditionalProperties(keys: Set) = apply { + keys.forEach(::removeAdditionalProperty) + } + + /** + * Returns an immutable instance of [MeRetrieveResponse]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .name() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): MeRetrieveResponse = + MeRetrieveResponse( + checkRequired("name", name), + bccRecipientEmail, + companyAddress, + companyCity, + companyCountry, + companyEmail, + companyName, + companyNumber, + companyTaxId, + companyZip, + creditBalance, + description, + (ibans ?: JsonMissing.of()).map { it.toImmutable() }, + (peppolIds ?: JsonMissing.of()).map { it.toImmutable() }, + plan, + smpRegistration, + smpRegistrationDate, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + fun validate(): MeRetrieveResponse = apply { + if (validated) { + return@apply + } + + name() + bccRecipientEmail() + companyAddress() + companyCity() + companyCountry() + companyEmail() + companyName() + companyNumber() + companyTaxId() + companyZip() + creditBalance() + description() + ibans() + peppolIds() + plan().ifPresent { it.validate() } + smpRegistration() + smpRegistrationDate() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: EInvoiceInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic + internal fun validity(): Int = + (if (name.asKnown().isPresent) 1 else 0) + + (if (bccRecipientEmail.asKnown().isPresent) 1 else 0) + + (if (companyAddress.asKnown().isPresent) 1 else 0) + + (if (companyCity.asKnown().isPresent) 1 else 0) + + (if (companyCountry.asKnown().isPresent) 1 else 0) + + (if (companyEmail.asKnown().isPresent) 1 else 0) + + (if (companyName.asKnown().isPresent) 1 else 0) + + (if (companyNumber.asKnown().isPresent) 1 else 0) + + (if (companyTaxId.asKnown().isPresent) 1 else 0) + + (if (companyZip.asKnown().isPresent) 1 else 0) + + (if (creditBalance.asKnown().isPresent) 1 else 0) + + (if (description.asKnown().isPresent) 1 else 0) + + (ibans.asKnown().getOrNull()?.size ?: 0) + + (peppolIds.asKnown().getOrNull()?.size ?: 0) + + (plan.asKnown().getOrNull()?.validity() ?: 0) + + (if (smpRegistration.asKnown().isPresent) 1 else 0) + + (if (smpRegistrationDate.asKnown().isPresent) 1 else 0) + + /** Plan of the tenant */ + class Plan @JsonCreator private constructor(private val value: JsonField) : Enum { + + /** + * Returns this class instance's raw value. + * + * This is usually only useful if this instance was deserialized from data that doesn't + * match any known member, and you want to know that value. For example, if the SDK is on an + * older version than the API, then the API may respond with new members that the SDK is + * unaware of. + */ + @com.fasterxml.jackson.annotation.JsonValue fun _value(): JsonField = value + + companion object { + + @JvmField val STARTER = of("starter") + + @JvmField val PRO = of("pro") + + @JvmField val ENTERPRISE = of("enterprise") + + @JvmStatic fun of(value: String) = Plan(JsonField.of(value)) + } + + /** An enum containing [Plan]'s known values. */ + enum class Known { + STARTER, + PRO, + ENTERPRISE, + } + + /** + * An enum containing [Plan]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [Plan] can contain an unknown value in a couple of cases: + * - It was deserialized from data that doesn't match any known member. For example, if the + * SDK is on an older version than the API, then the API may respond with new members that + * the SDK is unaware of. + * - It was constructed with an arbitrary value using the [of] method. + */ + enum class Value { + STARTER, + PRO, + ENTERPRISE, + /** An enum member indicating that [Plan] was instantiated with an unknown value. */ + _UNKNOWN, + } + + /** + * Returns an enum member corresponding to this class instance's value, or [Value._UNKNOWN] + * if the class was instantiated with an unknown value. + * + * Use the [known] method instead if you're certain the value is always known or if you want + * to throw for the unknown case. + */ + fun value(): Value = + when (this) { + STARTER -> Value.STARTER + PRO -> Value.PRO + ENTERPRISE -> Value.ENTERPRISE + else -> Value._UNKNOWN + } + + /** + * Returns an enum member corresponding to this class instance's value. + * + * Use the [value] method instead if you're uncertain the value is always known and don't + * want to throw for the unknown case. + * + * @throws EInvoiceInvalidDataException if this class instance's value is a not a known + * member. + */ + fun known(): Known = + when (this) { + STARTER -> Known.STARTER + PRO -> Known.PRO + ENTERPRISE -> Known.ENTERPRISE + else -> throw EInvoiceInvalidDataException("Unknown Plan: $value") + } + + /** + * Returns this class instance's primitive wire representation. + * + * This differs from the [toString] method because that method is primarily for debugging + * and generally doesn't throw. + * + * @throws EInvoiceInvalidDataException if this class instance's value does not have the + * expected primitive type. + */ + fun asString(): String = + _value().asString().orElseThrow { + EInvoiceInvalidDataException("Value is not a String") + } + + private var validated: Boolean = false + + fun validate(): Plan = apply { + if (validated) { + return@apply + } + + known() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: EInvoiceInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic internal fun validity(): Int = if (value() == Value._UNKNOWN) 0 else 1 + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Plan && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is MeRetrieveResponse && + name == other.name && + bccRecipientEmail == other.bccRecipientEmail && + companyAddress == other.companyAddress && + companyCity == other.companyCity && + companyCountry == other.companyCountry && + companyEmail == other.companyEmail && + companyName == other.companyName && + companyNumber == other.companyNumber && + companyTaxId == other.companyTaxId && + companyZip == other.companyZip && + creditBalance == other.creditBalance && + description == other.description && + ibans == other.ibans && + peppolIds == other.peppolIds && + plan == other.plan && + smpRegistration == other.smpRegistration && + smpRegistrationDate == other.smpRegistrationDate && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash( + name, + bccRecipientEmail, + companyAddress, + companyCity, + companyCountry, + companyEmail, + companyName, + companyNumber, + companyTaxId, + companyZip, + creditBalance, + description, + ibans, + peppolIds, + plan, + smpRegistration, + smpRegistrationDate, + additionalProperties, + ) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "MeRetrieveResponse{name=$name, bccRecipientEmail=$bccRecipientEmail, companyAddress=$companyAddress, companyCity=$companyCity, companyCountry=$companyCountry, companyEmail=$companyEmail, companyName=$companyName, companyNumber=$companyNumber, companyTaxId=$companyTaxId, companyZip=$companyZip, creditBalance=$creditBalance, description=$description, ibans=$ibans, peppolIds=$peppolIds, plan=$plan, smpRegistration=$smpRegistration, smpRegistrationDate=$smpRegistrationDate, additionalProperties=$additionalProperties}" +} diff --git a/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/models/outbox/OutboxListDraftDocumentsPage.kt b/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/models/outbox/OutboxListDraftDocumentsPage.kt index f99adc8..40e8445 100644 --- a/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/models/outbox/OutboxListDraftDocumentsPage.kt +++ b/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/models/outbox/OutboxListDraftDocumentsPage.kt @@ -14,6 +14,7 @@ import kotlin.jvm.optionals.getOrDefault import kotlin.jvm.optionals.getOrNull /** @see OutboxService.listDraftDocuments */ +@Deprecated("deprecated") class OutboxListDraftDocumentsPage private constructor( private val service: OutboxService, @@ -56,8 +57,8 @@ private constructor( } val pageNumber = page().getOrDefault(1) - val pageCount = total().getOrDefault(Long.MAX_VALUE) - return pageNumber < pageCount + val pageCount = total().getOrNull() + return pageCount == null || pageNumber < pageCount } fun nextPageParams(): OutboxListDraftDocumentsParams { diff --git a/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/models/outbox/OutboxListDraftDocumentsPageAsync.kt b/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/models/outbox/OutboxListDraftDocumentsPageAsync.kt index f1757aa..88bd8f6 100644 --- a/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/models/outbox/OutboxListDraftDocumentsPageAsync.kt +++ b/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/models/outbox/OutboxListDraftDocumentsPageAsync.kt @@ -16,6 +16,7 @@ import kotlin.jvm.optionals.getOrDefault import kotlin.jvm.optionals.getOrNull /** @see OutboxServiceAsync.listDraftDocuments */ +@Deprecated("deprecated") class OutboxListDraftDocumentsPageAsync private constructor( private val service: OutboxServiceAsync, @@ -59,8 +60,8 @@ private constructor( } val pageNumber = page().getOrDefault(1) - val pageCount = total().getOrDefault(Long.MAX_VALUE) - return pageNumber < pageCount + val pageCount = total().getOrNull() + return pageCount == null || pageNumber < pageCount } fun nextPageParams(): OutboxListDraftDocumentsParams { diff --git a/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/models/outbox/OutboxListDraftDocumentsParams.kt b/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/models/outbox/OutboxListDraftDocumentsParams.kt index 0907192..d7c984a 100644 --- a/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/models/outbox/OutboxListDraftDocumentsParams.kt +++ b/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/models/outbox/OutboxListDraftDocumentsParams.kt @@ -2,18 +2,33 @@ package com.e_invoice.api.models.outbox +import com.e_invoice.api.core.Enum +import com.e_invoice.api.core.JsonField import com.e_invoice.api.core.Params import com.e_invoice.api.core.http.Headers import com.e_invoice.api.core.http.QueryParams +import com.e_invoice.api.errors.EInvoiceInvalidDataException +import com.e_invoice.api.models.documents.DocumentType +import com.e_invoice.api.models.inbox.DocumentState +import com.fasterxml.jackson.annotation.JsonCreator import java.util.Objects import java.util.Optional import kotlin.jvm.optionals.getOrNull -/** Retrieve a paginated list of draft documents with filtering options. */ +/** + * Retrieve a paginated list of draft documents with filtering options including state and text + * search. + */ +@Deprecated("deprecated") class OutboxListDraftDocumentsParams private constructor( private val page: Long?, private val pageSize: Long?, + private val search: String?, + private val sortBy: SortBy?, + private val sortOrder: SortOrder?, + private val state: DocumentState?, + private val type: DocumentType?, private val additionalHeaders: Headers, private val additionalQueryParams: QueryParams, ) : Params { @@ -24,6 +39,21 @@ private constructor( /** Number of items per page */ fun pageSize(): Optional = Optional.ofNullable(pageSize) + /** Search in invoice number, seller/buyer names */ + fun search(): Optional = Optional.ofNullable(search) + + /** Field to sort by */ + fun sortBy(): Optional = Optional.ofNullable(sortBy) + + /** Sort direction (asc/desc) */ + fun sortOrder(): Optional = Optional.ofNullable(sortOrder) + + /** Filter by document state */ + fun state(): Optional = Optional.ofNullable(state) + + /** Filter by document type */ + fun type(): Optional = Optional.ofNullable(type) + /** Additional headers to send with the request. */ fun _additionalHeaders(): Headers = additionalHeaders @@ -48,6 +78,11 @@ private constructor( private var page: Long? = null private var pageSize: Long? = null + private var search: String? = null + private var sortBy: SortBy? = null + private var sortOrder: SortOrder? = null + private var state: DocumentState? = null + private var type: DocumentType? = null private var additionalHeaders: Headers.Builder = Headers.builder() private var additionalQueryParams: QueryParams.Builder = QueryParams.builder() @@ -55,6 +90,11 @@ private constructor( internal fun from(outboxListDraftDocumentsParams: OutboxListDraftDocumentsParams) = apply { page = outboxListDraftDocumentsParams.page pageSize = outboxListDraftDocumentsParams.pageSize + search = outboxListDraftDocumentsParams.search + sortBy = outboxListDraftDocumentsParams.sortBy + sortOrder = outboxListDraftDocumentsParams.sortOrder + state = outboxListDraftDocumentsParams.state + type = outboxListDraftDocumentsParams.type additionalHeaders = outboxListDraftDocumentsParams.additionalHeaders.toBuilder() additionalQueryParams = outboxListDraftDocumentsParams.additionalQueryParams.toBuilder() } @@ -85,6 +125,36 @@ private constructor( /** Alias for calling [Builder.pageSize] with `pageSize.orElse(null)`. */ fun pageSize(pageSize: Optional) = pageSize(pageSize.getOrNull()) + /** Search in invoice number, seller/buyer names */ + fun search(search: String?) = apply { this.search = search } + + /** Alias for calling [Builder.search] with `search.orElse(null)`. */ + fun search(search: Optional) = search(search.getOrNull()) + + /** Field to sort by */ + fun sortBy(sortBy: SortBy?) = apply { this.sortBy = sortBy } + + /** Alias for calling [Builder.sortBy] with `sortBy.orElse(null)`. */ + fun sortBy(sortBy: Optional) = sortBy(sortBy.getOrNull()) + + /** Sort direction (asc/desc) */ + fun sortOrder(sortOrder: SortOrder?) = apply { this.sortOrder = sortOrder } + + /** Alias for calling [Builder.sortOrder] with `sortOrder.orElse(null)`. */ + fun sortOrder(sortOrder: Optional) = sortOrder(sortOrder.getOrNull()) + + /** Filter by document state */ + fun state(state: DocumentState?) = apply { this.state = state } + + /** Alias for calling [Builder.state] with `state.orElse(null)`. */ + fun state(state: Optional) = state(state.getOrNull()) + + /** Filter by document type */ + fun type(type: DocumentType?) = apply { this.type = type } + + /** Alias for calling [Builder.type] with `type.orElse(null)`. */ + fun type(type: Optional) = type(type.getOrNull()) + fun additionalHeaders(additionalHeaders: Headers) = apply { this.additionalHeaders.clear() putAllAdditionalHeaders(additionalHeaders) @@ -192,6 +262,11 @@ private constructor( OutboxListDraftDocumentsParams( page, pageSize, + search, + sortBy, + sortOrder, + state, + type, additionalHeaders.build(), additionalQueryParams.build(), ) @@ -204,10 +279,303 @@ private constructor( .apply { page?.let { put("page", it.toString()) } pageSize?.let { put("page_size", it.toString()) } + search?.let { put("search", it) } + sortBy?.let { put("sort_by", it.toString()) } + sortOrder?.let { put("sort_order", it.toString()) } + state?.let { put("state", it.toString()) } + type?.let { put("type", it.toString()) } putAll(additionalQueryParams) } .build() + /** Field to sort by */ + class SortBy @JsonCreator private constructor(private val value: JsonField) : Enum { + + /** + * Returns this class instance's raw value. + * + * This is usually only useful if this instance was deserialized from data that doesn't + * match any known member, and you want to know that value. For example, if the SDK is on an + * older version than the API, then the API may respond with new members that the SDK is + * unaware of. + */ + @com.fasterxml.jackson.annotation.JsonValue fun _value(): JsonField = value + + companion object { + + @JvmField val CREATED_AT = of("created_at") + + @JvmField val INVOICE_DATE = of("invoice_date") + + @JvmField val DUE_DATE = of("due_date") + + @JvmField val INVOICE_TOTAL = of("invoice_total") + + @JvmField val CUSTOMER_NAME = of("customer_name") + + @JvmField val VENDOR_NAME = of("vendor_name") + + @JvmField val INVOICE_ID = of("invoice_id") + + @JvmStatic fun of(value: String) = SortBy(JsonField.of(value)) + } + + /** An enum containing [SortBy]'s known values. */ + enum class Known { + CREATED_AT, + INVOICE_DATE, + DUE_DATE, + INVOICE_TOTAL, + CUSTOMER_NAME, + VENDOR_NAME, + INVOICE_ID, + } + + /** + * An enum containing [SortBy]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [SortBy] can contain an unknown value in a couple of cases: + * - It was deserialized from data that doesn't match any known member. For example, if the + * SDK is on an older version than the API, then the API may respond with new members that + * the SDK is unaware of. + * - It was constructed with an arbitrary value using the [of] method. + */ + enum class Value { + CREATED_AT, + INVOICE_DATE, + DUE_DATE, + INVOICE_TOTAL, + CUSTOMER_NAME, + VENDOR_NAME, + INVOICE_ID, + /** An enum member indicating that [SortBy] was instantiated with an unknown value. */ + _UNKNOWN, + } + + /** + * Returns an enum member corresponding to this class instance's value, or [Value._UNKNOWN] + * if the class was instantiated with an unknown value. + * + * Use the [known] method instead if you're certain the value is always known or if you want + * to throw for the unknown case. + */ + fun value(): Value = + when (this) { + CREATED_AT -> Value.CREATED_AT + INVOICE_DATE -> Value.INVOICE_DATE + DUE_DATE -> Value.DUE_DATE + INVOICE_TOTAL -> Value.INVOICE_TOTAL + CUSTOMER_NAME -> Value.CUSTOMER_NAME + VENDOR_NAME -> Value.VENDOR_NAME + INVOICE_ID -> Value.INVOICE_ID + else -> Value._UNKNOWN + } + + /** + * Returns an enum member corresponding to this class instance's value. + * + * Use the [value] method instead if you're uncertain the value is always known and don't + * want to throw for the unknown case. + * + * @throws EInvoiceInvalidDataException if this class instance's value is a not a known + * member. + */ + fun known(): Known = + when (this) { + CREATED_AT -> Known.CREATED_AT + INVOICE_DATE -> Known.INVOICE_DATE + DUE_DATE -> Known.DUE_DATE + INVOICE_TOTAL -> Known.INVOICE_TOTAL + CUSTOMER_NAME -> Known.CUSTOMER_NAME + VENDOR_NAME -> Known.VENDOR_NAME + INVOICE_ID -> Known.INVOICE_ID + else -> throw EInvoiceInvalidDataException("Unknown SortBy: $value") + } + + /** + * Returns this class instance's primitive wire representation. + * + * This differs from the [toString] method because that method is primarily for debugging + * and generally doesn't throw. + * + * @throws EInvoiceInvalidDataException if this class instance's value does not have the + * expected primitive type. + */ + fun asString(): String = + _value().asString().orElseThrow { + EInvoiceInvalidDataException("Value is not a String") + } + + private var validated: Boolean = false + + fun validate(): SortBy = apply { + if (validated) { + return@apply + } + + known() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: EInvoiceInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic internal fun validity(): Int = if (value() == Value._UNKNOWN) 0 else 1 + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is SortBy && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + /** Sort direction (asc/desc) */ + class SortOrder @JsonCreator private constructor(private val value: JsonField) : Enum { + + /** + * Returns this class instance's raw value. + * + * This is usually only useful if this instance was deserialized from data that doesn't + * match any known member, and you want to know that value. For example, if the SDK is on an + * older version than the API, then the API may respond with new members that the SDK is + * unaware of. + */ + @com.fasterxml.jackson.annotation.JsonValue fun _value(): JsonField = value + + companion object { + + @JvmField val ASC = of("asc") + + @JvmField val DESC = of("desc") + + @JvmStatic fun of(value: String) = SortOrder(JsonField.of(value)) + } + + /** An enum containing [SortOrder]'s known values. */ + enum class Known { + ASC, + DESC, + } + + /** + * An enum containing [SortOrder]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [SortOrder] can contain an unknown value in a couple of cases: + * - It was deserialized from data that doesn't match any known member. For example, if the + * SDK is on an older version than the API, then the API may respond with new members that + * the SDK is unaware of. + * - It was constructed with an arbitrary value using the [of] method. + */ + enum class Value { + ASC, + DESC, + /** + * An enum member indicating that [SortOrder] was instantiated with an unknown value. + */ + _UNKNOWN, + } + + /** + * Returns an enum member corresponding to this class instance's value, or [Value._UNKNOWN] + * if the class was instantiated with an unknown value. + * + * Use the [known] method instead if you're certain the value is always known or if you want + * to throw for the unknown case. + */ + fun value(): Value = + when (this) { + ASC -> Value.ASC + DESC -> Value.DESC + else -> Value._UNKNOWN + } + + /** + * Returns an enum member corresponding to this class instance's value. + * + * Use the [value] method instead if you're uncertain the value is always known and don't + * want to throw for the unknown case. + * + * @throws EInvoiceInvalidDataException if this class instance's value is a not a known + * member. + */ + fun known(): Known = + when (this) { + ASC -> Known.ASC + DESC -> Known.DESC + else -> throw EInvoiceInvalidDataException("Unknown SortOrder: $value") + } + + /** + * Returns this class instance's primitive wire representation. + * + * This differs from the [toString] method because that method is primarily for debugging + * and generally doesn't throw. + * + * @throws EInvoiceInvalidDataException if this class instance's value does not have the + * expected primitive type. + */ + fun asString(): String = + _value().asString().orElseThrow { + EInvoiceInvalidDataException("Value is not a String") + } + + private var validated: Boolean = false + + fun validate(): SortOrder = apply { + if (validated) { + return@apply + } + + known() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: EInvoiceInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic internal fun validity(): Int = if (value() == Value._UNKNOWN) 0 else 1 + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is SortOrder && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + override fun equals(other: Any?): Boolean { if (this === other) { return true @@ -216,13 +584,28 @@ private constructor( return other is OutboxListDraftDocumentsParams && page == other.page && pageSize == other.pageSize && + search == other.search && + sortBy == other.sortBy && + sortOrder == other.sortOrder && + state == other.state && + type == other.type && additionalHeaders == other.additionalHeaders && additionalQueryParams == other.additionalQueryParams } override fun hashCode(): Int = - Objects.hash(page, pageSize, additionalHeaders, additionalQueryParams) + Objects.hash( + page, + pageSize, + search, + sortBy, + sortOrder, + state, + type, + additionalHeaders, + additionalQueryParams, + ) override fun toString() = - "OutboxListDraftDocumentsParams{page=$page, pageSize=$pageSize, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams}" + "OutboxListDraftDocumentsParams{page=$page, pageSize=$pageSize, search=$search, sortBy=$sortBy, sortOrder=$sortOrder, state=$state, type=$type, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams}" } diff --git a/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/models/outbox/OutboxListReceivedDocumentsPage.kt b/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/models/outbox/OutboxListReceivedDocumentsPage.kt index 3c05d1b..d10118e 100644 --- a/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/models/outbox/OutboxListReceivedDocumentsPage.kt +++ b/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/models/outbox/OutboxListReceivedDocumentsPage.kt @@ -56,8 +56,8 @@ private constructor( } val pageNumber = page().getOrDefault(1) - val pageCount = total().getOrDefault(Long.MAX_VALUE) - return pageNumber < pageCount + val pageCount = total().getOrNull() + return pageCount == null || pageNumber < pageCount } fun nextPageParams(): OutboxListReceivedDocumentsParams { diff --git a/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/models/outbox/OutboxListReceivedDocumentsPageAsync.kt b/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/models/outbox/OutboxListReceivedDocumentsPageAsync.kt index 168fcdf..4517f3c 100644 --- a/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/models/outbox/OutboxListReceivedDocumentsPageAsync.kt +++ b/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/models/outbox/OutboxListReceivedDocumentsPageAsync.kt @@ -59,8 +59,8 @@ private constructor( } val pageNumber = page().getOrDefault(1) - val pageCount = total().getOrDefault(Long.MAX_VALUE) - return pageNumber < pageCount + val pageCount = total().getOrNull() + return pageCount == null || pageNumber < pageCount } fun nextPageParams(): OutboxListReceivedDocumentsParams { diff --git a/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/models/outbox/OutboxListReceivedDocumentsParams.kt b/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/models/outbox/OutboxListReceivedDocumentsParams.kt index 1439ad2..315ae20 100644 --- a/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/models/outbox/OutboxListReceivedDocumentsParams.kt +++ b/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/models/outbox/OutboxListReceivedDocumentsParams.kt @@ -2,11 +2,14 @@ package com.e_invoice.api.models.outbox +import com.e_invoice.api.core.Enum +import com.e_invoice.api.core.JsonField import com.e_invoice.api.core.Params import com.e_invoice.api.core.http.Headers import com.e_invoice.api.core.http.QueryParams +import com.e_invoice.api.errors.EInvoiceInvalidDataException import com.e_invoice.api.models.documents.DocumentType -import com.e_invoice.api.models.inbox.DocumentState +import com.fasterxml.jackson.annotation.JsonCreator import java.time.OffsetDateTime import java.time.format.DateTimeFormatter import java.util.Objects @@ -23,9 +26,11 @@ private constructor( private val dateTo: OffsetDateTime?, private val page: Long?, private val pageSize: Long?, + private val receiver: String?, private val search: String?, private val sender: String?, - private val state: DocumentState?, + private val sortBy: SortBy?, + private val sortOrder: SortOrder?, private val type: DocumentType?, private val additionalHeaders: Headers, private val additionalQueryParams: QueryParams, @@ -43,16 +48,25 @@ private constructor( /** Number of items per page */ fun pageSize(): Optional = Optional.ofNullable(pageSize) + /** + * Filter by receiver (customer_name, customer_email, customer_tax_id, customer_company_id, + * customer_id) + */ + fun receiver(): Optional = Optional.ofNullable(receiver) + /** Search in invoice number, seller/buyer names */ fun search(): Optional = Optional.ofNullable(search) - /** Filter by sender ID */ + /** (Deprecated) Filter by sender ID */ fun sender(): Optional = Optional.ofNullable(sender) - /** Filter by document state */ - fun state(): Optional = Optional.ofNullable(state) + /** Field to sort by */ + fun sortBy(): Optional = Optional.ofNullable(sortBy) + + /** Sort direction (asc/desc) */ + fun sortOrder(): Optional = Optional.ofNullable(sortOrder) - /** Filter by document type */ + /** Filter by document type. If not provided, returns all types. */ fun type(): Optional = Optional.ofNullable(type) /** Additional headers to send with the request. */ @@ -81,9 +95,11 @@ private constructor( private var dateTo: OffsetDateTime? = null private var page: Long? = null private var pageSize: Long? = null + private var receiver: String? = null private var search: String? = null private var sender: String? = null - private var state: DocumentState? = null + private var sortBy: SortBy? = null + private var sortOrder: SortOrder? = null private var type: DocumentType? = null private var additionalHeaders: Headers.Builder = Headers.builder() private var additionalQueryParams: QueryParams.Builder = QueryParams.builder() @@ -95,9 +111,11 @@ private constructor( dateTo = outboxListReceivedDocumentsParams.dateTo page = outboxListReceivedDocumentsParams.page pageSize = outboxListReceivedDocumentsParams.pageSize + receiver = outboxListReceivedDocumentsParams.receiver search = outboxListReceivedDocumentsParams.search sender = outboxListReceivedDocumentsParams.sender - state = outboxListReceivedDocumentsParams.state + sortBy = outboxListReceivedDocumentsParams.sortBy + sortOrder = outboxListReceivedDocumentsParams.sortOrder type = outboxListReceivedDocumentsParams.type additionalHeaders = outboxListReceivedDocumentsParams.additionalHeaders.toBuilder() additionalQueryParams = @@ -142,25 +160,40 @@ private constructor( /** Alias for calling [Builder.pageSize] with `pageSize.orElse(null)`. */ fun pageSize(pageSize: Optional) = pageSize(pageSize.getOrNull()) + /** + * Filter by receiver (customer_name, customer_email, customer_tax_id, customer_company_id, + * customer_id) + */ + fun receiver(receiver: String?) = apply { this.receiver = receiver } + + /** Alias for calling [Builder.receiver] with `receiver.orElse(null)`. */ + fun receiver(receiver: Optional) = receiver(receiver.getOrNull()) + /** Search in invoice number, seller/buyer names */ fun search(search: String?) = apply { this.search = search } /** Alias for calling [Builder.search] with `search.orElse(null)`. */ fun search(search: Optional) = search(search.getOrNull()) - /** Filter by sender ID */ + /** (Deprecated) Filter by sender ID */ fun sender(sender: String?) = apply { this.sender = sender } /** Alias for calling [Builder.sender] with `sender.orElse(null)`. */ fun sender(sender: Optional) = sender(sender.getOrNull()) - /** Filter by document state */ - fun state(state: DocumentState?) = apply { this.state = state } + /** Field to sort by */ + fun sortBy(sortBy: SortBy?) = apply { this.sortBy = sortBy } + + /** Alias for calling [Builder.sortBy] with `sortBy.orElse(null)`. */ + fun sortBy(sortBy: Optional) = sortBy(sortBy.getOrNull()) + + /** Sort direction (asc/desc) */ + fun sortOrder(sortOrder: SortOrder?) = apply { this.sortOrder = sortOrder } - /** Alias for calling [Builder.state] with `state.orElse(null)`. */ - fun state(state: Optional) = state(state.getOrNull()) + /** Alias for calling [Builder.sortOrder] with `sortOrder.orElse(null)`. */ + fun sortOrder(sortOrder: Optional) = sortOrder(sortOrder.getOrNull()) - /** Filter by document type */ + /** Filter by document type. If not provided, returns all types. */ fun type(type: DocumentType?) = apply { this.type = type } /** Alias for calling [Builder.type] with `type.orElse(null)`. */ @@ -275,9 +308,11 @@ private constructor( dateTo, page, pageSize, + receiver, search, sender, - state, + sortBy, + sortOrder, type, additionalHeaders.build(), additionalQueryParams.build(), @@ -295,14 +330,304 @@ private constructor( dateTo?.let { put("date_to", DateTimeFormatter.ISO_OFFSET_DATE_TIME.format(it)) } page?.let { put("page", it.toString()) } pageSize?.let { put("page_size", it.toString()) } + receiver?.let { put("receiver", it) } search?.let { put("search", it) } sender?.let { put("sender", it) } - state?.let { put("state", it.toString()) } + sortBy?.let { put("sort_by", it.toString()) } + sortOrder?.let { put("sort_order", it.toString()) } type?.let { put("type", it.toString()) } putAll(additionalQueryParams) } .build() + /** Field to sort by */ + class SortBy @JsonCreator private constructor(private val value: JsonField) : Enum { + + /** + * Returns this class instance's raw value. + * + * This is usually only useful if this instance was deserialized from data that doesn't + * match any known member, and you want to know that value. For example, if the SDK is on an + * older version than the API, then the API may respond with new members that the SDK is + * unaware of. + */ + @com.fasterxml.jackson.annotation.JsonValue fun _value(): JsonField = value + + companion object { + + @JvmField val CREATED_AT = of("created_at") + + @JvmField val INVOICE_DATE = of("invoice_date") + + @JvmField val DUE_DATE = of("due_date") + + @JvmField val INVOICE_TOTAL = of("invoice_total") + + @JvmField val CUSTOMER_NAME = of("customer_name") + + @JvmField val VENDOR_NAME = of("vendor_name") + + @JvmField val INVOICE_ID = of("invoice_id") + + @JvmStatic fun of(value: String) = SortBy(JsonField.of(value)) + } + + /** An enum containing [SortBy]'s known values. */ + enum class Known { + CREATED_AT, + INVOICE_DATE, + DUE_DATE, + INVOICE_TOTAL, + CUSTOMER_NAME, + VENDOR_NAME, + INVOICE_ID, + } + + /** + * An enum containing [SortBy]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [SortBy] can contain an unknown value in a couple of cases: + * - It was deserialized from data that doesn't match any known member. For example, if the + * SDK is on an older version than the API, then the API may respond with new members that + * the SDK is unaware of. + * - It was constructed with an arbitrary value using the [of] method. + */ + enum class Value { + CREATED_AT, + INVOICE_DATE, + DUE_DATE, + INVOICE_TOTAL, + CUSTOMER_NAME, + VENDOR_NAME, + INVOICE_ID, + /** An enum member indicating that [SortBy] was instantiated with an unknown value. */ + _UNKNOWN, + } + + /** + * Returns an enum member corresponding to this class instance's value, or [Value._UNKNOWN] + * if the class was instantiated with an unknown value. + * + * Use the [known] method instead if you're certain the value is always known or if you want + * to throw for the unknown case. + */ + fun value(): Value = + when (this) { + CREATED_AT -> Value.CREATED_AT + INVOICE_DATE -> Value.INVOICE_DATE + DUE_DATE -> Value.DUE_DATE + INVOICE_TOTAL -> Value.INVOICE_TOTAL + CUSTOMER_NAME -> Value.CUSTOMER_NAME + VENDOR_NAME -> Value.VENDOR_NAME + INVOICE_ID -> Value.INVOICE_ID + else -> Value._UNKNOWN + } + + /** + * Returns an enum member corresponding to this class instance's value. + * + * Use the [value] method instead if you're uncertain the value is always known and don't + * want to throw for the unknown case. + * + * @throws EInvoiceInvalidDataException if this class instance's value is a not a known + * member. + */ + fun known(): Known = + when (this) { + CREATED_AT -> Known.CREATED_AT + INVOICE_DATE -> Known.INVOICE_DATE + DUE_DATE -> Known.DUE_DATE + INVOICE_TOTAL -> Known.INVOICE_TOTAL + CUSTOMER_NAME -> Known.CUSTOMER_NAME + VENDOR_NAME -> Known.VENDOR_NAME + INVOICE_ID -> Known.INVOICE_ID + else -> throw EInvoiceInvalidDataException("Unknown SortBy: $value") + } + + /** + * Returns this class instance's primitive wire representation. + * + * This differs from the [toString] method because that method is primarily for debugging + * and generally doesn't throw. + * + * @throws EInvoiceInvalidDataException if this class instance's value does not have the + * expected primitive type. + */ + fun asString(): String = + _value().asString().orElseThrow { + EInvoiceInvalidDataException("Value is not a String") + } + + private var validated: Boolean = false + + fun validate(): SortBy = apply { + if (validated) { + return@apply + } + + known() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: EInvoiceInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic internal fun validity(): Int = if (value() == Value._UNKNOWN) 0 else 1 + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is SortBy && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + /** Sort direction (asc/desc) */ + class SortOrder @JsonCreator private constructor(private val value: JsonField) : Enum { + + /** + * Returns this class instance's raw value. + * + * This is usually only useful if this instance was deserialized from data that doesn't + * match any known member, and you want to know that value. For example, if the SDK is on an + * older version than the API, then the API may respond with new members that the SDK is + * unaware of. + */ + @com.fasterxml.jackson.annotation.JsonValue fun _value(): JsonField = value + + companion object { + + @JvmField val ASC = of("asc") + + @JvmField val DESC = of("desc") + + @JvmStatic fun of(value: String) = SortOrder(JsonField.of(value)) + } + + /** An enum containing [SortOrder]'s known values. */ + enum class Known { + ASC, + DESC, + } + + /** + * An enum containing [SortOrder]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [SortOrder] can contain an unknown value in a couple of cases: + * - It was deserialized from data that doesn't match any known member. For example, if the + * SDK is on an older version than the API, then the API may respond with new members that + * the SDK is unaware of. + * - It was constructed with an arbitrary value using the [of] method. + */ + enum class Value { + ASC, + DESC, + /** + * An enum member indicating that [SortOrder] was instantiated with an unknown value. + */ + _UNKNOWN, + } + + /** + * Returns an enum member corresponding to this class instance's value, or [Value._UNKNOWN] + * if the class was instantiated with an unknown value. + * + * Use the [known] method instead if you're certain the value is always known or if you want + * to throw for the unknown case. + */ + fun value(): Value = + when (this) { + ASC -> Value.ASC + DESC -> Value.DESC + else -> Value._UNKNOWN + } + + /** + * Returns an enum member corresponding to this class instance's value. + * + * Use the [value] method instead if you're uncertain the value is always known and don't + * want to throw for the unknown case. + * + * @throws EInvoiceInvalidDataException if this class instance's value is a not a known + * member. + */ + fun known(): Known = + when (this) { + ASC -> Known.ASC + DESC -> Known.DESC + else -> throw EInvoiceInvalidDataException("Unknown SortOrder: $value") + } + + /** + * Returns this class instance's primitive wire representation. + * + * This differs from the [toString] method because that method is primarily for debugging + * and generally doesn't throw. + * + * @throws EInvoiceInvalidDataException if this class instance's value does not have the + * expected primitive type. + */ + fun asString(): String = + _value().asString().orElseThrow { + EInvoiceInvalidDataException("Value is not a String") + } + + private var validated: Boolean = false + + fun validate(): SortOrder = apply { + if (validated) { + return@apply + } + + known() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: EInvoiceInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic internal fun validity(): Int = if (value() == Value._UNKNOWN) 0 else 1 + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is SortOrder && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + override fun equals(other: Any?): Boolean { if (this === other) { return true @@ -313,9 +638,11 @@ private constructor( dateTo == other.dateTo && page == other.page && pageSize == other.pageSize && + receiver == other.receiver && search == other.search && sender == other.sender && - state == other.state && + sortBy == other.sortBy && + sortOrder == other.sortOrder && type == other.type && additionalHeaders == other.additionalHeaders && additionalQueryParams == other.additionalQueryParams @@ -327,14 +654,16 @@ private constructor( dateTo, page, pageSize, + receiver, search, sender, - state, + sortBy, + sortOrder, type, additionalHeaders, additionalQueryParams, ) override fun toString() = - "OutboxListReceivedDocumentsParams{dateFrom=$dateFrom, dateTo=$dateTo, page=$page, pageSize=$pageSize, search=$search, sender=$sender, state=$state, type=$type, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams}" + "OutboxListReceivedDocumentsParams{dateFrom=$dateFrom, dateTo=$dateTo, page=$page, pageSize=$pageSize, receiver=$receiver, search=$search, sender=$sender, sortBy=$sortBy, sortOrder=$sortOrder, type=$type, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams}" } diff --git a/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/services/async/DocumentServiceAsync.kt b/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/services/async/DocumentServiceAsync.kt index 088f18d..2ad35b5 100644 --- a/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/services/async/DocumentServiceAsync.kt +++ b/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/services/async/DocumentServiceAsync.kt @@ -6,12 +6,16 @@ import com.e_invoice.api.core.ClientOptions import com.e_invoice.api.core.RequestOptions import com.e_invoice.api.core.http.HttpResponseFor import com.e_invoice.api.models.documents.DocumentCreate +import com.e_invoice.api.models.documents.DocumentCreateFromPdfParams +import com.e_invoice.api.models.documents.DocumentCreateFromPdfResponse import com.e_invoice.api.models.documents.DocumentCreateParams import com.e_invoice.api.models.documents.DocumentDeleteParams import com.e_invoice.api.models.documents.DocumentDeleteResponse import com.e_invoice.api.models.documents.DocumentResponse import com.e_invoice.api.models.documents.DocumentRetrieveParams import com.e_invoice.api.models.documents.DocumentSendParams +import com.e_invoice.api.models.documents.DocumentValidateParams +import com.e_invoice.api.models.validate.UblDocumentValidation import com.e_invoice.api.services.async.documents.AttachmentServiceAsync import com.e_invoice.api.services.async.documents.UblServiceAsync import java.util.concurrent.CompletableFuture @@ -129,7 +133,30 @@ interface DocumentServiceAsync { ): CompletableFuture = delete(documentId, DocumentDeleteParams.none(), requestOptions) - /** Send an invoice or credit note via Peppol */ + /** + * Create a new invoice or credit note from a PDF file. If the 'ubl_document' field is set in + * the response, it indicates that sufficient details were extracted from the PDF to + * automatically generate a valid UBL document ready for sending. If 'ubl_document' is not set, + * human intervention may be required to ensure compliance. + */ + fun createFromPdf( + params: DocumentCreateFromPdfParams + ): CompletableFuture = + createFromPdf(params, RequestOptions.none()) + + /** @see createFromPdf */ + fun createFromPdf( + params: DocumentCreateFromPdfParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture + + /** + * Send an invoice or credit note via Peppol. By default, the sender and receiver Peppol IDs are + * derived from the company (tax) IDs in the document, regardless of whether the document was + * created from a UBL with a different endpoint ID. To explicitly set the sender or receiver + * Peppol ID, provide them via the query parameters (sender_peppol_scheme, sender_peppol_id, + * receiver_peppol_scheme, receiver_peppol_id). + */ fun send(documentId: String): CompletableFuture = send(documentId, DocumentSendParams.none()) @@ -164,6 +191,42 @@ interface DocumentServiceAsync { ): CompletableFuture = send(documentId, DocumentSendParams.none(), requestOptions) + /** Validate a UBL document according to Peppol BIS Billing 3.0 */ + fun validate(documentId: String): CompletableFuture = + validate(documentId, DocumentValidateParams.none()) + + /** @see validate */ + fun validate( + documentId: String, + params: DocumentValidateParams = DocumentValidateParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture = + validate(params.toBuilder().documentId(documentId).build(), requestOptions) + + /** @see validate */ + fun validate( + documentId: String, + params: DocumentValidateParams = DocumentValidateParams.none(), + ): CompletableFuture = + validate(documentId, params, RequestOptions.none()) + + /** @see validate */ + fun validate( + params: DocumentValidateParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture + + /** @see validate */ + fun validate(params: DocumentValidateParams): CompletableFuture = + validate(params, RequestOptions.none()) + + /** @see validate */ + fun validate( + documentId: String, + requestOptions: RequestOptions, + ): CompletableFuture = + validate(documentId, DocumentValidateParams.none(), requestOptions) + /** * A view of [DocumentServiceAsync] that provides access to raw HTTP responses for each method. */ @@ -295,6 +358,21 @@ interface DocumentServiceAsync { ): CompletableFuture> = delete(documentId, DocumentDeleteParams.none(), requestOptions) + /** + * Returns a raw HTTP response for `post /api/documents/pdf`, but is otherwise the same as + * [DocumentServiceAsync.createFromPdf]. + */ + fun createFromPdf( + params: DocumentCreateFromPdfParams + ): CompletableFuture> = + createFromPdf(params, RequestOptions.none()) + + /** @see createFromPdf */ + fun createFromPdf( + params: DocumentCreateFromPdfParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture> + /** * Returns a raw HTTP response for `post /api/documents/{document_id}/send`, but is * otherwise the same as [DocumentServiceAsync.send]. @@ -333,5 +411,48 @@ interface DocumentServiceAsync { requestOptions: RequestOptions, ): CompletableFuture> = send(documentId, DocumentSendParams.none(), requestOptions) + + /** + * Returns a raw HTTP response for `post /api/documents/{document_id}/validate`, but is + * otherwise the same as [DocumentServiceAsync.validate]. + */ + fun validate( + documentId: String + ): CompletableFuture> = + validate(documentId, DocumentValidateParams.none()) + + /** @see validate */ + fun validate( + documentId: String, + params: DocumentValidateParams = DocumentValidateParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture> = + validate(params.toBuilder().documentId(documentId).build(), requestOptions) + + /** @see validate */ + fun validate( + documentId: String, + params: DocumentValidateParams = DocumentValidateParams.none(), + ): CompletableFuture> = + validate(documentId, params, RequestOptions.none()) + + /** @see validate */ + fun validate( + params: DocumentValidateParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture> + + /** @see validate */ + fun validate( + params: DocumentValidateParams + ): CompletableFuture> = + validate(params, RequestOptions.none()) + + /** @see validate */ + fun validate( + documentId: String, + requestOptions: RequestOptions, + ): CompletableFuture> = + validate(documentId, DocumentValidateParams.none(), requestOptions) } } diff --git a/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/services/async/DocumentServiceAsyncImpl.kt b/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/services/async/DocumentServiceAsyncImpl.kt index ec2198d..182c156 100644 --- a/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/services/async/DocumentServiceAsyncImpl.kt +++ b/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/services/async/DocumentServiceAsyncImpl.kt @@ -14,14 +14,19 @@ import com.e_invoice.api.core.http.HttpResponse import com.e_invoice.api.core.http.HttpResponse.Handler import com.e_invoice.api.core.http.HttpResponseFor import com.e_invoice.api.core.http.json +import com.e_invoice.api.core.http.multipartFormData import com.e_invoice.api.core.http.parseable import com.e_invoice.api.core.prepareAsync +import com.e_invoice.api.models.documents.DocumentCreateFromPdfParams +import com.e_invoice.api.models.documents.DocumentCreateFromPdfResponse import com.e_invoice.api.models.documents.DocumentCreateParams import com.e_invoice.api.models.documents.DocumentDeleteParams import com.e_invoice.api.models.documents.DocumentDeleteResponse import com.e_invoice.api.models.documents.DocumentResponse import com.e_invoice.api.models.documents.DocumentRetrieveParams import com.e_invoice.api.models.documents.DocumentSendParams +import com.e_invoice.api.models.documents.DocumentValidateParams +import com.e_invoice.api.models.validate.UblDocumentValidation import com.e_invoice.api.services.async.documents.AttachmentServiceAsync import com.e_invoice.api.services.async.documents.AttachmentServiceAsyncImpl import com.e_invoice.api.services.async.documents.UblServiceAsync @@ -73,6 +78,13 @@ class DocumentServiceAsyncImpl internal constructor(private val clientOptions: C // delete /api/documents/{document_id} withRawResponse().delete(params, requestOptions).thenApply { it.parse() } + override fun createFromPdf( + params: DocumentCreateFromPdfParams, + requestOptions: RequestOptions, + ): CompletableFuture = + // post /api/documents/pdf + withRawResponse().createFromPdf(params, requestOptions).thenApply { it.parse() } + override fun send( params: DocumentSendParams, requestOptions: RequestOptions, @@ -80,6 +92,13 @@ class DocumentServiceAsyncImpl internal constructor(private val clientOptions: C // post /api/documents/{document_id}/send withRawResponse().send(params, requestOptions).thenApply { it.parse() } + override fun validate( + params: DocumentValidateParams, + requestOptions: RequestOptions, + ): CompletableFuture = + // post /api/documents/{document_id}/validate + withRawResponse().validate(params, requestOptions).thenApply { it.parse() } + class WithRawResponseImpl internal constructor(private val clientOptions: ClientOptions) : DocumentServiceAsync.WithRawResponse { @@ -203,6 +222,37 @@ class DocumentServiceAsyncImpl internal constructor(private val clientOptions: C } } + private val createFromPdfHandler: Handler = + jsonHandler(clientOptions.jsonMapper) + + override fun createFromPdf( + params: DocumentCreateFromPdfParams, + requestOptions: RequestOptions, + ): CompletableFuture> { + val request = + HttpRequest.builder() + .method(HttpMethod.POST) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments("api", "documents", "pdf") + .body(multipartFormData(clientOptions.jsonMapper, params._body())) + .build() + .prepareAsync(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + return request + .thenComposeAsync { clientOptions.httpClient.executeAsync(it, requestOptions) } + .thenApply { response -> + errorHandler.handle(response).parseable { + response + .use { createFromPdfHandler.handle(it) } + .also { + if (requestOptions.responseValidation!!) { + it.validate() + } + } + } + } + } + private val sendHandler: Handler = jsonHandler(clientOptions.jsonMapper) @@ -236,5 +286,39 @@ class DocumentServiceAsyncImpl internal constructor(private val clientOptions: C } } } + + private val validateHandler: Handler = + jsonHandler(clientOptions.jsonMapper) + + override fun validate( + params: DocumentValidateParams, + requestOptions: RequestOptions, + ): CompletableFuture> { + // We check here instead of in the params builder because this can be specified + // positionally or in the params class. + checkRequired("documentId", params.documentId().getOrNull()) + val request = + HttpRequest.builder() + .method(HttpMethod.POST) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments("api", "documents", params._pathParam(0), "validate") + .apply { params._body().ifPresent { body(json(clientOptions.jsonMapper, it)) } } + .build() + .prepareAsync(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + return request + .thenComposeAsync { clientOptions.httpClient.executeAsync(it, requestOptions) } + .thenApply { response -> + errorHandler.handle(response).parseable { + response + .use { validateHandler.handle(it) } + .also { + if (requestOptions.responseValidation!!) { + it.validate() + } + } + } + } + } } } diff --git a/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/services/async/MeServiceAsync.kt b/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/services/async/MeServiceAsync.kt new file mode 100644 index 0000000..eaf8aa3 --- /dev/null +++ b/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/services/async/MeServiceAsync.kt @@ -0,0 +1,80 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.e_invoice.api.services.async + +import com.e_invoice.api.core.ClientOptions +import com.e_invoice.api.core.RequestOptions +import com.e_invoice.api.core.http.HttpResponseFor +import com.e_invoice.api.models.me.MeRetrieveParams +import com.e_invoice.api.models.me.MeRetrieveResponse +import java.util.concurrent.CompletableFuture +import java.util.function.Consumer + +interface MeServiceAsync { + + /** + * Returns a view of this service that provides access to raw HTTP responses for each method. + */ + fun withRawResponse(): WithRawResponse + + /** + * Returns a view of this service with the given option modifications applied. + * + * The original service is not modified. + */ + fun withOptions(modifier: Consumer): MeServiceAsync + + /** Retrieve information about your account. */ + fun retrieve(): CompletableFuture = retrieve(MeRetrieveParams.none()) + + /** @see retrieve */ + fun retrieve( + params: MeRetrieveParams = MeRetrieveParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture + + /** @see retrieve */ + fun retrieve( + params: MeRetrieveParams = MeRetrieveParams.none() + ): CompletableFuture = retrieve(params, RequestOptions.none()) + + /** @see retrieve */ + fun retrieve(requestOptions: RequestOptions): CompletableFuture = + retrieve(MeRetrieveParams.none(), requestOptions) + + /** A view of [MeServiceAsync] that provides access to raw HTTP responses for each method. */ + interface WithRawResponse { + + /** + * Returns a view of this service with the given option modifications applied. + * + * The original service is not modified. + */ + fun withOptions(modifier: Consumer): MeServiceAsync.WithRawResponse + + /** + * Returns a raw HTTP response for `get /api/me/`, but is otherwise the same as + * [MeServiceAsync.retrieve]. + */ + fun retrieve(): CompletableFuture> = + retrieve(MeRetrieveParams.none()) + + /** @see retrieve */ + fun retrieve( + params: MeRetrieveParams = MeRetrieveParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture> + + /** @see retrieve */ + fun retrieve( + params: MeRetrieveParams = MeRetrieveParams.none() + ): CompletableFuture> = + retrieve(params, RequestOptions.none()) + + /** @see retrieve */ + fun retrieve( + requestOptions: RequestOptions + ): CompletableFuture> = + retrieve(MeRetrieveParams.none(), requestOptions) + } +} diff --git a/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/services/async/MeServiceAsyncImpl.kt b/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/services/async/MeServiceAsyncImpl.kt new file mode 100644 index 0000000..47db487 --- /dev/null +++ b/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/services/async/MeServiceAsyncImpl.kt @@ -0,0 +1,84 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.e_invoice.api.services.async + +import com.e_invoice.api.core.ClientOptions +import com.e_invoice.api.core.RequestOptions +import com.e_invoice.api.core.handlers.errorBodyHandler +import com.e_invoice.api.core.handlers.errorHandler +import com.e_invoice.api.core.handlers.jsonHandler +import com.e_invoice.api.core.http.HttpMethod +import com.e_invoice.api.core.http.HttpRequest +import com.e_invoice.api.core.http.HttpResponse +import com.e_invoice.api.core.http.HttpResponse.Handler +import com.e_invoice.api.core.http.HttpResponseFor +import com.e_invoice.api.core.http.parseable +import com.e_invoice.api.core.prepareAsync +import com.e_invoice.api.models.me.MeRetrieveParams +import com.e_invoice.api.models.me.MeRetrieveResponse +import java.util.concurrent.CompletableFuture +import java.util.function.Consumer + +class MeServiceAsyncImpl internal constructor(private val clientOptions: ClientOptions) : + MeServiceAsync { + + private val withRawResponse: MeServiceAsync.WithRawResponse by lazy { + WithRawResponseImpl(clientOptions) + } + + override fun withRawResponse(): MeServiceAsync.WithRawResponse = withRawResponse + + override fun withOptions(modifier: Consumer): MeServiceAsync = + MeServiceAsyncImpl(clientOptions.toBuilder().apply(modifier::accept).build()) + + override fun retrieve( + params: MeRetrieveParams, + requestOptions: RequestOptions, + ): CompletableFuture = + // get /api/me/ + withRawResponse().retrieve(params, requestOptions).thenApply { it.parse() } + + class WithRawResponseImpl internal constructor(private val clientOptions: ClientOptions) : + MeServiceAsync.WithRawResponse { + + private val errorHandler: Handler = + errorHandler(errorBodyHandler(clientOptions.jsonMapper)) + + override fun withOptions( + modifier: Consumer + ): MeServiceAsync.WithRawResponse = + MeServiceAsyncImpl.WithRawResponseImpl( + clientOptions.toBuilder().apply(modifier::accept).build() + ) + + private val retrieveHandler: Handler = + jsonHandler(clientOptions.jsonMapper) + + override fun retrieve( + params: MeRetrieveParams, + requestOptions: RequestOptions, + ): CompletableFuture> { + val request = + HttpRequest.builder() + .method(HttpMethod.GET) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments("api", "me", "") + .build() + .prepareAsync(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + return request + .thenComposeAsync { clientOptions.httpClient.executeAsync(it, requestOptions) } + .thenApply { response -> + errorHandler.handle(response).parseable { + response + .use { retrieveHandler.handle(it) } + .also { + if (requestOptions.responseValidation!!) { + it.validate() + } + } + } + } + } + } +} diff --git a/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/services/async/OutboxServiceAsync.kt b/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/services/async/OutboxServiceAsync.kt index 70ed926..bc29152 100644 --- a/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/services/async/OutboxServiceAsync.kt +++ b/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/services/async/OutboxServiceAsync.kt @@ -26,23 +26,30 @@ interface OutboxServiceAsync { */ fun withOptions(modifier: Consumer): OutboxServiceAsync - /** Retrieve a paginated list of draft documents with filtering options. */ + /** + * Retrieve a paginated list of draft documents with filtering options including state and text + * search. + */ + @Deprecated("deprecated") fun listDraftDocuments(): CompletableFuture = listDraftDocuments(OutboxListDraftDocumentsParams.none()) /** @see listDraftDocuments */ + @Deprecated("deprecated") fun listDraftDocuments( params: OutboxListDraftDocumentsParams = OutboxListDraftDocumentsParams.none(), requestOptions: RequestOptions = RequestOptions.none(), ): CompletableFuture /** @see listDraftDocuments */ + @Deprecated("deprecated") fun listDraftDocuments( params: OutboxListDraftDocumentsParams = OutboxListDraftDocumentsParams.none() ): CompletableFuture = listDraftDocuments(params, RequestOptions.none()) /** @see listDraftDocuments */ + @Deprecated("deprecated") fun listDraftDocuments( requestOptions: RequestOptions ): CompletableFuture = @@ -91,23 +98,27 @@ interface OutboxServiceAsync { * Returns a raw HTTP response for `get /api/outbox/drafts`, but is otherwise the same as * [OutboxServiceAsync.listDraftDocuments]. */ + @Deprecated("deprecated") fun listDraftDocuments(): CompletableFuture> = listDraftDocuments(OutboxListDraftDocumentsParams.none()) /** @see listDraftDocuments */ + @Deprecated("deprecated") fun listDraftDocuments( params: OutboxListDraftDocumentsParams = OutboxListDraftDocumentsParams.none(), requestOptions: RequestOptions = RequestOptions.none(), ): CompletableFuture> /** @see listDraftDocuments */ + @Deprecated("deprecated") fun listDraftDocuments( params: OutboxListDraftDocumentsParams = OutboxListDraftDocumentsParams.none() ): CompletableFuture> = listDraftDocuments(params, RequestOptions.none()) /** @see listDraftDocuments */ + @Deprecated("deprecated") fun listDraftDocuments( requestOptions: RequestOptions ): CompletableFuture> = diff --git a/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/services/async/OutboxServiceAsyncImpl.kt b/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/services/async/OutboxServiceAsyncImpl.kt index f89c860..c1c0edd 100644 --- a/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/services/async/OutboxServiceAsyncImpl.kt +++ b/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/services/async/OutboxServiceAsyncImpl.kt @@ -34,6 +34,7 @@ class OutboxServiceAsyncImpl internal constructor(private val clientOptions: Cli override fun withOptions(modifier: Consumer): OutboxServiceAsync = OutboxServiceAsyncImpl(clientOptions.toBuilder().apply(modifier::accept).build()) + @Deprecated("deprecated") override fun listDraftDocuments( params: OutboxListDraftDocumentsParams, requestOptions: RequestOptions, @@ -64,6 +65,7 @@ class OutboxServiceAsyncImpl internal constructor(private val clientOptions: Cli private val listDraftDocumentsHandler: Handler = jsonHandler(clientOptions.jsonMapper) + @Deprecated("deprecated") override fun listDraftDocuments( params: OutboxListDraftDocumentsParams, requestOptions: RequestOptions, diff --git a/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/services/async/documents/AttachmentServiceAsync.kt b/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/services/async/documents/AttachmentServiceAsync.kt index 78bd70e..710113d 100644 --- a/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/services/async/documents/AttachmentServiceAsync.kt +++ b/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/services/async/documents/AttachmentServiceAsync.kt @@ -115,13 +115,19 @@ interface AttachmentServiceAsync { requestOptions: RequestOptions = RequestOptions.none(), ): CompletableFuture - /** Add a new attachment to an invoice or credit note */ + /** + * Add one or more attachments to an invoice. Be careful: the attachments ARE NOT ADDED to the + * UBL! They are only stored in our database and can be downloaded later. To add attachments to + * the UBL, you need to add the attachment(s) via POST /api/documents + */ + @Deprecated("deprecated") fun add( documentId: String, params: AttachmentAddParams, ): CompletableFuture = add(documentId, params, RequestOptions.none()) /** @see add */ + @Deprecated("deprecated") fun add( documentId: String, params: AttachmentAddParams, @@ -130,10 +136,12 @@ interface AttachmentServiceAsync { add(params.toBuilder().documentId(documentId).build(), requestOptions) /** @see add */ + @Deprecated("deprecated") fun add(params: AttachmentAddParams): CompletableFuture = add(params, RequestOptions.none()) /** @see add */ + @Deprecated("deprecated") fun add( params: AttachmentAddParams, requestOptions: RequestOptions = RequestOptions.none(), @@ -261,6 +269,7 @@ interface AttachmentServiceAsync { * Returns a raw HTTP response for `post /api/documents/{document_id}/attachments`, but is * otherwise the same as [AttachmentServiceAsync.add]. */ + @Deprecated("deprecated") fun add( documentId: String, params: AttachmentAddParams, @@ -268,6 +277,7 @@ interface AttachmentServiceAsync { add(documentId, params, RequestOptions.none()) /** @see add */ + @Deprecated("deprecated") fun add( documentId: String, params: AttachmentAddParams, @@ -276,12 +286,14 @@ interface AttachmentServiceAsync { add(params.toBuilder().documentId(documentId).build(), requestOptions) /** @see add */ + @Deprecated("deprecated") fun add( params: AttachmentAddParams ): CompletableFuture> = add(params, RequestOptions.none()) /** @see add */ + @Deprecated("deprecated") fun add( params: AttachmentAddParams, requestOptions: RequestOptions = RequestOptions.none(), diff --git a/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/services/async/documents/AttachmentServiceAsyncImpl.kt b/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/services/async/documents/AttachmentServiceAsyncImpl.kt index 162a1da..507877f 100644 --- a/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/services/async/documents/AttachmentServiceAsyncImpl.kt +++ b/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/services/async/documents/AttachmentServiceAsyncImpl.kt @@ -60,6 +60,7 @@ class AttachmentServiceAsyncImpl internal constructor(private val clientOptions: // delete /api/documents/{document_id}/attachments/{attachment_id} withRawResponse().delete(params, requestOptions).thenApply { it.parse() } + @Deprecated("deprecated") override fun add( params: AttachmentAddParams, requestOptions: RequestOptions, @@ -195,6 +196,7 @@ class AttachmentServiceAsyncImpl internal constructor(private val clientOptions: private val addHandler: Handler = jsonHandler(clientOptions.jsonMapper) + @Deprecated("deprecated") override fun add( params: AttachmentAddParams, requestOptions: RequestOptions, diff --git a/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/services/async/documents/UblServiceAsync.kt b/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/services/async/documents/UblServiceAsync.kt index a965f55..c1f5776 100644 --- a/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/services/async/documents/UblServiceAsync.kt +++ b/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/services/async/documents/UblServiceAsync.kt @@ -5,6 +5,8 @@ package com.e_invoice.api.services.async.documents import com.e_invoice.api.core.ClientOptions import com.e_invoice.api.core.RequestOptions import com.e_invoice.api.core.http.HttpResponseFor +import com.e_invoice.api.models.documents.DocumentResponse +import com.e_invoice.api.models.documents.ubl.UblCreateFromUblParams import com.e_invoice.api.models.documents.ubl.UblGetParams import com.e_invoice.api.models.documents.ubl.UblGetResponse import java.util.concurrent.CompletableFuture @@ -24,6 +26,16 @@ interface UblServiceAsync { */ fun withOptions(modifier: Consumer): UblServiceAsync + /** Create a new invoice or credit note from a UBL file */ + fun createFromUbl(params: UblCreateFromUblParams): CompletableFuture = + createFromUbl(params, RequestOptions.none()) + + /** @see createFromUbl */ + fun createFromUbl( + params: UblCreateFromUblParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture + /** Get the UBL for an invoice or credit note */ fun get(documentId: String): CompletableFuture = get(documentId, UblGetParams.none()) @@ -66,6 +78,21 @@ interface UblServiceAsync { */ fun withOptions(modifier: Consumer): UblServiceAsync.WithRawResponse + /** + * Returns a raw HTTP response for `post /api/documents/ubl`, but is otherwise the same as + * [UblServiceAsync.createFromUbl]. + */ + fun createFromUbl( + params: UblCreateFromUblParams + ): CompletableFuture> = + createFromUbl(params, RequestOptions.none()) + + /** @see createFromUbl */ + fun createFromUbl( + params: UblCreateFromUblParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture> + /** * Returns a raw HTTP response for `get /api/documents/{document_id}/ubl`, but is otherwise * the same as [UblServiceAsync.get]. diff --git a/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/services/async/documents/UblServiceAsyncImpl.kt b/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/services/async/documents/UblServiceAsyncImpl.kt index 75d1d1b..155f769 100644 --- a/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/services/async/documents/UblServiceAsyncImpl.kt +++ b/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/services/async/documents/UblServiceAsyncImpl.kt @@ -13,8 +13,11 @@ import com.e_invoice.api.core.http.HttpRequest import com.e_invoice.api.core.http.HttpResponse import com.e_invoice.api.core.http.HttpResponse.Handler import com.e_invoice.api.core.http.HttpResponseFor +import com.e_invoice.api.core.http.multipartFormData import com.e_invoice.api.core.http.parseable import com.e_invoice.api.core.prepareAsync +import com.e_invoice.api.models.documents.DocumentResponse +import com.e_invoice.api.models.documents.ubl.UblCreateFromUblParams import com.e_invoice.api.models.documents.ubl.UblGetParams import com.e_invoice.api.models.documents.ubl.UblGetResponse import java.util.concurrent.CompletableFuture @@ -33,6 +36,13 @@ class UblServiceAsyncImpl internal constructor(private val clientOptions: Client override fun withOptions(modifier: Consumer): UblServiceAsync = UblServiceAsyncImpl(clientOptions.toBuilder().apply(modifier::accept).build()) + override fun createFromUbl( + params: UblCreateFromUblParams, + requestOptions: RequestOptions, + ): CompletableFuture = + // post /api/documents/ubl + withRawResponse().createFromUbl(params, requestOptions).thenApply { it.parse() } + override fun get( params: UblGetParams, requestOptions: RequestOptions, @@ -53,6 +63,37 @@ class UblServiceAsyncImpl internal constructor(private val clientOptions: Client clientOptions.toBuilder().apply(modifier::accept).build() ) + private val createFromUblHandler: Handler = + jsonHandler(clientOptions.jsonMapper) + + override fun createFromUbl( + params: UblCreateFromUblParams, + requestOptions: RequestOptions, + ): CompletableFuture> { + val request = + HttpRequest.builder() + .method(HttpMethod.POST) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments("api", "documents", "ubl") + .body(multipartFormData(clientOptions.jsonMapper, params._body())) + .build() + .prepareAsync(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + return request + .thenComposeAsync { clientOptions.httpClient.executeAsync(it, requestOptions) } + .thenApply { response -> + errorHandler.handle(response).parseable { + response + .use { createFromUblHandler.handle(it) } + .also { + if (requestOptions.responseValidation!!) { + it.validate() + } + } + } + } + } + private val getHandler: Handler = jsonHandler(clientOptions.jsonMapper) diff --git a/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/services/blocking/DocumentService.kt b/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/services/blocking/DocumentService.kt index b6bb7b9..5ba74d0 100644 --- a/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/services/blocking/DocumentService.kt +++ b/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/services/blocking/DocumentService.kt @@ -6,12 +6,16 @@ import com.e_invoice.api.core.ClientOptions import com.e_invoice.api.core.RequestOptions import com.e_invoice.api.core.http.HttpResponseFor import com.e_invoice.api.models.documents.DocumentCreate +import com.e_invoice.api.models.documents.DocumentCreateFromPdfParams +import com.e_invoice.api.models.documents.DocumentCreateFromPdfResponse import com.e_invoice.api.models.documents.DocumentCreateParams import com.e_invoice.api.models.documents.DocumentDeleteParams import com.e_invoice.api.models.documents.DocumentDeleteResponse import com.e_invoice.api.models.documents.DocumentResponse import com.e_invoice.api.models.documents.DocumentRetrieveParams import com.e_invoice.api.models.documents.DocumentSendParams +import com.e_invoice.api.models.documents.DocumentValidateParams +import com.e_invoice.api.models.validate.UblDocumentValidation import com.e_invoice.api.services.blocking.documents.AttachmentService import com.e_invoice.api.services.blocking.documents.UblService import com.google.errorprone.annotations.MustBeClosed @@ -123,7 +127,28 @@ interface DocumentService { fun delete(documentId: String, requestOptions: RequestOptions): DocumentDeleteResponse = delete(documentId, DocumentDeleteParams.none(), requestOptions) - /** Send an invoice or credit note via Peppol */ + /** + * Create a new invoice or credit note from a PDF file. If the 'ubl_document' field is set in + * the response, it indicates that sufficient details were extracted from the PDF to + * automatically generate a valid UBL document ready for sending. If 'ubl_document' is not set, + * human intervention may be required to ensure compliance. + */ + fun createFromPdf(params: DocumentCreateFromPdfParams): DocumentCreateFromPdfResponse = + createFromPdf(params, RequestOptions.none()) + + /** @see createFromPdf */ + fun createFromPdf( + params: DocumentCreateFromPdfParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): DocumentCreateFromPdfResponse + + /** + * Send an invoice or credit note via Peppol. By default, the sender and receiver Peppol IDs are + * derived from the company (tax) IDs in the document, regardless of whether the document was + * created from a UBL with a different endpoint ID. To explicitly set the sender or receiver + * Peppol ID, provide them via the query parameters (sender_peppol_scheme, sender_peppol_id, + * receiver_peppol_scheme, receiver_peppol_id). + */ fun send(documentId: String): DocumentResponse = send(documentId, DocumentSendParams.none()) /** @see send */ @@ -152,6 +177,38 @@ interface DocumentService { fun send(documentId: String, requestOptions: RequestOptions): DocumentResponse = send(documentId, DocumentSendParams.none(), requestOptions) + /** Validate a UBL document according to Peppol BIS Billing 3.0 */ + fun validate(documentId: String): UblDocumentValidation = + validate(documentId, DocumentValidateParams.none()) + + /** @see validate */ + fun validate( + documentId: String, + params: DocumentValidateParams = DocumentValidateParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): UblDocumentValidation = + validate(params.toBuilder().documentId(documentId).build(), requestOptions) + + /** @see validate */ + fun validate( + documentId: String, + params: DocumentValidateParams = DocumentValidateParams.none(), + ): UblDocumentValidation = validate(documentId, params, RequestOptions.none()) + + /** @see validate */ + fun validate( + params: DocumentValidateParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): UblDocumentValidation + + /** @see validate */ + fun validate(params: DocumentValidateParams): UblDocumentValidation = + validate(params, RequestOptions.none()) + + /** @see validate */ + fun validate(documentId: String, requestOptions: RequestOptions): UblDocumentValidation = + validate(documentId, DocumentValidateParams.none(), requestOptions) + /** A view of [DocumentService] that provides access to raw HTTP responses for each method. */ interface WithRawResponse { @@ -286,6 +343,23 @@ interface DocumentService { ): HttpResponseFor = delete(documentId, DocumentDeleteParams.none(), requestOptions) + /** + * Returns a raw HTTP response for `post /api/documents/pdf`, but is otherwise the same as + * [DocumentService.createFromPdf]. + */ + @MustBeClosed + fun createFromPdf( + params: DocumentCreateFromPdfParams + ): HttpResponseFor = + createFromPdf(params, RequestOptions.none()) + + /** @see createFromPdf */ + @MustBeClosed + fun createFromPdf( + params: DocumentCreateFromPdfParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor + /** * Returns a raw HTTP response for `post /api/documents/{document_id}/send`, but is * otherwise the same as [DocumentService.send]. @@ -329,5 +403,50 @@ interface DocumentService { requestOptions: RequestOptions, ): HttpResponseFor = send(documentId, DocumentSendParams.none(), requestOptions) + + /** + * Returns a raw HTTP response for `post /api/documents/{document_id}/validate`, but is + * otherwise the same as [DocumentService.validate]. + */ + @MustBeClosed + fun validate(documentId: String): HttpResponseFor = + validate(documentId, DocumentValidateParams.none()) + + /** @see validate */ + @MustBeClosed + fun validate( + documentId: String, + params: DocumentValidateParams = DocumentValidateParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor = + validate(params.toBuilder().documentId(documentId).build(), requestOptions) + + /** @see validate */ + @MustBeClosed + fun validate( + documentId: String, + params: DocumentValidateParams = DocumentValidateParams.none(), + ): HttpResponseFor = + validate(documentId, params, RequestOptions.none()) + + /** @see validate */ + @MustBeClosed + fun validate( + params: DocumentValidateParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor + + /** @see validate */ + @MustBeClosed + fun validate(params: DocumentValidateParams): HttpResponseFor = + validate(params, RequestOptions.none()) + + /** @see validate */ + @MustBeClosed + fun validate( + documentId: String, + requestOptions: RequestOptions, + ): HttpResponseFor = + validate(documentId, DocumentValidateParams.none(), requestOptions) } } diff --git a/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/services/blocking/DocumentServiceImpl.kt b/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/services/blocking/DocumentServiceImpl.kt index 4b32b73..fc6ec56 100644 --- a/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/services/blocking/DocumentServiceImpl.kt +++ b/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/services/blocking/DocumentServiceImpl.kt @@ -14,14 +14,19 @@ import com.e_invoice.api.core.http.HttpResponse import com.e_invoice.api.core.http.HttpResponse.Handler import com.e_invoice.api.core.http.HttpResponseFor import com.e_invoice.api.core.http.json +import com.e_invoice.api.core.http.multipartFormData import com.e_invoice.api.core.http.parseable import com.e_invoice.api.core.prepare +import com.e_invoice.api.models.documents.DocumentCreateFromPdfParams +import com.e_invoice.api.models.documents.DocumentCreateFromPdfResponse import com.e_invoice.api.models.documents.DocumentCreateParams import com.e_invoice.api.models.documents.DocumentDeleteParams import com.e_invoice.api.models.documents.DocumentDeleteResponse import com.e_invoice.api.models.documents.DocumentResponse import com.e_invoice.api.models.documents.DocumentRetrieveParams import com.e_invoice.api.models.documents.DocumentSendParams +import com.e_invoice.api.models.documents.DocumentValidateParams +import com.e_invoice.api.models.validate.UblDocumentValidation import com.e_invoice.api.services.blocking.documents.AttachmentService import com.e_invoice.api.services.blocking.documents.AttachmentServiceImpl import com.e_invoice.api.services.blocking.documents.UblService @@ -70,6 +75,13 @@ class DocumentServiceImpl internal constructor(private val clientOptions: Client // delete /api/documents/{document_id} withRawResponse().delete(params, requestOptions).parse() + override fun createFromPdf( + params: DocumentCreateFromPdfParams, + requestOptions: RequestOptions, + ): DocumentCreateFromPdfResponse = + // post /api/documents/pdf + withRawResponse().createFromPdf(params, requestOptions).parse() + override fun send( params: DocumentSendParams, requestOptions: RequestOptions, @@ -77,6 +89,13 @@ class DocumentServiceImpl internal constructor(private val clientOptions: Client // post /api/documents/{document_id}/send withRawResponse().send(params, requestOptions).parse() + override fun validate( + params: DocumentValidateParams, + requestOptions: RequestOptions, + ): UblDocumentValidation = + // post /api/documents/{document_id}/validate + withRawResponse().validate(params, requestOptions).parse() + class WithRawResponseImpl internal constructor(private val clientOptions: ClientOptions) : DocumentService.WithRawResponse { @@ -191,6 +210,34 @@ class DocumentServiceImpl internal constructor(private val clientOptions: Client } } + private val createFromPdfHandler: Handler = + jsonHandler(clientOptions.jsonMapper) + + override fun createFromPdf( + params: DocumentCreateFromPdfParams, + requestOptions: RequestOptions, + ): HttpResponseFor { + val request = + HttpRequest.builder() + .method(HttpMethod.POST) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments("api", "documents", "pdf") + .body(multipartFormData(clientOptions.jsonMapper, params._body())) + .build() + .prepare(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + val response = clientOptions.httpClient.execute(request, requestOptions) + return errorHandler.handle(response).parseable { + response + .use { createFromPdfHandler.handle(it) } + .also { + if (requestOptions.responseValidation!!) { + it.validate() + } + } + } + } + private val sendHandler: Handler = jsonHandler(clientOptions.jsonMapper) @@ -221,5 +268,36 @@ class DocumentServiceImpl internal constructor(private val clientOptions: Client } } } + + private val validateHandler: Handler = + jsonHandler(clientOptions.jsonMapper) + + override fun validate( + params: DocumentValidateParams, + requestOptions: RequestOptions, + ): HttpResponseFor { + // We check here instead of in the params builder because this can be specified + // positionally or in the params class. + checkRequired("documentId", params.documentId().getOrNull()) + val request = + HttpRequest.builder() + .method(HttpMethod.POST) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments("api", "documents", params._pathParam(0), "validate") + .apply { params._body().ifPresent { body(json(clientOptions.jsonMapper, it)) } } + .build() + .prepare(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + val response = clientOptions.httpClient.execute(request, requestOptions) + return errorHandler.handle(response).parseable { + response + .use { validateHandler.handle(it) } + .also { + if (requestOptions.responseValidation!!) { + it.validate() + } + } + } + } } } diff --git a/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/services/blocking/MeService.kt b/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/services/blocking/MeService.kt new file mode 100644 index 0000000..f6de205 --- /dev/null +++ b/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/services/blocking/MeService.kt @@ -0,0 +1,79 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.e_invoice.api.services.blocking + +import com.e_invoice.api.core.ClientOptions +import com.e_invoice.api.core.RequestOptions +import com.e_invoice.api.core.http.HttpResponseFor +import com.e_invoice.api.models.me.MeRetrieveParams +import com.e_invoice.api.models.me.MeRetrieveResponse +import com.google.errorprone.annotations.MustBeClosed +import java.util.function.Consumer + +interface MeService { + + /** + * Returns a view of this service that provides access to raw HTTP responses for each method. + */ + fun withRawResponse(): WithRawResponse + + /** + * Returns a view of this service with the given option modifications applied. + * + * The original service is not modified. + */ + fun withOptions(modifier: Consumer): MeService + + /** Retrieve information about your account. */ + fun retrieve(): MeRetrieveResponse = retrieve(MeRetrieveParams.none()) + + /** @see retrieve */ + fun retrieve( + params: MeRetrieveParams = MeRetrieveParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): MeRetrieveResponse + + /** @see retrieve */ + fun retrieve(params: MeRetrieveParams = MeRetrieveParams.none()): MeRetrieveResponse = + retrieve(params, RequestOptions.none()) + + /** @see retrieve */ + fun retrieve(requestOptions: RequestOptions): MeRetrieveResponse = + retrieve(MeRetrieveParams.none(), requestOptions) + + /** A view of [MeService] that provides access to raw HTTP responses for each method. */ + interface WithRawResponse { + + /** + * Returns a view of this service with the given option modifications applied. + * + * The original service is not modified. + */ + fun withOptions(modifier: Consumer): MeService.WithRawResponse + + /** + * Returns a raw HTTP response for `get /api/me/`, but is otherwise the same as + * [MeService.retrieve]. + */ + @MustBeClosed + fun retrieve(): HttpResponseFor = retrieve(MeRetrieveParams.none()) + + /** @see retrieve */ + @MustBeClosed + fun retrieve( + params: MeRetrieveParams = MeRetrieveParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor + + /** @see retrieve */ + @MustBeClosed + fun retrieve( + params: MeRetrieveParams = MeRetrieveParams.none() + ): HttpResponseFor = retrieve(params, RequestOptions.none()) + + /** @see retrieve */ + @MustBeClosed + fun retrieve(requestOptions: RequestOptions): HttpResponseFor = + retrieve(MeRetrieveParams.none(), requestOptions) + } +} diff --git a/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/services/blocking/MeServiceImpl.kt b/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/services/blocking/MeServiceImpl.kt new file mode 100644 index 0000000..715fcbd --- /dev/null +++ b/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/services/blocking/MeServiceImpl.kt @@ -0,0 +1,79 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.e_invoice.api.services.blocking + +import com.e_invoice.api.core.ClientOptions +import com.e_invoice.api.core.RequestOptions +import com.e_invoice.api.core.handlers.errorBodyHandler +import com.e_invoice.api.core.handlers.errorHandler +import com.e_invoice.api.core.handlers.jsonHandler +import com.e_invoice.api.core.http.HttpMethod +import com.e_invoice.api.core.http.HttpRequest +import com.e_invoice.api.core.http.HttpResponse +import com.e_invoice.api.core.http.HttpResponse.Handler +import com.e_invoice.api.core.http.HttpResponseFor +import com.e_invoice.api.core.http.parseable +import com.e_invoice.api.core.prepare +import com.e_invoice.api.models.me.MeRetrieveParams +import com.e_invoice.api.models.me.MeRetrieveResponse +import java.util.function.Consumer + +class MeServiceImpl internal constructor(private val clientOptions: ClientOptions) : MeService { + + private val withRawResponse: MeService.WithRawResponse by lazy { + WithRawResponseImpl(clientOptions) + } + + override fun withRawResponse(): MeService.WithRawResponse = withRawResponse + + override fun withOptions(modifier: Consumer): MeService = + MeServiceImpl(clientOptions.toBuilder().apply(modifier::accept).build()) + + override fun retrieve( + params: MeRetrieveParams, + requestOptions: RequestOptions, + ): MeRetrieveResponse = + // get /api/me/ + withRawResponse().retrieve(params, requestOptions).parse() + + class WithRawResponseImpl internal constructor(private val clientOptions: ClientOptions) : + MeService.WithRawResponse { + + private val errorHandler: Handler = + errorHandler(errorBodyHandler(clientOptions.jsonMapper)) + + override fun withOptions( + modifier: Consumer + ): MeService.WithRawResponse = + MeServiceImpl.WithRawResponseImpl( + clientOptions.toBuilder().apply(modifier::accept).build() + ) + + private val retrieveHandler: Handler = + jsonHandler(clientOptions.jsonMapper) + + override fun retrieve( + params: MeRetrieveParams, + requestOptions: RequestOptions, + ): HttpResponseFor { + val request = + HttpRequest.builder() + .method(HttpMethod.GET) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments("api", "me", "") + .build() + .prepare(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + val response = clientOptions.httpClient.execute(request, requestOptions) + return errorHandler.handle(response).parseable { + response + .use { retrieveHandler.handle(it) } + .also { + if (requestOptions.responseValidation!!) { + it.validate() + } + } + } + } + } +} diff --git a/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/services/blocking/OutboxService.kt b/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/services/blocking/OutboxService.kt index ddb3045..397cbaa 100644 --- a/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/services/blocking/OutboxService.kt +++ b/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/services/blocking/OutboxService.kt @@ -26,22 +26,29 @@ interface OutboxService { */ fun withOptions(modifier: Consumer): OutboxService - /** Retrieve a paginated list of draft documents with filtering options. */ + /** + * Retrieve a paginated list of draft documents with filtering options including state and text + * search. + */ + @Deprecated("deprecated") fun listDraftDocuments(): OutboxListDraftDocumentsPage = listDraftDocuments(OutboxListDraftDocumentsParams.none()) /** @see listDraftDocuments */ + @Deprecated("deprecated") fun listDraftDocuments( params: OutboxListDraftDocumentsParams = OutboxListDraftDocumentsParams.none(), requestOptions: RequestOptions = RequestOptions.none(), ): OutboxListDraftDocumentsPage /** @see listDraftDocuments */ + @Deprecated("deprecated") fun listDraftDocuments( params: OutboxListDraftDocumentsParams = OutboxListDraftDocumentsParams.none() ): OutboxListDraftDocumentsPage = listDraftDocuments(params, RequestOptions.none()) /** @see listDraftDocuments */ + @Deprecated("deprecated") fun listDraftDocuments(requestOptions: RequestOptions): OutboxListDraftDocumentsPage = listDraftDocuments(OutboxListDraftDocumentsParams.none(), requestOptions) @@ -81,11 +88,13 @@ interface OutboxService { * Returns a raw HTTP response for `get /api/outbox/drafts`, but is otherwise the same as * [OutboxService.listDraftDocuments]. */ + @Deprecated("deprecated") @MustBeClosed fun listDraftDocuments(): HttpResponseFor = listDraftDocuments(OutboxListDraftDocumentsParams.none()) /** @see listDraftDocuments */ + @Deprecated("deprecated") @MustBeClosed fun listDraftDocuments( params: OutboxListDraftDocumentsParams = OutboxListDraftDocumentsParams.none(), @@ -93,6 +102,7 @@ interface OutboxService { ): HttpResponseFor /** @see listDraftDocuments */ + @Deprecated("deprecated") @MustBeClosed fun listDraftDocuments( params: OutboxListDraftDocumentsParams = OutboxListDraftDocumentsParams.none() @@ -100,6 +110,7 @@ interface OutboxService { listDraftDocuments(params, RequestOptions.none()) /** @see listDraftDocuments */ + @Deprecated("deprecated") @MustBeClosed fun listDraftDocuments( requestOptions: RequestOptions diff --git a/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/services/blocking/OutboxServiceImpl.kt b/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/services/blocking/OutboxServiceImpl.kt index d71a19e..ffe4da6 100644 --- a/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/services/blocking/OutboxServiceImpl.kt +++ b/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/services/blocking/OutboxServiceImpl.kt @@ -33,6 +33,7 @@ class OutboxServiceImpl internal constructor(private val clientOptions: ClientOp override fun withOptions(modifier: Consumer): OutboxService = OutboxServiceImpl(clientOptions.toBuilder().apply(modifier::accept).build()) + @Deprecated("deprecated") override fun listDraftDocuments( params: OutboxListDraftDocumentsParams, requestOptions: RequestOptions, @@ -63,6 +64,7 @@ class OutboxServiceImpl internal constructor(private val clientOptions: ClientOp private val listDraftDocumentsHandler: Handler = jsonHandler(clientOptions.jsonMapper) + @Deprecated("deprecated") override fun listDraftDocuments( params: OutboxListDraftDocumentsParams, requestOptions: RequestOptions, diff --git a/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/services/blocking/documents/AttachmentService.kt b/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/services/blocking/documents/AttachmentService.kt index bb9d834..6bd87a2 100644 --- a/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/services/blocking/documents/AttachmentService.kt +++ b/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/services/blocking/documents/AttachmentService.kt @@ -107,11 +107,17 @@ interface AttachmentService { requestOptions: RequestOptions = RequestOptions.none(), ): AttachmentDeleteResponse - /** Add a new attachment to an invoice or credit note */ + /** + * Add one or more attachments to an invoice. Be careful: the attachments ARE NOT ADDED to the + * UBL! They are only stored in our database and can be downloaded later. To add attachments to + * the UBL, you need to add the attachment(s) via POST /api/documents + */ + @Deprecated("deprecated") fun add(documentId: String, params: AttachmentAddParams): DocumentAttachment = add(documentId, params, RequestOptions.none()) /** @see add */ + @Deprecated("deprecated") fun add( documentId: String, params: AttachmentAddParams, @@ -119,9 +125,11 @@ interface AttachmentService { ): DocumentAttachment = add(params.toBuilder().documentId(documentId).build(), requestOptions) /** @see add */ + @Deprecated("deprecated") fun add(params: AttachmentAddParams): DocumentAttachment = add(params, RequestOptions.none()) /** @see add */ + @Deprecated("deprecated") fun add( params: AttachmentAddParams, requestOptions: RequestOptions = RequestOptions.none(), @@ -254,6 +262,7 @@ interface AttachmentService { * Returns a raw HTTP response for `post /api/documents/{document_id}/attachments`, but is * otherwise the same as [AttachmentService.add]. */ + @Deprecated("deprecated") @MustBeClosed fun add( documentId: String, @@ -261,6 +270,7 @@ interface AttachmentService { ): HttpResponseFor = add(documentId, params, RequestOptions.none()) /** @see add */ + @Deprecated("deprecated") @MustBeClosed fun add( documentId: String, @@ -270,11 +280,13 @@ interface AttachmentService { add(params.toBuilder().documentId(documentId).build(), requestOptions) /** @see add */ + @Deprecated("deprecated") @MustBeClosed fun add(params: AttachmentAddParams): HttpResponseFor = add(params, RequestOptions.none()) /** @see add */ + @Deprecated("deprecated") @MustBeClosed fun add( params: AttachmentAddParams, diff --git a/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/services/blocking/documents/AttachmentServiceImpl.kt b/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/services/blocking/documents/AttachmentServiceImpl.kt index 3aa1f15..a75ae6c 100644 --- a/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/services/blocking/documents/AttachmentServiceImpl.kt +++ b/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/services/blocking/documents/AttachmentServiceImpl.kt @@ -59,6 +59,7 @@ class AttachmentServiceImpl internal constructor(private val clientOptions: Clie // delete /api/documents/{document_id}/attachments/{attachment_id} withRawResponse().delete(params, requestOptions).parse() + @Deprecated("deprecated") override fun add( params: AttachmentAddParams, requestOptions: RequestOptions, @@ -185,6 +186,7 @@ class AttachmentServiceImpl internal constructor(private val clientOptions: Clie private val addHandler: Handler = jsonHandler(clientOptions.jsonMapper) + @Deprecated("deprecated") override fun add( params: AttachmentAddParams, requestOptions: RequestOptions, diff --git a/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/services/blocking/documents/UblService.kt b/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/services/blocking/documents/UblService.kt index b9d4d30..cab4bcd 100644 --- a/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/services/blocking/documents/UblService.kt +++ b/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/services/blocking/documents/UblService.kt @@ -5,6 +5,8 @@ package com.e_invoice.api.services.blocking.documents import com.e_invoice.api.core.ClientOptions import com.e_invoice.api.core.RequestOptions import com.e_invoice.api.core.http.HttpResponseFor +import com.e_invoice.api.models.documents.DocumentResponse +import com.e_invoice.api.models.documents.ubl.UblCreateFromUblParams import com.e_invoice.api.models.documents.ubl.UblGetParams import com.e_invoice.api.models.documents.ubl.UblGetResponse import com.google.errorprone.annotations.MustBeClosed @@ -24,6 +26,16 @@ interface UblService { */ fun withOptions(modifier: Consumer): UblService + /** Create a new invoice or credit note from a UBL file */ + fun createFromUbl(params: UblCreateFromUblParams): DocumentResponse = + createFromUbl(params, RequestOptions.none()) + + /** @see createFromUbl */ + fun createFromUbl( + params: UblCreateFromUblParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): DocumentResponse + /** Get the UBL for an invoice or credit note */ fun get(documentId: String): UblGetResponse = get(documentId, UblGetParams.none()) @@ -61,6 +73,21 @@ interface UblService { */ fun withOptions(modifier: Consumer): UblService.WithRawResponse + /** + * Returns a raw HTTP response for `post /api/documents/ubl`, but is otherwise the same as + * [UblService.createFromUbl]. + */ + @MustBeClosed + fun createFromUbl(params: UblCreateFromUblParams): HttpResponseFor = + createFromUbl(params, RequestOptions.none()) + + /** @see createFromUbl */ + @MustBeClosed + fun createFromUbl( + params: UblCreateFromUblParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor + /** * Returns a raw HTTP response for `get /api/documents/{document_id}/ubl`, but is otherwise * the same as [UblService.get]. diff --git a/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/services/blocking/documents/UblServiceImpl.kt b/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/services/blocking/documents/UblServiceImpl.kt index 746287a..a35c082 100644 --- a/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/services/blocking/documents/UblServiceImpl.kt +++ b/e-invoice-java-core/src/main/kotlin/com/e_invoice/api/services/blocking/documents/UblServiceImpl.kt @@ -13,8 +13,11 @@ import com.e_invoice.api.core.http.HttpRequest import com.e_invoice.api.core.http.HttpResponse import com.e_invoice.api.core.http.HttpResponse.Handler import com.e_invoice.api.core.http.HttpResponseFor +import com.e_invoice.api.core.http.multipartFormData import com.e_invoice.api.core.http.parseable import com.e_invoice.api.core.prepare +import com.e_invoice.api.models.documents.DocumentResponse +import com.e_invoice.api.models.documents.ubl.UblCreateFromUblParams import com.e_invoice.api.models.documents.ubl.UblGetParams import com.e_invoice.api.models.documents.ubl.UblGetResponse import java.util.function.Consumer @@ -31,6 +34,13 @@ class UblServiceImpl internal constructor(private val clientOptions: ClientOptio override fun withOptions(modifier: Consumer): UblService = UblServiceImpl(clientOptions.toBuilder().apply(modifier::accept).build()) + override fun createFromUbl( + params: UblCreateFromUblParams, + requestOptions: RequestOptions, + ): DocumentResponse = + // post /api/documents/ubl + withRawResponse().createFromUbl(params, requestOptions).parse() + override fun get(params: UblGetParams, requestOptions: RequestOptions): UblGetResponse = // get /api/documents/{document_id}/ubl withRawResponse().get(params, requestOptions).parse() @@ -48,6 +58,34 @@ class UblServiceImpl internal constructor(private val clientOptions: ClientOptio clientOptions.toBuilder().apply(modifier::accept).build() ) + private val createFromUblHandler: Handler = + jsonHandler(clientOptions.jsonMapper) + + override fun createFromUbl( + params: UblCreateFromUblParams, + requestOptions: RequestOptions, + ): HttpResponseFor { + val request = + HttpRequest.builder() + .method(HttpMethod.POST) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments("api", "documents", "ubl") + .body(multipartFormData(clientOptions.jsonMapper, params._body())) + .build() + .prepare(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + val response = clientOptions.httpClient.execute(request, requestOptions) + return errorHandler.handle(response).parseable { + response + .use { createFromUblHandler.handle(it) } + .also { + if (requestOptions.responseValidation!!) { + it.validate() + } + } + } + } + private val getHandler: Handler = jsonHandler(clientOptions.jsonMapper) diff --git a/e-invoice-java-core/src/test/kotlin/com/e_invoice/api/core/ObjectMappersTest.kt b/e-invoice-java-core/src/test/kotlin/com/e_invoice/api/core/ObjectMappersTest.kt index 7cb2251..f20d04a 100644 --- a/e-invoice-java-core/src/test/kotlin/com/e_invoice/api/core/ObjectMappersTest.kt +++ b/e-invoice-java-core/src/test/kotlin/com/e_invoice/api/core/ObjectMappersTest.kt @@ -3,12 +3,14 @@ package com.e_invoice.api.core import com.fasterxml.jackson.annotation.JsonProperty import com.fasterxml.jackson.databind.exc.MismatchedInputException import com.fasterxml.jackson.module.kotlin.readValue -import java.time.LocalDateTime +import java.time.LocalDate +import java.time.LocalTime +import java.time.OffsetDateTime +import java.time.ZoneOffset import kotlin.reflect.KClass import org.assertj.core.api.Assertions.assertThat import org.assertj.core.api.Assertions.catchThrowable import org.junit.jupiter.api.Test -import org.junit.jupiter.api.assertDoesNotThrow import org.junit.jupiter.params.ParameterizedTest import org.junit.jupiter.params.provider.EnumSource import org.junitpioneer.jupiter.cartesian.CartesianTest @@ -46,11 +48,7 @@ internal class ObjectMappersTest { val VALID_CONVERSIONS = listOf( FLOAT to DOUBLE, - FLOAT to INTEGER, - FLOAT to LONG, DOUBLE to FLOAT, - DOUBLE to INTEGER, - DOUBLE to LONG, INTEGER to FLOAT, INTEGER to DOUBLE, INTEGER to LONG, @@ -58,14 +56,6 @@ internal class ObjectMappersTest { LONG to DOUBLE, LONG to INTEGER, CLASS to MAP, - // These aren't actually valid, but coercion configs don't work for String until - // v2.14.0: https://github.com/FasterXML/jackson-databind/issues/3240 - // We currently test on v2.13.4. - BOOLEAN to STRING, - FLOAT to STRING, - DOUBLE to STRING, - INTEGER to STRING, - LONG to STRING, ) } } @@ -84,19 +74,44 @@ internal class ObjectMappersTest { } } - enum class LenientLocalDateTimeTestCase(val string: String) { - DATE("1998-04-21"), - DATE_TIME("1998-04-21T04:00:00"), - ZONED_DATE_TIME_1("1998-04-21T04:00:00+03:00"), - ZONED_DATE_TIME_2("1998-04-21T04:00:00Z"), + enum class LenientOffsetDateTimeTestCase( + val string: String, + val expectedOffsetDateTime: OffsetDateTime, + ) { + DATE( + "1998-04-21", + expectedOffsetDateTime = + OffsetDateTime.of(LocalDate.of(1998, 4, 21), LocalTime.of(0, 0), ZoneOffset.UTC), + ), + DATE_TIME( + "1998-04-21T04:00:00", + expectedOffsetDateTime = + OffsetDateTime.of(LocalDate.of(1998, 4, 21), LocalTime.of(4, 0), ZoneOffset.UTC), + ), + ZONED_DATE_TIME_1( + "1998-04-21T04:00:00+03:00", + expectedOffsetDateTime = + OffsetDateTime.of( + LocalDate.of(1998, 4, 21), + LocalTime.of(4, 0), + ZoneOffset.ofHours(3), + ), + ), + ZONED_DATE_TIME_2( + "1998-04-21T04:00:00Z", + expectedOffsetDateTime = + OffsetDateTime.of(LocalDate.of(1998, 4, 21), LocalTime.of(4, 0), ZoneOffset.UTC), + ), } @ParameterizedTest @EnumSource - fun readLocalDateTime_lenient(testCase: LenientLocalDateTimeTestCase) { + fun readOffsetDateTime_lenient(testCase: LenientOffsetDateTimeTestCase) { val jsonMapper = jsonMapper() val json = jsonMapper.writeValueAsString(testCase.string) - assertDoesNotThrow { jsonMapper().readValue(json) } + val offsetDateTime = jsonMapper().readValue(json) + + assertThat(offsetDateTime).isEqualTo(testCase.expectedOffsetDateTime) } } diff --git a/e-invoice-java-core/src/test/kotlin/com/e_invoice/api/core/http/HttpRequestTest.kt b/e-invoice-java-core/src/test/kotlin/com/e_invoice/api/core/http/HttpRequestTest.kt new file mode 100644 index 0000000..c85ec05 --- /dev/null +++ b/e-invoice-java-core/src/test/kotlin/com/e_invoice/api/core/http/HttpRequestTest.kt @@ -0,0 +1,110 @@ +package com.e_invoice.api.core.http + +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.params.ParameterizedTest +import org.junit.jupiter.params.provider.EnumSource + +internal class HttpRequestTest { + + enum class UrlTestCase(val request: HttpRequest, val expectedUrl: String) { + BASE_URL_ONLY( + HttpRequest.builder().method(HttpMethod.GET).baseUrl("https://api.example.com").build(), + expectedUrl = "https://api.example.com", + ), + BASE_URL_WITH_TRAILING_SLASH( + HttpRequest.builder() + .method(HttpMethod.GET) + .baseUrl("https://api.example.com/") + .build(), + expectedUrl = "https://api.example.com/", + ), + SINGLE_PATH_SEGMENT( + HttpRequest.builder() + .method(HttpMethod.GET) + .baseUrl("https://api.example.com") + .addPathSegment("users") + .build(), + expectedUrl = "https://api.example.com/users", + ), + MULTIPLE_PATH_SEGMENTS( + HttpRequest.builder() + .method(HttpMethod.GET) + .baseUrl("https://api.example.com") + .addPathSegments("users", "123", "profile") + .build(), + expectedUrl = "https://api.example.com/users/123/profile", + ), + PATH_SEGMENT_WITH_SPECIAL_CHARS( + HttpRequest.builder() + .method(HttpMethod.GET) + .baseUrl("https://api.example.com") + .addPathSegment("user name") + .build(), + expectedUrl = "https://api.example.com/user+name", + ), + SINGLE_QUERY_PARAM( + HttpRequest.builder() + .method(HttpMethod.GET) + .baseUrl("https://api.example.com") + .addPathSegment("users") + .putQueryParam("limit", "10") + .build(), + expectedUrl = "https://api.example.com/users?limit=10", + ), + MULTIPLE_QUERY_PARAMS( + HttpRequest.builder() + .method(HttpMethod.GET) + .baseUrl("https://api.example.com") + .addPathSegment("users") + .putQueryParam("limit", "10") + .putQueryParam("offset", "20") + .build(), + expectedUrl = "https://api.example.com/users?limit=10&offset=20", + ), + QUERY_PARAM_WITH_SPECIAL_CHARS( + HttpRequest.builder() + .method(HttpMethod.GET) + .baseUrl("https://api.example.com") + .addPathSegment("search") + .putQueryParam("q", "hello world") + .build(), + expectedUrl = "https://api.example.com/search?q=hello+world", + ), + MULTIPLE_VALUES_SAME_PARAM( + HttpRequest.builder() + .method(HttpMethod.GET) + .baseUrl("https://api.example.com") + .addPathSegment("users") + .putQueryParams("tags", listOf("admin", "user")) + .build(), + expectedUrl = "https://api.example.com/users?tags=admin&tags=user", + ), + BASE_URL_WITH_TRAILING_SLASH_AND_PATH( + HttpRequest.builder() + .method(HttpMethod.GET) + .baseUrl("https://api.example.com/") + .addPathSegment("users") + .build(), + expectedUrl = "https://api.example.com/users", + ), + COMPLEX_URL( + HttpRequest.builder() + .method(HttpMethod.POST) + .baseUrl("https://api.example.com") + .addPathSegments("v1", "users", "123") + .putQueryParams("include", listOf("profile", "settings")) + .putQueryParam("format", "json") + .build(), + expectedUrl = + "https://api.example.com/v1/users/123?include=profile&include=settings&format=json", + ), + } + + @ParameterizedTest + @EnumSource + fun url(testCase: UrlTestCase) { + val actualUrl = testCase.request.url() + + assertThat(actualUrl).isEqualTo(testCase.expectedUrl) + } +} diff --git a/e-invoice-java-core/src/test/kotlin/com/e_invoice/api/models/documents/AllowanceTest.kt b/e-invoice-java-core/src/test/kotlin/com/e_invoice/api/models/documents/AllowanceTest.kt new file mode 100644 index 0000000..ecb459f --- /dev/null +++ b/e-invoice-java-core/src/test/kotlin/com/e_invoice/api/models/documents/AllowanceTest.kt @@ -0,0 +1,56 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.e_invoice.api.models.documents + +import com.e_invoice.api.core.jsonMapper +import com.fasterxml.jackson.module.kotlin.jacksonTypeRef +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class AllowanceTest { + + @Test + fun create() { + val allowance = + Allowance.builder() + .amount("amount") + .baseAmount("base_amount") + .multiplierFactor("multiplier_factor") + .reason("reason") + .reasonCode(Allowance.ReasonCode._41) + .taxCode(Allowance.TaxCode.AE) + .taxRate("tax_rate") + .build() + + assertThat(allowance.amount()).contains("amount") + assertThat(allowance.baseAmount()).contains("base_amount") + assertThat(allowance.multiplierFactor()).contains("multiplier_factor") + assertThat(allowance.reason()).contains("reason") + assertThat(allowance.reasonCode()).contains(Allowance.ReasonCode._41) + assertThat(allowance.taxCode()).contains(Allowance.TaxCode.AE) + assertThat(allowance.taxRate()).contains("tax_rate") + } + + @Test + fun roundtrip() { + val jsonMapper = jsonMapper() + val allowance = + Allowance.builder() + .amount("amount") + .baseAmount("base_amount") + .multiplierFactor("multiplier_factor") + .reason("reason") + .reasonCode(Allowance.ReasonCode._41) + .taxCode(Allowance.TaxCode.AE) + .taxRate("tax_rate") + .build() + + val roundtrippedAllowance = + jsonMapper.readValue( + jsonMapper.writeValueAsString(allowance), + jacksonTypeRef(), + ) + + assertThat(roundtrippedAllowance).isEqualTo(allowance) + } +} diff --git a/e-invoice-java-core/src/test/kotlin/com/e_invoice/api/models/documents/ChargeTest.kt b/e-invoice-java-core/src/test/kotlin/com/e_invoice/api/models/documents/ChargeTest.kt new file mode 100644 index 0000000..f308f4e --- /dev/null +++ b/e-invoice-java-core/src/test/kotlin/com/e_invoice/api/models/documents/ChargeTest.kt @@ -0,0 +1,53 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.e_invoice.api.models.documents + +import com.e_invoice.api.core.jsonMapper +import com.fasterxml.jackson.module.kotlin.jacksonTypeRef +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class ChargeTest { + + @Test + fun create() { + val charge = + Charge.builder() + .amount("amount") + .baseAmount("base_amount") + .multiplierFactor("multiplier_factor") + .reason("reason") + .reasonCode(Charge.ReasonCode.AA) + .taxCode(Charge.TaxCode.AE) + .taxRate("21.00") + .build() + + assertThat(charge.amount()).contains("amount") + assertThat(charge.baseAmount()).contains("base_amount") + assertThat(charge.multiplierFactor()).contains("multiplier_factor") + assertThat(charge.reason()).contains("reason") + assertThat(charge.reasonCode()).contains(Charge.ReasonCode.AA) + assertThat(charge.taxCode()).contains(Charge.TaxCode.AE) + assertThat(charge.taxRate()).contains("21.00") + } + + @Test + fun roundtrip() { + val jsonMapper = jsonMapper() + val charge = + Charge.builder() + .amount("amount") + .baseAmount("base_amount") + .multiplierFactor("multiplier_factor") + .reason("reason") + .reasonCode(Charge.ReasonCode.AA) + .taxCode(Charge.TaxCode.AE) + .taxRate("21.00") + .build() + + val roundtrippedCharge = + jsonMapper.readValue(jsonMapper.writeValueAsString(charge), jacksonTypeRef()) + + assertThat(roundtrippedCharge).isEqualTo(charge) + } +} diff --git a/e-invoice-java-core/src/test/kotlin/com/e_invoice/api/models/documents/DocumentCreateFromPdfParamsTest.kt b/e-invoice-java-core/src/test/kotlin/com/e_invoice/api/models/documents/DocumentCreateFromPdfParamsTest.kt new file mode 100644 index 0000000..e644893 --- /dev/null +++ b/e-invoice-java-core/src/test/kotlin/com/e_invoice/api/models/documents/DocumentCreateFromPdfParamsTest.kt @@ -0,0 +1,101 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.e_invoice.api.models.documents + +import com.e_invoice.api.core.MultipartField +import com.e_invoice.api.core.http.QueryParams +import java.io.InputStream +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class DocumentCreateFromPdfParamsTest { + + @Test + fun create() { + DocumentCreateFromPdfParams.builder() + .customerTaxId("customer_tax_id") + .vendorTaxId("vendor_tax_id") + .file("some content".byteInputStream()) + .build() + } + + @Test + fun queryParams() { + val params = + DocumentCreateFromPdfParams.builder() + .customerTaxId("customer_tax_id") + .vendorTaxId("vendor_tax_id") + .file("some content".byteInputStream()) + .build() + + val queryParams = params._queryParams() + + assertThat(queryParams) + .isEqualTo( + QueryParams.builder() + .put("customer_tax_id", "customer_tax_id") + .put("vendor_tax_id", "vendor_tax_id") + .build() + ) + } + + @Test + fun queryParamsWithoutOptionalFields() { + val params = + DocumentCreateFromPdfParams.builder().file("some content".byteInputStream()).build() + + val queryParams = params._queryParams() + + assertThat(queryParams).isEqualTo(QueryParams.builder().build()) + } + + @Test + fun body() { + val params = + DocumentCreateFromPdfParams.builder() + .customerTaxId("customer_tax_id") + .vendorTaxId("vendor_tax_id") + .file("some content".byteInputStream()) + .build() + + val body = params._body() + + assertThat(body.filterValues { !it.value.isNull() }) + .usingRecursiveComparison() + // TODO(AssertJ): Replace this and the `mapValues` below with: + // https://github.com/assertj/assertj/issues/3165 + .withEqualsForType( + { a, b -> a.readBytes() contentEquals b.readBytes() }, + InputStream::class.java, + ) + .isEqualTo( + mapOf("file" to MultipartField.of("some content".byteInputStream())).mapValues { + (_, field) -> + field.map { (it as? ByteArray)?.inputStream() ?: it } + } + ) + } + + @Test + fun bodyWithoutOptionalFields() { + val params = + DocumentCreateFromPdfParams.builder().file("some content".byteInputStream()).build() + + val body = params._body() + + assertThat(body.filterValues { !it.value.isNull() }) + .usingRecursiveComparison() + // TODO(AssertJ): Replace this and the `mapValues` below with: + // https://github.com/assertj/assertj/issues/3165 + .withEqualsForType( + { a, b -> a.readBytes() contentEquals b.readBytes() }, + InputStream::class.java, + ) + .isEqualTo( + mapOf("file" to MultipartField.of("some content".byteInputStream())).mapValues { + (_, field) -> + field.map { (it as? ByteArray)?.inputStream() ?: it } + } + ) + } +} diff --git a/e-invoice-java-core/src/test/kotlin/com/e_invoice/api/models/documents/DocumentCreateFromPdfResponseTest.kt b/e-invoice-java-core/src/test/kotlin/com/e_invoice/api/models/documents/DocumentCreateFromPdfResponseTest.kt new file mode 100644 index 0000000..0b348a2 --- /dev/null +++ b/e-invoice-java-core/src/test/kotlin/com/e_invoice/api/models/documents/DocumentCreateFromPdfResponseTest.kt @@ -0,0 +1,422 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.e_invoice.api.models.documents + +import com.e_invoice.api.core.jsonMapper +import com.e_invoice.api.models.inbox.DocumentState +import com.fasterxml.jackson.module.kotlin.jacksonTypeRef +import java.time.LocalDate +import kotlin.jvm.optionals.getOrNull +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class DocumentCreateFromPdfResponseTest { + + @Test + fun create() { + val documentCreateFromPdfResponse = + DocumentCreateFromPdfResponse.builder() + .addAllowance( + Allowance.builder() + .amount("amount") + .baseAmount("base_amount") + .multiplierFactor("multiplier_factor") + .reason("reason") + .reasonCode(Allowance.ReasonCode._41) + .taxCode(Allowance.TaxCode.AE) + .taxRate("tax_rate") + .build() + ) + .amountDue("amount_due") + .addAttachment( + DocumentAttachmentCreate.builder() + .fileName("file_name") + .fileData("file_data") + .fileSize(0L) + .fileType("file_type") + .build() + ) + .billingAddress("billing_address") + .billingAddressRecipient("billing_address_recipient") + .addCharge( + Charge.builder() + .amount("amount") + .baseAmount("base_amount") + .multiplierFactor("multiplier_factor") + .reason("reason") + .reasonCode(Charge.ReasonCode.AA) + .taxCode(Charge.TaxCode.AE) + .taxRate("21.00") + .build() + ) + .currency(CurrencyCode.EUR) + .customerAddress("customer_address") + .customerAddressRecipient("customer_address_recipient") + .customerCompanyId("1018265814") + .customerEmail("customer_email") + .customerId("customer_id") + .customerName("customer_name") + .customerTaxId("BE1018265814") + .direction(DocumentDirection.INBOUND) + .documentType(DocumentType.INVOICE) + .dueDate(LocalDate.parse("2019-12-27")) + .invoiceDate(LocalDate.parse("2019-12-27")) + .invoiceId("invoice_id") + .invoiceTotal("invoice_total") + .addItem( + DocumentCreateFromPdfResponse.Item.builder() + .addAllowance( + Allowance.builder() + .amount("amount") + .baseAmount("base_amount") + .multiplierFactor("multiplier_factor") + .reason("reason") + .reasonCode(Allowance.ReasonCode._41) + .taxCode(Allowance.TaxCode.AE) + .taxRate("tax_rate") + .build() + ) + .amount("amount") + .addCharge( + Charge.builder() + .amount("amount") + .baseAmount("base_amount") + .multiplierFactor("multiplier_factor") + .reason("reason") + .reasonCode(Charge.ReasonCode.AA) + .taxCode(Charge.TaxCode.AE) + .taxRate("21.00") + .build() + ) + .date(null) + .description("description") + .productCode("product_code") + .quantity("quantity") + .tax("tax") + .taxRate("21.00") + .unit(UnitOfMeasureCode._10) + .unitPrice("unit_price") + .build() + ) + .note("note") + .addPaymentDetail( + PaymentDetailCreate.builder() + .bankAccountNumber("bank_account_number") + .iban("iban") + .paymentReference("payment_reference") + .swift("swift") + .build() + ) + .paymentTerm("payment_term") + .purchaseOrder("purchase_order") + .remittanceAddress("remittance_address") + .remittanceAddressRecipient("remittance_address_recipient") + .serviceAddress("service_address") + .serviceAddressRecipient("service_address_recipient") + .serviceEndDate(LocalDate.parse("2019-12-27")) + .serviceStartDate(LocalDate.parse("2019-12-27")) + .shippingAddress("shipping_address") + .shippingAddressRecipient("shipping_address_recipient") + .state(DocumentState.DRAFT) + .subtotal("subtotal") + .success(true) + .taxCode(DocumentCreateFromPdfResponse.TaxCode.AE) + .addTaxDetail( + DocumentCreateFromPdfResponse.TaxDetail.builder() + .amount("amount") + .rate("rate") + .build() + ) + .totalDiscount("total_discount") + .totalTax("total_tax") + .ublDocument("ubl_document") + .vatex(DocumentCreateFromPdfResponse.Vatex.VATEX_EU_79_C) + .vatexNote("vatex_note") + .vendorAddress("vendor_address") + .vendorAddressRecipient("vendor_address_recipient") + .vendorCompanyId("1018265814") + .vendorEmail("vendor_email") + .vendorName("vendor_name") + .vendorTaxId("BE1018265814") + .build() + + assertThat(documentCreateFromPdfResponse.allowances().getOrNull()) + .containsExactly( + Allowance.builder() + .amount("amount") + .baseAmount("base_amount") + .multiplierFactor("multiplier_factor") + .reason("reason") + .reasonCode(Allowance.ReasonCode._41) + .taxCode(Allowance.TaxCode.AE) + .taxRate("tax_rate") + .build() + ) + assertThat(documentCreateFromPdfResponse.amountDue()).contains("amount_due") + assertThat(documentCreateFromPdfResponse.attachments().getOrNull()) + .containsExactly( + DocumentAttachmentCreate.builder() + .fileName("file_name") + .fileData("file_data") + .fileSize(0L) + .fileType("file_type") + .build() + ) + assertThat(documentCreateFromPdfResponse.billingAddress()).contains("billing_address") + assertThat(documentCreateFromPdfResponse.billingAddressRecipient()) + .contains("billing_address_recipient") + assertThat(documentCreateFromPdfResponse.charges().getOrNull()) + .containsExactly( + Charge.builder() + .amount("amount") + .baseAmount("base_amount") + .multiplierFactor("multiplier_factor") + .reason("reason") + .reasonCode(Charge.ReasonCode.AA) + .taxCode(Charge.TaxCode.AE) + .taxRate("21.00") + .build() + ) + assertThat(documentCreateFromPdfResponse.currency()).contains(CurrencyCode.EUR) + assertThat(documentCreateFromPdfResponse.customerAddress()).contains("customer_address") + assertThat(documentCreateFromPdfResponse.customerAddressRecipient()) + .contains("customer_address_recipient") + assertThat(documentCreateFromPdfResponse.customerCompanyId()).contains("1018265814") + assertThat(documentCreateFromPdfResponse.customerEmail()).contains("customer_email") + assertThat(documentCreateFromPdfResponse.customerId()).contains("customer_id") + assertThat(documentCreateFromPdfResponse.customerName()).contains("customer_name") + assertThat(documentCreateFromPdfResponse.customerTaxId()).contains("BE1018265814") + assertThat(documentCreateFromPdfResponse.direction()).contains(DocumentDirection.INBOUND) + assertThat(documentCreateFromPdfResponse.documentType()).contains(DocumentType.INVOICE) + assertThat(documentCreateFromPdfResponse.dueDate()).contains(LocalDate.parse("2019-12-27")) + assertThat(documentCreateFromPdfResponse.invoiceDate()) + .contains(LocalDate.parse("2019-12-27")) + assertThat(documentCreateFromPdfResponse.invoiceId()).contains("invoice_id") + assertThat(documentCreateFromPdfResponse.invoiceTotal()).contains("invoice_total") + assertThat(documentCreateFromPdfResponse.items().getOrNull()) + .containsExactly( + DocumentCreateFromPdfResponse.Item.builder() + .addAllowance( + Allowance.builder() + .amount("amount") + .baseAmount("base_amount") + .multiplierFactor("multiplier_factor") + .reason("reason") + .reasonCode(Allowance.ReasonCode._41) + .taxCode(Allowance.TaxCode.AE) + .taxRate("tax_rate") + .build() + ) + .amount("amount") + .addCharge( + Charge.builder() + .amount("amount") + .baseAmount("base_amount") + .multiplierFactor("multiplier_factor") + .reason("reason") + .reasonCode(Charge.ReasonCode.AA) + .taxCode(Charge.TaxCode.AE) + .taxRate("21.00") + .build() + ) + .date(null) + .description("description") + .productCode("product_code") + .quantity("quantity") + .tax("tax") + .taxRate("21.00") + .unit(UnitOfMeasureCode._10) + .unitPrice("unit_price") + .build() + ) + assertThat(documentCreateFromPdfResponse.note()).contains("note") + assertThat(documentCreateFromPdfResponse.paymentDetails().getOrNull()) + .containsExactly( + PaymentDetailCreate.builder() + .bankAccountNumber("bank_account_number") + .iban("iban") + .paymentReference("payment_reference") + .swift("swift") + .build() + ) + assertThat(documentCreateFromPdfResponse.paymentTerm()).contains("payment_term") + assertThat(documentCreateFromPdfResponse.purchaseOrder()).contains("purchase_order") + assertThat(documentCreateFromPdfResponse.remittanceAddress()).contains("remittance_address") + assertThat(documentCreateFromPdfResponse.remittanceAddressRecipient()) + .contains("remittance_address_recipient") + assertThat(documentCreateFromPdfResponse.serviceAddress()).contains("service_address") + assertThat(documentCreateFromPdfResponse.serviceAddressRecipient()) + .contains("service_address_recipient") + assertThat(documentCreateFromPdfResponse.serviceEndDate()) + .contains(LocalDate.parse("2019-12-27")) + assertThat(documentCreateFromPdfResponse.serviceStartDate()) + .contains(LocalDate.parse("2019-12-27")) + assertThat(documentCreateFromPdfResponse.shippingAddress()).contains("shipping_address") + assertThat(documentCreateFromPdfResponse.shippingAddressRecipient()) + .contains("shipping_address_recipient") + assertThat(documentCreateFromPdfResponse.state()).contains(DocumentState.DRAFT) + assertThat(documentCreateFromPdfResponse.subtotal()).contains("subtotal") + assertThat(documentCreateFromPdfResponse.success()).contains(true) + assertThat(documentCreateFromPdfResponse.taxCode()) + .contains(DocumentCreateFromPdfResponse.TaxCode.AE) + assertThat(documentCreateFromPdfResponse.taxDetails().getOrNull()) + .containsExactly( + DocumentCreateFromPdfResponse.TaxDetail.builder() + .amount("amount") + .rate("rate") + .build() + ) + assertThat(documentCreateFromPdfResponse.totalDiscount()).contains("total_discount") + assertThat(documentCreateFromPdfResponse.totalTax()).contains("total_tax") + assertThat(documentCreateFromPdfResponse.ublDocument()).contains("ubl_document") + assertThat(documentCreateFromPdfResponse.vatex()) + .contains(DocumentCreateFromPdfResponse.Vatex.VATEX_EU_79_C) + assertThat(documentCreateFromPdfResponse.vatexNote()).contains("vatex_note") + assertThat(documentCreateFromPdfResponse.vendorAddress()).contains("vendor_address") + assertThat(documentCreateFromPdfResponse.vendorAddressRecipient()) + .contains("vendor_address_recipient") + assertThat(documentCreateFromPdfResponse.vendorCompanyId()).contains("1018265814") + assertThat(documentCreateFromPdfResponse.vendorEmail()).contains("vendor_email") + assertThat(documentCreateFromPdfResponse.vendorName()).contains("vendor_name") + assertThat(documentCreateFromPdfResponse.vendorTaxId()).contains("BE1018265814") + } + + @Test + fun roundtrip() { + val jsonMapper = jsonMapper() + val documentCreateFromPdfResponse = + DocumentCreateFromPdfResponse.builder() + .addAllowance( + Allowance.builder() + .amount("amount") + .baseAmount("base_amount") + .multiplierFactor("multiplier_factor") + .reason("reason") + .reasonCode(Allowance.ReasonCode._41) + .taxCode(Allowance.TaxCode.AE) + .taxRate("tax_rate") + .build() + ) + .amountDue("amount_due") + .addAttachment( + DocumentAttachmentCreate.builder() + .fileName("file_name") + .fileData("file_data") + .fileSize(0L) + .fileType("file_type") + .build() + ) + .billingAddress("billing_address") + .billingAddressRecipient("billing_address_recipient") + .addCharge( + Charge.builder() + .amount("amount") + .baseAmount("base_amount") + .multiplierFactor("multiplier_factor") + .reason("reason") + .reasonCode(Charge.ReasonCode.AA) + .taxCode(Charge.TaxCode.AE) + .taxRate("21.00") + .build() + ) + .currency(CurrencyCode.EUR) + .customerAddress("customer_address") + .customerAddressRecipient("customer_address_recipient") + .customerCompanyId("1018265814") + .customerEmail("customer_email") + .customerId("customer_id") + .customerName("customer_name") + .customerTaxId("BE1018265814") + .direction(DocumentDirection.INBOUND) + .documentType(DocumentType.INVOICE) + .dueDate(LocalDate.parse("2019-12-27")) + .invoiceDate(LocalDate.parse("2019-12-27")) + .invoiceId("invoice_id") + .invoiceTotal("invoice_total") + .addItem( + DocumentCreateFromPdfResponse.Item.builder() + .addAllowance( + Allowance.builder() + .amount("amount") + .baseAmount("base_amount") + .multiplierFactor("multiplier_factor") + .reason("reason") + .reasonCode(Allowance.ReasonCode._41) + .taxCode(Allowance.TaxCode.AE) + .taxRate("tax_rate") + .build() + ) + .amount("amount") + .addCharge( + Charge.builder() + .amount("amount") + .baseAmount("base_amount") + .multiplierFactor("multiplier_factor") + .reason("reason") + .reasonCode(Charge.ReasonCode.AA) + .taxCode(Charge.TaxCode.AE) + .taxRate("21.00") + .build() + ) + .date(null) + .description("description") + .productCode("product_code") + .quantity("quantity") + .tax("tax") + .taxRate("21.00") + .unit(UnitOfMeasureCode._10) + .unitPrice("unit_price") + .build() + ) + .note("note") + .addPaymentDetail( + PaymentDetailCreate.builder() + .bankAccountNumber("bank_account_number") + .iban("iban") + .paymentReference("payment_reference") + .swift("swift") + .build() + ) + .paymentTerm("payment_term") + .purchaseOrder("purchase_order") + .remittanceAddress("remittance_address") + .remittanceAddressRecipient("remittance_address_recipient") + .serviceAddress("service_address") + .serviceAddressRecipient("service_address_recipient") + .serviceEndDate(LocalDate.parse("2019-12-27")) + .serviceStartDate(LocalDate.parse("2019-12-27")) + .shippingAddress("shipping_address") + .shippingAddressRecipient("shipping_address_recipient") + .state(DocumentState.DRAFT) + .subtotal("subtotal") + .success(true) + .taxCode(DocumentCreateFromPdfResponse.TaxCode.AE) + .addTaxDetail( + DocumentCreateFromPdfResponse.TaxDetail.builder() + .amount("amount") + .rate("rate") + .build() + ) + .totalDiscount("total_discount") + .totalTax("total_tax") + .ublDocument("ubl_document") + .vatex(DocumentCreateFromPdfResponse.Vatex.VATEX_EU_79_C) + .vatexNote("vatex_note") + .vendorAddress("vendor_address") + .vendorAddressRecipient("vendor_address_recipient") + .vendorCompanyId("1018265814") + .vendorEmail("vendor_email") + .vendorName("vendor_name") + .vendorTaxId("BE1018265814") + .build() + + val roundtrippedDocumentCreateFromPdfResponse = + jsonMapper.readValue( + jsonMapper.writeValueAsString(documentCreateFromPdfResponse), + jacksonTypeRef(), + ) + + assertThat(roundtrippedDocumentCreateFromPdfResponse) + .isEqualTo(documentCreateFromPdfResponse) + } +} diff --git a/e-invoice-java-core/src/test/kotlin/com/e_invoice/api/models/documents/DocumentCreateParamsTest.kt b/e-invoice-java-core/src/test/kotlin/com/e_invoice/api/models/documents/DocumentCreateParamsTest.kt index 8378674..08476ce 100644 --- a/e-invoice-java-core/src/test/kotlin/com/e_invoice/api/models/documents/DocumentCreateParamsTest.kt +++ b/e-invoice-java-core/src/test/kotlin/com/e_invoice/api/models/documents/DocumentCreateParamsTest.kt @@ -2,6 +2,7 @@ package com.e_invoice.api.models.documents +import com.e_invoice.api.core.http.QueryParams import com.e_invoice.api.models.inbox.DocumentState import java.time.LocalDate import org.assertj.core.api.Assertions.assertThat @@ -12,8 +13,20 @@ internal class DocumentCreateParamsTest { @Test fun create() { DocumentCreateParams.builder() + .constructPdf(true) .documentCreate( DocumentCreate.builder() + .addAllowance( + DocumentCreate.Allowance.builder() + .amount(0.0) + .baseAmount(0.0) + .multiplierFactor(0.0) + .reason("reason") + .reasonCode(DocumentCreate.Allowance.ReasonCode._41) + .taxCode(DocumentCreate.Allowance.TaxCode.AE) + .taxRate(0.0) + .build() + ) .amountDue(0.0) .addAttachment( DocumentAttachmentCreate.builder() @@ -25,13 +38,25 @@ internal class DocumentCreateParamsTest { ) .billingAddress("billing_address") .billingAddressRecipient("billing_address_recipient") + .addCharge( + DocumentCreate.Charge.builder() + .amount(0.0) + .baseAmount(0.0) + .multiplierFactor(0.0) + .reason("reason") + .reasonCode(DocumentCreate.Charge.ReasonCode.AA) + .taxCode(DocumentCreate.Charge.TaxCode.AE) + .taxRate("21.00") + .build() + ) .currency(CurrencyCode.EUR) .customerAddress("customer_address") .customerAddressRecipient("customer_address_recipient") + .customerCompanyId("1018265814") .customerEmail("customer_email") .customerId("customer_id") .customerName("customer_name") - .customerTaxId("customer_tax_id") + .customerTaxId("BE1018265814") .direction(DocumentDirection.INBOUND) .documentType(DocumentType.INVOICE) .dueDate(LocalDate.parse("2019-12-27")) @@ -40,13 +65,35 @@ internal class DocumentCreateParamsTest { .invoiceTotal(0.0) .addItem( DocumentCreate.Item.builder() + .addAllowance( + DocumentCreate.Item.Allowance.builder() + .amount(0.0) + .baseAmount(0.0) + .multiplierFactor(0.0) + .reason("reason") + .reasonCode(DocumentCreate.Item.Allowance.ReasonCode._41) + .taxCode(DocumentCreate.Item.Allowance.TaxCode.AE) + .taxRate(0.0) + .build() + ) .amount(0.0) + .addCharge( + DocumentCreate.Item.Charge.builder() + .amount(0.0) + .baseAmount(0.0) + .multiplierFactor(0.0) + .reason("reason") + .reasonCode(DocumentCreate.Item.Charge.ReasonCode.AA) + .taxCode(DocumentCreate.Item.Charge.TaxCode.AE) + .taxRate("21.00") + .build() + ) .date(null) .description("description") .productCode("product_code") .quantity(0.0) .tax(0.0) - .taxRate("tax_rate") + .taxRate("21.00") .unit(UnitOfMeasureCode._10) .unitPrice(0.0) .build() @@ -73,27 +120,188 @@ internal class DocumentCreateParamsTest { .shippingAddressRecipient("shipping_address_recipient") .state(DocumentState.DRAFT) .subtotal(0.0) + .taxCode(DocumentCreate.TaxCode.AE) .addTaxDetail( DocumentCreate.TaxDetail.builder().amount(0.0).rate("rate").build() ) .totalDiscount(0.0) .totalTax(0.0) + .vatex(DocumentCreate.Vatex.VATEX_EU_79_C) + .vatexNote("vatex_note") .vendorAddress("vendor_address") .vendorAddressRecipient("vendor_address_recipient") + .vendorCompanyId("1018265814") .vendorEmail("vendor_email") .vendorName("vendor_name") - .vendorTaxId("vendor_tax_id") + .vendorTaxId("BE1018265814") .build() ) .build() } + @Test + fun queryParams() { + val params = + DocumentCreateParams.builder() + .constructPdf(true) + .documentCreate( + DocumentCreate.builder() + .addAllowance( + DocumentCreate.Allowance.builder() + .amount(0.0) + .baseAmount(0.0) + .multiplierFactor(0.0) + .reason("reason") + .reasonCode(DocumentCreate.Allowance.ReasonCode._41) + .taxCode(DocumentCreate.Allowance.TaxCode.AE) + .taxRate(0.0) + .build() + ) + .amountDue(0.0) + .addAttachment( + DocumentAttachmentCreate.builder() + .fileName("file_name") + .fileData("file_data") + .fileSize(0L) + .fileType("file_type") + .build() + ) + .billingAddress("billing_address") + .billingAddressRecipient("billing_address_recipient") + .addCharge( + DocumentCreate.Charge.builder() + .amount(0.0) + .baseAmount(0.0) + .multiplierFactor(0.0) + .reason("reason") + .reasonCode(DocumentCreate.Charge.ReasonCode.AA) + .taxCode(DocumentCreate.Charge.TaxCode.AE) + .taxRate("21.00") + .build() + ) + .currency(CurrencyCode.EUR) + .customerAddress("customer_address") + .customerAddressRecipient("customer_address_recipient") + .customerCompanyId("1018265814") + .customerEmail("customer_email") + .customerId("customer_id") + .customerName("customer_name") + .customerTaxId("BE1018265814") + .direction(DocumentDirection.INBOUND) + .documentType(DocumentType.INVOICE) + .dueDate(LocalDate.parse("2019-12-27")) + .invoiceDate(LocalDate.parse("2019-12-27")) + .invoiceId("invoice_id") + .invoiceTotal(0.0) + .addItem( + DocumentCreate.Item.builder() + .addAllowance( + DocumentCreate.Item.Allowance.builder() + .amount(0.0) + .baseAmount(0.0) + .multiplierFactor(0.0) + .reason("reason") + .reasonCode(DocumentCreate.Item.Allowance.ReasonCode._41) + .taxCode(DocumentCreate.Item.Allowance.TaxCode.AE) + .taxRate(0.0) + .build() + ) + .amount(0.0) + .addCharge( + DocumentCreate.Item.Charge.builder() + .amount(0.0) + .baseAmount(0.0) + .multiplierFactor(0.0) + .reason("reason") + .reasonCode(DocumentCreate.Item.Charge.ReasonCode.AA) + .taxCode(DocumentCreate.Item.Charge.TaxCode.AE) + .taxRate("21.00") + .build() + ) + .date(null) + .description("description") + .productCode("product_code") + .quantity(0.0) + .tax(0.0) + .taxRate("21.00") + .unit(UnitOfMeasureCode._10) + .unitPrice(0.0) + .build() + ) + .note("note") + .addPaymentDetail( + PaymentDetailCreate.builder() + .bankAccountNumber("bank_account_number") + .iban("iban") + .paymentReference("payment_reference") + .swift("swift") + .build() + ) + .paymentTerm("payment_term") + .previousUnpaidBalance(0.0) + .purchaseOrder("purchase_order") + .remittanceAddress("remittance_address") + .remittanceAddressRecipient("remittance_address_recipient") + .serviceAddress("service_address") + .serviceAddressRecipient("service_address_recipient") + .serviceEndDate(LocalDate.parse("2019-12-27")) + .serviceStartDate(LocalDate.parse("2019-12-27")) + .shippingAddress("shipping_address") + .shippingAddressRecipient("shipping_address_recipient") + .state(DocumentState.DRAFT) + .subtotal(0.0) + .taxCode(DocumentCreate.TaxCode.AE) + .addTaxDetail( + DocumentCreate.TaxDetail.builder().amount(0.0).rate("rate").build() + ) + .totalDiscount(0.0) + .totalTax(0.0) + .vatex(DocumentCreate.Vatex.VATEX_EU_79_C) + .vatexNote("vatex_note") + .vendorAddress("vendor_address") + .vendorAddressRecipient("vendor_address_recipient") + .vendorCompanyId("1018265814") + .vendorEmail("vendor_email") + .vendorName("vendor_name") + .vendorTaxId("BE1018265814") + .build() + ) + .build() + + val queryParams = params._queryParams() + + assertThat(queryParams) + .isEqualTo(QueryParams.builder().put("construct_pdf", "true").build()) + } + + @Test + fun queryParamsWithoutOptionalFields() { + val params = + DocumentCreateParams.builder().documentCreate(DocumentCreate.builder().build()).build() + + val queryParams = params._queryParams() + + assertThat(queryParams).isEqualTo(QueryParams.builder().build()) + } + @Test fun body() { val params = DocumentCreateParams.builder() + .constructPdf(true) .documentCreate( DocumentCreate.builder() + .addAllowance( + DocumentCreate.Allowance.builder() + .amount(0.0) + .baseAmount(0.0) + .multiplierFactor(0.0) + .reason("reason") + .reasonCode(DocumentCreate.Allowance.ReasonCode._41) + .taxCode(DocumentCreate.Allowance.TaxCode.AE) + .taxRate(0.0) + .build() + ) .amountDue(0.0) .addAttachment( DocumentAttachmentCreate.builder() @@ -105,13 +313,25 @@ internal class DocumentCreateParamsTest { ) .billingAddress("billing_address") .billingAddressRecipient("billing_address_recipient") + .addCharge( + DocumentCreate.Charge.builder() + .amount(0.0) + .baseAmount(0.0) + .multiplierFactor(0.0) + .reason("reason") + .reasonCode(DocumentCreate.Charge.ReasonCode.AA) + .taxCode(DocumentCreate.Charge.TaxCode.AE) + .taxRate("21.00") + .build() + ) .currency(CurrencyCode.EUR) .customerAddress("customer_address") .customerAddressRecipient("customer_address_recipient") + .customerCompanyId("1018265814") .customerEmail("customer_email") .customerId("customer_id") .customerName("customer_name") - .customerTaxId("customer_tax_id") + .customerTaxId("BE1018265814") .direction(DocumentDirection.INBOUND) .documentType(DocumentType.INVOICE) .dueDate(LocalDate.parse("2019-12-27")) @@ -120,13 +340,35 @@ internal class DocumentCreateParamsTest { .invoiceTotal(0.0) .addItem( DocumentCreate.Item.builder() + .addAllowance( + DocumentCreate.Item.Allowance.builder() + .amount(0.0) + .baseAmount(0.0) + .multiplierFactor(0.0) + .reason("reason") + .reasonCode(DocumentCreate.Item.Allowance.ReasonCode._41) + .taxCode(DocumentCreate.Item.Allowance.TaxCode.AE) + .taxRate(0.0) + .build() + ) .amount(0.0) + .addCharge( + DocumentCreate.Item.Charge.builder() + .amount(0.0) + .baseAmount(0.0) + .multiplierFactor(0.0) + .reason("reason") + .reasonCode(DocumentCreate.Item.Charge.ReasonCode.AA) + .taxCode(DocumentCreate.Item.Charge.TaxCode.AE) + .taxRate("21.00") + .build() + ) .date(null) .description("description") .productCode("product_code") .quantity(0.0) .tax(0.0) - .taxRate("tax_rate") + .taxRate("21.00") .unit(UnitOfMeasureCode._10) .unitPrice(0.0) .build() @@ -153,16 +395,20 @@ internal class DocumentCreateParamsTest { .shippingAddressRecipient("shipping_address_recipient") .state(DocumentState.DRAFT) .subtotal(0.0) + .taxCode(DocumentCreate.TaxCode.AE) .addTaxDetail( DocumentCreate.TaxDetail.builder().amount(0.0).rate("rate").build() ) .totalDiscount(0.0) .totalTax(0.0) + .vatex(DocumentCreate.Vatex.VATEX_EU_79_C) + .vatexNote("vatex_note") .vendorAddress("vendor_address") .vendorAddressRecipient("vendor_address_recipient") + .vendorCompanyId("1018265814") .vendorEmail("vendor_email") .vendorName("vendor_name") - .vendorTaxId("vendor_tax_id") + .vendorTaxId("BE1018265814") .build() ) .build() @@ -172,6 +418,17 @@ internal class DocumentCreateParamsTest { assertThat(body) .isEqualTo( DocumentCreate.builder() + .addAllowance( + DocumentCreate.Allowance.builder() + .amount(0.0) + .baseAmount(0.0) + .multiplierFactor(0.0) + .reason("reason") + .reasonCode(DocumentCreate.Allowance.ReasonCode._41) + .taxCode(DocumentCreate.Allowance.TaxCode.AE) + .taxRate(0.0) + .build() + ) .amountDue(0.0) .addAttachment( DocumentAttachmentCreate.builder() @@ -183,13 +440,25 @@ internal class DocumentCreateParamsTest { ) .billingAddress("billing_address") .billingAddressRecipient("billing_address_recipient") + .addCharge( + DocumentCreate.Charge.builder() + .amount(0.0) + .baseAmount(0.0) + .multiplierFactor(0.0) + .reason("reason") + .reasonCode(DocumentCreate.Charge.ReasonCode.AA) + .taxCode(DocumentCreate.Charge.TaxCode.AE) + .taxRate("21.00") + .build() + ) .currency(CurrencyCode.EUR) .customerAddress("customer_address") .customerAddressRecipient("customer_address_recipient") + .customerCompanyId("1018265814") .customerEmail("customer_email") .customerId("customer_id") .customerName("customer_name") - .customerTaxId("customer_tax_id") + .customerTaxId("BE1018265814") .direction(DocumentDirection.INBOUND) .documentType(DocumentType.INVOICE) .dueDate(LocalDate.parse("2019-12-27")) @@ -198,13 +467,35 @@ internal class DocumentCreateParamsTest { .invoiceTotal(0.0) .addItem( DocumentCreate.Item.builder() + .addAllowance( + DocumentCreate.Item.Allowance.builder() + .amount(0.0) + .baseAmount(0.0) + .multiplierFactor(0.0) + .reason("reason") + .reasonCode(DocumentCreate.Item.Allowance.ReasonCode._41) + .taxCode(DocumentCreate.Item.Allowance.TaxCode.AE) + .taxRate(0.0) + .build() + ) .amount(0.0) + .addCharge( + DocumentCreate.Item.Charge.builder() + .amount(0.0) + .baseAmount(0.0) + .multiplierFactor(0.0) + .reason("reason") + .reasonCode(DocumentCreate.Item.Charge.ReasonCode.AA) + .taxCode(DocumentCreate.Item.Charge.TaxCode.AE) + .taxRate("21.00") + .build() + ) .date(null) .description("description") .productCode("product_code") .quantity(0.0) .tax(0.0) - .taxRate("tax_rate") + .taxRate("21.00") .unit(UnitOfMeasureCode._10) .unitPrice(0.0) .build() @@ -231,16 +522,20 @@ internal class DocumentCreateParamsTest { .shippingAddressRecipient("shipping_address_recipient") .state(DocumentState.DRAFT) .subtotal(0.0) + .taxCode(DocumentCreate.TaxCode.AE) .addTaxDetail( DocumentCreate.TaxDetail.builder().amount(0.0).rate("rate").build() ) .totalDiscount(0.0) .totalTax(0.0) + .vatex(DocumentCreate.Vatex.VATEX_EU_79_C) + .vatexNote("vatex_note") .vendorAddress("vendor_address") .vendorAddressRecipient("vendor_address_recipient") + .vendorCompanyId("1018265814") .vendorEmail("vendor_email") .vendorName("vendor_name") - .vendorTaxId("vendor_tax_id") + .vendorTaxId("BE1018265814") .build() ) } diff --git a/e-invoice-java-core/src/test/kotlin/com/e_invoice/api/models/documents/DocumentCreateTest.kt b/e-invoice-java-core/src/test/kotlin/com/e_invoice/api/models/documents/DocumentCreateTest.kt index fff0f2b..f98cbd4 100644 --- a/e-invoice-java-core/src/test/kotlin/com/e_invoice/api/models/documents/DocumentCreateTest.kt +++ b/e-invoice-java-core/src/test/kotlin/com/e_invoice/api/models/documents/DocumentCreateTest.kt @@ -16,6 +16,17 @@ internal class DocumentCreateTest { fun create() { val documentCreate = DocumentCreate.builder() + .addAllowance( + DocumentCreate.Allowance.builder() + .amount(0.0) + .baseAmount(0.0) + .multiplierFactor(0.0) + .reason("reason") + .reasonCode(DocumentCreate.Allowance.ReasonCode._41) + .taxCode(DocumentCreate.Allowance.TaxCode.AE) + .taxRate(0.0) + .build() + ) .amountDue(0.0) .addAttachment( DocumentAttachmentCreate.builder() @@ -27,13 +38,25 @@ internal class DocumentCreateTest { ) .billingAddress("billing_address") .billingAddressRecipient("billing_address_recipient") + .addCharge( + DocumentCreate.Charge.builder() + .amount(0.0) + .baseAmount(0.0) + .multiplierFactor(0.0) + .reason("reason") + .reasonCode(DocumentCreate.Charge.ReasonCode.AA) + .taxCode(DocumentCreate.Charge.TaxCode.AE) + .taxRate("21.00") + .build() + ) .currency(CurrencyCode.EUR) .customerAddress("customer_address") .customerAddressRecipient("customer_address_recipient") + .customerCompanyId("1018265814") .customerEmail("customer_email") .customerId("customer_id") .customerName("customer_name") - .customerTaxId("customer_tax_id") + .customerTaxId("BE1018265814") .direction(DocumentDirection.INBOUND) .documentType(DocumentType.INVOICE) .dueDate(LocalDate.parse("2019-12-27")) @@ -42,13 +65,35 @@ internal class DocumentCreateTest { .invoiceTotal(0.0) .addItem( DocumentCreate.Item.builder() + .addAllowance( + DocumentCreate.Item.Allowance.builder() + .amount(0.0) + .baseAmount(0.0) + .multiplierFactor(0.0) + .reason("reason") + .reasonCode(DocumentCreate.Item.Allowance.ReasonCode._41) + .taxCode(DocumentCreate.Item.Allowance.TaxCode.AE) + .taxRate(0.0) + .build() + ) .amount(0.0) + .addCharge( + DocumentCreate.Item.Charge.builder() + .amount(0.0) + .baseAmount(0.0) + .multiplierFactor(0.0) + .reason("reason") + .reasonCode(DocumentCreate.Item.Charge.ReasonCode.AA) + .taxCode(DocumentCreate.Item.Charge.TaxCode.AE) + .taxRate("21.00") + .build() + ) .date(null) .description("description") .productCode("product_code") .quantity(0.0) .tax(0.0) - .taxRate("tax_rate") + .taxRate("21.00") .unit(UnitOfMeasureCode._10) .unitPrice(0.0) .build() @@ -75,16 +120,32 @@ internal class DocumentCreateTest { .shippingAddressRecipient("shipping_address_recipient") .state(DocumentState.DRAFT) .subtotal(0.0) + .taxCode(DocumentCreate.TaxCode.AE) .addTaxDetail(DocumentCreate.TaxDetail.builder().amount(0.0).rate("rate").build()) .totalDiscount(0.0) .totalTax(0.0) + .vatex(DocumentCreate.Vatex.VATEX_EU_79_C) + .vatexNote("vatex_note") .vendorAddress("vendor_address") .vendorAddressRecipient("vendor_address_recipient") + .vendorCompanyId("1018265814") .vendorEmail("vendor_email") .vendorName("vendor_name") - .vendorTaxId("vendor_tax_id") + .vendorTaxId("BE1018265814") .build() + assertThat(documentCreate.allowances().getOrNull()) + .containsExactly( + DocumentCreate.Allowance.builder() + .amount(0.0) + .baseAmount(0.0) + .multiplierFactor(0.0) + .reason("reason") + .reasonCode(DocumentCreate.Allowance.ReasonCode._41) + .taxCode(DocumentCreate.Allowance.TaxCode.AE) + .taxRate(0.0) + .build() + ) assertThat(documentCreate.amountDue()).contains(DocumentCreate.AmountDue.ofNumber(0.0)) assertThat(documentCreate.attachments().getOrNull()) .containsExactly( @@ -97,13 +158,26 @@ internal class DocumentCreateTest { ) assertThat(documentCreate.billingAddress()).contains("billing_address") assertThat(documentCreate.billingAddressRecipient()).contains("billing_address_recipient") + assertThat(documentCreate.charges().getOrNull()) + .containsExactly( + DocumentCreate.Charge.builder() + .amount(0.0) + .baseAmount(0.0) + .multiplierFactor(0.0) + .reason("reason") + .reasonCode(DocumentCreate.Charge.ReasonCode.AA) + .taxCode(DocumentCreate.Charge.TaxCode.AE) + .taxRate("21.00") + .build() + ) assertThat(documentCreate.currency()).contains(CurrencyCode.EUR) assertThat(documentCreate.customerAddress()).contains("customer_address") assertThat(documentCreate.customerAddressRecipient()).contains("customer_address_recipient") + assertThat(documentCreate.customerCompanyId()).contains("1018265814") assertThat(documentCreate.customerEmail()).contains("customer_email") assertThat(documentCreate.customerId()).contains("customer_id") assertThat(documentCreate.customerName()).contains("customer_name") - assertThat(documentCreate.customerTaxId()).contains("customer_tax_id") + assertThat(documentCreate.customerTaxId()).contains("BE1018265814") assertThat(documentCreate.direction()).contains(DocumentDirection.INBOUND) assertThat(documentCreate.documentType()).contains(DocumentType.INVOICE) assertThat(documentCreate.dueDate()).contains(LocalDate.parse("2019-12-27")) @@ -114,13 +188,35 @@ internal class DocumentCreateTest { assertThat(documentCreate.items().getOrNull()) .containsExactly( DocumentCreate.Item.builder() + .addAllowance( + DocumentCreate.Item.Allowance.builder() + .amount(0.0) + .baseAmount(0.0) + .multiplierFactor(0.0) + .reason("reason") + .reasonCode(DocumentCreate.Item.Allowance.ReasonCode._41) + .taxCode(DocumentCreate.Item.Allowance.TaxCode.AE) + .taxRate(0.0) + .build() + ) .amount(0.0) + .addCharge( + DocumentCreate.Item.Charge.builder() + .amount(0.0) + .baseAmount(0.0) + .multiplierFactor(0.0) + .reason("reason") + .reasonCode(DocumentCreate.Item.Charge.ReasonCode.AA) + .taxCode(DocumentCreate.Item.Charge.TaxCode.AE) + .taxRate("21.00") + .build() + ) .date(null) .description("description") .productCode("product_code") .quantity(0.0) .tax(0.0) - .taxRate("tax_rate") + .taxRate("21.00") .unit(UnitOfMeasureCode._10) .unitPrice(0.0) .build() @@ -150,16 +246,20 @@ internal class DocumentCreateTest { assertThat(documentCreate.shippingAddressRecipient()).contains("shipping_address_recipient") assertThat(documentCreate.state()).contains(DocumentState.DRAFT) assertThat(documentCreate.subtotal()).contains(DocumentCreate.Subtotal.ofNumber(0.0)) + assertThat(documentCreate.taxCode()).contains(DocumentCreate.TaxCode.AE) assertThat(documentCreate.taxDetails().getOrNull()) .containsExactly(DocumentCreate.TaxDetail.builder().amount(0.0).rate("rate").build()) assertThat(documentCreate.totalDiscount()) .contains(DocumentCreate.TotalDiscount.ofNumber(0.0)) assertThat(documentCreate.totalTax()).contains(DocumentCreate.TotalTax.ofNumber(0.0)) + assertThat(documentCreate.vatex()).contains(DocumentCreate.Vatex.VATEX_EU_79_C) + assertThat(documentCreate.vatexNote()).contains("vatex_note") assertThat(documentCreate.vendorAddress()).contains("vendor_address") assertThat(documentCreate.vendorAddressRecipient()).contains("vendor_address_recipient") + assertThat(documentCreate.vendorCompanyId()).contains("1018265814") assertThat(documentCreate.vendorEmail()).contains("vendor_email") assertThat(documentCreate.vendorName()).contains("vendor_name") - assertThat(documentCreate.vendorTaxId()).contains("vendor_tax_id") + assertThat(documentCreate.vendorTaxId()).contains("BE1018265814") } @Test @@ -167,6 +267,17 @@ internal class DocumentCreateTest { val jsonMapper = jsonMapper() val documentCreate = DocumentCreate.builder() + .addAllowance( + DocumentCreate.Allowance.builder() + .amount(0.0) + .baseAmount(0.0) + .multiplierFactor(0.0) + .reason("reason") + .reasonCode(DocumentCreate.Allowance.ReasonCode._41) + .taxCode(DocumentCreate.Allowance.TaxCode.AE) + .taxRate(0.0) + .build() + ) .amountDue(0.0) .addAttachment( DocumentAttachmentCreate.builder() @@ -178,13 +289,25 @@ internal class DocumentCreateTest { ) .billingAddress("billing_address") .billingAddressRecipient("billing_address_recipient") + .addCharge( + DocumentCreate.Charge.builder() + .amount(0.0) + .baseAmount(0.0) + .multiplierFactor(0.0) + .reason("reason") + .reasonCode(DocumentCreate.Charge.ReasonCode.AA) + .taxCode(DocumentCreate.Charge.TaxCode.AE) + .taxRate("21.00") + .build() + ) .currency(CurrencyCode.EUR) .customerAddress("customer_address") .customerAddressRecipient("customer_address_recipient") + .customerCompanyId("1018265814") .customerEmail("customer_email") .customerId("customer_id") .customerName("customer_name") - .customerTaxId("customer_tax_id") + .customerTaxId("BE1018265814") .direction(DocumentDirection.INBOUND) .documentType(DocumentType.INVOICE) .dueDate(LocalDate.parse("2019-12-27")) @@ -193,13 +316,35 @@ internal class DocumentCreateTest { .invoiceTotal(0.0) .addItem( DocumentCreate.Item.builder() + .addAllowance( + DocumentCreate.Item.Allowance.builder() + .amount(0.0) + .baseAmount(0.0) + .multiplierFactor(0.0) + .reason("reason") + .reasonCode(DocumentCreate.Item.Allowance.ReasonCode._41) + .taxCode(DocumentCreate.Item.Allowance.TaxCode.AE) + .taxRate(0.0) + .build() + ) .amount(0.0) + .addCharge( + DocumentCreate.Item.Charge.builder() + .amount(0.0) + .baseAmount(0.0) + .multiplierFactor(0.0) + .reason("reason") + .reasonCode(DocumentCreate.Item.Charge.ReasonCode.AA) + .taxCode(DocumentCreate.Item.Charge.TaxCode.AE) + .taxRate("21.00") + .build() + ) .date(null) .description("description") .productCode("product_code") .quantity(0.0) .tax(0.0) - .taxRate("tax_rate") + .taxRate("21.00") .unit(UnitOfMeasureCode._10) .unitPrice(0.0) .build() @@ -226,14 +371,18 @@ internal class DocumentCreateTest { .shippingAddressRecipient("shipping_address_recipient") .state(DocumentState.DRAFT) .subtotal(0.0) + .taxCode(DocumentCreate.TaxCode.AE) .addTaxDetail(DocumentCreate.TaxDetail.builder().amount(0.0).rate("rate").build()) .totalDiscount(0.0) .totalTax(0.0) + .vatex(DocumentCreate.Vatex.VATEX_EU_79_C) + .vatexNote("vatex_note") .vendorAddress("vendor_address") .vendorAddressRecipient("vendor_address_recipient") + .vendorCompanyId("1018265814") .vendorEmail("vendor_email") .vendorName("vendor_name") - .vendorTaxId("vendor_tax_id") + .vendorTaxId("BE1018265814") .build() val roundtrippedDocumentCreate = diff --git a/e-invoice-java-core/src/test/kotlin/com/e_invoice/api/models/documents/DocumentResponseTest.kt b/e-invoice-java-core/src/test/kotlin/com/e_invoice/api/models/documents/DocumentResponseTest.kt index 3fcf1ab..73740db 100644 --- a/e-invoice-java-core/src/test/kotlin/com/e_invoice/api/models/documents/DocumentResponseTest.kt +++ b/e-invoice-java-core/src/test/kotlin/com/e_invoice/api/models/documents/DocumentResponseTest.kt @@ -7,6 +7,7 @@ import com.e_invoice.api.models.documents.attachments.DocumentAttachment import com.e_invoice.api.models.inbox.DocumentState import com.fasterxml.jackson.module.kotlin.jacksonTypeRef import java.time.LocalDate +import java.time.OffsetDateTime import kotlin.jvm.optionals.getOrNull import org.assertj.core.api.Assertions.assertThat import org.junit.jupiter.api.Test @@ -18,6 +19,18 @@ internal class DocumentResponseTest { val documentResponse = DocumentResponse.builder() .id("id") + .createdAt(OffsetDateTime.parse("2019-12-27T18:11:19.117Z")) + .addAllowance( + DocumentResponse.Allowance.builder() + .amount("amount") + .baseAmount("base_amount") + .multiplierFactor("multiplier_factor") + .reason("reason") + .reasonCode(DocumentResponse.Allowance.ReasonCode._41) + .taxCode(DocumentResponse.Allowance.TaxCode.AE) + .taxRate("tax_rate") + .build() + ) .amountDue("amount_due") .addAttachment( DocumentAttachment.builder() @@ -30,13 +43,25 @@ internal class DocumentResponseTest { ) .billingAddress("billing_address") .billingAddressRecipient("billing_address_recipient") + .addCharge( + DocumentResponse.Charge.builder() + .amount("amount") + .baseAmount("base_amount") + .multiplierFactor("multiplier_factor") + .reason("reason") + .reasonCode(DocumentResponse.Charge.ReasonCode.AA) + .taxCode(DocumentResponse.Charge.TaxCode.AE) + .taxRate("21.00") + .build() + ) .currency(CurrencyCode.EUR) .customerAddress("customer_address") .customerAddressRecipient("customer_address_recipient") + .customerCompanyId("1018265814") .customerEmail("customer_email") .customerId("customer_id") .customerName("customer_name") - .customerTaxId("customer_tax_id") + .customerTaxId("BE1018265814") .direction(DocumentDirection.INBOUND) .documentType(DocumentType.INVOICE) .dueDate(LocalDate.parse("2019-12-27")) @@ -45,13 +70,35 @@ internal class DocumentResponseTest { .invoiceTotal("invoice_total") .addItem( DocumentResponse.Item.builder() + .addAllowance( + Allowance.builder() + .amount("amount") + .baseAmount("base_amount") + .multiplierFactor("multiplier_factor") + .reason("reason") + .reasonCode(Allowance.ReasonCode._41) + .taxCode(Allowance.TaxCode.AE) + .taxRate("tax_rate") + .build() + ) .amount("amount") + .addCharge( + Charge.builder() + .amount("amount") + .baseAmount("base_amount") + .multiplierFactor("multiplier_factor") + .reason("reason") + .reasonCode(Charge.ReasonCode.AA) + .taxCode(Charge.TaxCode.AE) + .taxRate("21.00") + .build() + ) .date(null) .description("description") .productCode("product_code") .quantity("quantity") .tax("tax") - .taxRate("tax_rate") + .taxRate("21.00") .unit(UnitOfMeasureCode._10) .unitPrice("unit_price") .build() @@ -66,7 +113,6 @@ internal class DocumentResponseTest { .build() ) .paymentTerm("payment_term") - .previousUnpaidBalance("previous_unpaid_balance") .purchaseOrder("purchase_order") .remittanceAddress("remittance_address") .remittanceAddressRecipient("remittance_address_recipient") @@ -78,19 +124,37 @@ internal class DocumentResponseTest { .shippingAddressRecipient("shipping_address_recipient") .state(DocumentState.DRAFT) .subtotal("subtotal") + .taxCode(DocumentResponse.TaxCode.AE) .addTaxDetail( DocumentResponse.TaxDetail.builder().amount("amount").rate("rate").build() ) .totalDiscount("total_discount") .totalTax("total_tax") + .vatex(DocumentResponse.Vatex.VATEX_EU_79_C) + .vatexNote("vatex_note") .vendorAddress("vendor_address") .vendorAddressRecipient("vendor_address_recipient") + .vendorCompanyId("1018265814") .vendorEmail("vendor_email") .vendorName("vendor_name") - .vendorTaxId("vendor_tax_id") + .vendorTaxId("BE1018265814") .build() assertThat(documentResponse.id()).isEqualTo("id") + assertThat(documentResponse.createdAt()) + .isEqualTo(OffsetDateTime.parse("2019-12-27T18:11:19.117Z")) + assertThat(documentResponse.allowances().getOrNull()) + .containsExactly( + DocumentResponse.Allowance.builder() + .amount("amount") + .baseAmount("base_amount") + .multiplierFactor("multiplier_factor") + .reason("reason") + .reasonCode(DocumentResponse.Allowance.ReasonCode._41) + .taxCode(DocumentResponse.Allowance.TaxCode.AE) + .taxRate("tax_rate") + .build() + ) assertThat(documentResponse.amountDue()).contains("amount_due") assertThat(documentResponse.attachments().getOrNull()) .containsExactly( @@ -104,14 +168,27 @@ internal class DocumentResponseTest { ) assertThat(documentResponse.billingAddress()).contains("billing_address") assertThat(documentResponse.billingAddressRecipient()).contains("billing_address_recipient") + assertThat(documentResponse.charges().getOrNull()) + .containsExactly( + DocumentResponse.Charge.builder() + .amount("amount") + .baseAmount("base_amount") + .multiplierFactor("multiplier_factor") + .reason("reason") + .reasonCode(DocumentResponse.Charge.ReasonCode.AA) + .taxCode(DocumentResponse.Charge.TaxCode.AE) + .taxRate("21.00") + .build() + ) assertThat(documentResponse.currency()).contains(CurrencyCode.EUR) assertThat(documentResponse.customerAddress()).contains("customer_address") assertThat(documentResponse.customerAddressRecipient()) .contains("customer_address_recipient") + assertThat(documentResponse.customerCompanyId()).contains("1018265814") assertThat(documentResponse.customerEmail()).contains("customer_email") assertThat(documentResponse.customerId()).contains("customer_id") assertThat(documentResponse.customerName()).contains("customer_name") - assertThat(documentResponse.customerTaxId()).contains("customer_tax_id") + assertThat(documentResponse.customerTaxId()).contains("BE1018265814") assertThat(documentResponse.direction()).contains(DocumentDirection.INBOUND) assertThat(documentResponse.documentType()).contains(DocumentType.INVOICE) assertThat(documentResponse.dueDate()).contains(LocalDate.parse("2019-12-27")) @@ -121,13 +198,35 @@ internal class DocumentResponseTest { assertThat(documentResponse.items().getOrNull()) .containsExactly( DocumentResponse.Item.builder() + .addAllowance( + Allowance.builder() + .amount("amount") + .baseAmount("base_amount") + .multiplierFactor("multiplier_factor") + .reason("reason") + .reasonCode(Allowance.ReasonCode._41) + .taxCode(Allowance.TaxCode.AE) + .taxRate("tax_rate") + .build() + ) .amount("amount") + .addCharge( + Charge.builder() + .amount("amount") + .baseAmount("base_amount") + .multiplierFactor("multiplier_factor") + .reason("reason") + .reasonCode(Charge.ReasonCode.AA) + .taxCode(Charge.TaxCode.AE) + .taxRate("21.00") + .build() + ) .date(null) .description("description") .productCode("product_code") .quantity("quantity") .tax("tax") - .taxRate("tax_rate") + .taxRate("21.00") .unit(UnitOfMeasureCode._10) .unitPrice("unit_price") .build() @@ -143,7 +242,6 @@ internal class DocumentResponseTest { .build() ) assertThat(documentResponse.paymentTerm()).contains("payment_term") - assertThat(documentResponse.previousUnpaidBalance()).contains("previous_unpaid_balance") assertThat(documentResponse.purchaseOrder()).contains("purchase_order") assertThat(documentResponse.remittanceAddress()).contains("remittance_address") assertThat(documentResponse.remittanceAddressRecipient()) @@ -157,17 +255,21 @@ internal class DocumentResponseTest { .contains("shipping_address_recipient") assertThat(documentResponse.state()).contains(DocumentState.DRAFT) assertThat(documentResponse.subtotal()).contains("subtotal") + assertThat(documentResponse.taxCode()).contains(DocumentResponse.TaxCode.AE) assertThat(documentResponse.taxDetails().getOrNull()) .containsExactly( DocumentResponse.TaxDetail.builder().amount("amount").rate("rate").build() ) assertThat(documentResponse.totalDiscount()).contains("total_discount") assertThat(documentResponse.totalTax()).contains("total_tax") + assertThat(documentResponse.vatex()).contains(DocumentResponse.Vatex.VATEX_EU_79_C) + assertThat(documentResponse.vatexNote()).contains("vatex_note") assertThat(documentResponse.vendorAddress()).contains("vendor_address") assertThat(documentResponse.vendorAddressRecipient()).contains("vendor_address_recipient") + assertThat(documentResponse.vendorCompanyId()).contains("1018265814") assertThat(documentResponse.vendorEmail()).contains("vendor_email") assertThat(documentResponse.vendorName()).contains("vendor_name") - assertThat(documentResponse.vendorTaxId()).contains("vendor_tax_id") + assertThat(documentResponse.vendorTaxId()).contains("BE1018265814") } @Test @@ -176,6 +278,18 @@ internal class DocumentResponseTest { val documentResponse = DocumentResponse.builder() .id("id") + .createdAt(OffsetDateTime.parse("2019-12-27T18:11:19.117Z")) + .addAllowance( + DocumentResponse.Allowance.builder() + .amount("amount") + .baseAmount("base_amount") + .multiplierFactor("multiplier_factor") + .reason("reason") + .reasonCode(DocumentResponse.Allowance.ReasonCode._41) + .taxCode(DocumentResponse.Allowance.TaxCode.AE) + .taxRate("tax_rate") + .build() + ) .amountDue("amount_due") .addAttachment( DocumentAttachment.builder() @@ -188,13 +302,25 @@ internal class DocumentResponseTest { ) .billingAddress("billing_address") .billingAddressRecipient("billing_address_recipient") + .addCharge( + DocumentResponse.Charge.builder() + .amount("amount") + .baseAmount("base_amount") + .multiplierFactor("multiplier_factor") + .reason("reason") + .reasonCode(DocumentResponse.Charge.ReasonCode.AA) + .taxCode(DocumentResponse.Charge.TaxCode.AE) + .taxRate("21.00") + .build() + ) .currency(CurrencyCode.EUR) .customerAddress("customer_address") .customerAddressRecipient("customer_address_recipient") + .customerCompanyId("1018265814") .customerEmail("customer_email") .customerId("customer_id") .customerName("customer_name") - .customerTaxId("customer_tax_id") + .customerTaxId("BE1018265814") .direction(DocumentDirection.INBOUND) .documentType(DocumentType.INVOICE) .dueDate(LocalDate.parse("2019-12-27")) @@ -203,13 +329,35 @@ internal class DocumentResponseTest { .invoiceTotal("invoice_total") .addItem( DocumentResponse.Item.builder() + .addAllowance( + Allowance.builder() + .amount("amount") + .baseAmount("base_amount") + .multiplierFactor("multiplier_factor") + .reason("reason") + .reasonCode(Allowance.ReasonCode._41) + .taxCode(Allowance.TaxCode.AE) + .taxRate("tax_rate") + .build() + ) .amount("amount") + .addCharge( + Charge.builder() + .amount("amount") + .baseAmount("base_amount") + .multiplierFactor("multiplier_factor") + .reason("reason") + .reasonCode(Charge.ReasonCode.AA) + .taxCode(Charge.TaxCode.AE) + .taxRate("21.00") + .build() + ) .date(null) .description("description") .productCode("product_code") .quantity("quantity") .tax("tax") - .taxRate("tax_rate") + .taxRate("21.00") .unit(UnitOfMeasureCode._10) .unitPrice("unit_price") .build() @@ -224,7 +372,6 @@ internal class DocumentResponseTest { .build() ) .paymentTerm("payment_term") - .previousUnpaidBalance("previous_unpaid_balance") .purchaseOrder("purchase_order") .remittanceAddress("remittance_address") .remittanceAddressRecipient("remittance_address_recipient") @@ -236,16 +383,20 @@ internal class DocumentResponseTest { .shippingAddressRecipient("shipping_address_recipient") .state(DocumentState.DRAFT) .subtotal("subtotal") + .taxCode(DocumentResponse.TaxCode.AE) .addTaxDetail( DocumentResponse.TaxDetail.builder().amount("amount").rate("rate").build() ) .totalDiscount("total_discount") .totalTax("total_tax") + .vatex(DocumentResponse.Vatex.VATEX_EU_79_C) + .vatexNote("vatex_note") .vendorAddress("vendor_address") .vendorAddressRecipient("vendor_address_recipient") + .vendorCompanyId("1018265814") .vendorEmail("vendor_email") .vendorName("vendor_name") - .vendorTaxId("vendor_tax_id") + .vendorTaxId("BE1018265814") .build() val roundtrippedDocumentResponse = diff --git a/e-invoice-java-core/src/test/kotlin/com/e_invoice/api/models/documents/DocumentValidateParamsTest.kt b/e-invoice-java-core/src/test/kotlin/com/e_invoice/api/models/documents/DocumentValidateParamsTest.kt new file mode 100644 index 0000000..e012ebc --- /dev/null +++ b/e-invoice-java-core/src/test/kotlin/com/e_invoice/api/models/documents/DocumentValidateParamsTest.kt @@ -0,0 +1,23 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.e_invoice.api.models.documents + +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class DocumentValidateParamsTest { + + @Test + fun create() { + DocumentValidateParams.builder().documentId("document_id").build() + } + + @Test + fun pathParams() { + val params = DocumentValidateParams.builder().documentId("document_id").build() + + assertThat(params._pathParam(0)).isEqualTo("document_id") + // out-of-bound path param + assertThat(params._pathParam(1)).isEqualTo("") + } +} diff --git a/e-invoice-java-core/src/test/kotlin/com/e_invoice/api/models/documents/ubl/UblCreateFromUblParamsTest.kt b/e-invoice-java-core/src/test/kotlin/com/e_invoice/api/models/documents/ubl/UblCreateFromUblParamsTest.kt new file mode 100644 index 0000000..a2fa17b --- /dev/null +++ b/e-invoice-java-core/src/test/kotlin/com/e_invoice/api/models/documents/ubl/UblCreateFromUblParamsTest.kt @@ -0,0 +1,38 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.e_invoice.api.models.documents.ubl + +import com.e_invoice.api.core.MultipartField +import java.io.InputStream +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class UblCreateFromUblParamsTest { + + @Test + fun create() { + UblCreateFromUblParams.builder().file("some content".byteInputStream()).build() + } + + @Test + fun body() { + val params = UblCreateFromUblParams.builder().file("some content".byteInputStream()).build() + + val body = params._body() + + assertThat(body.filterValues { !it.value.isNull() }) + .usingRecursiveComparison() + // TODO(AssertJ): Replace this and the `mapValues` below with: + // https://github.com/assertj/assertj/issues/3165 + .withEqualsForType( + { a, b -> a.readBytes() contentEquals b.readBytes() }, + InputStream::class.java, + ) + .isEqualTo( + mapOf("file" to MultipartField.of("some content".byteInputStream())).mapValues { + (_, field) -> + field.map { (it as? ByteArray)?.inputStream() ?: it } + } + ) + } +} diff --git a/e-invoice-java-core/src/test/kotlin/com/e_invoice/api/models/inbox/InboxListCreditNotesParamsTest.kt b/e-invoice-java-core/src/test/kotlin/com/e_invoice/api/models/inbox/InboxListCreditNotesParamsTest.kt index 4410f38..ecb45de 100644 --- a/e-invoice-java-core/src/test/kotlin/com/e_invoice/api/models/inbox/InboxListCreditNotesParamsTest.kt +++ b/e-invoice-java-core/src/test/kotlin/com/e_invoice/api/models/inbox/InboxListCreditNotesParamsTest.kt @@ -10,17 +10,35 @@ internal class InboxListCreditNotesParamsTest { @Test fun create() { - InboxListCreditNotesParams.builder().page(1L).pageSize(1L).build() + InboxListCreditNotesParams.builder() + .page(1L) + .pageSize(1L) + .sortBy(InboxListCreditNotesParams.SortBy.CREATED_AT) + .sortOrder(InboxListCreditNotesParams.SortOrder.ASC) + .build() } @Test fun queryParams() { - val params = InboxListCreditNotesParams.builder().page(1L).pageSize(1L).build() + val params = + InboxListCreditNotesParams.builder() + .page(1L) + .pageSize(1L) + .sortBy(InboxListCreditNotesParams.SortBy.CREATED_AT) + .sortOrder(InboxListCreditNotesParams.SortOrder.ASC) + .build() val queryParams = params._queryParams() assertThat(queryParams) - .isEqualTo(QueryParams.builder().put("page", "1").put("page_size", "1").build()) + .isEqualTo( + QueryParams.builder() + .put("page", "1") + .put("page_size", "1") + .put("sort_by", "created_at") + .put("sort_order", "asc") + .build() + ) } @Test diff --git a/e-invoice-java-core/src/test/kotlin/com/e_invoice/api/models/inbox/InboxListInvoicesParamsTest.kt b/e-invoice-java-core/src/test/kotlin/com/e_invoice/api/models/inbox/InboxListInvoicesParamsTest.kt index a50637f..9533902 100644 --- a/e-invoice-java-core/src/test/kotlin/com/e_invoice/api/models/inbox/InboxListInvoicesParamsTest.kt +++ b/e-invoice-java-core/src/test/kotlin/com/e_invoice/api/models/inbox/InboxListInvoicesParamsTest.kt @@ -10,17 +10,35 @@ internal class InboxListInvoicesParamsTest { @Test fun create() { - InboxListInvoicesParams.builder().page(1L).pageSize(1L).build() + InboxListInvoicesParams.builder() + .page(1L) + .pageSize(1L) + .sortBy(InboxListInvoicesParams.SortBy.CREATED_AT) + .sortOrder(InboxListInvoicesParams.SortOrder.ASC) + .build() } @Test fun queryParams() { - val params = InboxListInvoicesParams.builder().page(1L).pageSize(1L).build() + val params = + InboxListInvoicesParams.builder() + .page(1L) + .pageSize(1L) + .sortBy(InboxListInvoicesParams.SortBy.CREATED_AT) + .sortOrder(InboxListInvoicesParams.SortOrder.ASC) + .build() val queryParams = params._queryParams() assertThat(queryParams) - .isEqualTo(QueryParams.builder().put("page", "1").put("page_size", "1").build()) + .isEqualTo( + QueryParams.builder() + .put("page", "1") + .put("page_size", "1") + .put("sort_by", "created_at") + .put("sort_order", "asc") + .build() + ) } @Test diff --git a/e-invoice-java-core/src/test/kotlin/com/e_invoice/api/models/inbox/InboxListParamsTest.kt b/e-invoice-java-core/src/test/kotlin/com/e_invoice/api/models/inbox/InboxListParamsTest.kt index 82caeb7..094ac87 100644 --- a/e-invoice-java-core/src/test/kotlin/com/e_invoice/api/models/inbox/InboxListParamsTest.kt +++ b/e-invoice-java-core/src/test/kotlin/com/e_invoice/api/models/inbox/InboxListParamsTest.kt @@ -19,7 +19,8 @@ internal class InboxListParamsTest { .pageSize(1L) .search("search") .sender("sender") - .state(DocumentState.DRAFT) + .sortBy(InboxListParams.SortBy.CREATED_AT) + .sortOrder(InboxListParams.SortOrder.ASC) .type(DocumentType.INVOICE) .build() } @@ -34,7 +35,8 @@ internal class InboxListParamsTest { .pageSize(1L) .search("search") .sender("sender") - .state(DocumentState.DRAFT) + .sortBy(InboxListParams.SortBy.CREATED_AT) + .sortOrder(InboxListParams.SortOrder.ASC) .type(DocumentType.INVOICE) .build() @@ -49,7 +51,8 @@ internal class InboxListParamsTest { .put("page_size", "1") .put("search", "search") .put("sender", "sender") - .put("state", "DRAFT") + .put("sort_by", "created_at") + .put("sort_order", "asc") .put("type", "INVOICE") .build() ) diff --git a/e-invoice-java-core/src/test/kotlin/com/e_invoice/api/models/inbox/PaginatedDocumentResponseTest.kt b/e-invoice-java-core/src/test/kotlin/com/e_invoice/api/models/inbox/PaginatedDocumentResponseTest.kt index f7d2eee..a006f2e 100644 --- a/e-invoice-java-core/src/test/kotlin/com/e_invoice/api/models/inbox/PaginatedDocumentResponseTest.kt +++ b/e-invoice-java-core/src/test/kotlin/com/e_invoice/api/models/inbox/PaginatedDocumentResponseTest.kt @@ -3,6 +3,8 @@ package com.e_invoice.api.models.inbox import com.e_invoice.api.core.jsonMapper +import com.e_invoice.api.models.documents.Allowance +import com.e_invoice.api.models.documents.Charge import com.e_invoice.api.models.documents.CurrencyCode import com.e_invoice.api.models.documents.DocumentDirection import com.e_invoice.api.models.documents.DocumentResponse @@ -11,6 +13,7 @@ import com.e_invoice.api.models.documents.UnitOfMeasureCode import com.e_invoice.api.models.documents.attachments.DocumentAttachment import com.fasterxml.jackson.module.kotlin.jacksonTypeRef import java.time.LocalDate +import java.time.OffsetDateTime import org.assertj.core.api.Assertions.assertThat import org.junit.jupiter.api.Test @@ -20,9 +23,22 @@ internal class PaginatedDocumentResponseTest { fun create() { val paginatedDocumentResponse = PaginatedDocumentResponse.builder() + .hasNextPage(true) .addItem( DocumentResponse.builder() .id("id") + .createdAt(OffsetDateTime.parse("2019-12-27T18:11:19.117Z")) + .addAllowance( + DocumentResponse.Allowance.builder() + .amount("amount") + .baseAmount("base_amount") + .multiplierFactor("multiplier_factor") + .reason("reason") + .reasonCode(DocumentResponse.Allowance.ReasonCode._41) + .taxCode(DocumentResponse.Allowance.TaxCode.AE) + .taxRate("tax_rate") + .build() + ) .amountDue("amount_due") .addAttachment( DocumentAttachment.builder() @@ -35,13 +51,25 @@ internal class PaginatedDocumentResponseTest { ) .billingAddress("billing_address") .billingAddressRecipient("billing_address_recipient") + .addCharge( + DocumentResponse.Charge.builder() + .amount("amount") + .baseAmount("base_amount") + .multiplierFactor("multiplier_factor") + .reason("reason") + .reasonCode(DocumentResponse.Charge.ReasonCode.AA) + .taxCode(DocumentResponse.Charge.TaxCode.AE) + .taxRate("21.00") + .build() + ) .currency(CurrencyCode.EUR) .customerAddress("customer_address") .customerAddressRecipient("customer_address_recipient") + .customerCompanyId("1018265814") .customerEmail("customer_email") .customerId("customer_id") .customerName("customer_name") - .customerTaxId("customer_tax_id") + .customerTaxId("BE1018265814") .direction(DocumentDirection.INBOUND) .documentType(DocumentType.INVOICE) .dueDate(LocalDate.parse("2019-12-27")) @@ -50,13 +78,35 @@ internal class PaginatedDocumentResponseTest { .invoiceTotal("invoice_total") .addItem( DocumentResponse.Item.builder() + .addAllowance( + Allowance.builder() + .amount("amount") + .baseAmount("base_amount") + .multiplierFactor("multiplier_factor") + .reason("reason") + .reasonCode(Allowance.ReasonCode._41) + .taxCode(Allowance.TaxCode.AE) + .taxRate("tax_rate") + .build() + ) .amount("amount") + .addCharge( + Charge.builder() + .amount("amount") + .baseAmount("base_amount") + .multiplierFactor("multiplier_factor") + .reason("reason") + .reasonCode(Charge.ReasonCode.AA) + .taxCode(Charge.TaxCode.AE) + .taxRate("21.00") + .build() + ) .date(null) .description("description") .productCode("product_code") .quantity("quantity") .tax("tax") - .taxRate("tax_rate") + .taxRate("21.00") .unit(UnitOfMeasureCode._10) .unitPrice("unit_price") .build() @@ -71,7 +121,6 @@ internal class PaginatedDocumentResponseTest { .build() ) .paymentTerm("payment_term") - .previousUnpaidBalance("previous_unpaid_balance") .purchaseOrder("purchase_order") .remittanceAddress("remittance_address") .remittanceAddressRecipient("remittance_address_recipient") @@ -83,6 +132,7 @@ internal class PaginatedDocumentResponseTest { .shippingAddressRecipient("shipping_address_recipient") .state(DocumentState.DRAFT) .subtotal("subtotal") + .taxCode(DocumentResponse.TaxCode.AE) .addTaxDetail( DocumentResponse.TaxDetail.builder() .amount("amount") @@ -91,11 +141,14 @@ internal class PaginatedDocumentResponseTest { ) .totalDiscount("total_discount") .totalTax("total_tax") + .vatex(DocumentResponse.Vatex.VATEX_EU_79_C) + .vatexNote("vatex_note") .vendorAddress("vendor_address") .vendorAddressRecipient("vendor_address_recipient") + .vendorCompanyId("1018265814") .vendorEmail("vendor_email") .vendorName("vendor_name") - .vendorTaxId("vendor_tax_id") + .vendorTaxId("BE1018265814") .build() ) .page(0L) @@ -104,10 +157,23 @@ internal class PaginatedDocumentResponseTest { .total(0L) .build() + assertThat(paginatedDocumentResponse.hasNextPage()).isEqualTo(true) assertThat(paginatedDocumentResponse.items()) .containsExactly( DocumentResponse.builder() .id("id") + .createdAt(OffsetDateTime.parse("2019-12-27T18:11:19.117Z")) + .addAllowance( + DocumentResponse.Allowance.builder() + .amount("amount") + .baseAmount("base_amount") + .multiplierFactor("multiplier_factor") + .reason("reason") + .reasonCode(DocumentResponse.Allowance.ReasonCode._41) + .taxCode(DocumentResponse.Allowance.TaxCode.AE) + .taxRate("tax_rate") + .build() + ) .amountDue("amount_due") .addAttachment( DocumentAttachment.builder() @@ -120,13 +186,25 @@ internal class PaginatedDocumentResponseTest { ) .billingAddress("billing_address") .billingAddressRecipient("billing_address_recipient") + .addCharge( + DocumentResponse.Charge.builder() + .amount("amount") + .baseAmount("base_amount") + .multiplierFactor("multiplier_factor") + .reason("reason") + .reasonCode(DocumentResponse.Charge.ReasonCode.AA) + .taxCode(DocumentResponse.Charge.TaxCode.AE) + .taxRate("21.00") + .build() + ) .currency(CurrencyCode.EUR) .customerAddress("customer_address") .customerAddressRecipient("customer_address_recipient") + .customerCompanyId("1018265814") .customerEmail("customer_email") .customerId("customer_id") .customerName("customer_name") - .customerTaxId("customer_tax_id") + .customerTaxId("BE1018265814") .direction(DocumentDirection.INBOUND) .documentType(DocumentType.INVOICE) .dueDate(LocalDate.parse("2019-12-27")) @@ -135,13 +213,35 @@ internal class PaginatedDocumentResponseTest { .invoiceTotal("invoice_total") .addItem( DocumentResponse.Item.builder() + .addAllowance( + Allowance.builder() + .amount("amount") + .baseAmount("base_amount") + .multiplierFactor("multiplier_factor") + .reason("reason") + .reasonCode(Allowance.ReasonCode._41) + .taxCode(Allowance.TaxCode.AE) + .taxRate("tax_rate") + .build() + ) .amount("amount") + .addCharge( + Charge.builder() + .amount("amount") + .baseAmount("base_amount") + .multiplierFactor("multiplier_factor") + .reason("reason") + .reasonCode(Charge.ReasonCode.AA) + .taxCode(Charge.TaxCode.AE) + .taxRate("21.00") + .build() + ) .date(null) .description("description") .productCode("product_code") .quantity("quantity") .tax("tax") - .taxRate("tax_rate") + .taxRate("21.00") .unit(UnitOfMeasureCode._10) .unitPrice("unit_price") .build() @@ -156,7 +256,6 @@ internal class PaginatedDocumentResponseTest { .build() ) .paymentTerm("payment_term") - .previousUnpaidBalance("previous_unpaid_balance") .purchaseOrder("purchase_order") .remittanceAddress("remittance_address") .remittanceAddressRecipient("remittance_address_recipient") @@ -168,16 +267,20 @@ internal class PaginatedDocumentResponseTest { .shippingAddressRecipient("shipping_address_recipient") .state(DocumentState.DRAFT) .subtotal("subtotal") + .taxCode(DocumentResponse.TaxCode.AE) .addTaxDetail( DocumentResponse.TaxDetail.builder().amount("amount").rate("rate").build() ) .totalDiscount("total_discount") .totalTax("total_tax") + .vatex(DocumentResponse.Vatex.VATEX_EU_79_C) + .vatexNote("vatex_note") .vendorAddress("vendor_address") .vendorAddressRecipient("vendor_address_recipient") + .vendorCompanyId("1018265814") .vendorEmail("vendor_email") .vendorName("vendor_name") - .vendorTaxId("vendor_tax_id") + .vendorTaxId("BE1018265814") .build() ) assertThat(paginatedDocumentResponse.page()).isEqualTo(0L) @@ -191,9 +294,22 @@ internal class PaginatedDocumentResponseTest { val jsonMapper = jsonMapper() val paginatedDocumentResponse = PaginatedDocumentResponse.builder() + .hasNextPage(true) .addItem( DocumentResponse.builder() .id("id") + .createdAt(OffsetDateTime.parse("2019-12-27T18:11:19.117Z")) + .addAllowance( + DocumentResponse.Allowance.builder() + .amount("amount") + .baseAmount("base_amount") + .multiplierFactor("multiplier_factor") + .reason("reason") + .reasonCode(DocumentResponse.Allowance.ReasonCode._41) + .taxCode(DocumentResponse.Allowance.TaxCode.AE) + .taxRate("tax_rate") + .build() + ) .amountDue("amount_due") .addAttachment( DocumentAttachment.builder() @@ -206,13 +322,25 @@ internal class PaginatedDocumentResponseTest { ) .billingAddress("billing_address") .billingAddressRecipient("billing_address_recipient") + .addCharge( + DocumentResponse.Charge.builder() + .amount("amount") + .baseAmount("base_amount") + .multiplierFactor("multiplier_factor") + .reason("reason") + .reasonCode(DocumentResponse.Charge.ReasonCode.AA) + .taxCode(DocumentResponse.Charge.TaxCode.AE) + .taxRate("21.00") + .build() + ) .currency(CurrencyCode.EUR) .customerAddress("customer_address") .customerAddressRecipient("customer_address_recipient") + .customerCompanyId("1018265814") .customerEmail("customer_email") .customerId("customer_id") .customerName("customer_name") - .customerTaxId("customer_tax_id") + .customerTaxId("BE1018265814") .direction(DocumentDirection.INBOUND) .documentType(DocumentType.INVOICE) .dueDate(LocalDate.parse("2019-12-27")) @@ -221,13 +349,35 @@ internal class PaginatedDocumentResponseTest { .invoiceTotal("invoice_total") .addItem( DocumentResponse.Item.builder() + .addAllowance( + Allowance.builder() + .amount("amount") + .baseAmount("base_amount") + .multiplierFactor("multiplier_factor") + .reason("reason") + .reasonCode(Allowance.ReasonCode._41) + .taxCode(Allowance.TaxCode.AE) + .taxRate("tax_rate") + .build() + ) .amount("amount") + .addCharge( + Charge.builder() + .amount("amount") + .baseAmount("base_amount") + .multiplierFactor("multiplier_factor") + .reason("reason") + .reasonCode(Charge.ReasonCode.AA) + .taxCode(Charge.TaxCode.AE) + .taxRate("21.00") + .build() + ) .date(null) .description("description") .productCode("product_code") .quantity("quantity") .tax("tax") - .taxRate("tax_rate") + .taxRate("21.00") .unit(UnitOfMeasureCode._10) .unitPrice("unit_price") .build() @@ -242,7 +392,6 @@ internal class PaginatedDocumentResponseTest { .build() ) .paymentTerm("payment_term") - .previousUnpaidBalance("previous_unpaid_balance") .purchaseOrder("purchase_order") .remittanceAddress("remittance_address") .remittanceAddressRecipient("remittance_address_recipient") @@ -254,6 +403,7 @@ internal class PaginatedDocumentResponseTest { .shippingAddressRecipient("shipping_address_recipient") .state(DocumentState.DRAFT) .subtotal("subtotal") + .taxCode(DocumentResponse.TaxCode.AE) .addTaxDetail( DocumentResponse.TaxDetail.builder() .amount("amount") @@ -262,11 +412,14 @@ internal class PaginatedDocumentResponseTest { ) .totalDiscount("total_discount") .totalTax("total_tax") + .vatex(DocumentResponse.Vatex.VATEX_EU_79_C) + .vatexNote("vatex_note") .vendorAddress("vendor_address") .vendorAddressRecipient("vendor_address_recipient") + .vendorCompanyId("1018265814") .vendorEmail("vendor_email") .vendorName("vendor_name") - .vendorTaxId("vendor_tax_id") + .vendorTaxId("BE1018265814") .build() ) .page(0L) diff --git a/e-invoice-java-core/src/test/kotlin/com/e_invoice/api/models/lookup/LookupRetrieveResponseTest.kt b/e-invoice-java-core/src/test/kotlin/com/e_invoice/api/models/lookup/LookupRetrieveResponseTest.kt index bc695d1..ab81f34 100644 --- a/e-invoice-java-core/src/test/kotlin/com/e_invoice/api/models/lookup/LookupRetrieveResponseTest.kt +++ b/e-invoice-java-core/src/test/kotlin/com/e_invoice/api/models/lookup/LookupRetrieveResponseTest.kt @@ -51,6 +51,8 @@ internal class LookupRetrieveResponseTest { .smlHostname("edelivery.tech.ec.europa.eu") .status("success") .error("DNS lookup failed: no such domain") + .lookupMethod("naptr") + .smpHostname("smp.e-invoice.be") .build() ) .addError("DNS lookup failed") @@ -59,9 +61,9 @@ internal class LookupRetrieveResponseTest { .queryMetadata( LookupRetrieveResponse.QueryMetadata.builder() .identifierScheme("iso6523-actorid-upis") - .identifierValue("0192:991825827") + .identifierValue("0208:1018265814") .smlDomain("edelivery.tech.ec.europa.eu") - .timestamp("2023-04-12T14:32:10.123456") + .timestamp("2026-01-12T14:32:10.123456") .version("1.0.0") .build() ) @@ -173,6 +175,8 @@ internal class LookupRetrieveResponseTest { .smlHostname("edelivery.tech.ec.europa.eu") .status("success") .error("DNS lookup failed: no such domain") + .lookupMethod("naptr") + .smpHostname("smp.e-invoice.be") .build() ) assertThat(lookupRetrieveResponse.errors()) @@ -182,9 +186,9 @@ internal class LookupRetrieveResponseTest { .isEqualTo( LookupRetrieveResponse.QueryMetadata.builder() .identifierScheme("iso6523-actorid-upis") - .identifierValue("0192:991825827") + .identifierValue("0208:1018265814") .smlDomain("edelivery.tech.ec.europa.eu") - .timestamp("2023-04-12T14:32:10.123456") + .timestamp("2026-01-12T14:32:10.123456") .version("1.0.0") .build() ) @@ -296,6 +300,8 @@ internal class LookupRetrieveResponseTest { .smlHostname("edelivery.tech.ec.europa.eu") .status("success") .error("DNS lookup failed: no such domain") + .lookupMethod("naptr") + .smpHostname("smp.e-invoice.be") .build() ) .addError("DNS lookup failed") @@ -304,9 +310,9 @@ internal class LookupRetrieveResponseTest { .queryMetadata( LookupRetrieveResponse.QueryMetadata.builder() .identifierScheme("iso6523-actorid-upis") - .identifierValue("0192:991825827") + .identifierValue("0208:1018265814") .smlDomain("edelivery.tech.ec.europa.eu") - .timestamp("2023-04-12T14:32:10.123456") + .timestamp("2026-01-12T14:32:10.123456") .version("1.0.0") .build() ) diff --git a/e-invoice-java-core/src/test/kotlin/com/e_invoice/api/models/me/MeRetrieveParamsTest.kt b/e-invoice-java-core/src/test/kotlin/com/e_invoice/api/models/me/MeRetrieveParamsTest.kt new file mode 100644 index 0000000..c7522d1 --- /dev/null +++ b/e-invoice-java-core/src/test/kotlin/com/e_invoice/api/models/me/MeRetrieveParamsTest.kt @@ -0,0 +1,13 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.e_invoice.api.models.me + +import org.junit.jupiter.api.Test + +internal class MeRetrieveParamsTest { + + @Test + fun create() { + MeRetrieveParams.builder().build() + } +} diff --git a/e-invoice-java-core/src/test/kotlin/com/e_invoice/api/models/me/MeRetrieveResponseTest.kt b/e-invoice-java-core/src/test/kotlin/com/e_invoice/api/models/me/MeRetrieveResponseTest.kt new file mode 100644 index 0000000..b2625c9 --- /dev/null +++ b/e-invoice-java-core/src/test/kotlin/com/e_invoice/api/models/me/MeRetrieveResponseTest.kt @@ -0,0 +1,89 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.e_invoice.api.models.me + +import com.e_invoice.api.core.jsonMapper +import com.fasterxml.jackson.module.kotlin.jacksonTypeRef +import java.time.OffsetDateTime +import kotlin.jvm.optionals.getOrNull +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class MeRetrieveResponseTest { + + @Test + fun create() { + val meRetrieveResponse = + MeRetrieveResponse.builder() + .name("name") + .bccRecipientEmail("bcc_recipient_email") + .companyAddress("Brusselsesteenweg 119/A") + .companyCity("Zemst") + .companyCountry("Belgium") + .companyEmail("info@e-invoice.be") + .companyName("E-INVOICE BV") + .companyNumber("1018265814") + .companyTaxId("BE1018265814") + .companyZip("1980") + .creditBalance(0L) + .description("description") + .addIban("string") + .addPeppolId("string") + .plan(MeRetrieveResponse.Plan.STARTER) + .smpRegistration(true) + .smpRegistrationDate(OffsetDateTime.parse("2019-12-27T18:11:19.117Z")) + .build() + + assertThat(meRetrieveResponse.name()).isEqualTo("name") + assertThat(meRetrieveResponse.bccRecipientEmail()).contains("bcc_recipient_email") + assertThat(meRetrieveResponse.companyAddress()).contains("Brusselsesteenweg 119/A") + assertThat(meRetrieveResponse.companyCity()).contains("Zemst") + assertThat(meRetrieveResponse.companyCountry()).contains("Belgium") + assertThat(meRetrieveResponse.companyEmail()).contains("info@e-invoice.be") + assertThat(meRetrieveResponse.companyName()).contains("E-INVOICE BV") + assertThat(meRetrieveResponse.companyNumber()).contains("1018265814") + assertThat(meRetrieveResponse.companyTaxId()).contains("BE1018265814") + assertThat(meRetrieveResponse.companyZip()).contains("1980") + assertThat(meRetrieveResponse.creditBalance()).contains(0L) + assertThat(meRetrieveResponse.description()).contains("description") + assertThat(meRetrieveResponse.ibans().getOrNull()).containsExactly("string") + assertThat(meRetrieveResponse.peppolIds().getOrNull()).containsExactly("string") + assertThat(meRetrieveResponse.plan()).contains(MeRetrieveResponse.Plan.STARTER) + assertThat(meRetrieveResponse.smpRegistration()).contains(true) + assertThat(meRetrieveResponse.smpRegistrationDate()) + .contains(OffsetDateTime.parse("2019-12-27T18:11:19.117Z")) + } + + @Test + fun roundtrip() { + val jsonMapper = jsonMapper() + val meRetrieveResponse = + MeRetrieveResponse.builder() + .name("name") + .bccRecipientEmail("bcc_recipient_email") + .companyAddress("Brusselsesteenweg 119/A") + .companyCity("Zemst") + .companyCountry("Belgium") + .companyEmail("info@e-invoice.be") + .companyName("E-INVOICE BV") + .companyNumber("1018265814") + .companyTaxId("BE1018265814") + .companyZip("1980") + .creditBalance(0L) + .description("description") + .addIban("string") + .addPeppolId("string") + .plan(MeRetrieveResponse.Plan.STARTER) + .smpRegistration(true) + .smpRegistrationDate(OffsetDateTime.parse("2019-12-27T18:11:19.117Z")) + .build() + + val roundtrippedMeRetrieveResponse = + jsonMapper.readValue( + jsonMapper.writeValueAsString(meRetrieveResponse), + jacksonTypeRef(), + ) + + assertThat(roundtrippedMeRetrieveResponse).isEqualTo(meRetrieveResponse) + } +} diff --git a/e-invoice-java-core/src/test/kotlin/com/e_invoice/api/models/outbox/OutboxListDraftDocumentsParamsTest.kt b/e-invoice-java-core/src/test/kotlin/com/e_invoice/api/models/outbox/OutboxListDraftDocumentsParamsTest.kt index df4033e..45b6567 100644 --- a/e-invoice-java-core/src/test/kotlin/com/e_invoice/api/models/outbox/OutboxListDraftDocumentsParamsTest.kt +++ b/e-invoice-java-core/src/test/kotlin/com/e_invoice/api/models/outbox/OutboxListDraftDocumentsParamsTest.kt @@ -3,6 +3,8 @@ package com.e_invoice.api.models.outbox import com.e_invoice.api.core.http.QueryParams +import com.e_invoice.api.models.documents.DocumentType +import com.e_invoice.api.models.inbox.DocumentState import org.assertj.core.api.Assertions.assertThat import org.junit.jupiter.api.Test @@ -10,17 +12,44 @@ internal class OutboxListDraftDocumentsParamsTest { @Test fun create() { - OutboxListDraftDocumentsParams.builder().page(1L).pageSize(1L).build() + OutboxListDraftDocumentsParams.builder() + .page(1L) + .pageSize(1L) + .search("search") + .sortBy(OutboxListDraftDocumentsParams.SortBy.CREATED_AT) + .sortOrder(OutboxListDraftDocumentsParams.SortOrder.ASC) + .state(DocumentState.DRAFT) + .type(DocumentType.INVOICE) + .build() } @Test fun queryParams() { - val params = OutboxListDraftDocumentsParams.builder().page(1L).pageSize(1L).build() + val params = + OutboxListDraftDocumentsParams.builder() + .page(1L) + .pageSize(1L) + .search("search") + .sortBy(OutboxListDraftDocumentsParams.SortBy.CREATED_AT) + .sortOrder(OutboxListDraftDocumentsParams.SortOrder.ASC) + .state(DocumentState.DRAFT) + .type(DocumentType.INVOICE) + .build() val queryParams = params._queryParams() assertThat(queryParams) - .isEqualTo(QueryParams.builder().put("page", "1").put("page_size", "1").build()) + .isEqualTo( + QueryParams.builder() + .put("page", "1") + .put("page_size", "1") + .put("search", "search") + .put("sort_by", "created_at") + .put("sort_order", "asc") + .put("state", "DRAFT") + .put("type", "INVOICE") + .build() + ) } @Test diff --git a/e-invoice-java-core/src/test/kotlin/com/e_invoice/api/models/outbox/OutboxListReceivedDocumentsParamsTest.kt b/e-invoice-java-core/src/test/kotlin/com/e_invoice/api/models/outbox/OutboxListReceivedDocumentsParamsTest.kt index 0148e9f..345ce6b 100644 --- a/e-invoice-java-core/src/test/kotlin/com/e_invoice/api/models/outbox/OutboxListReceivedDocumentsParamsTest.kt +++ b/e-invoice-java-core/src/test/kotlin/com/e_invoice/api/models/outbox/OutboxListReceivedDocumentsParamsTest.kt @@ -4,7 +4,6 @@ package com.e_invoice.api.models.outbox import com.e_invoice.api.core.http.QueryParams import com.e_invoice.api.models.documents.DocumentType -import com.e_invoice.api.models.inbox.DocumentState import java.time.OffsetDateTime import org.assertj.core.api.Assertions.assertThat import org.junit.jupiter.api.Test @@ -18,9 +17,11 @@ internal class OutboxListReceivedDocumentsParamsTest { .dateTo(OffsetDateTime.parse("2019-12-27T18:11:19.117Z")) .page(1L) .pageSize(1L) + .receiver("receiver") .search("search") .sender("sender") - .state(DocumentState.DRAFT) + .sortBy(OutboxListReceivedDocumentsParams.SortBy.CREATED_AT) + .sortOrder(OutboxListReceivedDocumentsParams.SortOrder.ASC) .type(DocumentType.INVOICE) .build() } @@ -33,9 +34,11 @@ internal class OutboxListReceivedDocumentsParamsTest { .dateTo(OffsetDateTime.parse("2019-12-27T18:11:19.117Z")) .page(1L) .pageSize(1L) + .receiver("receiver") .search("search") .sender("sender") - .state(DocumentState.DRAFT) + .sortBy(OutboxListReceivedDocumentsParams.SortBy.CREATED_AT) + .sortOrder(OutboxListReceivedDocumentsParams.SortOrder.ASC) .type(DocumentType.INVOICE) .build() @@ -48,9 +51,11 @@ internal class OutboxListReceivedDocumentsParamsTest { .put("date_to", "2019-12-27T18:11:19.117Z") .put("page", "1") .put("page_size", "1") + .put("receiver", "receiver") .put("search", "search") .put("sender", "sender") - .put("state", "DRAFT") + .put("sort_by", "created_at") + .put("sort_order", "asc") .put("type", "INVOICE") .build() ) diff --git a/e-invoice-java-core/src/test/kotlin/com/e_invoice/api/models/validate/ValidateValidateJsonParamsTest.kt b/e-invoice-java-core/src/test/kotlin/com/e_invoice/api/models/validate/ValidateValidateJsonParamsTest.kt index a468954..c7813a7 100644 --- a/e-invoice-java-core/src/test/kotlin/com/e_invoice/api/models/validate/ValidateValidateJsonParamsTest.kt +++ b/e-invoice-java-core/src/test/kotlin/com/e_invoice/api/models/validate/ValidateValidateJsonParamsTest.kt @@ -21,6 +21,17 @@ internal class ValidateValidateJsonParamsTest { ValidateValidateJsonParams.builder() .documentCreate( DocumentCreate.builder() + .addAllowance( + DocumentCreate.Allowance.builder() + .amount(0.0) + .baseAmount(0.0) + .multiplierFactor(0.0) + .reason("reason") + .reasonCode(DocumentCreate.Allowance.ReasonCode._41) + .taxCode(DocumentCreate.Allowance.TaxCode.AE) + .taxRate(0.0) + .build() + ) .amountDue(0.0) .addAttachment( DocumentAttachmentCreate.builder() @@ -32,13 +43,25 @@ internal class ValidateValidateJsonParamsTest { ) .billingAddress("billing_address") .billingAddressRecipient("billing_address_recipient") + .addCharge( + DocumentCreate.Charge.builder() + .amount(0.0) + .baseAmount(0.0) + .multiplierFactor(0.0) + .reason("reason") + .reasonCode(DocumentCreate.Charge.ReasonCode.AA) + .taxCode(DocumentCreate.Charge.TaxCode.AE) + .taxRate("21.00") + .build() + ) .currency(CurrencyCode.EUR) .customerAddress("customer_address") .customerAddressRecipient("customer_address_recipient") + .customerCompanyId("1018265814") .customerEmail("customer_email") .customerId("customer_id") .customerName("customer_name") - .customerTaxId("customer_tax_id") + .customerTaxId("BE1018265814") .direction(DocumentDirection.INBOUND) .documentType(DocumentType.INVOICE) .dueDate(LocalDate.parse("2019-12-27")) @@ -47,13 +70,35 @@ internal class ValidateValidateJsonParamsTest { .invoiceTotal(0.0) .addItem( DocumentCreate.Item.builder() + .addAllowance( + DocumentCreate.Item.Allowance.builder() + .amount(0.0) + .baseAmount(0.0) + .multiplierFactor(0.0) + .reason("reason") + .reasonCode(DocumentCreate.Item.Allowance.ReasonCode._41) + .taxCode(DocumentCreate.Item.Allowance.TaxCode.AE) + .taxRate(0.0) + .build() + ) .amount(0.0) + .addCharge( + DocumentCreate.Item.Charge.builder() + .amount(0.0) + .baseAmount(0.0) + .multiplierFactor(0.0) + .reason("reason") + .reasonCode(DocumentCreate.Item.Charge.ReasonCode.AA) + .taxCode(DocumentCreate.Item.Charge.TaxCode.AE) + .taxRate("21.00") + .build() + ) .date(null) .description("description") .productCode("product_code") .quantity(0.0) .tax(0.0) - .taxRate("tax_rate") + .taxRate("21.00") .unit(UnitOfMeasureCode._10) .unitPrice(0.0) .build() @@ -80,16 +125,20 @@ internal class ValidateValidateJsonParamsTest { .shippingAddressRecipient("shipping_address_recipient") .state(DocumentState.DRAFT) .subtotal(0.0) + .taxCode(DocumentCreate.TaxCode.AE) .addTaxDetail( DocumentCreate.TaxDetail.builder().amount(0.0).rate("rate").build() ) .totalDiscount(0.0) .totalTax(0.0) + .vatex(DocumentCreate.Vatex.VATEX_EU_79_C) + .vatexNote("vatex_note") .vendorAddress("vendor_address") .vendorAddressRecipient("vendor_address_recipient") + .vendorCompanyId("1018265814") .vendorEmail("vendor_email") .vendorName("vendor_name") - .vendorTaxId("vendor_tax_id") + .vendorTaxId("BE1018265814") .build() ) .build() @@ -101,6 +150,17 @@ internal class ValidateValidateJsonParamsTest { ValidateValidateJsonParams.builder() .documentCreate( DocumentCreate.builder() + .addAllowance( + DocumentCreate.Allowance.builder() + .amount(0.0) + .baseAmount(0.0) + .multiplierFactor(0.0) + .reason("reason") + .reasonCode(DocumentCreate.Allowance.ReasonCode._41) + .taxCode(DocumentCreate.Allowance.TaxCode.AE) + .taxRate(0.0) + .build() + ) .amountDue(0.0) .addAttachment( DocumentAttachmentCreate.builder() @@ -112,13 +172,25 @@ internal class ValidateValidateJsonParamsTest { ) .billingAddress("billing_address") .billingAddressRecipient("billing_address_recipient") + .addCharge( + DocumentCreate.Charge.builder() + .amount(0.0) + .baseAmount(0.0) + .multiplierFactor(0.0) + .reason("reason") + .reasonCode(DocumentCreate.Charge.ReasonCode.AA) + .taxCode(DocumentCreate.Charge.TaxCode.AE) + .taxRate("21.00") + .build() + ) .currency(CurrencyCode.EUR) .customerAddress("customer_address") .customerAddressRecipient("customer_address_recipient") + .customerCompanyId("1018265814") .customerEmail("customer_email") .customerId("customer_id") .customerName("customer_name") - .customerTaxId("customer_tax_id") + .customerTaxId("BE1018265814") .direction(DocumentDirection.INBOUND) .documentType(DocumentType.INVOICE) .dueDate(LocalDate.parse("2019-12-27")) @@ -127,13 +199,35 @@ internal class ValidateValidateJsonParamsTest { .invoiceTotal(0.0) .addItem( DocumentCreate.Item.builder() + .addAllowance( + DocumentCreate.Item.Allowance.builder() + .amount(0.0) + .baseAmount(0.0) + .multiplierFactor(0.0) + .reason("reason") + .reasonCode(DocumentCreate.Item.Allowance.ReasonCode._41) + .taxCode(DocumentCreate.Item.Allowance.TaxCode.AE) + .taxRate(0.0) + .build() + ) .amount(0.0) + .addCharge( + DocumentCreate.Item.Charge.builder() + .amount(0.0) + .baseAmount(0.0) + .multiplierFactor(0.0) + .reason("reason") + .reasonCode(DocumentCreate.Item.Charge.ReasonCode.AA) + .taxCode(DocumentCreate.Item.Charge.TaxCode.AE) + .taxRate("21.00") + .build() + ) .date(null) .description("description") .productCode("product_code") .quantity(0.0) .tax(0.0) - .taxRate("tax_rate") + .taxRate("21.00") .unit(UnitOfMeasureCode._10) .unitPrice(0.0) .build() @@ -160,16 +254,20 @@ internal class ValidateValidateJsonParamsTest { .shippingAddressRecipient("shipping_address_recipient") .state(DocumentState.DRAFT) .subtotal(0.0) + .taxCode(DocumentCreate.TaxCode.AE) .addTaxDetail( DocumentCreate.TaxDetail.builder().amount(0.0).rate("rate").build() ) .totalDiscount(0.0) .totalTax(0.0) + .vatex(DocumentCreate.Vatex.VATEX_EU_79_C) + .vatexNote("vatex_note") .vendorAddress("vendor_address") .vendorAddressRecipient("vendor_address_recipient") + .vendorCompanyId("1018265814") .vendorEmail("vendor_email") .vendorName("vendor_name") - .vendorTaxId("vendor_tax_id") + .vendorTaxId("BE1018265814") .build() ) .build() @@ -179,6 +277,17 @@ internal class ValidateValidateJsonParamsTest { assertThat(body) .isEqualTo( DocumentCreate.builder() + .addAllowance( + DocumentCreate.Allowance.builder() + .amount(0.0) + .baseAmount(0.0) + .multiplierFactor(0.0) + .reason("reason") + .reasonCode(DocumentCreate.Allowance.ReasonCode._41) + .taxCode(DocumentCreate.Allowance.TaxCode.AE) + .taxRate(0.0) + .build() + ) .amountDue(0.0) .addAttachment( DocumentAttachmentCreate.builder() @@ -190,13 +299,25 @@ internal class ValidateValidateJsonParamsTest { ) .billingAddress("billing_address") .billingAddressRecipient("billing_address_recipient") + .addCharge( + DocumentCreate.Charge.builder() + .amount(0.0) + .baseAmount(0.0) + .multiplierFactor(0.0) + .reason("reason") + .reasonCode(DocumentCreate.Charge.ReasonCode.AA) + .taxCode(DocumentCreate.Charge.TaxCode.AE) + .taxRate("21.00") + .build() + ) .currency(CurrencyCode.EUR) .customerAddress("customer_address") .customerAddressRecipient("customer_address_recipient") + .customerCompanyId("1018265814") .customerEmail("customer_email") .customerId("customer_id") .customerName("customer_name") - .customerTaxId("customer_tax_id") + .customerTaxId("BE1018265814") .direction(DocumentDirection.INBOUND) .documentType(DocumentType.INVOICE) .dueDate(LocalDate.parse("2019-12-27")) @@ -205,13 +326,35 @@ internal class ValidateValidateJsonParamsTest { .invoiceTotal(0.0) .addItem( DocumentCreate.Item.builder() + .addAllowance( + DocumentCreate.Item.Allowance.builder() + .amount(0.0) + .baseAmount(0.0) + .multiplierFactor(0.0) + .reason("reason") + .reasonCode(DocumentCreate.Item.Allowance.ReasonCode._41) + .taxCode(DocumentCreate.Item.Allowance.TaxCode.AE) + .taxRate(0.0) + .build() + ) .amount(0.0) + .addCharge( + DocumentCreate.Item.Charge.builder() + .amount(0.0) + .baseAmount(0.0) + .multiplierFactor(0.0) + .reason("reason") + .reasonCode(DocumentCreate.Item.Charge.ReasonCode.AA) + .taxCode(DocumentCreate.Item.Charge.TaxCode.AE) + .taxRate("21.00") + .build() + ) .date(null) .description("description") .productCode("product_code") .quantity(0.0) .tax(0.0) - .taxRate("tax_rate") + .taxRate("21.00") .unit(UnitOfMeasureCode._10) .unitPrice(0.0) .build() @@ -238,16 +381,20 @@ internal class ValidateValidateJsonParamsTest { .shippingAddressRecipient("shipping_address_recipient") .state(DocumentState.DRAFT) .subtotal(0.0) + .taxCode(DocumentCreate.TaxCode.AE) .addTaxDetail( DocumentCreate.TaxDetail.builder().amount(0.0).rate("rate").build() ) .totalDiscount(0.0) .totalTax(0.0) + .vatex(DocumentCreate.Vatex.VATEX_EU_79_C) + .vatexNote("vatex_note") .vendorAddress("vendor_address") .vendorAddressRecipient("vendor_address_recipient") + .vendorCompanyId("1018265814") .vendorEmail("vendor_email") .vendorName("vendor_name") - .vendorTaxId("vendor_tax_id") + .vendorTaxId("BE1018265814") .build() ) } diff --git a/e-invoice-java-core/src/test/kotlin/com/e_invoice/api/services/ErrorHandlingTest.kt b/e-invoice-java-core/src/test/kotlin/com/e_invoice/api/services/ErrorHandlingTest.kt index 238a059..a2a4397 100644 --- a/e-invoice-java-core/src/test/kotlin/com/e_invoice/api/services/ErrorHandlingTest.kt +++ b/e-invoice-java-core/src/test/kotlin/com/e_invoice/api/services/ErrorHandlingTest.kt @@ -19,6 +19,7 @@ import com.e_invoice.api.errors.UnprocessableEntityException import com.e_invoice.api.models.documents.CurrencyCode import com.e_invoice.api.models.documents.DocumentAttachmentCreate import com.e_invoice.api.models.documents.DocumentCreate +import com.e_invoice.api.models.documents.DocumentCreateParams import com.e_invoice.api.models.documents.DocumentDirection import com.e_invoice.api.models.documents.DocumentType import com.e_invoice.api.models.documents.PaymentDetailCreate @@ -79,76 +80,137 @@ internal class ErrorHandlingTest { val e = assertThrows { documentService.create( - DocumentCreate.builder() - .amountDue(0.0) - .addAttachment( - DocumentAttachmentCreate.builder() - .fileName("file_name") - .fileData("file_data") - .fileSize(0L) - .fileType("file_type") + DocumentCreateParams.builder() + .constructPdf(true) + .documentCreate( + DocumentCreate.builder() + .addAllowance( + DocumentCreate.Allowance.builder() + .amount(0.0) + .baseAmount(0.0) + .multiplierFactor(0.0) + .reason("reason") + .reasonCode(DocumentCreate.Allowance.ReasonCode._41) + .taxCode(DocumentCreate.Allowance.TaxCode.AE) + .taxRate(0.0) + .build() + ) + .amountDue(0.0) + .addAttachment( + DocumentAttachmentCreate.builder() + .fileName("file_name") + .fileData("file_data") + .fileSize(0L) + .fileType("file_type") + .build() + ) + .billingAddress("billing_address") + .billingAddressRecipient("billing_address_recipient") + .addCharge( + DocumentCreate.Charge.builder() + .amount(0.0) + .baseAmount(0.0) + .multiplierFactor(0.0) + .reason("reason") + .reasonCode(DocumentCreate.Charge.ReasonCode.AA) + .taxCode(DocumentCreate.Charge.TaxCode.AE) + .taxRate("21.00") + .build() + ) + .currency(CurrencyCode.EUR) + .customerAddress("customer_address") + .customerAddressRecipient("customer_address_recipient") + .customerCompanyId("1018265814") + .customerEmail("customer_email") + .customerId("customer_id") + .customerName("customer_name") + .customerTaxId("BE1018265814") + .direction(DocumentDirection.INBOUND) + .documentType(DocumentType.INVOICE) + .dueDate(LocalDate.parse("2019-12-27")) + .invoiceDate(LocalDate.parse("2019-12-27")) + .invoiceId("invoice_id") + .invoiceTotal(0.0) + .addItem( + DocumentCreate.Item.builder() + .addAllowance( + DocumentCreate.Item.Allowance.builder() + .amount(0.0) + .baseAmount(0.0) + .multiplierFactor(0.0) + .reason("reason") + .reasonCode( + DocumentCreate.Item.Allowance.ReasonCode._41 + ) + .taxCode(DocumentCreate.Item.Allowance.TaxCode.AE) + .taxRate(0.0) + .build() + ) + .amount(0.0) + .addCharge( + DocumentCreate.Item.Charge.builder() + .amount(0.0) + .baseAmount(0.0) + .multiplierFactor(0.0) + .reason("reason") + .reasonCode( + DocumentCreate.Item.Charge.ReasonCode.AA + ) + .taxCode(DocumentCreate.Item.Charge.TaxCode.AE) + .taxRate("21.00") + .build() + ) + .date(null) + .description("description") + .productCode("product_code") + .quantity(0.0) + .tax(0.0) + .taxRate("21.00") + .unit(UnitOfMeasureCode._10) + .unitPrice(0.0) + .build() + ) + .note("note") + .addPaymentDetail( + PaymentDetailCreate.builder() + .bankAccountNumber("bank_account_number") + .iban("iban") + .paymentReference("payment_reference") + .swift("swift") + .build() + ) + .paymentTerm("payment_term") + .previousUnpaidBalance(0.0) + .purchaseOrder("purchase_order") + .remittanceAddress("remittance_address") + .remittanceAddressRecipient("remittance_address_recipient") + .serviceAddress("service_address") + .serviceAddressRecipient("service_address_recipient") + .serviceEndDate(LocalDate.parse("2019-12-27")) + .serviceStartDate(LocalDate.parse("2019-12-27")) + .shippingAddress("shipping_address") + .shippingAddressRecipient("shipping_address_recipient") + .state(DocumentState.DRAFT) + .subtotal(0.0) + .taxCode(DocumentCreate.TaxCode.AE) + .addTaxDetail( + DocumentCreate.TaxDetail.builder() + .amount(0.0) + .rate("rate") + .build() + ) + .totalDiscount(0.0) + .totalTax(0.0) + .vatex(DocumentCreate.Vatex.VATEX_EU_79_C) + .vatexNote("vatex_note") + .vendorAddress("vendor_address") + .vendorAddressRecipient("vendor_address_recipient") + .vendorCompanyId("1018265814") + .vendorEmail("vendor_email") + .vendorName("vendor_name") + .vendorTaxId("BE1018265814") .build() ) - .billingAddress("billing_address") - .billingAddressRecipient("billing_address_recipient") - .currency(CurrencyCode.EUR) - .customerAddress("customer_address") - .customerAddressRecipient("customer_address_recipient") - .customerEmail("customer_email") - .customerId("customer_id") - .customerName("customer_name") - .customerTaxId("customer_tax_id") - .direction(DocumentDirection.INBOUND) - .documentType(DocumentType.INVOICE) - .dueDate(LocalDate.parse("2019-12-27")) - .invoiceDate(LocalDate.parse("2019-12-27")) - .invoiceId("invoice_id") - .invoiceTotal(0.0) - .addItem( - DocumentCreate.Item.builder() - .amount(0.0) - .date(null) - .description("description") - .productCode("product_code") - .quantity(0.0) - .tax(0.0) - .taxRate("tax_rate") - .unit(UnitOfMeasureCode._10) - .unitPrice(0.0) - .build() - ) - .note("note") - .addPaymentDetail( - PaymentDetailCreate.builder() - .bankAccountNumber("bank_account_number") - .iban("iban") - .paymentReference("payment_reference") - .swift("swift") - .build() - ) - .paymentTerm("payment_term") - .previousUnpaidBalance(0.0) - .purchaseOrder("purchase_order") - .remittanceAddress("remittance_address") - .remittanceAddressRecipient("remittance_address_recipient") - .serviceAddress("service_address") - .serviceAddressRecipient("service_address_recipient") - .serviceEndDate(LocalDate.parse("2019-12-27")) - .serviceStartDate(LocalDate.parse("2019-12-27")) - .shippingAddress("shipping_address") - .shippingAddressRecipient("shipping_address_recipient") - .state(DocumentState.DRAFT) - .subtotal(0.0) - .addTaxDetail( - DocumentCreate.TaxDetail.builder().amount(0.0).rate("rate").build() - ) - .totalDiscount(0.0) - .totalTax(0.0) - .vendorAddress("vendor_address") - .vendorAddressRecipient("vendor_address_recipient") - .vendorEmail("vendor_email") - .vendorName("vendor_name") - .vendorTaxId("vendor_tax_id") .build() ) } @@ -171,76 +233,137 @@ internal class ErrorHandlingTest { val e = assertThrows { documentService.create( - DocumentCreate.builder() - .amountDue(0.0) - .addAttachment( - DocumentAttachmentCreate.builder() - .fileName("file_name") - .fileData("file_data") - .fileSize(0L) - .fileType("file_type") + DocumentCreateParams.builder() + .constructPdf(true) + .documentCreate( + DocumentCreate.builder() + .addAllowance( + DocumentCreate.Allowance.builder() + .amount(0.0) + .baseAmount(0.0) + .multiplierFactor(0.0) + .reason("reason") + .reasonCode(DocumentCreate.Allowance.ReasonCode._41) + .taxCode(DocumentCreate.Allowance.TaxCode.AE) + .taxRate(0.0) + .build() + ) + .amountDue(0.0) + .addAttachment( + DocumentAttachmentCreate.builder() + .fileName("file_name") + .fileData("file_data") + .fileSize(0L) + .fileType("file_type") + .build() + ) + .billingAddress("billing_address") + .billingAddressRecipient("billing_address_recipient") + .addCharge( + DocumentCreate.Charge.builder() + .amount(0.0) + .baseAmount(0.0) + .multiplierFactor(0.0) + .reason("reason") + .reasonCode(DocumentCreate.Charge.ReasonCode.AA) + .taxCode(DocumentCreate.Charge.TaxCode.AE) + .taxRate("21.00") + .build() + ) + .currency(CurrencyCode.EUR) + .customerAddress("customer_address") + .customerAddressRecipient("customer_address_recipient") + .customerCompanyId("1018265814") + .customerEmail("customer_email") + .customerId("customer_id") + .customerName("customer_name") + .customerTaxId("BE1018265814") + .direction(DocumentDirection.INBOUND) + .documentType(DocumentType.INVOICE) + .dueDate(LocalDate.parse("2019-12-27")) + .invoiceDate(LocalDate.parse("2019-12-27")) + .invoiceId("invoice_id") + .invoiceTotal(0.0) + .addItem( + DocumentCreate.Item.builder() + .addAllowance( + DocumentCreate.Item.Allowance.builder() + .amount(0.0) + .baseAmount(0.0) + .multiplierFactor(0.0) + .reason("reason") + .reasonCode( + DocumentCreate.Item.Allowance.ReasonCode._41 + ) + .taxCode(DocumentCreate.Item.Allowance.TaxCode.AE) + .taxRate(0.0) + .build() + ) + .amount(0.0) + .addCharge( + DocumentCreate.Item.Charge.builder() + .amount(0.0) + .baseAmount(0.0) + .multiplierFactor(0.0) + .reason("reason") + .reasonCode( + DocumentCreate.Item.Charge.ReasonCode.AA + ) + .taxCode(DocumentCreate.Item.Charge.TaxCode.AE) + .taxRate("21.00") + .build() + ) + .date(null) + .description("description") + .productCode("product_code") + .quantity(0.0) + .tax(0.0) + .taxRate("21.00") + .unit(UnitOfMeasureCode._10) + .unitPrice(0.0) + .build() + ) + .note("note") + .addPaymentDetail( + PaymentDetailCreate.builder() + .bankAccountNumber("bank_account_number") + .iban("iban") + .paymentReference("payment_reference") + .swift("swift") + .build() + ) + .paymentTerm("payment_term") + .previousUnpaidBalance(0.0) + .purchaseOrder("purchase_order") + .remittanceAddress("remittance_address") + .remittanceAddressRecipient("remittance_address_recipient") + .serviceAddress("service_address") + .serviceAddressRecipient("service_address_recipient") + .serviceEndDate(LocalDate.parse("2019-12-27")) + .serviceStartDate(LocalDate.parse("2019-12-27")) + .shippingAddress("shipping_address") + .shippingAddressRecipient("shipping_address_recipient") + .state(DocumentState.DRAFT) + .subtotal(0.0) + .taxCode(DocumentCreate.TaxCode.AE) + .addTaxDetail( + DocumentCreate.TaxDetail.builder() + .amount(0.0) + .rate("rate") + .build() + ) + .totalDiscount(0.0) + .totalTax(0.0) + .vatex(DocumentCreate.Vatex.VATEX_EU_79_C) + .vatexNote("vatex_note") + .vendorAddress("vendor_address") + .vendorAddressRecipient("vendor_address_recipient") + .vendorCompanyId("1018265814") + .vendorEmail("vendor_email") + .vendorName("vendor_name") + .vendorTaxId("BE1018265814") .build() ) - .billingAddress("billing_address") - .billingAddressRecipient("billing_address_recipient") - .currency(CurrencyCode.EUR) - .customerAddress("customer_address") - .customerAddressRecipient("customer_address_recipient") - .customerEmail("customer_email") - .customerId("customer_id") - .customerName("customer_name") - .customerTaxId("customer_tax_id") - .direction(DocumentDirection.INBOUND) - .documentType(DocumentType.INVOICE) - .dueDate(LocalDate.parse("2019-12-27")) - .invoiceDate(LocalDate.parse("2019-12-27")) - .invoiceId("invoice_id") - .invoiceTotal(0.0) - .addItem( - DocumentCreate.Item.builder() - .amount(0.0) - .date(null) - .description("description") - .productCode("product_code") - .quantity(0.0) - .tax(0.0) - .taxRate("tax_rate") - .unit(UnitOfMeasureCode._10) - .unitPrice(0.0) - .build() - ) - .note("note") - .addPaymentDetail( - PaymentDetailCreate.builder() - .bankAccountNumber("bank_account_number") - .iban("iban") - .paymentReference("payment_reference") - .swift("swift") - .build() - ) - .paymentTerm("payment_term") - .previousUnpaidBalance(0.0) - .purchaseOrder("purchase_order") - .remittanceAddress("remittance_address") - .remittanceAddressRecipient("remittance_address_recipient") - .serviceAddress("service_address") - .serviceAddressRecipient("service_address_recipient") - .serviceEndDate(LocalDate.parse("2019-12-27")) - .serviceStartDate(LocalDate.parse("2019-12-27")) - .shippingAddress("shipping_address") - .shippingAddressRecipient("shipping_address_recipient") - .state(DocumentState.DRAFT) - .subtotal(0.0) - .addTaxDetail( - DocumentCreate.TaxDetail.builder().amount(0.0).rate("rate").build() - ) - .totalDiscount(0.0) - .totalTax(0.0) - .vendorAddress("vendor_address") - .vendorAddressRecipient("vendor_address_recipient") - .vendorEmail("vendor_email") - .vendorName("vendor_name") - .vendorTaxId("vendor_tax_id") .build() ) } @@ -263,76 +386,137 @@ internal class ErrorHandlingTest { val e = assertThrows { documentService.create( - DocumentCreate.builder() - .amountDue(0.0) - .addAttachment( - DocumentAttachmentCreate.builder() - .fileName("file_name") - .fileData("file_data") - .fileSize(0L) - .fileType("file_type") - .build() - ) - .billingAddress("billing_address") - .billingAddressRecipient("billing_address_recipient") - .currency(CurrencyCode.EUR) - .customerAddress("customer_address") - .customerAddressRecipient("customer_address_recipient") - .customerEmail("customer_email") - .customerId("customer_id") - .customerName("customer_name") - .customerTaxId("customer_tax_id") - .direction(DocumentDirection.INBOUND) - .documentType(DocumentType.INVOICE) - .dueDate(LocalDate.parse("2019-12-27")) - .invoiceDate(LocalDate.parse("2019-12-27")) - .invoiceId("invoice_id") - .invoiceTotal(0.0) - .addItem( - DocumentCreate.Item.builder() - .amount(0.0) - .date(null) - .description("description") - .productCode("product_code") - .quantity(0.0) - .tax(0.0) - .taxRate("tax_rate") - .unit(UnitOfMeasureCode._10) - .unitPrice(0.0) - .build() - ) - .note("note") - .addPaymentDetail( - PaymentDetailCreate.builder() - .bankAccountNumber("bank_account_number") - .iban("iban") - .paymentReference("payment_reference") - .swift("swift") + DocumentCreateParams.builder() + .constructPdf(true) + .documentCreate( + DocumentCreate.builder() + .addAllowance( + DocumentCreate.Allowance.builder() + .amount(0.0) + .baseAmount(0.0) + .multiplierFactor(0.0) + .reason("reason") + .reasonCode(DocumentCreate.Allowance.ReasonCode._41) + .taxCode(DocumentCreate.Allowance.TaxCode.AE) + .taxRate(0.0) + .build() + ) + .amountDue(0.0) + .addAttachment( + DocumentAttachmentCreate.builder() + .fileName("file_name") + .fileData("file_data") + .fileSize(0L) + .fileType("file_type") + .build() + ) + .billingAddress("billing_address") + .billingAddressRecipient("billing_address_recipient") + .addCharge( + DocumentCreate.Charge.builder() + .amount(0.0) + .baseAmount(0.0) + .multiplierFactor(0.0) + .reason("reason") + .reasonCode(DocumentCreate.Charge.ReasonCode.AA) + .taxCode(DocumentCreate.Charge.TaxCode.AE) + .taxRate("21.00") + .build() + ) + .currency(CurrencyCode.EUR) + .customerAddress("customer_address") + .customerAddressRecipient("customer_address_recipient") + .customerCompanyId("1018265814") + .customerEmail("customer_email") + .customerId("customer_id") + .customerName("customer_name") + .customerTaxId("BE1018265814") + .direction(DocumentDirection.INBOUND) + .documentType(DocumentType.INVOICE) + .dueDate(LocalDate.parse("2019-12-27")) + .invoiceDate(LocalDate.parse("2019-12-27")) + .invoiceId("invoice_id") + .invoiceTotal(0.0) + .addItem( + DocumentCreate.Item.builder() + .addAllowance( + DocumentCreate.Item.Allowance.builder() + .amount(0.0) + .baseAmount(0.0) + .multiplierFactor(0.0) + .reason("reason") + .reasonCode( + DocumentCreate.Item.Allowance.ReasonCode._41 + ) + .taxCode(DocumentCreate.Item.Allowance.TaxCode.AE) + .taxRate(0.0) + .build() + ) + .amount(0.0) + .addCharge( + DocumentCreate.Item.Charge.builder() + .amount(0.0) + .baseAmount(0.0) + .multiplierFactor(0.0) + .reason("reason") + .reasonCode( + DocumentCreate.Item.Charge.ReasonCode.AA + ) + .taxCode(DocumentCreate.Item.Charge.TaxCode.AE) + .taxRate("21.00") + .build() + ) + .date(null) + .description("description") + .productCode("product_code") + .quantity(0.0) + .tax(0.0) + .taxRate("21.00") + .unit(UnitOfMeasureCode._10) + .unitPrice(0.0) + .build() + ) + .note("note") + .addPaymentDetail( + PaymentDetailCreate.builder() + .bankAccountNumber("bank_account_number") + .iban("iban") + .paymentReference("payment_reference") + .swift("swift") + .build() + ) + .paymentTerm("payment_term") + .previousUnpaidBalance(0.0) + .purchaseOrder("purchase_order") + .remittanceAddress("remittance_address") + .remittanceAddressRecipient("remittance_address_recipient") + .serviceAddress("service_address") + .serviceAddressRecipient("service_address_recipient") + .serviceEndDate(LocalDate.parse("2019-12-27")) + .serviceStartDate(LocalDate.parse("2019-12-27")) + .shippingAddress("shipping_address") + .shippingAddressRecipient("shipping_address_recipient") + .state(DocumentState.DRAFT) + .subtotal(0.0) + .taxCode(DocumentCreate.TaxCode.AE) + .addTaxDetail( + DocumentCreate.TaxDetail.builder() + .amount(0.0) + .rate("rate") + .build() + ) + .totalDiscount(0.0) + .totalTax(0.0) + .vatex(DocumentCreate.Vatex.VATEX_EU_79_C) + .vatexNote("vatex_note") + .vendorAddress("vendor_address") + .vendorAddressRecipient("vendor_address_recipient") + .vendorCompanyId("1018265814") + .vendorEmail("vendor_email") + .vendorName("vendor_name") + .vendorTaxId("BE1018265814") .build() ) - .paymentTerm("payment_term") - .previousUnpaidBalance(0.0) - .purchaseOrder("purchase_order") - .remittanceAddress("remittance_address") - .remittanceAddressRecipient("remittance_address_recipient") - .serviceAddress("service_address") - .serviceAddressRecipient("service_address_recipient") - .serviceEndDate(LocalDate.parse("2019-12-27")) - .serviceStartDate(LocalDate.parse("2019-12-27")) - .shippingAddress("shipping_address") - .shippingAddressRecipient("shipping_address_recipient") - .state(DocumentState.DRAFT) - .subtotal(0.0) - .addTaxDetail( - DocumentCreate.TaxDetail.builder().amount(0.0).rate("rate").build() - ) - .totalDiscount(0.0) - .totalTax(0.0) - .vendorAddress("vendor_address") - .vendorAddressRecipient("vendor_address_recipient") - .vendorEmail("vendor_email") - .vendorName("vendor_name") - .vendorTaxId("vendor_tax_id") .build() ) } @@ -355,76 +539,137 @@ internal class ErrorHandlingTest { val e = assertThrows { documentService.create( - DocumentCreate.builder() - .amountDue(0.0) - .addAttachment( - DocumentAttachmentCreate.builder() - .fileName("file_name") - .fileData("file_data") - .fileSize(0L) - .fileType("file_type") - .build() - ) - .billingAddress("billing_address") - .billingAddressRecipient("billing_address_recipient") - .currency(CurrencyCode.EUR) - .customerAddress("customer_address") - .customerAddressRecipient("customer_address_recipient") - .customerEmail("customer_email") - .customerId("customer_id") - .customerName("customer_name") - .customerTaxId("customer_tax_id") - .direction(DocumentDirection.INBOUND) - .documentType(DocumentType.INVOICE) - .dueDate(LocalDate.parse("2019-12-27")) - .invoiceDate(LocalDate.parse("2019-12-27")) - .invoiceId("invoice_id") - .invoiceTotal(0.0) - .addItem( - DocumentCreate.Item.builder() - .amount(0.0) - .date(null) - .description("description") - .productCode("product_code") - .quantity(0.0) - .tax(0.0) - .taxRate("tax_rate") - .unit(UnitOfMeasureCode._10) - .unitPrice(0.0) + DocumentCreateParams.builder() + .constructPdf(true) + .documentCreate( + DocumentCreate.builder() + .addAllowance( + DocumentCreate.Allowance.builder() + .amount(0.0) + .baseAmount(0.0) + .multiplierFactor(0.0) + .reason("reason") + .reasonCode(DocumentCreate.Allowance.ReasonCode._41) + .taxCode(DocumentCreate.Allowance.TaxCode.AE) + .taxRate(0.0) + .build() + ) + .amountDue(0.0) + .addAttachment( + DocumentAttachmentCreate.builder() + .fileName("file_name") + .fileData("file_data") + .fileSize(0L) + .fileType("file_type") + .build() + ) + .billingAddress("billing_address") + .billingAddressRecipient("billing_address_recipient") + .addCharge( + DocumentCreate.Charge.builder() + .amount(0.0) + .baseAmount(0.0) + .multiplierFactor(0.0) + .reason("reason") + .reasonCode(DocumentCreate.Charge.ReasonCode.AA) + .taxCode(DocumentCreate.Charge.TaxCode.AE) + .taxRate("21.00") + .build() + ) + .currency(CurrencyCode.EUR) + .customerAddress("customer_address") + .customerAddressRecipient("customer_address_recipient") + .customerCompanyId("1018265814") + .customerEmail("customer_email") + .customerId("customer_id") + .customerName("customer_name") + .customerTaxId("BE1018265814") + .direction(DocumentDirection.INBOUND) + .documentType(DocumentType.INVOICE) + .dueDate(LocalDate.parse("2019-12-27")) + .invoiceDate(LocalDate.parse("2019-12-27")) + .invoiceId("invoice_id") + .invoiceTotal(0.0) + .addItem( + DocumentCreate.Item.builder() + .addAllowance( + DocumentCreate.Item.Allowance.builder() + .amount(0.0) + .baseAmount(0.0) + .multiplierFactor(0.0) + .reason("reason") + .reasonCode( + DocumentCreate.Item.Allowance.ReasonCode._41 + ) + .taxCode(DocumentCreate.Item.Allowance.TaxCode.AE) + .taxRate(0.0) + .build() + ) + .amount(0.0) + .addCharge( + DocumentCreate.Item.Charge.builder() + .amount(0.0) + .baseAmount(0.0) + .multiplierFactor(0.0) + .reason("reason") + .reasonCode( + DocumentCreate.Item.Charge.ReasonCode.AA + ) + .taxCode(DocumentCreate.Item.Charge.TaxCode.AE) + .taxRate("21.00") + .build() + ) + .date(null) + .description("description") + .productCode("product_code") + .quantity(0.0) + .tax(0.0) + .taxRate("21.00") + .unit(UnitOfMeasureCode._10) + .unitPrice(0.0) + .build() + ) + .note("note") + .addPaymentDetail( + PaymentDetailCreate.builder() + .bankAccountNumber("bank_account_number") + .iban("iban") + .paymentReference("payment_reference") + .swift("swift") + .build() + ) + .paymentTerm("payment_term") + .previousUnpaidBalance(0.0) + .purchaseOrder("purchase_order") + .remittanceAddress("remittance_address") + .remittanceAddressRecipient("remittance_address_recipient") + .serviceAddress("service_address") + .serviceAddressRecipient("service_address_recipient") + .serviceEndDate(LocalDate.parse("2019-12-27")) + .serviceStartDate(LocalDate.parse("2019-12-27")) + .shippingAddress("shipping_address") + .shippingAddressRecipient("shipping_address_recipient") + .state(DocumentState.DRAFT) + .subtotal(0.0) + .taxCode(DocumentCreate.TaxCode.AE) + .addTaxDetail( + DocumentCreate.TaxDetail.builder() + .amount(0.0) + .rate("rate") + .build() + ) + .totalDiscount(0.0) + .totalTax(0.0) + .vatex(DocumentCreate.Vatex.VATEX_EU_79_C) + .vatexNote("vatex_note") + .vendorAddress("vendor_address") + .vendorAddressRecipient("vendor_address_recipient") + .vendorCompanyId("1018265814") + .vendorEmail("vendor_email") + .vendorName("vendor_name") + .vendorTaxId("BE1018265814") .build() ) - .note("note") - .addPaymentDetail( - PaymentDetailCreate.builder() - .bankAccountNumber("bank_account_number") - .iban("iban") - .paymentReference("payment_reference") - .swift("swift") - .build() - ) - .paymentTerm("payment_term") - .previousUnpaidBalance(0.0) - .purchaseOrder("purchase_order") - .remittanceAddress("remittance_address") - .remittanceAddressRecipient("remittance_address_recipient") - .serviceAddress("service_address") - .serviceAddressRecipient("service_address_recipient") - .serviceEndDate(LocalDate.parse("2019-12-27")) - .serviceStartDate(LocalDate.parse("2019-12-27")) - .shippingAddress("shipping_address") - .shippingAddressRecipient("shipping_address_recipient") - .state(DocumentState.DRAFT) - .subtotal(0.0) - .addTaxDetail( - DocumentCreate.TaxDetail.builder().amount(0.0).rate("rate").build() - ) - .totalDiscount(0.0) - .totalTax(0.0) - .vendorAddress("vendor_address") - .vendorAddressRecipient("vendor_address_recipient") - .vendorEmail("vendor_email") - .vendorName("vendor_name") - .vendorTaxId("vendor_tax_id") .build() ) } @@ -447,76 +692,137 @@ internal class ErrorHandlingTest { val e = assertThrows { documentService.create( - DocumentCreate.builder() - .amountDue(0.0) - .addAttachment( - DocumentAttachmentCreate.builder() - .fileName("file_name") - .fileData("file_data") - .fileSize(0L) - .fileType("file_type") - .build() - ) - .billingAddress("billing_address") - .billingAddressRecipient("billing_address_recipient") - .currency(CurrencyCode.EUR) - .customerAddress("customer_address") - .customerAddressRecipient("customer_address_recipient") - .customerEmail("customer_email") - .customerId("customer_id") - .customerName("customer_name") - .customerTaxId("customer_tax_id") - .direction(DocumentDirection.INBOUND) - .documentType(DocumentType.INVOICE) - .dueDate(LocalDate.parse("2019-12-27")) - .invoiceDate(LocalDate.parse("2019-12-27")) - .invoiceId("invoice_id") - .invoiceTotal(0.0) - .addItem( - DocumentCreate.Item.builder() - .amount(0.0) - .date(null) - .description("description") - .productCode("product_code") - .quantity(0.0) - .tax(0.0) - .taxRate("tax_rate") - .unit(UnitOfMeasureCode._10) - .unitPrice(0.0) + DocumentCreateParams.builder() + .constructPdf(true) + .documentCreate( + DocumentCreate.builder() + .addAllowance( + DocumentCreate.Allowance.builder() + .amount(0.0) + .baseAmount(0.0) + .multiplierFactor(0.0) + .reason("reason") + .reasonCode(DocumentCreate.Allowance.ReasonCode._41) + .taxCode(DocumentCreate.Allowance.TaxCode.AE) + .taxRate(0.0) + .build() + ) + .amountDue(0.0) + .addAttachment( + DocumentAttachmentCreate.builder() + .fileName("file_name") + .fileData("file_data") + .fileSize(0L) + .fileType("file_type") + .build() + ) + .billingAddress("billing_address") + .billingAddressRecipient("billing_address_recipient") + .addCharge( + DocumentCreate.Charge.builder() + .amount(0.0) + .baseAmount(0.0) + .multiplierFactor(0.0) + .reason("reason") + .reasonCode(DocumentCreate.Charge.ReasonCode.AA) + .taxCode(DocumentCreate.Charge.TaxCode.AE) + .taxRate("21.00") + .build() + ) + .currency(CurrencyCode.EUR) + .customerAddress("customer_address") + .customerAddressRecipient("customer_address_recipient") + .customerCompanyId("1018265814") + .customerEmail("customer_email") + .customerId("customer_id") + .customerName("customer_name") + .customerTaxId("BE1018265814") + .direction(DocumentDirection.INBOUND) + .documentType(DocumentType.INVOICE) + .dueDate(LocalDate.parse("2019-12-27")) + .invoiceDate(LocalDate.parse("2019-12-27")) + .invoiceId("invoice_id") + .invoiceTotal(0.0) + .addItem( + DocumentCreate.Item.builder() + .addAllowance( + DocumentCreate.Item.Allowance.builder() + .amount(0.0) + .baseAmount(0.0) + .multiplierFactor(0.0) + .reason("reason") + .reasonCode( + DocumentCreate.Item.Allowance.ReasonCode._41 + ) + .taxCode(DocumentCreate.Item.Allowance.TaxCode.AE) + .taxRate(0.0) + .build() + ) + .amount(0.0) + .addCharge( + DocumentCreate.Item.Charge.builder() + .amount(0.0) + .baseAmount(0.0) + .multiplierFactor(0.0) + .reason("reason") + .reasonCode( + DocumentCreate.Item.Charge.ReasonCode.AA + ) + .taxCode(DocumentCreate.Item.Charge.TaxCode.AE) + .taxRate("21.00") + .build() + ) + .date(null) + .description("description") + .productCode("product_code") + .quantity(0.0) + .tax(0.0) + .taxRate("21.00") + .unit(UnitOfMeasureCode._10) + .unitPrice(0.0) + .build() + ) + .note("note") + .addPaymentDetail( + PaymentDetailCreate.builder() + .bankAccountNumber("bank_account_number") + .iban("iban") + .paymentReference("payment_reference") + .swift("swift") + .build() + ) + .paymentTerm("payment_term") + .previousUnpaidBalance(0.0) + .purchaseOrder("purchase_order") + .remittanceAddress("remittance_address") + .remittanceAddressRecipient("remittance_address_recipient") + .serviceAddress("service_address") + .serviceAddressRecipient("service_address_recipient") + .serviceEndDate(LocalDate.parse("2019-12-27")) + .serviceStartDate(LocalDate.parse("2019-12-27")) + .shippingAddress("shipping_address") + .shippingAddressRecipient("shipping_address_recipient") + .state(DocumentState.DRAFT) + .subtotal(0.0) + .taxCode(DocumentCreate.TaxCode.AE) + .addTaxDetail( + DocumentCreate.TaxDetail.builder() + .amount(0.0) + .rate("rate") + .build() + ) + .totalDiscount(0.0) + .totalTax(0.0) + .vatex(DocumentCreate.Vatex.VATEX_EU_79_C) + .vatexNote("vatex_note") + .vendorAddress("vendor_address") + .vendorAddressRecipient("vendor_address_recipient") + .vendorCompanyId("1018265814") + .vendorEmail("vendor_email") + .vendorName("vendor_name") + .vendorTaxId("BE1018265814") .build() ) - .note("note") - .addPaymentDetail( - PaymentDetailCreate.builder() - .bankAccountNumber("bank_account_number") - .iban("iban") - .paymentReference("payment_reference") - .swift("swift") - .build() - ) - .paymentTerm("payment_term") - .previousUnpaidBalance(0.0) - .purchaseOrder("purchase_order") - .remittanceAddress("remittance_address") - .remittanceAddressRecipient("remittance_address_recipient") - .serviceAddress("service_address") - .serviceAddressRecipient("service_address_recipient") - .serviceEndDate(LocalDate.parse("2019-12-27")) - .serviceStartDate(LocalDate.parse("2019-12-27")) - .shippingAddress("shipping_address") - .shippingAddressRecipient("shipping_address_recipient") - .state(DocumentState.DRAFT) - .subtotal(0.0) - .addTaxDetail( - DocumentCreate.TaxDetail.builder().amount(0.0).rate("rate").build() - ) - .totalDiscount(0.0) - .totalTax(0.0) - .vendorAddress("vendor_address") - .vendorAddressRecipient("vendor_address_recipient") - .vendorEmail("vendor_email") - .vendorName("vendor_name") - .vendorTaxId("vendor_tax_id") .build() ) } @@ -539,76 +845,137 @@ internal class ErrorHandlingTest { val e = assertThrows { documentService.create( - DocumentCreate.builder() - .amountDue(0.0) - .addAttachment( - DocumentAttachmentCreate.builder() - .fileName("file_name") - .fileData("file_data") - .fileSize(0L) - .fileType("file_type") + DocumentCreateParams.builder() + .constructPdf(true) + .documentCreate( + DocumentCreate.builder() + .addAllowance( + DocumentCreate.Allowance.builder() + .amount(0.0) + .baseAmount(0.0) + .multiplierFactor(0.0) + .reason("reason") + .reasonCode(DocumentCreate.Allowance.ReasonCode._41) + .taxCode(DocumentCreate.Allowance.TaxCode.AE) + .taxRate(0.0) + .build() + ) + .amountDue(0.0) + .addAttachment( + DocumentAttachmentCreate.builder() + .fileName("file_name") + .fileData("file_data") + .fileSize(0L) + .fileType("file_type") + .build() + ) + .billingAddress("billing_address") + .billingAddressRecipient("billing_address_recipient") + .addCharge( + DocumentCreate.Charge.builder() + .amount(0.0) + .baseAmount(0.0) + .multiplierFactor(0.0) + .reason("reason") + .reasonCode(DocumentCreate.Charge.ReasonCode.AA) + .taxCode(DocumentCreate.Charge.TaxCode.AE) + .taxRate("21.00") + .build() + ) + .currency(CurrencyCode.EUR) + .customerAddress("customer_address") + .customerAddressRecipient("customer_address_recipient") + .customerCompanyId("1018265814") + .customerEmail("customer_email") + .customerId("customer_id") + .customerName("customer_name") + .customerTaxId("BE1018265814") + .direction(DocumentDirection.INBOUND) + .documentType(DocumentType.INVOICE) + .dueDate(LocalDate.parse("2019-12-27")) + .invoiceDate(LocalDate.parse("2019-12-27")) + .invoiceId("invoice_id") + .invoiceTotal(0.0) + .addItem( + DocumentCreate.Item.builder() + .addAllowance( + DocumentCreate.Item.Allowance.builder() + .amount(0.0) + .baseAmount(0.0) + .multiplierFactor(0.0) + .reason("reason") + .reasonCode( + DocumentCreate.Item.Allowance.ReasonCode._41 + ) + .taxCode(DocumentCreate.Item.Allowance.TaxCode.AE) + .taxRate(0.0) + .build() + ) + .amount(0.0) + .addCharge( + DocumentCreate.Item.Charge.builder() + .amount(0.0) + .baseAmount(0.0) + .multiplierFactor(0.0) + .reason("reason") + .reasonCode( + DocumentCreate.Item.Charge.ReasonCode.AA + ) + .taxCode(DocumentCreate.Item.Charge.TaxCode.AE) + .taxRate("21.00") + .build() + ) + .date(null) + .description("description") + .productCode("product_code") + .quantity(0.0) + .tax(0.0) + .taxRate("21.00") + .unit(UnitOfMeasureCode._10) + .unitPrice(0.0) + .build() + ) + .note("note") + .addPaymentDetail( + PaymentDetailCreate.builder() + .bankAccountNumber("bank_account_number") + .iban("iban") + .paymentReference("payment_reference") + .swift("swift") + .build() + ) + .paymentTerm("payment_term") + .previousUnpaidBalance(0.0) + .purchaseOrder("purchase_order") + .remittanceAddress("remittance_address") + .remittanceAddressRecipient("remittance_address_recipient") + .serviceAddress("service_address") + .serviceAddressRecipient("service_address_recipient") + .serviceEndDate(LocalDate.parse("2019-12-27")) + .serviceStartDate(LocalDate.parse("2019-12-27")) + .shippingAddress("shipping_address") + .shippingAddressRecipient("shipping_address_recipient") + .state(DocumentState.DRAFT) + .subtotal(0.0) + .taxCode(DocumentCreate.TaxCode.AE) + .addTaxDetail( + DocumentCreate.TaxDetail.builder() + .amount(0.0) + .rate("rate") + .build() + ) + .totalDiscount(0.0) + .totalTax(0.0) + .vatex(DocumentCreate.Vatex.VATEX_EU_79_C) + .vatexNote("vatex_note") + .vendorAddress("vendor_address") + .vendorAddressRecipient("vendor_address_recipient") + .vendorCompanyId("1018265814") + .vendorEmail("vendor_email") + .vendorName("vendor_name") + .vendorTaxId("BE1018265814") .build() ) - .billingAddress("billing_address") - .billingAddressRecipient("billing_address_recipient") - .currency(CurrencyCode.EUR) - .customerAddress("customer_address") - .customerAddressRecipient("customer_address_recipient") - .customerEmail("customer_email") - .customerId("customer_id") - .customerName("customer_name") - .customerTaxId("customer_tax_id") - .direction(DocumentDirection.INBOUND) - .documentType(DocumentType.INVOICE) - .dueDate(LocalDate.parse("2019-12-27")) - .invoiceDate(LocalDate.parse("2019-12-27")) - .invoiceId("invoice_id") - .invoiceTotal(0.0) - .addItem( - DocumentCreate.Item.builder() - .amount(0.0) - .date(null) - .description("description") - .productCode("product_code") - .quantity(0.0) - .tax(0.0) - .taxRate("tax_rate") - .unit(UnitOfMeasureCode._10) - .unitPrice(0.0) - .build() - ) - .note("note") - .addPaymentDetail( - PaymentDetailCreate.builder() - .bankAccountNumber("bank_account_number") - .iban("iban") - .paymentReference("payment_reference") - .swift("swift") - .build() - ) - .paymentTerm("payment_term") - .previousUnpaidBalance(0.0) - .purchaseOrder("purchase_order") - .remittanceAddress("remittance_address") - .remittanceAddressRecipient("remittance_address_recipient") - .serviceAddress("service_address") - .serviceAddressRecipient("service_address_recipient") - .serviceEndDate(LocalDate.parse("2019-12-27")) - .serviceStartDate(LocalDate.parse("2019-12-27")) - .shippingAddress("shipping_address") - .shippingAddressRecipient("shipping_address_recipient") - .state(DocumentState.DRAFT) - .subtotal(0.0) - .addTaxDetail( - DocumentCreate.TaxDetail.builder().amount(0.0).rate("rate").build() - ) - .totalDiscount(0.0) - .totalTax(0.0) - .vendorAddress("vendor_address") - .vendorAddressRecipient("vendor_address_recipient") - .vendorEmail("vendor_email") - .vendorName("vendor_name") - .vendorTaxId("vendor_tax_id") .build() ) } @@ -631,76 +998,137 @@ internal class ErrorHandlingTest { val e = assertThrows { documentService.create( - DocumentCreate.builder() - .amountDue(0.0) - .addAttachment( - DocumentAttachmentCreate.builder() - .fileName("file_name") - .fileData("file_data") - .fileSize(0L) - .fileType("file_type") + DocumentCreateParams.builder() + .constructPdf(true) + .documentCreate( + DocumentCreate.builder() + .addAllowance( + DocumentCreate.Allowance.builder() + .amount(0.0) + .baseAmount(0.0) + .multiplierFactor(0.0) + .reason("reason") + .reasonCode(DocumentCreate.Allowance.ReasonCode._41) + .taxCode(DocumentCreate.Allowance.TaxCode.AE) + .taxRate(0.0) + .build() + ) + .amountDue(0.0) + .addAttachment( + DocumentAttachmentCreate.builder() + .fileName("file_name") + .fileData("file_data") + .fileSize(0L) + .fileType("file_type") + .build() + ) + .billingAddress("billing_address") + .billingAddressRecipient("billing_address_recipient") + .addCharge( + DocumentCreate.Charge.builder() + .amount(0.0) + .baseAmount(0.0) + .multiplierFactor(0.0) + .reason("reason") + .reasonCode(DocumentCreate.Charge.ReasonCode.AA) + .taxCode(DocumentCreate.Charge.TaxCode.AE) + .taxRate("21.00") + .build() + ) + .currency(CurrencyCode.EUR) + .customerAddress("customer_address") + .customerAddressRecipient("customer_address_recipient") + .customerCompanyId("1018265814") + .customerEmail("customer_email") + .customerId("customer_id") + .customerName("customer_name") + .customerTaxId("BE1018265814") + .direction(DocumentDirection.INBOUND) + .documentType(DocumentType.INVOICE) + .dueDate(LocalDate.parse("2019-12-27")) + .invoiceDate(LocalDate.parse("2019-12-27")) + .invoiceId("invoice_id") + .invoiceTotal(0.0) + .addItem( + DocumentCreate.Item.builder() + .addAllowance( + DocumentCreate.Item.Allowance.builder() + .amount(0.0) + .baseAmount(0.0) + .multiplierFactor(0.0) + .reason("reason") + .reasonCode( + DocumentCreate.Item.Allowance.ReasonCode._41 + ) + .taxCode(DocumentCreate.Item.Allowance.TaxCode.AE) + .taxRate(0.0) + .build() + ) + .amount(0.0) + .addCharge( + DocumentCreate.Item.Charge.builder() + .amount(0.0) + .baseAmount(0.0) + .multiplierFactor(0.0) + .reason("reason") + .reasonCode( + DocumentCreate.Item.Charge.ReasonCode.AA + ) + .taxCode(DocumentCreate.Item.Charge.TaxCode.AE) + .taxRate("21.00") + .build() + ) + .date(null) + .description("description") + .productCode("product_code") + .quantity(0.0) + .tax(0.0) + .taxRate("21.00") + .unit(UnitOfMeasureCode._10) + .unitPrice(0.0) + .build() + ) + .note("note") + .addPaymentDetail( + PaymentDetailCreate.builder() + .bankAccountNumber("bank_account_number") + .iban("iban") + .paymentReference("payment_reference") + .swift("swift") + .build() + ) + .paymentTerm("payment_term") + .previousUnpaidBalance(0.0) + .purchaseOrder("purchase_order") + .remittanceAddress("remittance_address") + .remittanceAddressRecipient("remittance_address_recipient") + .serviceAddress("service_address") + .serviceAddressRecipient("service_address_recipient") + .serviceEndDate(LocalDate.parse("2019-12-27")) + .serviceStartDate(LocalDate.parse("2019-12-27")) + .shippingAddress("shipping_address") + .shippingAddressRecipient("shipping_address_recipient") + .state(DocumentState.DRAFT) + .subtotal(0.0) + .taxCode(DocumentCreate.TaxCode.AE) + .addTaxDetail( + DocumentCreate.TaxDetail.builder() + .amount(0.0) + .rate("rate") + .build() + ) + .totalDiscount(0.0) + .totalTax(0.0) + .vatex(DocumentCreate.Vatex.VATEX_EU_79_C) + .vatexNote("vatex_note") + .vendorAddress("vendor_address") + .vendorAddressRecipient("vendor_address_recipient") + .vendorCompanyId("1018265814") + .vendorEmail("vendor_email") + .vendorName("vendor_name") + .vendorTaxId("BE1018265814") .build() ) - .billingAddress("billing_address") - .billingAddressRecipient("billing_address_recipient") - .currency(CurrencyCode.EUR) - .customerAddress("customer_address") - .customerAddressRecipient("customer_address_recipient") - .customerEmail("customer_email") - .customerId("customer_id") - .customerName("customer_name") - .customerTaxId("customer_tax_id") - .direction(DocumentDirection.INBOUND) - .documentType(DocumentType.INVOICE) - .dueDate(LocalDate.parse("2019-12-27")) - .invoiceDate(LocalDate.parse("2019-12-27")) - .invoiceId("invoice_id") - .invoiceTotal(0.0) - .addItem( - DocumentCreate.Item.builder() - .amount(0.0) - .date(null) - .description("description") - .productCode("product_code") - .quantity(0.0) - .tax(0.0) - .taxRate("tax_rate") - .unit(UnitOfMeasureCode._10) - .unitPrice(0.0) - .build() - ) - .note("note") - .addPaymentDetail( - PaymentDetailCreate.builder() - .bankAccountNumber("bank_account_number") - .iban("iban") - .paymentReference("payment_reference") - .swift("swift") - .build() - ) - .paymentTerm("payment_term") - .previousUnpaidBalance(0.0) - .purchaseOrder("purchase_order") - .remittanceAddress("remittance_address") - .remittanceAddressRecipient("remittance_address_recipient") - .serviceAddress("service_address") - .serviceAddressRecipient("service_address_recipient") - .serviceEndDate(LocalDate.parse("2019-12-27")) - .serviceStartDate(LocalDate.parse("2019-12-27")) - .shippingAddress("shipping_address") - .shippingAddressRecipient("shipping_address_recipient") - .state(DocumentState.DRAFT) - .subtotal(0.0) - .addTaxDetail( - DocumentCreate.TaxDetail.builder().amount(0.0).rate("rate").build() - ) - .totalDiscount(0.0) - .totalTax(0.0) - .vendorAddress("vendor_address") - .vendorAddressRecipient("vendor_address_recipient") - .vendorEmail("vendor_email") - .vendorName("vendor_name") - .vendorTaxId("vendor_tax_id") .build() ) } @@ -723,76 +1151,137 @@ internal class ErrorHandlingTest { val e = assertThrows { documentService.create( - DocumentCreate.builder() - .amountDue(0.0) - .addAttachment( - DocumentAttachmentCreate.builder() - .fileName("file_name") - .fileData("file_data") - .fileSize(0L) - .fileType("file_type") - .build() - ) - .billingAddress("billing_address") - .billingAddressRecipient("billing_address_recipient") - .currency(CurrencyCode.EUR) - .customerAddress("customer_address") - .customerAddressRecipient("customer_address_recipient") - .customerEmail("customer_email") - .customerId("customer_id") - .customerName("customer_name") - .customerTaxId("customer_tax_id") - .direction(DocumentDirection.INBOUND) - .documentType(DocumentType.INVOICE) - .dueDate(LocalDate.parse("2019-12-27")) - .invoiceDate(LocalDate.parse("2019-12-27")) - .invoiceId("invoice_id") - .invoiceTotal(0.0) - .addItem( - DocumentCreate.Item.builder() - .amount(0.0) - .date(null) - .description("description") - .productCode("product_code") - .quantity(0.0) - .tax(0.0) - .taxRate("tax_rate") - .unit(UnitOfMeasureCode._10) - .unitPrice(0.0) - .build() - ) - .note("note") - .addPaymentDetail( - PaymentDetailCreate.builder() - .bankAccountNumber("bank_account_number") - .iban("iban") - .paymentReference("payment_reference") - .swift("swift") + DocumentCreateParams.builder() + .constructPdf(true) + .documentCreate( + DocumentCreate.builder() + .addAllowance( + DocumentCreate.Allowance.builder() + .amount(0.0) + .baseAmount(0.0) + .multiplierFactor(0.0) + .reason("reason") + .reasonCode(DocumentCreate.Allowance.ReasonCode._41) + .taxCode(DocumentCreate.Allowance.TaxCode.AE) + .taxRate(0.0) + .build() + ) + .amountDue(0.0) + .addAttachment( + DocumentAttachmentCreate.builder() + .fileName("file_name") + .fileData("file_data") + .fileSize(0L) + .fileType("file_type") + .build() + ) + .billingAddress("billing_address") + .billingAddressRecipient("billing_address_recipient") + .addCharge( + DocumentCreate.Charge.builder() + .amount(0.0) + .baseAmount(0.0) + .multiplierFactor(0.0) + .reason("reason") + .reasonCode(DocumentCreate.Charge.ReasonCode.AA) + .taxCode(DocumentCreate.Charge.TaxCode.AE) + .taxRate("21.00") + .build() + ) + .currency(CurrencyCode.EUR) + .customerAddress("customer_address") + .customerAddressRecipient("customer_address_recipient") + .customerCompanyId("1018265814") + .customerEmail("customer_email") + .customerId("customer_id") + .customerName("customer_name") + .customerTaxId("BE1018265814") + .direction(DocumentDirection.INBOUND) + .documentType(DocumentType.INVOICE) + .dueDate(LocalDate.parse("2019-12-27")) + .invoiceDate(LocalDate.parse("2019-12-27")) + .invoiceId("invoice_id") + .invoiceTotal(0.0) + .addItem( + DocumentCreate.Item.builder() + .addAllowance( + DocumentCreate.Item.Allowance.builder() + .amount(0.0) + .baseAmount(0.0) + .multiplierFactor(0.0) + .reason("reason") + .reasonCode( + DocumentCreate.Item.Allowance.ReasonCode._41 + ) + .taxCode(DocumentCreate.Item.Allowance.TaxCode.AE) + .taxRate(0.0) + .build() + ) + .amount(0.0) + .addCharge( + DocumentCreate.Item.Charge.builder() + .amount(0.0) + .baseAmount(0.0) + .multiplierFactor(0.0) + .reason("reason") + .reasonCode( + DocumentCreate.Item.Charge.ReasonCode.AA + ) + .taxCode(DocumentCreate.Item.Charge.TaxCode.AE) + .taxRate("21.00") + .build() + ) + .date(null) + .description("description") + .productCode("product_code") + .quantity(0.0) + .tax(0.0) + .taxRate("21.00") + .unit(UnitOfMeasureCode._10) + .unitPrice(0.0) + .build() + ) + .note("note") + .addPaymentDetail( + PaymentDetailCreate.builder() + .bankAccountNumber("bank_account_number") + .iban("iban") + .paymentReference("payment_reference") + .swift("swift") + .build() + ) + .paymentTerm("payment_term") + .previousUnpaidBalance(0.0) + .purchaseOrder("purchase_order") + .remittanceAddress("remittance_address") + .remittanceAddressRecipient("remittance_address_recipient") + .serviceAddress("service_address") + .serviceAddressRecipient("service_address_recipient") + .serviceEndDate(LocalDate.parse("2019-12-27")) + .serviceStartDate(LocalDate.parse("2019-12-27")) + .shippingAddress("shipping_address") + .shippingAddressRecipient("shipping_address_recipient") + .state(DocumentState.DRAFT) + .subtotal(0.0) + .taxCode(DocumentCreate.TaxCode.AE) + .addTaxDetail( + DocumentCreate.TaxDetail.builder() + .amount(0.0) + .rate("rate") + .build() + ) + .totalDiscount(0.0) + .totalTax(0.0) + .vatex(DocumentCreate.Vatex.VATEX_EU_79_C) + .vatexNote("vatex_note") + .vendorAddress("vendor_address") + .vendorAddressRecipient("vendor_address_recipient") + .vendorCompanyId("1018265814") + .vendorEmail("vendor_email") + .vendorName("vendor_name") + .vendorTaxId("BE1018265814") .build() ) - .paymentTerm("payment_term") - .previousUnpaidBalance(0.0) - .purchaseOrder("purchase_order") - .remittanceAddress("remittance_address") - .remittanceAddressRecipient("remittance_address_recipient") - .serviceAddress("service_address") - .serviceAddressRecipient("service_address_recipient") - .serviceEndDate(LocalDate.parse("2019-12-27")) - .serviceStartDate(LocalDate.parse("2019-12-27")) - .shippingAddress("shipping_address") - .shippingAddressRecipient("shipping_address_recipient") - .state(DocumentState.DRAFT) - .subtotal(0.0) - .addTaxDetail( - DocumentCreate.TaxDetail.builder().amount(0.0).rate("rate").build() - ) - .totalDiscount(0.0) - .totalTax(0.0) - .vendorAddress("vendor_address") - .vendorAddressRecipient("vendor_address_recipient") - .vendorEmail("vendor_email") - .vendorName("vendor_name") - .vendorTaxId("vendor_tax_id") .build() ) } @@ -815,76 +1304,137 @@ internal class ErrorHandlingTest { val e = assertThrows { documentService.create( - DocumentCreate.builder() - .amountDue(0.0) - .addAttachment( - DocumentAttachmentCreate.builder() - .fileName("file_name") - .fileData("file_data") - .fileSize(0L) - .fileType("file_type") + DocumentCreateParams.builder() + .constructPdf(true) + .documentCreate( + DocumentCreate.builder() + .addAllowance( + DocumentCreate.Allowance.builder() + .amount(0.0) + .baseAmount(0.0) + .multiplierFactor(0.0) + .reason("reason") + .reasonCode(DocumentCreate.Allowance.ReasonCode._41) + .taxCode(DocumentCreate.Allowance.TaxCode.AE) + .taxRate(0.0) + .build() + ) + .amountDue(0.0) + .addAttachment( + DocumentAttachmentCreate.builder() + .fileName("file_name") + .fileData("file_data") + .fileSize(0L) + .fileType("file_type") + .build() + ) + .billingAddress("billing_address") + .billingAddressRecipient("billing_address_recipient") + .addCharge( + DocumentCreate.Charge.builder() + .amount(0.0) + .baseAmount(0.0) + .multiplierFactor(0.0) + .reason("reason") + .reasonCode(DocumentCreate.Charge.ReasonCode.AA) + .taxCode(DocumentCreate.Charge.TaxCode.AE) + .taxRate("21.00") + .build() + ) + .currency(CurrencyCode.EUR) + .customerAddress("customer_address") + .customerAddressRecipient("customer_address_recipient") + .customerCompanyId("1018265814") + .customerEmail("customer_email") + .customerId("customer_id") + .customerName("customer_name") + .customerTaxId("BE1018265814") + .direction(DocumentDirection.INBOUND) + .documentType(DocumentType.INVOICE) + .dueDate(LocalDate.parse("2019-12-27")) + .invoiceDate(LocalDate.parse("2019-12-27")) + .invoiceId("invoice_id") + .invoiceTotal(0.0) + .addItem( + DocumentCreate.Item.builder() + .addAllowance( + DocumentCreate.Item.Allowance.builder() + .amount(0.0) + .baseAmount(0.0) + .multiplierFactor(0.0) + .reason("reason") + .reasonCode( + DocumentCreate.Item.Allowance.ReasonCode._41 + ) + .taxCode(DocumentCreate.Item.Allowance.TaxCode.AE) + .taxRate(0.0) + .build() + ) + .amount(0.0) + .addCharge( + DocumentCreate.Item.Charge.builder() + .amount(0.0) + .baseAmount(0.0) + .multiplierFactor(0.0) + .reason("reason") + .reasonCode( + DocumentCreate.Item.Charge.ReasonCode.AA + ) + .taxCode(DocumentCreate.Item.Charge.TaxCode.AE) + .taxRate("21.00") + .build() + ) + .date(null) + .description("description") + .productCode("product_code") + .quantity(0.0) + .tax(0.0) + .taxRate("21.00") + .unit(UnitOfMeasureCode._10) + .unitPrice(0.0) + .build() + ) + .note("note") + .addPaymentDetail( + PaymentDetailCreate.builder() + .bankAccountNumber("bank_account_number") + .iban("iban") + .paymentReference("payment_reference") + .swift("swift") + .build() + ) + .paymentTerm("payment_term") + .previousUnpaidBalance(0.0) + .purchaseOrder("purchase_order") + .remittanceAddress("remittance_address") + .remittanceAddressRecipient("remittance_address_recipient") + .serviceAddress("service_address") + .serviceAddressRecipient("service_address_recipient") + .serviceEndDate(LocalDate.parse("2019-12-27")) + .serviceStartDate(LocalDate.parse("2019-12-27")) + .shippingAddress("shipping_address") + .shippingAddressRecipient("shipping_address_recipient") + .state(DocumentState.DRAFT) + .subtotal(0.0) + .taxCode(DocumentCreate.TaxCode.AE) + .addTaxDetail( + DocumentCreate.TaxDetail.builder() + .amount(0.0) + .rate("rate") + .build() + ) + .totalDiscount(0.0) + .totalTax(0.0) + .vatex(DocumentCreate.Vatex.VATEX_EU_79_C) + .vatexNote("vatex_note") + .vendorAddress("vendor_address") + .vendorAddressRecipient("vendor_address_recipient") + .vendorCompanyId("1018265814") + .vendorEmail("vendor_email") + .vendorName("vendor_name") + .vendorTaxId("BE1018265814") .build() ) - .billingAddress("billing_address") - .billingAddressRecipient("billing_address_recipient") - .currency(CurrencyCode.EUR) - .customerAddress("customer_address") - .customerAddressRecipient("customer_address_recipient") - .customerEmail("customer_email") - .customerId("customer_id") - .customerName("customer_name") - .customerTaxId("customer_tax_id") - .direction(DocumentDirection.INBOUND) - .documentType(DocumentType.INVOICE) - .dueDate(LocalDate.parse("2019-12-27")) - .invoiceDate(LocalDate.parse("2019-12-27")) - .invoiceId("invoice_id") - .invoiceTotal(0.0) - .addItem( - DocumentCreate.Item.builder() - .amount(0.0) - .date(null) - .description("description") - .productCode("product_code") - .quantity(0.0) - .tax(0.0) - .taxRate("tax_rate") - .unit(UnitOfMeasureCode._10) - .unitPrice(0.0) - .build() - ) - .note("note") - .addPaymentDetail( - PaymentDetailCreate.builder() - .bankAccountNumber("bank_account_number") - .iban("iban") - .paymentReference("payment_reference") - .swift("swift") - .build() - ) - .paymentTerm("payment_term") - .previousUnpaidBalance(0.0) - .purchaseOrder("purchase_order") - .remittanceAddress("remittance_address") - .remittanceAddressRecipient("remittance_address_recipient") - .serviceAddress("service_address") - .serviceAddressRecipient("service_address_recipient") - .serviceEndDate(LocalDate.parse("2019-12-27")) - .serviceStartDate(LocalDate.parse("2019-12-27")) - .shippingAddress("shipping_address") - .shippingAddressRecipient("shipping_address_recipient") - .state(DocumentState.DRAFT) - .subtotal(0.0) - .addTaxDetail( - DocumentCreate.TaxDetail.builder().amount(0.0).rate("rate").build() - ) - .totalDiscount(0.0) - .totalTax(0.0) - .vendorAddress("vendor_address") - .vendorAddressRecipient("vendor_address_recipient") - .vendorEmail("vendor_email") - .vendorName("vendor_name") - .vendorTaxId("vendor_tax_id") .build() ) } @@ -907,76 +1457,137 @@ internal class ErrorHandlingTest { val e = assertThrows { documentService.create( - DocumentCreate.builder() - .amountDue(0.0) - .addAttachment( - DocumentAttachmentCreate.builder() - .fileName("file_name") - .fileData("file_data") - .fileSize(0L) - .fileType("file_type") - .build() - ) - .billingAddress("billing_address") - .billingAddressRecipient("billing_address_recipient") - .currency(CurrencyCode.EUR) - .customerAddress("customer_address") - .customerAddressRecipient("customer_address_recipient") - .customerEmail("customer_email") - .customerId("customer_id") - .customerName("customer_name") - .customerTaxId("customer_tax_id") - .direction(DocumentDirection.INBOUND) - .documentType(DocumentType.INVOICE) - .dueDate(LocalDate.parse("2019-12-27")) - .invoiceDate(LocalDate.parse("2019-12-27")) - .invoiceId("invoice_id") - .invoiceTotal(0.0) - .addItem( - DocumentCreate.Item.builder() - .amount(0.0) - .date(null) - .description("description") - .productCode("product_code") - .quantity(0.0) - .tax(0.0) - .taxRate("tax_rate") - .unit(UnitOfMeasureCode._10) - .unitPrice(0.0) - .build() - ) - .note("note") - .addPaymentDetail( - PaymentDetailCreate.builder() - .bankAccountNumber("bank_account_number") - .iban("iban") - .paymentReference("payment_reference") - .swift("swift") + DocumentCreateParams.builder() + .constructPdf(true) + .documentCreate( + DocumentCreate.builder() + .addAllowance( + DocumentCreate.Allowance.builder() + .amount(0.0) + .baseAmount(0.0) + .multiplierFactor(0.0) + .reason("reason") + .reasonCode(DocumentCreate.Allowance.ReasonCode._41) + .taxCode(DocumentCreate.Allowance.TaxCode.AE) + .taxRate(0.0) + .build() + ) + .amountDue(0.0) + .addAttachment( + DocumentAttachmentCreate.builder() + .fileName("file_name") + .fileData("file_data") + .fileSize(0L) + .fileType("file_type") + .build() + ) + .billingAddress("billing_address") + .billingAddressRecipient("billing_address_recipient") + .addCharge( + DocumentCreate.Charge.builder() + .amount(0.0) + .baseAmount(0.0) + .multiplierFactor(0.0) + .reason("reason") + .reasonCode(DocumentCreate.Charge.ReasonCode.AA) + .taxCode(DocumentCreate.Charge.TaxCode.AE) + .taxRate("21.00") + .build() + ) + .currency(CurrencyCode.EUR) + .customerAddress("customer_address") + .customerAddressRecipient("customer_address_recipient") + .customerCompanyId("1018265814") + .customerEmail("customer_email") + .customerId("customer_id") + .customerName("customer_name") + .customerTaxId("BE1018265814") + .direction(DocumentDirection.INBOUND) + .documentType(DocumentType.INVOICE) + .dueDate(LocalDate.parse("2019-12-27")) + .invoiceDate(LocalDate.parse("2019-12-27")) + .invoiceId("invoice_id") + .invoiceTotal(0.0) + .addItem( + DocumentCreate.Item.builder() + .addAllowance( + DocumentCreate.Item.Allowance.builder() + .amount(0.0) + .baseAmount(0.0) + .multiplierFactor(0.0) + .reason("reason") + .reasonCode( + DocumentCreate.Item.Allowance.ReasonCode._41 + ) + .taxCode(DocumentCreate.Item.Allowance.TaxCode.AE) + .taxRate(0.0) + .build() + ) + .amount(0.0) + .addCharge( + DocumentCreate.Item.Charge.builder() + .amount(0.0) + .baseAmount(0.0) + .multiplierFactor(0.0) + .reason("reason") + .reasonCode( + DocumentCreate.Item.Charge.ReasonCode.AA + ) + .taxCode(DocumentCreate.Item.Charge.TaxCode.AE) + .taxRate("21.00") + .build() + ) + .date(null) + .description("description") + .productCode("product_code") + .quantity(0.0) + .tax(0.0) + .taxRate("21.00") + .unit(UnitOfMeasureCode._10) + .unitPrice(0.0) + .build() + ) + .note("note") + .addPaymentDetail( + PaymentDetailCreate.builder() + .bankAccountNumber("bank_account_number") + .iban("iban") + .paymentReference("payment_reference") + .swift("swift") + .build() + ) + .paymentTerm("payment_term") + .previousUnpaidBalance(0.0) + .purchaseOrder("purchase_order") + .remittanceAddress("remittance_address") + .remittanceAddressRecipient("remittance_address_recipient") + .serviceAddress("service_address") + .serviceAddressRecipient("service_address_recipient") + .serviceEndDate(LocalDate.parse("2019-12-27")) + .serviceStartDate(LocalDate.parse("2019-12-27")) + .shippingAddress("shipping_address") + .shippingAddressRecipient("shipping_address_recipient") + .state(DocumentState.DRAFT) + .subtotal(0.0) + .taxCode(DocumentCreate.TaxCode.AE) + .addTaxDetail( + DocumentCreate.TaxDetail.builder() + .amount(0.0) + .rate("rate") + .build() + ) + .totalDiscount(0.0) + .totalTax(0.0) + .vatex(DocumentCreate.Vatex.VATEX_EU_79_C) + .vatexNote("vatex_note") + .vendorAddress("vendor_address") + .vendorAddressRecipient("vendor_address_recipient") + .vendorCompanyId("1018265814") + .vendorEmail("vendor_email") + .vendorName("vendor_name") + .vendorTaxId("BE1018265814") .build() ) - .paymentTerm("payment_term") - .previousUnpaidBalance(0.0) - .purchaseOrder("purchase_order") - .remittanceAddress("remittance_address") - .remittanceAddressRecipient("remittance_address_recipient") - .serviceAddress("service_address") - .serviceAddressRecipient("service_address_recipient") - .serviceEndDate(LocalDate.parse("2019-12-27")) - .serviceStartDate(LocalDate.parse("2019-12-27")) - .shippingAddress("shipping_address") - .shippingAddressRecipient("shipping_address_recipient") - .state(DocumentState.DRAFT) - .subtotal(0.0) - .addTaxDetail( - DocumentCreate.TaxDetail.builder().amount(0.0).rate("rate").build() - ) - .totalDiscount(0.0) - .totalTax(0.0) - .vendorAddress("vendor_address") - .vendorAddressRecipient("vendor_address_recipient") - .vendorEmail("vendor_email") - .vendorName("vendor_name") - .vendorTaxId("vendor_tax_id") .build() ) } @@ -999,76 +1610,137 @@ internal class ErrorHandlingTest { val e = assertThrows { documentService.create( - DocumentCreate.builder() - .amountDue(0.0) - .addAttachment( - DocumentAttachmentCreate.builder() - .fileName("file_name") - .fileData("file_data") - .fileSize(0L) - .fileType("file_type") - .build() - ) - .billingAddress("billing_address") - .billingAddressRecipient("billing_address_recipient") - .currency(CurrencyCode.EUR) - .customerAddress("customer_address") - .customerAddressRecipient("customer_address_recipient") - .customerEmail("customer_email") - .customerId("customer_id") - .customerName("customer_name") - .customerTaxId("customer_tax_id") - .direction(DocumentDirection.INBOUND) - .documentType(DocumentType.INVOICE) - .dueDate(LocalDate.parse("2019-12-27")) - .invoiceDate(LocalDate.parse("2019-12-27")) - .invoiceId("invoice_id") - .invoiceTotal(0.0) - .addItem( - DocumentCreate.Item.builder() - .amount(0.0) - .date(null) - .description("description") - .productCode("product_code") - .quantity(0.0) - .tax(0.0) - .taxRate("tax_rate") - .unit(UnitOfMeasureCode._10) - .unitPrice(0.0) - .build() - ) - .note("note") - .addPaymentDetail( - PaymentDetailCreate.builder() - .bankAccountNumber("bank_account_number") - .iban("iban") - .paymentReference("payment_reference") - .swift("swift") + DocumentCreateParams.builder() + .constructPdf(true) + .documentCreate( + DocumentCreate.builder() + .addAllowance( + DocumentCreate.Allowance.builder() + .amount(0.0) + .baseAmount(0.0) + .multiplierFactor(0.0) + .reason("reason") + .reasonCode(DocumentCreate.Allowance.ReasonCode._41) + .taxCode(DocumentCreate.Allowance.TaxCode.AE) + .taxRate(0.0) + .build() + ) + .amountDue(0.0) + .addAttachment( + DocumentAttachmentCreate.builder() + .fileName("file_name") + .fileData("file_data") + .fileSize(0L) + .fileType("file_type") + .build() + ) + .billingAddress("billing_address") + .billingAddressRecipient("billing_address_recipient") + .addCharge( + DocumentCreate.Charge.builder() + .amount(0.0) + .baseAmount(0.0) + .multiplierFactor(0.0) + .reason("reason") + .reasonCode(DocumentCreate.Charge.ReasonCode.AA) + .taxCode(DocumentCreate.Charge.TaxCode.AE) + .taxRate("21.00") + .build() + ) + .currency(CurrencyCode.EUR) + .customerAddress("customer_address") + .customerAddressRecipient("customer_address_recipient") + .customerCompanyId("1018265814") + .customerEmail("customer_email") + .customerId("customer_id") + .customerName("customer_name") + .customerTaxId("BE1018265814") + .direction(DocumentDirection.INBOUND) + .documentType(DocumentType.INVOICE) + .dueDate(LocalDate.parse("2019-12-27")) + .invoiceDate(LocalDate.parse("2019-12-27")) + .invoiceId("invoice_id") + .invoiceTotal(0.0) + .addItem( + DocumentCreate.Item.builder() + .addAllowance( + DocumentCreate.Item.Allowance.builder() + .amount(0.0) + .baseAmount(0.0) + .multiplierFactor(0.0) + .reason("reason") + .reasonCode( + DocumentCreate.Item.Allowance.ReasonCode._41 + ) + .taxCode(DocumentCreate.Item.Allowance.TaxCode.AE) + .taxRate(0.0) + .build() + ) + .amount(0.0) + .addCharge( + DocumentCreate.Item.Charge.builder() + .amount(0.0) + .baseAmount(0.0) + .multiplierFactor(0.0) + .reason("reason") + .reasonCode( + DocumentCreate.Item.Charge.ReasonCode.AA + ) + .taxCode(DocumentCreate.Item.Charge.TaxCode.AE) + .taxRate("21.00") + .build() + ) + .date(null) + .description("description") + .productCode("product_code") + .quantity(0.0) + .tax(0.0) + .taxRate("21.00") + .unit(UnitOfMeasureCode._10) + .unitPrice(0.0) + .build() + ) + .note("note") + .addPaymentDetail( + PaymentDetailCreate.builder() + .bankAccountNumber("bank_account_number") + .iban("iban") + .paymentReference("payment_reference") + .swift("swift") + .build() + ) + .paymentTerm("payment_term") + .previousUnpaidBalance(0.0) + .purchaseOrder("purchase_order") + .remittanceAddress("remittance_address") + .remittanceAddressRecipient("remittance_address_recipient") + .serviceAddress("service_address") + .serviceAddressRecipient("service_address_recipient") + .serviceEndDate(LocalDate.parse("2019-12-27")) + .serviceStartDate(LocalDate.parse("2019-12-27")) + .shippingAddress("shipping_address") + .shippingAddressRecipient("shipping_address_recipient") + .state(DocumentState.DRAFT) + .subtotal(0.0) + .taxCode(DocumentCreate.TaxCode.AE) + .addTaxDetail( + DocumentCreate.TaxDetail.builder() + .amount(0.0) + .rate("rate") + .build() + ) + .totalDiscount(0.0) + .totalTax(0.0) + .vatex(DocumentCreate.Vatex.VATEX_EU_79_C) + .vatexNote("vatex_note") + .vendorAddress("vendor_address") + .vendorAddressRecipient("vendor_address_recipient") + .vendorCompanyId("1018265814") + .vendorEmail("vendor_email") + .vendorName("vendor_name") + .vendorTaxId("BE1018265814") .build() ) - .paymentTerm("payment_term") - .previousUnpaidBalance(0.0) - .purchaseOrder("purchase_order") - .remittanceAddress("remittance_address") - .remittanceAddressRecipient("remittance_address_recipient") - .serviceAddress("service_address") - .serviceAddressRecipient("service_address_recipient") - .serviceEndDate(LocalDate.parse("2019-12-27")) - .serviceStartDate(LocalDate.parse("2019-12-27")) - .shippingAddress("shipping_address") - .shippingAddressRecipient("shipping_address_recipient") - .state(DocumentState.DRAFT) - .subtotal(0.0) - .addTaxDetail( - DocumentCreate.TaxDetail.builder().amount(0.0).rate("rate").build() - ) - .totalDiscount(0.0) - .totalTax(0.0) - .vendorAddress("vendor_address") - .vendorAddressRecipient("vendor_address_recipient") - .vendorEmail("vendor_email") - .vendorName("vendor_name") - .vendorTaxId("vendor_tax_id") .build() ) } @@ -1091,76 +1763,137 @@ internal class ErrorHandlingTest { val e = assertThrows { documentService.create( - DocumentCreate.builder() - .amountDue(0.0) - .addAttachment( - DocumentAttachmentCreate.builder() - .fileName("file_name") - .fileData("file_data") - .fileSize(0L) - .fileType("file_type") - .build() - ) - .billingAddress("billing_address") - .billingAddressRecipient("billing_address_recipient") - .currency(CurrencyCode.EUR) - .customerAddress("customer_address") - .customerAddressRecipient("customer_address_recipient") - .customerEmail("customer_email") - .customerId("customer_id") - .customerName("customer_name") - .customerTaxId("customer_tax_id") - .direction(DocumentDirection.INBOUND) - .documentType(DocumentType.INVOICE) - .dueDate(LocalDate.parse("2019-12-27")) - .invoiceDate(LocalDate.parse("2019-12-27")) - .invoiceId("invoice_id") - .invoiceTotal(0.0) - .addItem( - DocumentCreate.Item.builder() - .amount(0.0) - .date(null) - .description("description") - .productCode("product_code") - .quantity(0.0) - .tax(0.0) - .taxRate("tax_rate") - .unit(UnitOfMeasureCode._10) - .unitPrice(0.0) - .build() - ) - .note("note") - .addPaymentDetail( - PaymentDetailCreate.builder() - .bankAccountNumber("bank_account_number") - .iban("iban") - .paymentReference("payment_reference") - .swift("swift") + DocumentCreateParams.builder() + .constructPdf(true) + .documentCreate( + DocumentCreate.builder() + .addAllowance( + DocumentCreate.Allowance.builder() + .amount(0.0) + .baseAmount(0.0) + .multiplierFactor(0.0) + .reason("reason") + .reasonCode(DocumentCreate.Allowance.ReasonCode._41) + .taxCode(DocumentCreate.Allowance.TaxCode.AE) + .taxRate(0.0) + .build() + ) + .amountDue(0.0) + .addAttachment( + DocumentAttachmentCreate.builder() + .fileName("file_name") + .fileData("file_data") + .fileSize(0L) + .fileType("file_type") + .build() + ) + .billingAddress("billing_address") + .billingAddressRecipient("billing_address_recipient") + .addCharge( + DocumentCreate.Charge.builder() + .amount(0.0) + .baseAmount(0.0) + .multiplierFactor(0.0) + .reason("reason") + .reasonCode(DocumentCreate.Charge.ReasonCode.AA) + .taxCode(DocumentCreate.Charge.TaxCode.AE) + .taxRate("21.00") + .build() + ) + .currency(CurrencyCode.EUR) + .customerAddress("customer_address") + .customerAddressRecipient("customer_address_recipient") + .customerCompanyId("1018265814") + .customerEmail("customer_email") + .customerId("customer_id") + .customerName("customer_name") + .customerTaxId("BE1018265814") + .direction(DocumentDirection.INBOUND) + .documentType(DocumentType.INVOICE) + .dueDate(LocalDate.parse("2019-12-27")) + .invoiceDate(LocalDate.parse("2019-12-27")) + .invoiceId("invoice_id") + .invoiceTotal(0.0) + .addItem( + DocumentCreate.Item.builder() + .addAllowance( + DocumentCreate.Item.Allowance.builder() + .amount(0.0) + .baseAmount(0.0) + .multiplierFactor(0.0) + .reason("reason") + .reasonCode( + DocumentCreate.Item.Allowance.ReasonCode._41 + ) + .taxCode(DocumentCreate.Item.Allowance.TaxCode.AE) + .taxRate(0.0) + .build() + ) + .amount(0.0) + .addCharge( + DocumentCreate.Item.Charge.builder() + .amount(0.0) + .baseAmount(0.0) + .multiplierFactor(0.0) + .reason("reason") + .reasonCode( + DocumentCreate.Item.Charge.ReasonCode.AA + ) + .taxCode(DocumentCreate.Item.Charge.TaxCode.AE) + .taxRate("21.00") + .build() + ) + .date(null) + .description("description") + .productCode("product_code") + .quantity(0.0) + .tax(0.0) + .taxRate("21.00") + .unit(UnitOfMeasureCode._10) + .unitPrice(0.0) + .build() + ) + .note("note") + .addPaymentDetail( + PaymentDetailCreate.builder() + .bankAccountNumber("bank_account_number") + .iban("iban") + .paymentReference("payment_reference") + .swift("swift") + .build() + ) + .paymentTerm("payment_term") + .previousUnpaidBalance(0.0) + .purchaseOrder("purchase_order") + .remittanceAddress("remittance_address") + .remittanceAddressRecipient("remittance_address_recipient") + .serviceAddress("service_address") + .serviceAddressRecipient("service_address_recipient") + .serviceEndDate(LocalDate.parse("2019-12-27")) + .serviceStartDate(LocalDate.parse("2019-12-27")) + .shippingAddress("shipping_address") + .shippingAddressRecipient("shipping_address_recipient") + .state(DocumentState.DRAFT) + .subtotal(0.0) + .taxCode(DocumentCreate.TaxCode.AE) + .addTaxDetail( + DocumentCreate.TaxDetail.builder() + .amount(0.0) + .rate("rate") + .build() + ) + .totalDiscount(0.0) + .totalTax(0.0) + .vatex(DocumentCreate.Vatex.VATEX_EU_79_C) + .vatexNote("vatex_note") + .vendorAddress("vendor_address") + .vendorAddressRecipient("vendor_address_recipient") + .vendorCompanyId("1018265814") + .vendorEmail("vendor_email") + .vendorName("vendor_name") + .vendorTaxId("BE1018265814") .build() ) - .paymentTerm("payment_term") - .previousUnpaidBalance(0.0) - .purchaseOrder("purchase_order") - .remittanceAddress("remittance_address") - .remittanceAddressRecipient("remittance_address_recipient") - .serviceAddress("service_address") - .serviceAddressRecipient("service_address_recipient") - .serviceEndDate(LocalDate.parse("2019-12-27")) - .serviceStartDate(LocalDate.parse("2019-12-27")) - .shippingAddress("shipping_address") - .shippingAddressRecipient("shipping_address_recipient") - .state(DocumentState.DRAFT) - .subtotal(0.0) - .addTaxDetail( - DocumentCreate.TaxDetail.builder().amount(0.0).rate("rate").build() - ) - .totalDiscount(0.0) - .totalTax(0.0) - .vendorAddress("vendor_address") - .vendorAddressRecipient("vendor_address_recipient") - .vendorEmail("vendor_email") - .vendorName("vendor_name") - .vendorTaxId("vendor_tax_id") .build() ) } @@ -1183,76 +1916,137 @@ internal class ErrorHandlingTest { val e = assertThrows { documentService.create( - DocumentCreate.builder() - .amountDue(0.0) - .addAttachment( - DocumentAttachmentCreate.builder() - .fileName("file_name") - .fileData("file_data") - .fileSize(0L) - .fileType("file_type") - .build() - ) - .billingAddress("billing_address") - .billingAddressRecipient("billing_address_recipient") - .currency(CurrencyCode.EUR) - .customerAddress("customer_address") - .customerAddressRecipient("customer_address_recipient") - .customerEmail("customer_email") - .customerId("customer_id") - .customerName("customer_name") - .customerTaxId("customer_tax_id") - .direction(DocumentDirection.INBOUND) - .documentType(DocumentType.INVOICE) - .dueDate(LocalDate.parse("2019-12-27")) - .invoiceDate(LocalDate.parse("2019-12-27")) - .invoiceId("invoice_id") - .invoiceTotal(0.0) - .addItem( - DocumentCreate.Item.builder() - .amount(0.0) - .date(null) - .description("description") - .productCode("product_code") - .quantity(0.0) - .tax(0.0) - .taxRate("tax_rate") - .unit(UnitOfMeasureCode._10) - .unitPrice(0.0) - .build() - ) - .note("note") - .addPaymentDetail( - PaymentDetailCreate.builder() - .bankAccountNumber("bank_account_number") - .iban("iban") - .paymentReference("payment_reference") - .swift("swift") + DocumentCreateParams.builder() + .constructPdf(true) + .documentCreate( + DocumentCreate.builder() + .addAllowance( + DocumentCreate.Allowance.builder() + .amount(0.0) + .baseAmount(0.0) + .multiplierFactor(0.0) + .reason("reason") + .reasonCode(DocumentCreate.Allowance.ReasonCode._41) + .taxCode(DocumentCreate.Allowance.TaxCode.AE) + .taxRate(0.0) + .build() + ) + .amountDue(0.0) + .addAttachment( + DocumentAttachmentCreate.builder() + .fileName("file_name") + .fileData("file_data") + .fileSize(0L) + .fileType("file_type") + .build() + ) + .billingAddress("billing_address") + .billingAddressRecipient("billing_address_recipient") + .addCharge( + DocumentCreate.Charge.builder() + .amount(0.0) + .baseAmount(0.0) + .multiplierFactor(0.0) + .reason("reason") + .reasonCode(DocumentCreate.Charge.ReasonCode.AA) + .taxCode(DocumentCreate.Charge.TaxCode.AE) + .taxRate("21.00") + .build() + ) + .currency(CurrencyCode.EUR) + .customerAddress("customer_address") + .customerAddressRecipient("customer_address_recipient") + .customerCompanyId("1018265814") + .customerEmail("customer_email") + .customerId("customer_id") + .customerName("customer_name") + .customerTaxId("BE1018265814") + .direction(DocumentDirection.INBOUND) + .documentType(DocumentType.INVOICE) + .dueDate(LocalDate.parse("2019-12-27")) + .invoiceDate(LocalDate.parse("2019-12-27")) + .invoiceId("invoice_id") + .invoiceTotal(0.0) + .addItem( + DocumentCreate.Item.builder() + .addAllowance( + DocumentCreate.Item.Allowance.builder() + .amount(0.0) + .baseAmount(0.0) + .multiplierFactor(0.0) + .reason("reason") + .reasonCode( + DocumentCreate.Item.Allowance.ReasonCode._41 + ) + .taxCode(DocumentCreate.Item.Allowance.TaxCode.AE) + .taxRate(0.0) + .build() + ) + .amount(0.0) + .addCharge( + DocumentCreate.Item.Charge.builder() + .amount(0.0) + .baseAmount(0.0) + .multiplierFactor(0.0) + .reason("reason") + .reasonCode( + DocumentCreate.Item.Charge.ReasonCode.AA + ) + .taxCode(DocumentCreate.Item.Charge.TaxCode.AE) + .taxRate("21.00") + .build() + ) + .date(null) + .description("description") + .productCode("product_code") + .quantity(0.0) + .tax(0.0) + .taxRate("21.00") + .unit(UnitOfMeasureCode._10) + .unitPrice(0.0) + .build() + ) + .note("note") + .addPaymentDetail( + PaymentDetailCreate.builder() + .bankAccountNumber("bank_account_number") + .iban("iban") + .paymentReference("payment_reference") + .swift("swift") + .build() + ) + .paymentTerm("payment_term") + .previousUnpaidBalance(0.0) + .purchaseOrder("purchase_order") + .remittanceAddress("remittance_address") + .remittanceAddressRecipient("remittance_address_recipient") + .serviceAddress("service_address") + .serviceAddressRecipient("service_address_recipient") + .serviceEndDate(LocalDate.parse("2019-12-27")) + .serviceStartDate(LocalDate.parse("2019-12-27")) + .shippingAddress("shipping_address") + .shippingAddressRecipient("shipping_address_recipient") + .state(DocumentState.DRAFT) + .subtotal(0.0) + .taxCode(DocumentCreate.TaxCode.AE) + .addTaxDetail( + DocumentCreate.TaxDetail.builder() + .amount(0.0) + .rate("rate") + .build() + ) + .totalDiscount(0.0) + .totalTax(0.0) + .vatex(DocumentCreate.Vatex.VATEX_EU_79_C) + .vatexNote("vatex_note") + .vendorAddress("vendor_address") + .vendorAddressRecipient("vendor_address_recipient") + .vendorCompanyId("1018265814") + .vendorEmail("vendor_email") + .vendorName("vendor_name") + .vendorTaxId("BE1018265814") .build() ) - .paymentTerm("payment_term") - .previousUnpaidBalance(0.0) - .purchaseOrder("purchase_order") - .remittanceAddress("remittance_address") - .remittanceAddressRecipient("remittance_address_recipient") - .serviceAddress("service_address") - .serviceAddressRecipient("service_address_recipient") - .serviceEndDate(LocalDate.parse("2019-12-27")) - .serviceStartDate(LocalDate.parse("2019-12-27")) - .shippingAddress("shipping_address") - .shippingAddressRecipient("shipping_address_recipient") - .state(DocumentState.DRAFT) - .subtotal(0.0) - .addTaxDetail( - DocumentCreate.TaxDetail.builder().amount(0.0).rate("rate").build() - ) - .totalDiscount(0.0) - .totalTax(0.0) - .vendorAddress("vendor_address") - .vendorAddressRecipient("vendor_address_recipient") - .vendorEmail("vendor_email") - .vendorName("vendor_name") - .vendorTaxId("vendor_tax_id") .build() ) } @@ -1275,76 +2069,137 @@ internal class ErrorHandlingTest { val e = assertThrows { documentService.create( - DocumentCreate.builder() - .amountDue(0.0) - .addAttachment( - DocumentAttachmentCreate.builder() - .fileName("file_name") - .fileData("file_data") - .fileSize(0L) - .fileType("file_type") - .build() - ) - .billingAddress("billing_address") - .billingAddressRecipient("billing_address_recipient") - .currency(CurrencyCode.EUR) - .customerAddress("customer_address") - .customerAddressRecipient("customer_address_recipient") - .customerEmail("customer_email") - .customerId("customer_id") - .customerName("customer_name") - .customerTaxId("customer_tax_id") - .direction(DocumentDirection.INBOUND) - .documentType(DocumentType.INVOICE) - .dueDate(LocalDate.parse("2019-12-27")) - .invoiceDate(LocalDate.parse("2019-12-27")) - .invoiceId("invoice_id") - .invoiceTotal(0.0) - .addItem( - DocumentCreate.Item.builder() - .amount(0.0) - .date(null) - .description("description") - .productCode("product_code") - .quantity(0.0) - .tax(0.0) - .taxRate("tax_rate") - .unit(UnitOfMeasureCode._10) - .unitPrice(0.0) + DocumentCreateParams.builder() + .constructPdf(true) + .documentCreate( + DocumentCreate.builder() + .addAllowance( + DocumentCreate.Allowance.builder() + .amount(0.0) + .baseAmount(0.0) + .multiplierFactor(0.0) + .reason("reason") + .reasonCode(DocumentCreate.Allowance.ReasonCode._41) + .taxCode(DocumentCreate.Allowance.TaxCode.AE) + .taxRate(0.0) + .build() + ) + .amountDue(0.0) + .addAttachment( + DocumentAttachmentCreate.builder() + .fileName("file_name") + .fileData("file_data") + .fileSize(0L) + .fileType("file_type") + .build() + ) + .billingAddress("billing_address") + .billingAddressRecipient("billing_address_recipient") + .addCharge( + DocumentCreate.Charge.builder() + .amount(0.0) + .baseAmount(0.0) + .multiplierFactor(0.0) + .reason("reason") + .reasonCode(DocumentCreate.Charge.ReasonCode.AA) + .taxCode(DocumentCreate.Charge.TaxCode.AE) + .taxRate("21.00") + .build() + ) + .currency(CurrencyCode.EUR) + .customerAddress("customer_address") + .customerAddressRecipient("customer_address_recipient") + .customerCompanyId("1018265814") + .customerEmail("customer_email") + .customerId("customer_id") + .customerName("customer_name") + .customerTaxId("BE1018265814") + .direction(DocumentDirection.INBOUND) + .documentType(DocumentType.INVOICE) + .dueDate(LocalDate.parse("2019-12-27")) + .invoiceDate(LocalDate.parse("2019-12-27")) + .invoiceId("invoice_id") + .invoiceTotal(0.0) + .addItem( + DocumentCreate.Item.builder() + .addAllowance( + DocumentCreate.Item.Allowance.builder() + .amount(0.0) + .baseAmount(0.0) + .multiplierFactor(0.0) + .reason("reason") + .reasonCode( + DocumentCreate.Item.Allowance.ReasonCode._41 + ) + .taxCode(DocumentCreate.Item.Allowance.TaxCode.AE) + .taxRate(0.0) + .build() + ) + .amount(0.0) + .addCharge( + DocumentCreate.Item.Charge.builder() + .amount(0.0) + .baseAmount(0.0) + .multiplierFactor(0.0) + .reason("reason") + .reasonCode( + DocumentCreate.Item.Charge.ReasonCode.AA + ) + .taxCode(DocumentCreate.Item.Charge.TaxCode.AE) + .taxRate("21.00") + .build() + ) + .date(null) + .description("description") + .productCode("product_code") + .quantity(0.0) + .tax(0.0) + .taxRate("21.00") + .unit(UnitOfMeasureCode._10) + .unitPrice(0.0) + .build() + ) + .note("note") + .addPaymentDetail( + PaymentDetailCreate.builder() + .bankAccountNumber("bank_account_number") + .iban("iban") + .paymentReference("payment_reference") + .swift("swift") + .build() + ) + .paymentTerm("payment_term") + .previousUnpaidBalance(0.0) + .purchaseOrder("purchase_order") + .remittanceAddress("remittance_address") + .remittanceAddressRecipient("remittance_address_recipient") + .serviceAddress("service_address") + .serviceAddressRecipient("service_address_recipient") + .serviceEndDate(LocalDate.parse("2019-12-27")) + .serviceStartDate(LocalDate.parse("2019-12-27")) + .shippingAddress("shipping_address") + .shippingAddressRecipient("shipping_address_recipient") + .state(DocumentState.DRAFT) + .subtotal(0.0) + .taxCode(DocumentCreate.TaxCode.AE) + .addTaxDetail( + DocumentCreate.TaxDetail.builder() + .amount(0.0) + .rate("rate") + .build() + ) + .totalDiscount(0.0) + .totalTax(0.0) + .vatex(DocumentCreate.Vatex.VATEX_EU_79_C) + .vatexNote("vatex_note") + .vendorAddress("vendor_address") + .vendorAddressRecipient("vendor_address_recipient") + .vendorCompanyId("1018265814") + .vendorEmail("vendor_email") + .vendorName("vendor_name") + .vendorTaxId("BE1018265814") .build() ) - .note("note") - .addPaymentDetail( - PaymentDetailCreate.builder() - .bankAccountNumber("bank_account_number") - .iban("iban") - .paymentReference("payment_reference") - .swift("swift") - .build() - ) - .paymentTerm("payment_term") - .previousUnpaidBalance(0.0) - .purchaseOrder("purchase_order") - .remittanceAddress("remittance_address") - .remittanceAddressRecipient("remittance_address_recipient") - .serviceAddress("service_address") - .serviceAddressRecipient("service_address_recipient") - .serviceEndDate(LocalDate.parse("2019-12-27")) - .serviceStartDate(LocalDate.parse("2019-12-27")) - .shippingAddress("shipping_address") - .shippingAddressRecipient("shipping_address_recipient") - .state(DocumentState.DRAFT) - .subtotal(0.0) - .addTaxDetail( - DocumentCreate.TaxDetail.builder().amount(0.0).rate("rate").build() - ) - .totalDiscount(0.0) - .totalTax(0.0) - .vendorAddress("vendor_address") - .vendorAddressRecipient("vendor_address_recipient") - .vendorEmail("vendor_email") - .vendorName("vendor_name") - .vendorTaxId("vendor_tax_id") .build() ) } @@ -1367,76 +2222,137 @@ internal class ErrorHandlingTest { val e = assertThrows { documentService.create( - DocumentCreate.builder() - .amountDue(0.0) - .addAttachment( - DocumentAttachmentCreate.builder() - .fileName("file_name") - .fileData("file_data") - .fileSize(0L) - .fileType("file_type") + DocumentCreateParams.builder() + .constructPdf(true) + .documentCreate( + DocumentCreate.builder() + .addAllowance( + DocumentCreate.Allowance.builder() + .amount(0.0) + .baseAmount(0.0) + .multiplierFactor(0.0) + .reason("reason") + .reasonCode(DocumentCreate.Allowance.ReasonCode._41) + .taxCode(DocumentCreate.Allowance.TaxCode.AE) + .taxRate(0.0) + .build() + ) + .amountDue(0.0) + .addAttachment( + DocumentAttachmentCreate.builder() + .fileName("file_name") + .fileData("file_data") + .fileSize(0L) + .fileType("file_type") + .build() + ) + .billingAddress("billing_address") + .billingAddressRecipient("billing_address_recipient") + .addCharge( + DocumentCreate.Charge.builder() + .amount(0.0) + .baseAmount(0.0) + .multiplierFactor(0.0) + .reason("reason") + .reasonCode(DocumentCreate.Charge.ReasonCode.AA) + .taxCode(DocumentCreate.Charge.TaxCode.AE) + .taxRate("21.00") + .build() + ) + .currency(CurrencyCode.EUR) + .customerAddress("customer_address") + .customerAddressRecipient("customer_address_recipient") + .customerCompanyId("1018265814") + .customerEmail("customer_email") + .customerId("customer_id") + .customerName("customer_name") + .customerTaxId("BE1018265814") + .direction(DocumentDirection.INBOUND) + .documentType(DocumentType.INVOICE) + .dueDate(LocalDate.parse("2019-12-27")) + .invoiceDate(LocalDate.parse("2019-12-27")) + .invoiceId("invoice_id") + .invoiceTotal(0.0) + .addItem( + DocumentCreate.Item.builder() + .addAllowance( + DocumentCreate.Item.Allowance.builder() + .amount(0.0) + .baseAmount(0.0) + .multiplierFactor(0.0) + .reason("reason") + .reasonCode( + DocumentCreate.Item.Allowance.ReasonCode._41 + ) + .taxCode(DocumentCreate.Item.Allowance.TaxCode.AE) + .taxRate(0.0) + .build() + ) + .amount(0.0) + .addCharge( + DocumentCreate.Item.Charge.builder() + .amount(0.0) + .baseAmount(0.0) + .multiplierFactor(0.0) + .reason("reason") + .reasonCode( + DocumentCreate.Item.Charge.ReasonCode.AA + ) + .taxCode(DocumentCreate.Item.Charge.TaxCode.AE) + .taxRate("21.00") + .build() + ) + .date(null) + .description("description") + .productCode("product_code") + .quantity(0.0) + .tax(0.0) + .taxRate("21.00") + .unit(UnitOfMeasureCode._10) + .unitPrice(0.0) + .build() + ) + .note("note") + .addPaymentDetail( + PaymentDetailCreate.builder() + .bankAccountNumber("bank_account_number") + .iban("iban") + .paymentReference("payment_reference") + .swift("swift") + .build() + ) + .paymentTerm("payment_term") + .previousUnpaidBalance(0.0) + .purchaseOrder("purchase_order") + .remittanceAddress("remittance_address") + .remittanceAddressRecipient("remittance_address_recipient") + .serviceAddress("service_address") + .serviceAddressRecipient("service_address_recipient") + .serviceEndDate(LocalDate.parse("2019-12-27")) + .serviceStartDate(LocalDate.parse("2019-12-27")) + .shippingAddress("shipping_address") + .shippingAddressRecipient("shipping_address_recipient") + .state(DocumentState.DRAFT) + .subtotal(0.0) + .taxCode(DocumentCreate.TaxCode.AE) + .addTaxDetail( + DocumentCreate.TaxDetail.builder() + .amount(0.0) + .rate("rate") + .build() + ) + .totalDiscount(0.0) + .totalTax(0.0) + .vatex(DocumentCreate.Vatex.VATEX_EU_79_C) + .vatexNote("vatex_note") + .vendorAddress("vendor_address") + .vendorAddressRecipient("vendor_address_recipient") + .vendorCompanyId("1018265814") + .vendorEmail("vendor_email") + .vendorName("vendor_name") + .vendorTaxId("BE1018265814") .build() ) - .billingAddress("billing_address") - .billingAddressRecipient("billing_address_recipient") - .currency(CurrencyCode.EUR) - .customerAddress("customer_address") - .customerAddressRecipient("customer_address_recipient") - .customerEmail("customer_email") - .customerId("customer_id") - .customerName("customer_name") - .customerTaxId("customer_tax_id") - .direction(DocumentDirection.INBOUND) - .documentType(DocumentType.INVOICE) - .dueDate(LocalDate.parse("2019-12-27")) - .invoiceDate(LocalDate.parse("2019-12-27")) - .invoiceId("invoice_id") - .invoiceTotal(0.0) - .addItem( - DocumentCreate.Item.builder() - .amount(0.0) - .date(null) - .description("description") - .productCode("product_code") - .quantity(0.0) - .tax(0.0) - .taxRate("tax_rate") - .unit(UnitOfMeasureCode._10) - .unitPrice(0.0) - .build() - ) - .note("note") - .addPaymentDetail( - PaymentDetailCreate.builder() - .bankAccountNumber("bank_account_number") - .iban("iban") - .paymentReference("payment_reference") - .swift("swift") - .build() - ) - .paymentTerm("payment_term") - .previousUnpaidBalance(0.0) - .purchaseOrder("purchase_order") - .remittanceAddress("remittance_address") - .remittanceAddressRecipient("remittance_address_recipient") - .serviceAddress("service_address") - .serviceAddressRecipient("service_address_recipient") - .serviceEndDate(LocalDate.parse("2019-12-27")) - .serviceStartDate(LocalDate.parse("2019-12-27")) - .shippingAddress("shipping_address") - .shippingAddressRecipient("shipping_address_recipient") - .state(DocumentState.DRAFT) - .subtotal(0.0) - .addTaxDetail( - DocumentCreate.TaxDetail.builder().amount(0.0).rate("rate").build() - ) - .totalDiscount(0.0) - .totalTax(0.0) - .vendorAddress("vendor_address") - .vendorAddressRecipient("vendor_address_recipient") - .vendorEmail("vendor_email") - .vendorName("vendor_name") - .vendorTaxId("vendor_tax_id") .build() ) } @@ -1459,76 +2375,137 @@ internal class ErrorHandlingTest { val e = assertThrows { documentService.create( - DocumentCreate.builder() - .amountDue(0.0) - .addAttachment( - DocumentAttachmentCreate.builder() - .fileName("file_name") - .fileData("file_data") - .fileSize(0L) - .fileType("file_type") + DocumentCreateParams.builder() + .constructPdf(true) + .documentCreate( + DocumentCreate.builder() + .addAllowance( + DocumentCreate.Allowance.builder() + .amount(0.0) + .baseAmount(0.0) + .multiplierFactor(0.0) + .reason("reason") + .reasonCode(DocumentCreate.Allowance.ReasonCode._41) + .taxCode(DocumentCreate.Allowance.TaxCode.AE) + .taxRate(0.0) + .build() + ) + .amountDue(0.0) + .addAttachment( + DocumentAttachmentCreate.builder() + .fileName("file_name") + .fileData("file_data") + .fileSize(0L) + .fileType("file_type") + .build() + ) + .billingAddress("billing_address") + .billingAddressRecipient("billing_address_recipient") + .addCharge( + DocumentCreate.Charge.builder() + .amount(0.0) + .baseAmount(0.0) + .multiplierFactor(0.0) + .reason("reason") + .reasonCode(DocumentCreate.Charge.ReasonCode.AA) + .taxCode(DocumentCreate.Charge.TaxCode.AE) + .taxRate("21.00") + .build() + ) + .currency(CurrencyCode.EUR) + .customerAddress("customer_address") + .customerAddressRecipient("customer_address_recipient") + .customerCompanyId("1018265814") + .customerEmail("customer_email") + .customerId("customer_id") + .customerName("customer_name") + .customerTaxId("BE1018265814") + .direction(DocumentDirection.INBOUND) + .documentType(DocumentType.INVOICE) + .dueDate(LocalDate.parse("2019-12-27")) + .invoiceDate(LocalDate.parse("2019-12-27")) + .invoiceId("invoice_id") + .invoiceTotal(0.0) + .addItem( + DocumentCreate.Item.builder() + .addAllowance( + DocumentCreate.Item.Allowance.builder() + .amount(0.0) + .baseAmount(0.0) + .multiplierFactor(0.0) + .reason("reason") + .reasonCode( + DocumentCreate.Item.Allowance.ReasonCode._41 + ) + .taxCode(DocumentCreate.Item.Allowance.TaxCode.AE) + .taxRate(0.0) + .build() + ) + .amount(0.0) + .addCharge( + DocumentCreate.Item.Charge.builder() + .amount(0.0) + .baseAmount(0.0) + .multiplierFactor(0.0) + .reason("reason") + .reasonCode( + DocumentCreate.Item.Charge.ReasonCode.AA + ) + .taxCode(DocumentCreate.Item.Charge.TaxCode.AE) + .taxRate("21.00") + .build() + ) + .date(null) + .description("description") + .productCode("product_code") + .quantity(0.0) + .tax(0.0) + .taxRate("21.00") + .unit(UnitOfMeasureCode._10) + .unitPrice(0.0) + .build() + ) + .note("note") + .addPaymentDetail( + PaymentDetailCreate.builder() + .bankAccountNumber("bank_account_number") + .iban("iban") + .paymentReference("payment_reference") + .swift("swift") + .build() + ) + .paymentTerm("payment_term") + .previousUnpaidBalance(0.0) + .purchaseOrder("purchase_order") + .remittanceAddress("remittance_address") + .remittanceAddressRecipient("remittance_address_recipient") + .serviceAddress("service_address") + .serviceAddressRecipient("service_address_recipient") + .serviceEndDate(LocalDate.parse("2019-12-27")) + .serviceStartDate(LocalDate.parse("2019-12-27")) + .shippingAddress("shipping_address") + .shippingAddressRecipient("shipping_address_recipient") + .state(DocumentState.DRAFT) + .subtotal(0.0) + .taxCode(DocumentCreate.TaxCode.AE) + .addTaxDetail( + DocumentCreate.TaxDetail.builder() + .amount(0.0) + .rate("rate") + .build() + ) + .totalDiscount(0.0) + .totalTax(0.0) + .vatex(DocumentCreate.Vatex.VATEX_EU_79_C) + .vatexNote("vatex_note") + .vendorAddress("vendor_address") + .vendorAddressRecipient("vendor_address_recipient") + .vendorCompanyId("1018265814") + .vendorEmail("vendor_email") + .vendorName("vendor_name") + .vendorTaxId("BE1018265814") .build() ) - .billingAddress("billing_address") - .billingAddressRecipient("billing_address_recipient") - .currency(CurrencyCode.EUR) - .customerAddress("customer_address") - .customerAddressRecipient("customer_address_recipient") - .customerEmail("customer_email") - .customerId("customer_id") - .customerName("customer_name") - .customerTaxId("customer_tax_id") - .direction(DocumentDirection.INBOUND) - .documentType(DocumentType.INVOICE) - .dueDate(LocalDate.parse("2019-12-27")) - .invoiceDate(LocalDate.parse("2019-12-27")) - .invoiceId("invoice_id") - .invoiceTotal(0.0) - .addItem( - DocumentCreate.Item.builder() - .amount(0.0) - .date(null) - .description("description") - .productCode("product_code") - .quantity(0.0) - .tax(0.0) - .taxRate("tax_rate") - .unit(UnitOfMeasureCode._10) - .unitPrice(0.0) - .build() - ) - .note("note") - .addPaymentDetail( - PaymentDetailCreate.builder() - .bankAccountNumber("bank_account_number") - .iban("iban") - .paymentReference("payment_reference") - .swift("swift") - .build() - ) - .paymentTerm("payment_term") - .previousUnpaidBalance(0.0) - .purchaseOrder("purchase_order") - .remittanceAddress("remittance_address") - .remittanceAddressRecipient("remittance_address_recipient") - .serviceAddress("service_address") - .serviceAddressRecipient("service_address_recipient") - .serviceEndDate(LocalDate.parse("2019-12-27")) - .serviceStartDate(LocalDate.parse("2019-12-27")) - .shippingAddress("shipping_address") - .shippingAddressRecipient("shipping_address_recipient") - .state(DocumentState.DRAFT) - .subtotal(0.0) - .addTaxDetail( - DocumentCreate.TaxDetail.builder().amount(0.0).rate("rate").build() - ) - .totalDiscount(0.0) - .totalTax(0.0) - .vendorAddress("vendor_address") - .vendorAddressRecipient("vendor_address_recipient") - .vendorEmail("vendor_email") - .vendorName("vendor_name") - .vendorTaxId("vendor_tax_id") .build() ) } @@ -1549,76 +2526,137 @@ internal class ErrorHandlingTest { val e = assertThrows { documentService.create( - DocumentCreate.builder() - .amountDue(0.0) - .addAttachment( - DocumentAttachmentCreate.builder() - .fileName("file_name") - .fileData("file_data") - .fileSize(0L) - .fileType("file_type") + DocumentCreateParams.builder() + .constructPdf(true) + .documentCreate( + DocumentCreate.builder() + .addAllowance( + DocumentCreate.Allowance.builder() + .amount(0.0) + .baseAmount(0.0) + .multiplierFactor(0.0) + .reason("reason") + .reasonCode(DocumentCreate.Allowance.ReasonCode._41) + .taxCode(DocumentCreate.Allowance.TaxCode.AE) + .taxRate(0.0) + .build() + ) + .amountDue(0.0) + .addAttachment( + DocumentAttachmentCreate.builder() + .fileName("file_name") + .fileData("file_data") + .fileSize(0L) + .fileType("file_type") + .build() + ) + .billingAddress("billing_address") + .billingAddressRecipient("billing_address_recipient") + .addCharge( + DocumentCreate.Charge.builder() + .amount(0.0) + .baseAmount(0.0) + .multiplierFactor(0.0) + .reason("reason") + .reasonCode(DocumentCreate.Charge.ReasonCode.AA) + .taxCode(DocumentCreate.Charge.TaxCode.AE) + .taxRate("21.00") + .build() + ) + .currency(CurrencyCode.EUR) + .customerAddress("customer_address") + .customerAddressRecipient("customer_address_recipient") + .customerCompanyId("1018265814") + .customerEmail("customer_email") + .customerId("customer_id") + .customerName("customer_name") + .customerTaxId("BE1018265814") + .direction(DocumentDirection.INBOUND) + .documentType(DocumentType.INVOICE) + .dueDate(LocalDate.parse("2019-12-27")) + .invoiceDate(LocalDate.parse("2019-12-27")) + .invoiceId("invoice_id") + .invoiceTotal(0.0) + .addItem( + DocumentCreate.Item.builder() + .addAllowance( + DocumentCreate.Item.Allowance.builder() + .amount(0.0) + .baseAmount(0.0) + .multiplierFactor(0.0) + .reason("reason") + .reasonCode( + DocumentCreate.Item.Allowance.ReasonCode._41 + ) + .taxCode(DocumentCreate.Item.Allowance.TaxCode.AE) + .taxRate(0.0) + .build() + ) + .amount(0.0) + .addCharge( + DocumentCreate.Item.Charge.builder() + .amount(0.0) + .baseAmount(0.0) + .multiplierFactor(0.0) + .reason("reason") + .reasonCode( + DocumentCreate.Item.Charge.ReasonCode.AA + ) + .taxCode(DocumentCreate.Item.Charge.TaxCode.AE) + .taxRate("21.00") + .build() + ) + .date(null) + .description("description") + .productCode("product_code") + .quantity(0.0) + .tax(0.0) + .taxRate("21.00") + .unit(UnitOfMeasureCode._10) + .unitPrice(0.0) + .build() + ) + .note("note") + .addPaymentDetail( + PaymentDetailCreate.builder() + .bankAccountNumber("bank_account_number") + .iban("iban") + .paymentReference("payment_reference") + .swift("swift") + .build() + ) + .paymentTerm("payment_term") + .previousUnpaidBalance(0.0) + .purchaseOrder("purchase_order") + .remittanceAddress("remittance_address") + .remittanceAddressRecipient("remittance_address_recipient") + .serviceAddress("service_address") + .serviceAddressRecipient("service_address_recipient") + .serviceEndDate(LocalDate.parse("2019-12-27")) + .serviceStartDate(LocalDate.parse("2019-12-27")) + .shippingAddress("shipping_address") + .shippingAddressRecipient("shipping_address_recipient") + .state(DocumentState.DRAFT) + .subtotal(0.0) + .taxCode(DocumentCreate.TaxCode.AE) + .addTaxDetail( + DocumentCreate.TaxDetail.builder() + .amount(0.0) + .rate("rate") + .build() + ) + .totalDiscount(0.0) + .totalTax(0.0) + .vatex(DocumentCreate.Vatex.VATEX_EU_79_C) + .vatexNote("vatex_note") + .vendorAddress("vendor_address") + .vendorAddressRecipient("vendor_address_recipient") + .vendorCompanyId("1018265814") + .vendorEmail("vendor_email") + .vendorName("vendor_name") + .vendorTaxId("BE1018265814") .build() ) - .billingAddress("billing_address") - .billingAddressRecipient("billing_address_recipient") - .currency(CurrencyCode.EUR) - .customerAddress("customer_address") - .customerAddressRecipient("customer_address_recipient") - .customerEmail("customer_email") - .customerId("customer_id") - .customerName("customer_name") - .customerTaxId("customer_tax_id") - .direction(DocumentDirection.INBOUND) - .documentType(DocumentType.INVOICE) - .dueDate(LocalDate.parse("2019-12-27")) - .invoiceDate(LocalDate.parse("2019-12-27")) - .invoiceId("invoice_id") - .invoiceTotal(0.0) - .addItem( - DocumentCreate.Item.builder() - .amount(0.0) - .date(null) - .description("description") - .productCode("product_code") - .quantity(0.0) - .tax(0.0) - .taxRate("tax_rate") - .unit(UnitOfMeasureCode._10) - .unitPrice(0.0) - .build() - ) - .note("note") - .addPaymentDetail( - PaymentDetailCreate.builder() - .bankAccountNumber("bank_account_number") - .iban("iban") - .paymentReference("payment_reference") - .swift("swift") - .build() - ) - .paymentTerm("payment_term") - .previousUnpaidBalance(0.0) - .purchaseOrder("purchase_order") - .remittanceAddress("remittance_address") - .remittanceAddressRecipient("remittance_address_recipient") - .serviceAddress("service_address") - .serviceAddressRecipient("service_address_recipient") - .serviceEndDate(LocalDate.parse("2019-12-27")) - .serviceStartDate(LocalDate.parse("2019-12-27")) - .shippingAddress("shipping_address") - .shippingAddressRecipient("shipping_address_recipient") - .state(DocumentState.DRAFT) - .subtotal(0.0) - .addTaxDetail( - DocumentCreate.TaxDetail.builder().amount(0.0).rate("rate").build() - ) - .totalDiscount(0.0) - .totalTax(0.0) - .vendorAddress("vendor_address") - .vendorAddressRecipient("vendor_address_recipient") - .vendorEmail("vendor_email") - .vendorName("vendor_name") - .vendorTaxId("vendor_tax_id") .build() ) } diff --git a/e-invoice-java-core/src/test/kotlin/com/e_invoice/api/services/ServiceParamsTest.kt b/e-invoice-java-core/src/test/kotlin/com/e_invoice/api/services/ServiceParamsTest.kt index eb5ef34..df07769 100644 --- a/e-invoice-java-core/src/test/kotlin/com/e_invoice/api/services/ServiceParamsTest.kt +++ b/e-invoice-java-core/src/test/kotlin/com/e_invoice/api/services/ServiceParamsTest.kt @@ -7,6 +7,7 @@ import com.e_invoice.api.client.okhttp.EInvoiceOkHttpClient import com.e_invoice.api.models.documents.CurrencyCode import com.e_invoice.api.models.documents.DocumentAttachmentCreate import com.e_invoice.api.models.documents.DocumentCreate +import com.e_invoice.api.models.documents.DocumentCreateParams import com.e_invoice.api.models.documents.DocumentDirection import com.e_invoice.api.models.documents.DocumentType import com.e_invoice.api.models.documents.PaymentDetailCreate @@ -49,74 +50,132 @@ internal class ServiceParamsTest { stubFor(post(anyUrl()).willReturn(ok("{}"))) documentService.create( - DocumentCreate.builder() - .amountDue(0.0) - .addAttachment( - DocumentAttachmentCreate.builder() - .fileName("file_name") - .fileData("file_data") - .fileSize(0L) - .fileType("file_type") + DocumentCreateParams.builder() + .constructPdf(true) + .documentCreate( + DocumentCreate.builder() + .addAllowance( + DocumentCreate.Allowance.builder() + .amount(0.0) + .baseAmount(0.0) + .multiplierFactor(0.0) + .reason("reason") + .reasonCode(DocumentCreate.Allowance.ReasonCode._41) + .taxCode(DocumentCreate.Allowance.TaxCode.AE) + .taxRate(0.0) + .build() + ) + .amountDue(0.0) + .addAttachment( + DocumentAttachmentCreate.builder() + .fileName("file_name") + .fileData("file_data") + .fileSize(0L) + .fileType("file_type") + .build() + ) + .billingAddress("billing_address") + .billingAddressRecipient("billing_address_recipient") + .addCharge( + DocumentCreate.Charge.builder() + .amount(0.0) + .baseAmount(0.0) + .multiplierFactor(0.0) + .reason("reason") + .reasonCode(DocumentCreate.Charge.ReasonCode.AA) + .taxCode(DocumentCreate.Charge.TaxCode.AE) + .taxRate("21.00") + .build() + ) + .currency(CurrencyCode.EUR) + .customerAddress("customer_address") + .customerAddressRecipient("customer_address_recipient") + .customerCompanyId("1018265814") + .customerEmail("customer_email") + .customerId("customer_id") + .customerName("customer_name") + .customerTaxId("BE1018265814") + .direction(DocumentDirection.INBOUND) + .documentType(DocumentType.INVOICE) + .dueDate(LocalDate.parse("2019-12-27")) + .invoiceDate(LocalDate.parse("2019-12-27")) + .invoiceId("invoice_id") + .invoiceTotal(0.0) + .addItem( + DocumentCreate.Item.builder() + .addAllowance( + DocumentCreate.Item.Allowance.builder() + .amount(0.0) + .baseAmount(0.0) + .multiplierFactor(0.0) + .reason("reason") + .reasonCode(DocumentCreate.Item.Allowance.ReasonCode._41) + .taxCode(DocumentCreate.Item.Allowance.TaxCode.AE) + .taxRate(0.0) + .build() + ) + .amount(0.0) + .addCharge( + DocumentCreate.Item.Charge.builder() + .amount(0.0) + .baseAmount(0.0) + .multiplierFactor(0.0) + .reason("reason") + .reasonCode(DocumentCreate.Item.Charge.ReasonCode.AA) + .taxCode(DocumentCreate.Item.Charge.TaxCode.AE) + .taxRate("21.00") + .build() + ) + .date(null) + .description("description") + .productCode("product_code") + .quantity(0.0) + .tax(0.0) + .taxRate("21.00") + .unit(UnitOfMeasureCode._10) + .unitPrice(0.0) + .build() + ) + .note("note") + .addPaymentDetail( + PaymentDetailCreate.builder() + .bankAccountNumber("bank_account_number") + .iban("iban") + .paymentReference("payment_reference") + .swift("swift") + .build() + ) + .paymentTerm("payment_term") + .previousUnpaidBalance(0.0) + .purchaseOrder("purchase_order") + .remittanceAddress("remittance_address") + .remittanceAddressRecipient("remittance_address_recipient") + .serviceAddress("service_address") + .serviceAddressRecipient("service_address_recipient") + .serviceEndDate(LocalDate.parse("2019-12-27")) + .serviceStartDate(LocalDate.parse("2019-12-27")) + .shippingAddress("shipping_address") + .shippingAddressRecipient("shipping_address_recipient") + .state(DocumentState.DRAFT) + .subtotal(0.0) + .taxCode(DocumentCreate.TaxCode.AE) + .addTaxDetail( + DocumentCreate.TaxDetail.builder().amount(0.0).rate("rate").build() + ) + .totalDiscount(0.0) + .totalTax(0.0) + .vatex(DocumentCreate.Vatex.VATEX_EU_79_C) + .vatexNote("vatex_note") + .vendorAddress("vendor_address") + .vendorAddressRecipient("vendor_address_recipient") + .vendorCompanyId("1018265814") + .vendorEmail("vendor_email") + .vendorName("vendor_name") + .vendorTaxId("BE1018265814") .build() ) - .billingAddress("billing_address") - .billingAddressRecipient("billing_address_recipient") - .currency(CurrencyCode.EUR) - .customerAddress("customer_address") - .customerAddressRecipient("customer_address_recipient") - .customerEmail("customer_email") - .customerId("customer_id") - .customerName("customer_name") - .customerTaxId("customer_tax_id") - .direction(DocumentDirection.INBOUND) - .documentType(DocumentType.INVOICE) - .dueDate(LocalDate.parse("2019-12-27")) - .invoiceDate(LocalDate.parse("2019-12-27")) - .invoiceId("invoice_id") - .invoiceTotal(0.0) - .addItem( - DocumentCreate.Item.builder() - .amount(0.0) - .date(null) - .description("description") - .productCode("product_code") - .quantity(0.0) - .tax(0.0) - .taxRate("tax_rate") - .unit(UnitOfMeasureCode._10) - .unitPrice(0.0) - .build() - ) - .note("note") - .addPaymentDetail( - PaymentDetailCreate.builder() - .bankAccountNumber("bank_account_number") - .iban("iban") - .paymentReference("payment_reference") - .swift("swift") - .build() - ) - .paymentTerm("payment_term") - .previousUnpaidBalance(0.0) - .purchaseOrder("purchase_order") - .remittanceAddress("remittance_address") - .remittanceAddressRecipient("remittance_address_recipient") - .serviceAddress("service_address") - .serviceAddressRecipient("service_address_recipient") - .serviceEndDate(LocalDate.parse("2019-12-27")) - .serviceStartDate(LocalDate.parse("2019-12-27")) - .shippingAddress("shipping_address") - .shippingAddressRecipient("shipping_address_recipient") - .state(DocumentState.DRAFT) - .subtotal(0.0) - .addTaxDetail(DocumentCreate.TaxDetail.builder().amount(0.0).rate("rate").build()) - .totalDiscount(0.0) - .totalTax(0.0) - .vendorAddress("vendor_address") - .vendorAddressRecipient("vendor_address_recipient") - .vendorEmail("vendor_email") - .vendorName("vendor_name") - .vendorTaxId("vendor_tax_id") + .putAdditionalHeader("Secret-Header", "42") + .putAdditionalQueryParam("secret_query_param", "42") .build() ) diff --git a/e-invoice-java-core/src/test/kotlin/com/e_invoice/api/services/async/DocumentServiceAsyncTest.kt b/e-invoice-java-core/src/test/kotlin/com/e_invoice/api/services/async/DocumentServiceAsyncTest.kt index 4edc2f0..b7ba41d 100644 --- a/e-invoice-java-core/src/test/kotlin/com/e_invoice/api/services/async/DocumentServiceAsyncTest.kt +++ b/e-invoice-java-core/src/test/kotlin/com/e_invoice/api/services/async/DocumentServiceAsyncTest.kt @@ -7,6 +7,8 @@ import com.e_invoice.api.client.okhttp.EInvoiceOkHttpClientAsync import com.e_invoice.api.models.documents.CurrencyCode import com.e_invoice.api.models.documents.DocumentAttachmentCreate import com.e_invoice.api.models.documents.DocumentCreate +import com.e_invoice.api.models.documents.DocumentCreateFromPdfParams +import com.e_invoice.api.models.documents.DocumentCreateParams import com.e_invoice.api.models.documents.DocumentDirection import com.e_invoice.api.models.documents.DocumentSendParams import com.e_invoice.api.models.documents.DocumentType @@ -33,76 +35,132 @@ internal class DocumentServiceAsyncTest { val documentResponseFuture = documentServiceAsync.create( - DocumentCreate.builder() - .amountDue(0.0) - .addAttachment( - DocumentAttachmentCreate.builder() - .fileName("file_name") - .fileData("file_data") - .fileSize(0L) - .fileType("file_type") + DocumentCreateParams.builder() + .constructPdf(true) + .documentCreate( + DocumentCreate.builder() + .addAllowance( + DocumentCreate.Allowance.builder() + .amount(0.0) + .baseAmount(0.0) + .multiplierFactor(0.0) + .reason("reason") + .reasonCode(DocumentCreate.Allowance.ReasonCode._41) + .taxCode(DocumentCreate.Allowance.TaxCode.AE) + .taxRate(0.0) + .build() + ) + .amountDue(0.0) + .addAttachment( + DocumentAttachmentCreate.builder() + .fileName("file_name") + .fileData("file_data") + .fileSize(0L) + .fileType("file_type") + .build() + ) + .billingAddress("billing_address") + .billingAddressRecipient("billing_address_recipient") + .addCharge( + DocumentCreate.Charge.builder() + .amount(0.0) + .baseAmount(0.0) + .multiplierFactor(0.0) + .reason("reason") + .reasonCode(DocumentCreate.Charge.ReasonCode.AA) + .taxCode(DocumentCreate.Charge.TaxCode.AE) + .taxRate("21.00") + .build() + ) + .currency(CurrencyCode.EUR) + .customerAddress("customer_address") + .customerAddressRecipient("customer_address_recipient") + .customerCompanyId("1018265814") + .customerEmail("customer_email") + .customerId("customer_id") + .customerName("customer_name") + .customerTaxId("BE1018265814") + .direction(DocumentDirection.INBOUND) + .documentType(DocumentType.INVOICE) + .dueDate(LocalDate.parse("2019-12-27")) + .invoiceDate(LocalDate.parse("2019-12-27")) + .invoiceId("invoice_id") + .invoiceTotal(0.0) + .addItem( + DocumentCreate.Item.builder() + .addAllowance( + DocumentCreate.Item.Allowance.builder() + .amount(0.0) + .baseAmount(0.0) + .multiplierFactor(0.0) + .reason("reason") + .reasonCode( + DocumentCreate.Item.Allowance.ReasonCode._41 + ) + .taxCode(DocumentCreate.Item.Allowance.TaxCode.AE) + .taxRate(0.0) + .build() + ) + .amount(0.0) + .addCharge( + DocumentCreate.Item.Charge.builder() + .amount(0.0) + .baseAmount(0.0) + .multiplierFactor(0.0) + .reason("reason") + .reasonCode(DocumentCreate.Item.Charge.ReasonCode.AA) + .taxCode(DocumentCreate.Item.Charge.TaxCode.AE) + .taxRate("21.00") + .build() + ) + .date(null) + .description("description") + .productCode("product_code") + .quantity(0.0) + .tax(0.0) + .taxRate("21.00") + .unit(UnitOfMeasureCode._10) + .unitPrice(0.0) + .build() + ) + .note("note") + .addPaymentDetail( + PaymentDetailCreate.builder() + .bankAccountNumber("bank_account_number") + .iban("iban") + .paymentReference("payment_reference") + .swift("swift") + .build() + ) + .paymentTerm("payment_term") + .previousUnpaidBalance(0.0) + .purchaseOrder("purchase_order") + .remittanceAddress("remittance_address") + .remittanceAddressRecipient("remittance_address_recipient") + .serviceAddress("service_address") + .serviceAddressRecipient("service_address_recipient") + .serviceEndDate(LocalDate.parse("2019-12-27")) + .serviceStartDate(LocalDate.parse("2019-12-27")) + .shippingAddress("shipping_address") + .shippingAddressRecipient("shipping_address_recipient") + .state(DocumentState.DRAFT) + .subtotal(0.0) + .taxCode(DocumentCreate.TaxCode.AE) + .addTaxDetail( + DocumentCreate.TaxDetail.builder().amount(0.0).rate("rate").build() + ) + .totalDiscount(0.0) + .totalTax(0.0) + .vatex(DocumentCreate.Vatex.VATEX_EU_79_C) + .vatexNote("vatex_note") + .vendorAddress("vendor_address") + .vendorAddressRecipient("vendor_address_recipient") + .vendorCompanyId("1018265814") + .vendorEmail("vendor_email") + .vendorName("vendor_name") + .vendorTaxId("BE1018265814") .build() ) - .billingAddress("billing_address") - .billingAddressRecipient("billing_address_recipient") - .currency(CurrencyCode.EUR) - .customerAddress("customer_address") - .customerAddressRecipient("customer_address_recipient") - .customerEmail("customer_email") - .customerId("customer_id") - .customerName("customer_name") - .customerTaxId("customer_tax_id") - .direction(DocumentDirection.INBOUND) - .documentType(DocumentType.INVOICE) - .dueDate(LocalDate.parse("2019-12-27")) - .invoiceDate(LocalDate.parse("2019-12-27")) - .invoiceId("invoice_id") - .invoiceTotal(0.0) - .addItem( - DocumentCreate.Item.builder() - .amount(0.0) - .date(null) - .description("description") - .productCode("product_code") - .quantity(0.0) - .tax(0.0) - .taxRate("tax_rate") - .unit(UnitOfMeasureCode._10) - .unitPrice(0.0) - .build() - ) - .note("note") - .addPaymentDetail( - PaymentDetailCreate.builder() - .bankAccountNumber("bank_account_number") - .iban("iban") - .paymentReference("payment_reference") - .swift("swift") - .build() - ) - .paymentTerm("payment_term") - .previousUnpaidBalance(0.0) - .purchaseOrder("purchase_order") - .remittanceAddress("remittance_address") - .remittanceAddressRecipient("remittance_address_recipient") - .serviceAddress("service_address") - .serviceAddressRecipient("service_address_recipient") - .serviceEndDate(LocalDate.parse("2019-12-27")) - .serviceStartDate(LocalDate.parse("2019-12-27")) - .shippingAddress("shipping_address") - .shippingAddressRecipient("shipping_address_recipient") - .state(DocumentState.DRAFT) - .subtotal(0.0) - .addTaxDetail( - DocumentCreate.TaxDetail.builder().amount(0.0).rate("rate").build() - ) - .totalDiscount(0.0) - .totalTax(0.0) - .vendorAddress("vendor_address") - .vendorAddressRecipient("vendor_address_recipient") - .vendorEmail("vendor_email") - .vendorName("vendor_name") - .vendorTaxId("vendor_tax_id") .build() ) @@ -142,6 +200,29 @@ internal class DocumentServiceAsyncTest { document.validate() } + @Disabled("Prism tests are disabled") + @Test + fun createFromPdf() { + val client = + EInvoiceOkHttpClientAsync.builder() + .baseUrl(TestServerExtension.BASE_URL) + .apiKey("My API Key") + .build() + val documentServiceAsync = client.documents() + + val responseFuture = + documentServiceAsync.createFromPdf( + DocumentCreateFromPdfParams.builder() + .customerTaxId("customer_tax_id") + .vendorTaxId("vendor_tax_id") + .file("some content".byteInputStream()) + .build() + ) + + val response = responseFuture.get() + response.validate() + } + @Disabled("Prism tests are disabled") @Test fun send() { @@ -167,4 +248,20 @@ internal class DocumentServiceAsyncTest { val documentResponse = documentResponseFuture.get() documentResponse.validate() } + + @Disabled("Prism tests are disabled") + @Test + fun validate() { + val client = + EInvoiceOkHttpClientAsync.builder() + .baseUrl(TestServerExtension.BASE_URL) + .apiKey("My API Key") + .build() + val documentServiceAsync = client.documents() + + val ublDocumentValidationFuture = documentServiceAsync.validate("document_id") + + val ublDocumentValidation = ublDocumentValidationFuture.get() + ublDocumentValidation.validate() + } } diff --git a/e-invoice-java-core/src/test/kotlin/com/e_invoice/api/services/async/MeServiceAsyncTest.kt b/e-invoice-java-core/src/test/kotlin/com/e_invoice/api/services/async/MeServiceAsyncTest.kt new file mode 100644 index 0000000..afeb131 --- /dev/null +++ b/e-invoice-java-core/src/test/kotlin/com/e_invoice/api/services/async/MeServiceAsyncTest.kt @@ -0,0 +1,29 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.e_invoice.api.services.async + +import com.e_invoice.api.TestServerExtension +import com.e_invoice.api.client.okhttp.EInvoiceOkHttpClientAsync +import org.junit.jupiter.api.Disabled +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.extension.ExtendWith + +@ExtendWith(TestServerExtension::class) +internal class MeServiceAsyncTest { + + @Disabled("Prism tests are disabled") + @Test + fun retrieve() { + val client = + EInvoiceOkHttpClientAsync.builder() + .baseUrl(TestServerExtension.BASE_URL) + .apiKey("My API Key") + .build() + val meServiceAsync = client.me() + + val meFuture = meServiceAsync.retrieve() + + val me = meFuture.get() + me.validate() + } +} diff --git a/e-invoice-java-core/src/test/kotlin/com/e_invoice/api/services/async/ValidateServiceAsyncTest.kt b/e-invoice-java-core/src/test/kotlin/com/e_invoice/api/services/async/ValidateServiceAsyncTest.kt index 4ad06da..cf0d0f2 100644 --- a/e-invoice-java-core/src/test/kotlin/com/e_invoice/api/services/async/ValidateServiceAsyncTest.kt +++ b/e-invoice-java-core/src/test/kotlin/com/e_invoice/api/services/async/ValidateServiceAsyncTest.kt @@ -35,6 +35,17 @@ internal class ValidateServiceAsyncTest { val ublDocumentValidationFuture = validateServiceAsync.validateJson( DocumentCreate.builder() + .addAllowance( + DocumentCreate.Allowance.builder() + .amount(0.0) + .baseAmount(0.0) + .multiplierFactor(0.0) + .reason("reason") + .reasonCode(DocumentCreate.Allowance.ReasonCode._41) + .taxCode(DocumentCreate.Allowance.TaxCode.AE) + .taxRate(0.0) + .build() + ) .amountDue(0.0) .addAttachment( DocumentAttachmentCreate.builder() @@ -46,13 +57,25 @@ internal class ValidateServiceAsyncTest { ) .billingAddress("billing_address") .billingAddressRecipient("billing_address_recipient") + .addCharge( + DocumentCreate.Charge.builder() + .amount(0.0) + .baseAmount(0.0) + .multiplierFactor(0.0) + .reason("reason") + .reasonCode(DocumentCreate.Charge.ReasonCode.AA) + .taxCode(DocumentCreate.Charge.TaxCode.AE) + .taxRate("21.00") + .build() + ) .currency(CurrencyCode.EUR) .customerAddress("customer_address") .customerAddressRecipient("customer_address_recipient") + .customerCompanyId("1018265814") .customerEmail("customer_email") .customerId("customer_id") .customerName("customer_name") - .customerTaxId("customer_tax_id") + .customerTaxId("BE1018265814") .direction(DocumentDirection.INBOUND) .documentType(DocumentType.INVOICE) .dueDate(LocalDate.parse("2019-12-27")) @@ -61,13 +84,35 @@ internal class ValidateServiceAsyncTest { .invoiceTotal(0.0) .addItem( DocumentCreate.Item.builder() + .addAllowance( + DocumentCreate.Item.Allowance.builder() + .amount(0.0) + .baseAmount(0.0) + .multiplierFactor(0.0) + .reason("reason") + .reasonCode(DocumentCreate.Item.Allowance.ReasonCode._41) + .taxCode(DocumentCreate.Item.Allowance.TaxCode.AE) + .taxRate(0.0) + .build() + ) .amount(0.0) + .addCharge( + DocumentCreate.Item.Charge.builder() + .amount(0.0) + .baseAmount(0.0) + .multiplierFactor(0.0) + .reason("reason") + .reasonCode(DocumentCreate.Item.Charge.ReasonCode.AA) + .taxCode(DocumentCreate.Item.Charge.TaxCode.AE) + .taxRate("21.00") + .build() + ) .date(null) .description("description") .productCode("product_code") .quantity(0.0) .tax(0.0) - .taxRate("tax_rate") + .taxRate("21.00") .unit(UnitOfMeasureCode._10) .unitPrice(0.0) .build() @@ -94,16 +139,20 @@ internal class ValidateServiceAsyncTest { .shippingAddressRecipient("shipping_address_recipient") .state(DocumentState.DRAFT) .subtotal(0.0) + .taxCode(DocumentCreate.TaxCode.AE) .addTaxDetail( DocumentCreate.TaxDetail.builder().amount(0.0).rate("rate").build() ) .totalDiscount(0.0) .totalTax(0.0) + .vatex(DocumentCreate.Vatex.VATEX_EU_79_C) + .vatexNote("vatex_note") .vendorAddress("vendor_address") .vendorAddressRecipient("vendor_address_recipient") + .vendorCompanyId("1018265814") .vendorEmail("vendor_email") .vendorName("vendor_name") - .vendorTaxId("vendor_tax_id") + .vendorTaxId("BE1018265814") .build() ) diff --git a/e-invoice-java-core/src/test/kotlin/com/e_invoice/api/services/async/documents/UblServiceAsyncTest.kt b/e-invoice-java-core/src/test/kotlin/com/e_invoice/api/services/async/documents/UblServiceAsyncTest.kt index 230f1e7..57b55f9 100644 --- a/e-invoice-java-core/src/test/kotlin/com/e_invoice/api/services/async/documents/UblServiceAsyncTest.kt +++ b/e-invoice-java-core/src/test/kotlin/com/e_invoice/api/services/async/documents/UblServiceAsyncTest.kt @@ -4,6 +4,7 @@ package com.e_invoice.api.services.async.documents import com.e_invoice.api.TestServerExtension import com.e_invoice.api.client.okhttp.EInvoiceOkHttpClientAsync +import com.e_invoice.api.models.documents.ubl.UblCreateFromUblParams import org.junit.jupiter.api.Disabled import org.junit.jupiter.api.Test import org.junit.jupiter.api.extension.ExtendWith @@ -11,6 +12,25 @@ import org.junit.jupiter.api.extension.ExtendWith @ExtendWith(TestServerExtension::class) internal class UblServiceAsyncTest { + @Disabled("Prism tests are disabled") + @Test + fun createFromUbl() { + val client = + EInvoiceOkHttpClientAsync.builder() + .baseUrl(TestServerExtension.BASE_URL) + .apiKey("My API Key") + .build() + val ublServiceAsync = client.documents().ubl() + + val documentResponseFuture = + ublServiceAsync.createFromUbl( + UblCreateFromUblParams.builder().file("some content".byteInputStream()).build() + ) + + val documentResponse = documentResponseFuture.get() + documentResponse.validate() + } + @Disabled("Prism tests are disabled") @Test fun get() { diff --git a/e-invoice-java-core/src/test/kotlin/com/e_invoice/api/services/blocking/DocumentServiceTest.kt b/e-invoice-java-core/src/test/kotlin/com/e_invoice/api/services/blocking/DocumentServiceTest.kt index 8d4aecf..0e142d9 100644 --- a/e-invoice-java-core/src/test/kotlin/com/e_invoice/api/services/blocking/DocumentServiceTest.kt +++ b/e-invoice-java-core/src/test/kotlin/com/e_invoice/api/services/blocking/DocumentServiceTest.kt @@ -7,6 +7,8 @@ import com.e_invoice.api.client.okhttp.EInvoiceOkHttpClient import com.e_invoice.api.models.documents.CurrencyCode import com.e_invoice.api.models.documents.DocumentAttachmentCreate import com.e_invoice.api.models.documents.DocumentCreate +import com.e_invoice.api.models.documents.DocumentCreateFromPdfParams +import com.e_invoice.api.models.documents.DocumentCreateParams import com.e_invoice.api.models.documents.DocumentDirection import com.e_invoice.api.models.documents.DocumentSendParams import com.e_invoice.api.models.documents.DocumentType @@ -33,76 +35,132 @@ internal class DocumentServiceTest { val documentResponse = documentService.create( - DocumentCreate.builder() - .amountDue(0.0) - .addAttachment( - DocumentAttachmentCreate.builder() - .fileName("file_name") - .fileData("file_data") - .fileSize(0L) - .fileType("file_type") + DocumentCreateParams.builder() + .constructPdf(true) + .documentCreate( + DocumentCreate.builder() + .addAllowance( + DocumentCreate.Allowance.builder() + .amount(0.0) + .baseAmount(0.0) + .multiplierFactor(0.0) + .reason("reason") + .reasonCode(DocumentCreate.Allowance.ReasonCode._41) + .taxCode(DocumentCreate.Allowance.TaxCode.AE) + .taxRate(0.0) + .build() + ) + .amountDue(0.0) + .addAttachment( + DocumentAttachmentCreate.builder() + .fileName("file_name") + .fileData("file_data") + .fileSize(0L) + .fileType("file_type") + .build() + ) + .billingAddress("billing_address") + .billingAddressRecipient("billing_address_recipient") + .addCharge( + DocumentCreate.Charge.builder() + .amount(0.0) + .baseAmount(0.0) + .multiplierFactor(0.0) + .reason("reason") + .reasonCode(DocumentCreate.Charge.ReasonCode.AA) + .taxCode(DocumentCreate.Charge.TaxCode.AE) + .taxRate("21.00") + .build() + ) + .currency(CurrencyCode.EUR) + .customerAddress("customer_address") + .customerAddressRecipient("customer_address_recipient") + .customerCompanyId("1018265814") + .customerEmail("customer_email") + .customerId("customer_id") + .customerName("customer_name") + .customerTaxId("BE1018265814") + .direction(DocumentDirection.INBOUND) + .documentType(DocumentType.INVOICE) + .dueDate(LocalDate.parse("2019-12-27")) + .invoiceDate(LocalDate.parse("2019-12-27")) + .invoiceId("invoice_id") + .invoiceTotal(0.0) + .addItem( + DocumentCreate.Item.builder() + .addAllowance( + DocumentCreate.Item.Allowance.builder() + .amount(0.0) + .baseAmount(0.0) + .multiplierFactor(0.0) + .reason("reason") + .reasonCode( + DocumentCreate.Item.Allowance.ReasonCode._41 + ) + .taxCode(DocumentCreate.Item.Allowance.TaxCode.AE) + .taxRate(0.0) + .build() + ) + .amount(0.0) + .addCharge( + DocumentCreate.Item.Charge.builder() + .amount(0.0) + .baseAmount(0.0) + .multiplierFactor(0.0) + .reason("reason") + .reasonCode(DocumentCreate.Item.Charge.ReasonCode.AA) + .taxCode(DocumentCreate.Item.Charge.TaxCode.AE) + .taxRate("21.00") + .build() + ) + .date(null) + .description("description") + .productCode("product_code") + .quantity(0.0) + .tax(0.0) + .taxRate("21.00") + .unit(UnitOfMeasureCode._10) + .unitPrice(0.0) + .build() + ) + .note("note") + .addPaymentDetail( + PaymentDetailCreate.builder() + .bankAccountNumber("bank_account_number") + .iban("iban") + .paymentReference("payment_reference") + .swift("swift") + .build() + ) + .paymentTerm("payment_term") + .previousUnpaidBalance(0.0) + .purchaseOrder("purchase_order") + .remittanceAddress("remittance_address") + .remittanceAddressRecipient("remittance_address_recipient") + .serviceAddress("service_address") + .serviceAddressRecipient("service_address_recipient") + .serviceEndDate(LocalDate.parse("2019-12-27")) + .serviceStartDate(LocalDate.parse("2019-12-27")) + .shippingAddress("shipping_address") + .shippingAddressRecipient("shipping_address_recipient") + .state(DocumentState.DRAFT) + .subtotal(0.0) + .taxCode(DocumentCreate.TaxCode.AE) + .addTaxDetail( + DocumentCreate.TaxDetail.builder().amount(0.0).rate("rate").build() + ) + .totalDiscount(0.0) + .totalTax(0.0) + .vatex(DocumentCreate.Vatex.VATEX_EU_79_C) + .vatexNote("vatex_note") + .vendorAddress("vendor_address") + .vendorAddressRecipient("vendor_address_recipient") + .vendorCompanyId("1018265814") + .vendorEmail("vendor_email") + .vendorName("vendor_name") + .vendorTaxId("BE1018265814") .build() ) - .billingAddress("billing_address") - .billingAddressRecipient("billing_address_recipient") - .currency(CurrencyCode.EUR) - .customerAddress("customer_address") - .customerAddressRecipient("customer_address_recipient") - .customerEmail("customer_email") - .customerId("customer_id") - .customerName("customer_name") - .customerTaxId("customer_tax_id") - .direction(DocumentDirection.INBOUND) - .documentType(DocumentType.INVOICE) - .dueDate(LocalDate.parse("2019-12-27")) - .invoiceDate(LocalDate.parse("2019-12-27")) - .invoiceId("invoice_id") - .invoiceTotal(0.0) - .addItem( - DocumentCreate.Item.builder() - .amount(0.0) - .date(null) - .description("description") - .productCode("product_code") - .quantity(0.0) - .tax(0.0) - .taxRate("tax_rate") - .unit(UnitOfMeasureCode._10) - .unitPrice(0.0) - .build() - ) - .note("note") - .addPaymentDetail( - PaymentDetailCreate.builder() - .bankAccountNumber("bank_account_number") - .iban("iban") - .paymentReference("payment_reference") - .swift("swift") - .build() - ) - .paymentTerm("payment_term") - .previousUnpaidBalance(0.0) - .purchaseOrder("purchase_order") - .remittanceAddress("remittance_address") - .remittanceAddressRecipient("remittance_address_recipient") - .serviceAddress("service_address") - .serviceAddressRecipient("service_address_recipient") - .serviceEndDate(LocalDate.parse("2019-12-27")) - .serviceStartDate(LocalDate.parse("2019-12-27")) - .shippingAddress("shipping_address") - .shippingAddressRecipient("shipping_address_recipient") - .state(DocumentState.DRAFT) - .subtotal(0.0) - .addTaxDetail( - DocumentCreate.TaxDetail.builder().amount(0.0).rate("rate").build() - ) - .totalDiscount(0.0) - .totalTax(0.0) - .vendorAddress("vendor_address") - .vendorAddressRecipient("vendor_address_recipient") - .vendorEmail("vendor_email") - .vendorName("vendor_name") - .vendorTaxId("vendor_tax_id") .build() ) @@ -139,6 +197,28 @@ internal class DocumentServiceTest { document.validate() } + @Disabled("Prism tests are disabled") + @Test + fun createFromPdf() { + val client = + EInvoiceOkHttpClient.builder() + .baseUrl(TestServerExtension.BASE_URL) + .apiKey("My API Key") + .build() + val documentService = client.documents() + + val response = + documentService.createFromPdf( + DocumentCreateFromPdfParams.builder() + .customerTaxId("customer_tax_id") + .vendorTaxId("vendor_tax_id") + .file("some content".byteInputStream()) + .build() + ) + + response.validate() + } + @Disabled("Prism tests are disabled") @Test fun send() { @@ -163,4 +243,19 @@ internal class DocumentServiceTest { documentResponse.validate() } + + @Disabled("Prism tests are disabled") + @Test + fun validate() { + val client = + EInvoiceOkHttpClient.builder() + .baseUrl(TestServerExtension.BASE_URL) + .apiKey("My API Key") + .build() + val documentService = client.documents() + + val ublDocumentValidation = documentService.validate("document_id") + + ublDocumentValidation.validate() + } } diff --git a/e-invoice-java-core/src/test/kotlin/com/e_invoice/api/services/blocking/MeServiceTest.kt b/e-invoice-java-core/src/test/kotlin/com/e_invoice/api/services/blocking/MeServiceTest.kt new file mode 100644 index 0000000..a41faee --- /dev/null +++ b/e-invoice-java-core/src/test/kotlin/com/e_invoice/api/services/blocking/MeServiceTest.kt @@ -0,0 +1,28 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.e_invoice.api.services.blocking + +import com.e_invoice.api.TestServerExtension +import com.e_invoice.api.client.okhttp.EInvoiceOkHttpClient +import org.junit.jupiter.api.Disabled +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.extension.ExtendWith + +@ExtendWith(TestServerExtension::class) +internal class MeServiceTest { + + @Disabled("Prism tests are disabled") + @Test + fun retrieve() { + val client = + EInvoiceOkHttpClient.builder() + .baseUrl(TestServerExtension.BASE_URL) + .apiKey("My API Key") + .build() + val meService = client.me() + + val me = meService.retrieve() + + me.validate() + } +} diff --git a/e-invoice-java-core/src/test/kotlin/com/e_invoice/api/services/blocking/ValidateServiceTest.kt b/e-invoice-java-core/src/test/kotlin/com/e_invoice/api/services/blocking/ValidateServiceTest.kt index aa7a03c..e53bd7e 100644 --- a/e-invoice-java-core/src/test/kotlin/com/e_invoice/api/services/blocking/ValidateServiceTest.kt +++ b/e-invoice-java-core/src/test/kotlin/com/e_invoice/api/services/blocking/ValidateServiceTest.kt @@ -35,6 +35,17 @@ internal class ValidateServiceTest { val ublDocumentValidation = validateService.validateJson( DocumentCreate.builder() + .addAllowance( + DocumentCreate.Allowance.builder() + .amount(0.0) + .baseAmount(0.0) + .multiplierFactor(0.0) + .reason("reason") + .reasonCode(DocumentCreate.Allowance.ReasonCode._41) + .taxCode(DocumentCreate.Allowance.TaxCode.AE) + .taxRate(0.0) + .build() + ) .amountDue(0.0) .addAttachment( DocumentAttachmentCreate.builder() @@ -46,13 +57,25 @@ internal class ValidateServiceTest { ) .billingAddress("billing_address") .billingAddressRecipient("billing_address_recipient") + .addCharge( + DocumentCreate.Charge.builder() + .amount(0.0) + .baseAmount(0.0) + .multiplierFactor(0.0) + .reason("reason") + .reasonCode(DocumentCreate.Charge.ReasonCode.AA) + .taxCode(DocumentCreate.Charge.TaxCode.AE) + .taxRate("21.00") + .build() + ) .currency(CurrencyCode.EUR) .customerAddress("customer_address") .customerAddressRecipient("customer_address_recipient") + .customerCompanyId("1018265814") .customerEmail("customer_email") .customerId("customer_id") .customerName("customer_name") - .customerTaxId("customer_tax_id") + .customerTaxId("BE1018265814") .direction(DocumentDirection.INBOUND) .documentType(DocumentType.INVOICE) .dueDate(LocalDate.parse("2019-12-27")) @@ -61,13 +84,35 @@ internal class ValidateServiceTest { .invoiceTotal(0.0) .addItem( DocumentCreate.Item.builder() + .addAllowance( + DocumentCreate.Item.Allowance.builder() + .amount(0.0) + .baseAmount(0.0) + .multiplierFactor(0.0) + .reason("reason") + .reasonCode(DocumentCreate.Item.Allowance.ReasonCode._41) + .taxCode(DocumentCreate.Item.Allowance.TaxCode.AE) + .taxRate(0.0) + .build() + ) .amount(0.0) + .addCharge( + DocumentCreate.Item.Charge.builder() + .amount(0.0) + .baseAmount(0.0) + .multiplierFactor(0.0) + .reason("reason") + .reasonCode(DocumentCreate.Item.Charge.ReasonCode.AA) + .taxCode(DocumentCreate.Item.Charge.TaxCode.AE) + .taxRate("21.00") + .build() + ) .date(null) .description("description") .productCode("product_code") .quantity(0.0) .tax(0.0) - .taxRate("tax_rate") + .taxRate("21.00") .unit(UnitOfMeasureCode._10) .unitPrice(0.0) .build() @@ -94,16 +139,20 @@ internal class ValidateServiceTest { .shippingAddressRecipient("shipping_address_recipient") .state(DocumentState.DRAFT) .subtotal(0.0) + .taxCode(DocumentCreate.TaxCode.AE) .addTaxDetail( DocumentCreate.TaxDetail.builder().amount(0.0).rate("rate").build() ) .totalDiscount(0.0) .totalTax(0.0) + .vatex(DocumentCreate.Vatex.VATEX_EU_79_C) + .vatexNote("vatex_note") .vendorAddress("vendor_address") .vendorAddressRecipient("vendor_address_recipient") + .vendorCompanyId("1018265814") .vendorEmail("vendor_email") .vendorName("vendor_name") - .vendorTaxId("vendor_tax_id") + .vendorTaxId("BE1018265814") .build() ) diff --git a/e-invoice-java-core/src/test/kotlin/com/e_invoice/api/services/blocking/documents/UblServiceTest.kt b/e-invoice-java-core/src/test/kotlin/com/e_invoice/api/services/blocking/documents/UblServiceTest.kt index e07b788..935995b 100644 --- a/e-invoice-java-core/src/test/kotlin/com/e_invoice/api/services/blocking/documents/UblServiceTest.kt +++ b/e-invoice-java-core/src/test/kotlin/com/e_invoice/api/services/blocking/documents/UblServiceTest.kt @@ -4,6 +4,7 @@ package com.e_invoice.api.services.blocking.documents import com.e_invoice.api.TestServerExtension import com.e_invoice.api.client.okhttp.EInvoiceOkHttpClient +import com.e_invoice.api.models.documents.ubl.UblCreateFromUblParams import org.junit.jupiter.api.Disabled import org.junit.jupiter.api.Test import org.junit.jupiter.api.extension.ExtendWith @@ -11,6 +12,24 @@ import org.junit.jupiter.api.extension.ExtendWith @ExtendWith(TestServerExtension::class) internal class UblServiceTest { + @Disabled("Prism tests are disabled") + @Test + fun createFromUbl() { + val client = + EInvoiceOkHttpClient.builder() + .baseUrl(TestServerExtension.BASE_URL) + .apiKey("My API Key") + .build() + val ublService = client.documents().ubl() + + val documentResponse = + ublService.createFromUbl( + UblCreateFromUblParams.builder().file("some content".byteInputStream()).build() + ) + + documentResponse.validate() + } + @Disabled("Prism tests are disabled") @Test fun get() { diff --git a/e-invoice-java-proguard-test/build.gradle.kts b/e-invoice-java-proguard-test/build.gradle.kts index 3bd9779..60afc8d 100644 --- a/e-invoice-java-proguard-test/build.gradle.kts +++ b/e-invoice-java-proguard-test/build.gradle.kts @@ -18,8 +18,8 @@ dependencies { testImplementation(project(":e-invoice-java")) testImplementation(kotlin("test")) testImplementation("org.junit.jupiter:junit-jupiter-api:5.9.3") - testImplementation("org.assertj:assertj-core:3.25.3") - testImplementation("com.fasterxml.jackson.module:jackson-module-kotlin:2.13.4") + testImplementation("org.assertj:assertj-core:3.27.7") + testImplementation("com.fasterxml.jackson.module:jackson-module-kotlin:2.14.0") } tasks.shadowJar { diff --git a/e-invoice-java-proguard-test/src/test/kotlin/com/e_invoice/api/proguard/ProGuardCompatibilityTest.kt b/e-invoice-java-proguard-test/src/test/kotlin/com/e_invoice/api/proguard/ProGuardCompatibilityTest.kt index f97f978..301a053 100644 --- a/e-invoice-java-proguard-test/src/test/kotlin/com/e_invoice/api/proguard/ProGuardCompatibilityTest.kt +++ b/e-invoice-java-proguard-test/src/test/kotlin/com/e_invoice/api/proguard/ProGuardCompatibilityTest.kt @@ -4,8 +4,8 @@ package com.e_invoice.api.proguard import com.e_invoice.api.client.okhttp.EInvoiceOkHttpClient import com.e_invoice.api.core.jsonMapper +import com.e_invoice.api.models.documents.Allowance import com.e_invoice.api.models.documents.CurrencyCode -import com.e_invoice.api.models.documents.DocumentAttachmentCreate import com.fasterxml.jackson.module.kotlin.jacksonTypeRef import kotlin.reflect.full.memberFunctions import kotlin.reflect.jvm.javaMethod @@ -53,27 +53,31 @@ internal class ProGuardCompatibilityTest { assertThat(client.outbox()).isNotNull() assertThat(client.validate()).isNotNull() assertThat(client.lookup()).isNotNull() + assertThat(client.me()).isNotNull() assertThat(client.webhooks()).isNotNull() } @Test - fun documentAttachmentCreateRoundtrip() { + fun allowanceRoundtrip() { val jsonMapper = jsonMapper() - val documentAttachmentCreate = - DocumentAttachmentCreate.builder() - .fileName("file_name") - .fileData("file_data") - .fileSize(0L) - .fileType("file_type") + val allowance = + Allowance.builder() + .amount("amount") + .baseAmount("base_amount") + .multiplierFactor("multiplier_factor") + .reason("reason") + .reasonCode(Allowance.ReasonCode._41) + .taxCode(Allowance.TaxCode.AE) + .taxRate("tax_rate") .build() - val roundtrippedDocumentAttachmentCreate = + val roundtrippedAllowance = jsonMapper.readValue( - jsonMapper.writeValueAsString(documentAttachmentCreate), - jacksonTypeRef(), + jsonMapper.writeValueAsString(allowance), + jacksonTypeRef(), ) - assertThat(roundtrippedDocumentAttachmentCreate).isEqualTo(documentAttachmentCreate) + assertThat(roundtrippedAllowance).isEqualTo(allowance) } @Test diff --git a/scripts/build b/scripts/build index f406348..16a2b00 100755 --- a/scripts/build +++ b/scripts/build @@ -5,4 +5,4 @@ set -e cd "$(dirname "$0")/.." echo "==> Building classes" -./gradlew build testClasses -x test +./gradlew build testClasses "$@" -x test diff --git a/scripts/upload-artifacts b/scripts/upload-artifacts new file mode 100755 index 0000000..10f3c70 --- /dev/null +++ b/scripts/upload-artifacts @@ -0,0 +1,193 @@ +#!/usr/bin/env bash + +set -euo pipefail + +# ANSI Color Codes +GREEN='\033[32m' +RED='\033[31m' +NC='\033[0m' # No Color + +MAVEN_REPO_PATH="./build/local-maven-repo" + +log_error() { + local msg="$1" + local headers="$2" + local body="$3" + echo -e "${RED}${msg}${NC}" + [[ -f "$headers" ]] && echo -e "${RED}Headers:$(cat "$headers")${NC}" + echo -e "${RED}Body: ${body}${NC}" + exit 1 +} + +upload_file() { + local file_name="$1" + local tmp_headers + tmp_headers=$(mktemp) + + if [ -f "$file_name" ]; then + echo -e "${GREEN}Processing file: $file_name${NC}" + pkg_file_name="mvn${file_name#"${MAVEN_REPO_PATH}"}" + + # Get signed URL for uploading artifact file + signed_url_response=$(curl -X POST -G "$URL" \ + -sS --retry 5 \ + -D "$tmp_headers" \ + --data-urlencode "filename=$pkg_file_name" \ + -H "Authorization: Bearer $AUTH" \ + -H "Content-Type: application/json") + + # Validate JSON and extract URL + if ! signed_url=$(echo "$signed_url_response" | jq -e -r '.url' 2>/dev/null) || [[ "$signed_url" == "null" ]]; then + log_error "Failed to get valid signed URL" "$tmp_headers" "$signed_url_response" + fi + + # Set content-type based on file extension + local extension="${file_name##*.}" + local content_type + case "$extension" in + jar) content_type="application/java-archive" ;; + md5|sha1|sha256|sha512) content_type="text/plain" ;; + module) content_type="application/json" ;; + pom|xml) content_type="application/xml" ;; + html) content_type="text/html" ;; + *) content_type="application/octet-stream" ;; + esac + + # Upload file + upload_response=$(curl -v -X PUT \ + --retry 5 \ + --retry-all-errors \ + -D "$tmp_headers" \ + -H "Content-Type: $content_type" \ + --data-binary "@${file_name}" "$signed_url" 2>&1) + + if ! echo "$upload_response" | grep -q "HTTP/[0-9.]* 200"; then + log_error "Failed to upload artifact file" "$tmp_headers" "$upload_response" + fi + + # Insert small throttle to reduce rate limiting risk + sleep 0.1 + fi +} + +walk_tree() { + local current_dir="$1" + + for entry in "$current_dir"/*; do + # Check that entry is valid + [ -e "$entry" ] || [ -h "$entry" ] || continue + + if [ -d "$entry" ]; then + walk_tree "$entry" + else + upload_file "$entry" + fi + done +} + +generate_instructions() { + cat << EOF > "$MAVEN_REPO_PATH/index.html" + + + + Maven Repo + + +

Stainless SDK Maven Repository

+

This is the Maven repository for your Stainless Java SDK build.

+ +

Project configuration

+ +

The details depend on whether you're using Maven or Gradle as your build tool.

+ +

Maven

+ +

Add the following to your project's pom.xml:

+
<repositories>
+    <repository>
+        <id>stainless-sdk-repo</id>
+        <url>https://pkg.stainless.com/s/${PROJECT}/${SHA}/mvn</url>
+    </repository>
+</repositories>
+ +

Gradle

+

Add the following to your build.gradle file:

+
repositories {
+    maven {
+        url "https://pkg.stainless.com/s/${PROJECT}/${SHA}/mvn"
+    }
+}
+ +
+

Configuring authentication (if required)

+ +

Some accounts may require authentication to access the repository. If so, use the + following instructions, replacing YOUR_STAINLESS_API_TOKEN with your actual token.

+ +

Maven with authentication

+ +

First, ensure you have the following in your Maven settings.xml for repo authentication:

+
<servers>
+    <server>
+        <id>stainless-sdk-repo</id>
+        <configuration>
+            <httpHeaders>
+                <property>
+                    <name>Authorization</name>
+                    <value>Bearer YOUR_STAINLESS_API_TOKEN</value>
+                </property>
+            </httpHeaders>
+        </configuration>
+    </server>
+</servers>
+ +

Then, add the following to your project's pom.xml:

+
<repositories>
+    <repository>
+        <id>stainless-sdk-repo</id>
+        <url>https://pkg.stainless.com/s/${PROJECT}/${SHA}/mvn</url>
+    </repository>
+</repositories>
+ +

Gradle with authentication

+

Add the following to your build.gradle file:

+
repositories {
+    maven {
+        url "https://pkg.stainless.com/s/${PROJECT}/${SHA}/mvn"
+        credentials(HttpHeaderCredentials) {
+            name = "Authorization"
+            value = "Bearer YOUR_STAINLESS_API_TOKEN"
+        }
+        authentication {
+            header(HttpHeaderAuthentication)
+        }
+    }
+}
+
+ +

Using the repository

+

Once you've configured the repository, you can include dependencies from it as usual. See your + project README + for more details.

+ + +EOF + upload_file "${MAVEN_REPO_PATH}/index.html" + + echo "Configure maven or gradle to use the repo located at 'https://pkg.stainless.com/s/${PROJECT}/${SHA}/mvn'" + echo "For more details, see the directions in https://pkg.stainless.com/s/${PROJECT}/${SHA}/mvn/index.html" +} + +cd "$(dirname "$0")/.." + +echo "::group::Creating local Maven content" +./gradlew publishMavenPublicationToLocalFileSystemRepository -PpublishLocal +echo "::endgroup::" + +echo "::group::Uploading to pkg.stainless.com" +walk_tree "$MAVEN_REPO_PATH" +echo "::endgroup::" + +echo "::group::Generating instructions" +generate_instructions +echo "::endgroup::"