// File generated from our OpenAPI spec by Stainless.

package com.increase.api.models.cardpurchasesupplements

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 com.increase.api.core.Enum
import com.increase.api.core.ExcludeMissing
import com.increase.api.core.JsonField
import com.increase.api.core.JsonMissing
import com.increase.api.core.JsonValue
import com.increase.api.core.checkKnown
import com.increase.api.core.checkRequired
import com.increase.api.core.toImmutable
import com.increase.api.errors.IncreaseInvalidDataException
import java.time.LocalDate
import java.util.Collections
import java.util.Objects
import java.util.Optional
import kotlin.jvm.optionals.getOrNull

/**
 * Additional information about a card purchase (e.g., settlement or refund), such as level 3 line
 * item data.
 */
class CardPurchaseSupplement
@JsonCreator(mode = JsonCreator.Mode.DISABLED)
private constructor(
    private val id: JsonField<String>,
    private val cardPaymentId: JsonField<String>,
    private val invoice: JsonField<Invoice>,
    private val lineItems: JsonField<List<LineItem>>,
    private val shipping: JsonField<Shipping>,
    private val transactionId: JsonField<String>,
    private val type: JsonField<Type>,
    private val additionalProperties: MutableMap<String, JsonValue>,
) {

    @JsonCreator
    private constructor(
        @JsonProperty("id") @ExcludeMissing id: JsonField<String> = JsonMissing.of(),
        @JsonProperty("card_payment_id")
        @ExcludeMissing
        cardPaymentId: JsonField<String> = JsonMissing.of(),
        @JsonProperty("invoice") @ExcludeMissing invoice: JsonField<Invoice> = JsonMissing.of(),
        @JsonProperty("line_items")
        @ExcludeMissing
        lineItems: JsonField<List<LineItem>> = JsonMissing.of(),
        @JsonProperty("shipping") @ExcludeMissing shipping: JsonField<Shipping> = JsonMissing.of(),
        @JsonProperty("transaction_id")
        @ExcludeMissing
        transactionId: JsonField<String> = JsonMissing.of(),
        @JsonProperty("type") @ExcludeMissing type: JsonField<Type> = JsonMissing.of(),
    ) : this(id, cardPaymentId, invoice, lineItems, shipping, transactionId, type, mutableMapOf())

    /**
     * The Card Purchase Supplement identifier.
     *
     * @throws IncreaseInvalidDataException 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 id(): String = id.getRequired("id")

    /**
     * The ID of the Card Payment this transaction belongs to.
     *
     * @throws IncreaseInvalidDataException if the JSON field has an unexpected type (e.g. if the
     *   server responded with an unexpected value).
     */
    fun cardPaymentId(): Optional<String> = cardPaymentId.getOptional("card_payment_id")

    /**
     * Invoice-level information about the payment.
     *
     * @throws IncreaseInvalidDataException if the JSON field has an unexpected type (e.g. if the
     *   server responded with an unexpected value).
     */
    fun invoice(): Optional<Invoice> = invoice.getOptional("invoice")

    /**
     * Line item information, such as individual products purchased.
     *
     * @throws IncreaseInvalidDataException if the JSON field has an unexpected type (e.g. if the
     *   server responded with an unexpected value).
     */
    fun lineItems(): Optional<List<LineItem>> = lineItems.getOptional("line_items")

    /**
     * Shipping information for the purchase.
     *
     * @throws IncreaseInvalidDataException if the JSON field has an unexpected type (e.g. if the
     *   server responded with an unexpected value).
     */
    fun shipping(): Optional<Shipping> = shipping.getOptional("shipping")

    /**
     * The ID of the transaction.
     *
     * @throws IncreaseInvalidDataException 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 transactionId(): String = transactionId.getRequired("transaction_id")

    /**
     * A constant representing the object's type. For this resource it will always be
     * `card_purchase_supplement`.
     *
     * @throws IncreaseInvalidDataException 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 type(): Type = type.getRequired("type")

    /**
     * Returns the raw JSON value of [id].
     *
     * Unlike [id], this method doesn't throw if the JSON field has an unexpected type.
     */
    @JsonProperty("id") @ExcludeMissing fun _id(): JsonField<String> = id

    /**
     * Returns the raw JSON value of [cardPaymentId].
     *
     * Unlike [cardPaymentId], this method doesn't throw if the JSON field has an unexpected type.
     */
    @JsonProperty("card_payment_id")
    @ExcludeMissing
    fun _cardPaymentId(): JsonField<String> = cardPaymentId

    /**
     * Returns the raw JSON value of [invoice].
     *
     * Unlike [invoice], this method doesn't throw if the JSON field has an unexpected type.
     */
    @JsonProperty("invoice") @ExcludeMissing fun _invoice(): JsonField<Invoice> = invoice

    /**
     * Returns the raw JSON value of [lineItems].
     *
     * Unlike [lineItems], this method doesn't throw if the JSON field has an unexpected type.
     */
    @JsonProperty("line_items")
    @ExcludeMissing
    fun _lineItems(): JsonField<List<LineItem>> = lineItems

    /**
     * Returns the raw JSON value of [shipping].
     *
     * Unlike [shipping], this method doesn't throw if the JSON field has an unexpected type.
     */
    @JsonProperty("shipping") @ExcludeMissing fun _shipping(): JsonField<Shipping> = shipping

    /**
     * Returns the raw JSON value of [transactionId].
     *
     * Unlike [transactionId], this method doesn't throw if the JSON field has an unexpected type.
     */
    @JsonProperty("transaction_id")
    @ExcludeMissing
    fun _transactionId(): JsonField<String> = transactionId

    /**
     * Returns the raw JSON value of [type].
     *
     * Unlike [type], this method doesn't throw if the JSON field has an unexpected type.
     */
    @JsonProperty("type") @ExcludeMissing fun _type(): JsonField<Type> = type

    @JsonAnySetter
    private fun putAdditionalProperty(key: String, value: JsonValue) {
        additionalProperties.put(key, value)
    }

    @JsonAnyGetter
    @ExcludeMissing
    fun _additionalProperties(): Map<String, JsonValue> =
        Collections.unmodifiableMap(additionalProperties)

    fun toBuilder() = Builder().from(this)

    companion object {

        /**
         * Returns a mutable builder for constructing an instance of [CardPurchaseSupplement].
         *
         * The following fields are required:
         * ```java
         * .id()
         * .cardPaymentId()
         * .invoice()
         * .lineItems()
         * .shipping()
         * .transactionId()
         * .type()
         * ```
         */
        @JvmStatic fun builder() = Builder()
    }

    /** A builder for [CardPurchaseSupplement]. */
    class Builder internal constructor() {

        private var id: JsonField<String>? = null
        private var cardPaymentId: JsonField<String>? = null
        private var invoice: JsonField<Invoice>? = null
        private var lineItems: JsonField<MutableList<LineItem>>? = null
        private var shipping: JsonField<Shipping>? = null
        private var transactionId: JsonField<String>? = null
        private var type: JsonField<Type>? = null
        private var additionalProperties: MutableMap<String, JsonValue> = mutableMapOf()

        @JvmSynthetic
        internal fun from(cardPurchaseSupplement: CardPurchaseSupplement) = apply {
            id = cardPurchaseSupplement.id
            cardPaymentId = cardPurchaseSupplement.cardPaymentId
            invoice = cardPurchaseSupplement.invoice
            lineItems = cardPurchaseSupplement.lineItems.map { it.toMutableList() }
            shipping = cardPurchaseSupplement.shipping
            transactionId = cardPurchaseSupplement.transactionId
            type = cardPurchaseSupplement.type
            additionalProperties = cardPurchaseSupplement.additionalProperties.toMutableMap()
        }

        /** The Card Purchase Supplement identifier. */
        fun id(id: String) = id(JsonField.of(id))

        /**
         * Sets [Builder.id] to an arbitrary JSON value.
         *
         * You should usually call [Builder.id] with a well-typed [String] value instead. This
         * method is primarily for setting the field to an undocumented or not yet supported value.
         */
        fun id(id: JsonField<String>) = apply { this.id = id }

        /** The ID of the Card Payment this transaction belongs to. */
        fun cardPaymentId(cardPaymentId: String?) =
            cardPaymentId(JsonField.ofNullable(cardPaymentId))

        /** Alias for calling [Builder.cardPaymentId] with `cardPaymentId.orElse(null)`. */
        fun cardPaymentId(cardPaymentId: Optional<String>) =
            cardPaymentId(cardPaymentId.getOrNull())

        /**
         * Sets [Builder.cardPaymentId] to an arbitrary JSON value.
         *
         * You should usually call [Builder.cardPaymentId] with a well-typed [String] value instead.
         * This method is primarily for setting the field to an undocumented or not yet supported
         * value.
         */
        fun cardPaymentId(cardPaymentId: JsonField<String>) = apply {
            this.cardPaymentId = cardPaymentId
        }

        /** Invoice-level information about the payment. */
        fun invoice(invoice: Invoice?) = invoice(JsonField.ofNullable(invoice))

        /** Alias for calling [Builder.invoice] with `invoice.orElse(null)`. */
        fun invoice(invoice: Optional<Invoice>) = invoice(invoice.getOrNull())

        /**
         * Sets [Builder.invoice] to an arbitrary JSON value.
         *
         * You should usually call [Builder.invoice] with a well-typed [Invoice] value instead. This
         * method is primarily for setting the field to an undocumented or not yet supported value.
         */
        fun invoice(invoice: JsonField<Invoice>) = apply { this.invoice = invoice }

        /** Line item information, such as individual products purchased. */
        fun lineItems(lineItems: List<LineItem>?) = lineItems(JsonField.ofNullable(lineItems))

        /** Alias for calling [Builder.lineItems] with `lineItems.orElse(null)`. */
        fun lineItems(lineItems: Optional<List<LineItem>>) = lineItems(lineItems.getOrNull())

        /**
         * Sets [Builder.lineItems] to an arbitrary JSON value.
         *
         * You should usually call [Builder.lineItems] with a well-typed `List<LineItem>` value
         * instead. This method is primarily for setting the field to an undocumented or not yet
         * supported value.
         */
        fun lineItems(lineItems: JsonField<List<LineItem>>) = apply {
            this.lineItems = lineItems.map { it.toMutableList() }
        }

        /**
         * Adds a single [LineItem] to [lineItems].
         *
         * @throws IllegalStateException if the field was previously set to a non-list.
         */
        fun addLineItem(lineItem: LineItem) = apply {
            lineItems =
                (lineItems ?: JsonField.of(mutableListOf())).also {
                    checkKnown("lineItems", it).add(lineItem)
                }
        }

        /** Shipping information for the purchase. */
        fun shipping(shipping: Shipping?) = shipping(JsonField.ofNullable(shipping))

        /** Alias for calling [Builder.shipping] with `shipping.orElse(null)`. */
        fun shipping(shipping: Optional<Shipping>) = shipping(shipping.getOrNull())

        /**
         * Sets [Builder.shipping] to an arbitrary JSON value.
         *
         * You should usually call [Builder.shipping] with a well-typed [Shipping] value instead.
         * This method is primarily for setting the field to an undocumented or not yet supported
         * value.
         */
        fun shipping(shipping: JsonField<Shipping>) = apply { this.shipping = shipping }

        /** The ID of the transaction. */
        fun transactionId(transactionId: String) = transactionId(JsonField.of(transactionId))

        /**
         * Sets [Builder.transactionId] to an arbitrary JSON value.
         *
         * You should usually call [Builder.transactionId] with a well-typed [String] value instead.
         * This method is primarily for setting the field to an undocumented or not yet supported
         * value.
         */
        fun transactionId(transactionId: JsonField<String>) = apply {
            this.transactionId = transactionId
        }

        /**
         * A constant representing the object's type. For this resource it will always be
         * `card_purchase_supplement`.
         */
        fun type(type: Type) = type(JsonField.of(type))

        /**
         * Sets [Builder.type] to an arbitrary JSON value.
         *
         * You should usually call [Builder.type] with a well-typed [Type] value instead. This
         * method is primarily for setting the field to an undocumented or not yet supported value.
         */
        fun type(type: JsonField<Type>) = apply { this.type = type }

        fun additionalProperties(additionalProperties: Map<String, JsonValue>) = apply {
            this.additionalProperties.clear()
            putAllAdditionalProperties(additionalProperties)
        }

        fun putAdditionalProperty(key: String, value: JsonValue) = apply {
            additionalProperties.put(key, value)
        }

        fun putAllAdditionalProperties(additionalProperties: Map<String, JsonValue>) = apply {
            this.additionalProperties.putAll(additionalProperties)
        }

        fun removeAdditionalProperty(key: String) = apply { additionalProperties.remove(key) }

        fun removeAllAdditionalProperties(keys: Set<String>) = apply {
            keys.forEach(::removeAdditionalProperty)
        }

        /**
         * Returns an immutable instance of [CardPurchaseSupplement].
         *
         * Further updates to this [Builder] will not mutate the returned instance.
         *
         * The following fields are required:
         * ```java
         * .id()
         * .cardPaymentId()
         * .invoice()
         * .lineItems()
         * .shipping()
         * .transactionId()
         * .type()
         * ```
         *
         * @throws IllegalStateException if any required field is unset.
         */
        fun build(): CardPurchaseSupplement =
            CardPurchaseSupplement(
                checkRequired("id", id),
                checkRequired("cardPaymentId", cardPaymentId),
                checkRequired("invoice", invoice),
                checkRequired("lineItems", lineItems).map { it.toImmutable() },
                checkRequired("shipping", shipping),
                checkRequired("transactionId", transactionId),
                checkRequired("type", type),
                additionalProperties.toMutableMap(),
            )
    }

    private var validated: Boolean = false

    /**
     * Validates that the types of all values in this object match their expected types recursively.
     *
     * This method is _not_ forwards compatible with new types from the API for existing fields.
     *
     * @throws IncreaseInvalidDataException if any value type in this object doesn't match its
     *   expected type.
     */
    fun validate(): CardPurchaseSupplement = apply {
        if (validated) {
            return@apply
        }

        id()
        cardPaymentId()
        invoice().ifPresent { it.validate() }
        lineItems().ifPresent { it.forEach { it.validate() } }
        shipping().ifPresent { it.validate() }
        transactionId()
        type().validate()
        validated = true
    }

    fun isValid(): Boolean =
        try {
            validate()
            true
        } catch (e: IncreaseInvalidDataException) {
            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 (id.asKnown().isPresent) 1 else 0) +
            (if (cardPaymentId.asKnown().isPresent) 1 else 0) +
            (invoice.asKnown().getOrNull()?.validity() ?: 0) +
            (lineItems.asKnown().getOrNull()?.sumOf { it.validity().toInt() } ?: 0) +
            (shipping.asKnown().getOrNull()?.validity() ?: 0) +
            (if (transactionId.asKnown().isPresent) 1 else 0) +
            (type.asKnown().getOrNull()?.validity() ?: 0)

    /** Invoice-level information about the payment. */
    class Invoice
    @JsonCreator(mode = JsonCreator.Mode.DISABLED)
    private constructor(
        private val discountAmount: JsonField<Long>,
        private val discountCurrency: JsonField<String>,
        private val discountTreatmentCode: JsonField<DiscountTreatmentCode>,
        private val dutyTaxAmount: JsonField<Long>,
        private val dutyTaxCurrency: JsonField<String>,
        private val orderDate: JsonField<LocalDate>,
        private val shippingAmount: JsonField<Long>,
        private val shippingCurrency: JsonField<String>,
        private val shippingDestinationCountryCode: JsonField<String>,
        private val shippingDestinationPostalCode: JsonField<String>,
        private val shippingSourcePostalCode: JsonField<String>,
        private val shippingTaxAmount: JsonField<Long>,
        private val shippingTaxCurrency: JsonField<String>,
        private val shippingTaxRate: JsonField<String>,
        private val taxTreatments: JsonField<TaxTreatments>,
        private val uniqueValueAddedTaxInvoiceReference: JsonField<String>,
        private val additionalProperties: MutableMap<String, JsonValue>,
    ) {

        @JsonCreator
        private constructor(
            @JsonProperty("discount_amount")
            @ExcludeMissing
            discountAmount: JsonField<Long> = JsonMissing.of(),
            @JsonProperty("discount_currency")
            @ExcludeMissing
            discountCurrency: JsonField<String> = JsonMissing.of(),
            @JsonProperty("discount_treatment_code")
            @ExcludeMissing
            discountTreatmentCode: JsonField<DiscountTreatmentCode> = JsonMissing.of(),
            @JsonProperty("duty_tax_amount")
            @ExcludeMissing
            dutyTaxAmount: JsonField<Long> = JsonMissing.of(),
            @JsonProperty("duty_tax_currency")
            @ExcludeMissing
            dutyTaxCurrency: JsonField<String> = JsonMissing.of(),
            @JsonProperty("order_date")
            @ExcludeMissing
            orderDate: JsonField<LocalDate> = JsonMissing.of(),
            @JsonProperty("shipping_amount")
            @ExcludeMissing
            shippingAmount: JsonField<Long> = JsonMissing.of(),
            @JsonProperty("shipping_currency")
            @ExcludeMissing
            shippingCurrency: JsonField<String> = JsonMissing.of(),
            @JsonProperty("shipping_destination_country_code")
            @ExcludeMissing
            shippingDestinationCountryCode: JsonField<String> = JsonMissing.of(),
            @JsonProperty("shipping_destination_postal_code")
            @ExcludeMissing
            shippingDestinationPostalCode: JsonField<String> = JsonMissing.of(),
            @JsonProperty("shipping_source_postal_code")
            @ExcludeMissing
            shippingSourcePostalCode: JsonField<String> = JsonMissing.of(),
            @JsonProperty("shipping_tax_amount")
            @ExcludeMissing
            shippingTaxAmount: JsonField<Long> = JsonMissing.of(),
            @JsonProperty("shipping_tax_currency")
            @ExcludeMissing
            shippingTaxCurrency: JsonField<String> = JsonMissing.of(),
            @JsonProperty("shipping_tax_rate")
            @ExcludeMissing
            shippingTaxRate: JsonField<String> = JsonMissing.of(),
            @JsonProperty("tax_treatments")
            @ExcludeMissing
            taxTreatments: JsonField<TaxTreatments> = JsonMissing.of(),
            @JsonProperty("unique_value_added_tax_invoice_reference")
            @ExcludeMissing
            uniqueValueAddedTaxInvoiceReference: JsonField<String> = JsonMissing.of(),
        ) : this(
            discountAmount,
            discountCurrency,
            discountTreatmentCode,
            dutyTaxAmount,
            dutyTaxCurrency,
            orderDate,
            shippingAmount,
            shippingCurrency,
            shippingDestinationCountryCode,
            shippingDestinationPostalCode,
            shippingSourcePostalCode,
            shippingTaxAmount,
            shippingTaxCurrency,
            shippingTaxRate,
            taxTreatments,
            uniqueValueAddedTaxInvoiceReference,
            mutableMapOf(),
        )

        /**
         * Discount given to cardholder.
         *
         * @throws IncreaseInvalidDataException if the JSON field has an unexpected type (e.g. if
         *   the server responded with an unexpected value).
         */
        fun discountAmount(): Optional<Long> = discountAmount.getOptional("discount_amount")

        /**
         * The [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217) code for the discount.
         *
         * @throws IncreaseInvalidDataException if the JSON field has an unexpected type (e.g. if
         *   the server responded with an unexpected value).
         */
        fun discountCurrency(): Optional<String> = discountCurrency.getOptional("discount_currency")

        /**
         * Indicates how the merchant applied the discount.
         *
         * @throws IncreaseInvalidDataException if the JSON field has an unexpected type (e.g. if
         *   the server responded with an unexpected value).
         */
        fun discountTreatmentCode(): Optional<DiscountTreatmentCode> =
            discountTreatmentCode.getOptional("discount_treatment_code")

        /**
         * Amount of duty taxes.
         *
         * @throws IncreaseInvalidDataException if the JSON field has an unexpected type (e.g. if
         *   the server responded with an unexpected value).
         */
        fun dutyTaxAmount(): Optional<Long> = dutyTaxAmount.getOptional("duty_tax_amount")

        /**
         * The [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217) code for the duty tax.
         *
         * @throws IncreaseInvalidDataException if the JSON field has an unexpected type (e.g. if
         *   the server responded with an unexpected value).
         */
        fun dutyTaxCurrency(): Optional<String> = dutyTaxCurrency.getOptional("duty_tax_currency")

        /**
         * Date the order was taken.
         *
         * @throws IncreaseInvalidDataException if the JSON field has an unexpected type (e.g. if
         *   the server responded with an unexpected value).
         */
        fun orderDate(): Optional<LocalDate> = orderDate.getOptional("order_date")

        /**
         * The shipping cost.
         *
         * @throws IncreaseInvalidDataException if the JSON field has an unexpected type (e.g. if
         *   the server responded with an unexpected value).
         */
        fun shippingAmount(): Optional<Long> = shippingAmount.getOptional("shipping_amount")

        /**
         * The [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217) code for the shipping cost.
         *
         * @throws IncreaseInvalidDataException if the JSON field has an unexpected type (e.g. if
         *   the server responded with an unexpected value).
         */
        fun shippingCurrency(): Optional<String> = shippingCurrency.getOptional("shipping_currency")

        /**
         * Country code of the shipping destination.
         *
         * @throws IncreaseInvalidDataException if the JSON field has an unexpected type (e.g. if
         *   the server responded with an unexpected value).
         */
        fun shippingDestinationCountryCode(): Optional<String> =
            shippingDestinationCountryCode.getOptional("shipping_destination_country_code")

        /**
         * Postal code of the shipping destination.
         *
         * @throws IncreaseInvalidDataException if the JSON field has an unexpected type (e.g. if
         *   the server responded with an unexpected value).
         */
        fun shippingDestinationPostalCode(): Optional<String> =
            shippingDestinationPostalCode.getOptional("shipping_destination_postal_code")

        /**
         * Postal code of the location being shipped from.
         *
         * @throws IncreaseInvalidDataException if the JSON field has an unexpected type (e.g. if
         *   the server responded with an unexpected value).
         */
        fun shippingSourcePostalCode(): Optional<String> =
            shippingSourcePostalCode.getOptional("shipping_source_postal_code")

        /**
         * Taxes paid for freight and shipping.
         *
         * @throws IncreaseInvalidDataException if the JSON field has an unexpected type (e.g. if
         *   the server responded with an unexpected value).
         */
        fun shippingTaxAmount(): Optional<Long> =
            shippingTaxAmount.getOptional("shipping_tax_amount")

        /**
         * The [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217) code for the shipping tax.
         *
         * @throws IncreaseInvalidDataException if the JSON field has an unexpected type (e.g. if
         *   the server responded with an unexpected value).
         */
        fun shippingTaxCurrency(): Optional<String> =
            shippingTaxCurrency.getOptional("shipping_tax_currency")

        /**
         * Tax rate for freight and shipping.
         *
         * @throws IncreaseInvalidDataException if the JSON field has an unexpected type (e.g. if
         *   the server responded with an unexpected value).
         */
        fun shippingTaxRate(): Optional<String> = shippingTaxRate.getOptional("shipping_tax_rate")

        /**
         * Indicates how the merchant applied taxes.
         *
         * @throws IncreaseInvalidDataException if the JSON field has an unexpected type (e.g. if
         *   the server responded with an unexpected value).
         */
        fun taxTreatments(): Optional<TaxTreatments> = taxTreatments.getOptional("tax_treatments")

        /**
         * Value added tax invoice reference number.
         *
         * @throws IncreaseInvalidDataException if the JSON field has an unexpected type (e.g. if
         *   the server responded with an unexpected value).
         */
        fun uniqueValueAddedTaxInvoiceReference(): Optional<String> =
            uniqueValueAddedTaxInvoiceReference.getOptional(
                "unique_value_added_tax_invoice_reference"
            )

        /**
         * Returns the raw JSON value of [discountAmount].
         *
         * Unlike [discountAmount], this method doesn't throw if the JSON field has an unexpected
         * type.
         */
        @JsonProperty("discount_amount")
        @ExcludeMissing
        fun _discountAmount(): JsonField<Long> = discountAmount

        /**
         * Returns the raw JSON value of [discountCurrency].
         *
         * Unlike [discountCurrency], this method doesn't throw if the JSON field has an unexpected
         * type.
         */
        @JsonProperty("discount_currency")
        @ExcludeMissing
        fun _discountCurrency(): JsonField<String> = discountCurrency

        /**
         * Returns the raw JSON value of [discountTreatmentCode].
         *
         * Unlike [discountTreatmentCode], this method doesn't throw if the JSON field has an
         * unexpected type.
         */
        @JsonProperty("discount_treatment_code")
        @ExcludeMissing
        fun _discountTreatmentCode(): JsonField<DiscountTreatmentCode> = discountTreatmentCode

        /**
         * Returns the raw JSON value of [dutyTaxAmount].
         *
         * Unlike [dutyTaxAmount], this method doesn't throw if the JSON field has an unexpected
         * type.
         */
        @JsonProperty("duty_tax_amount")
        @ExcludeMissing
        fun _dutyTaxAmount(): JsonField<Long> = dutyTaxAmount

        /**
         * Returns the raw JSON value of [dutyTaxCurrency].
         *
         * Unlike [dutyTaxCurrency], this method doesn't throw if the JSON field has an unexpected
         * type.
         */
        @JsonProperty("duty_tax_currency")
        @ExcludeMissing
        fun _dutyTaxCurrency(): JsonField<String> = dutyTaxCurrency

        /**
         * Returns the raw JSON value of [orderDate].
         *
         * Unlike [orderDate], this method doesn't throw if the JSON field has an unexpected type.
         */
        @JsonProperty("order_date")
        @ExcludeMissing
        fun _orderDate(): JsonField<LocalDate> = orderDate

        /**
         * Returns the raw JSON value of [shippingAmount].
         *
         * Unlike [shippingAmount], this method doesn't throw if the JSON field has an unexpected
         * type.
         */
        @JsonProperty("shipping_amount")
        @ExcludeMissing
        fun _shippingAmount(): JsonField<Long> = shippingAmount

        /**
         * Returns the raw JSON value of [shippingCurrency].
         *
         * Unlike [shippingCurrency], this method doesn't throw if the JSON field has an unexpected
         * type.
         */
        @JsonProperty("shipping_currency")
        @ExcludeMissing
        fun _shippingCurrency(): JsonField<String> = shippingCurrency

        /**
         * Returns the raw JSON value of [shippingDestinationCountryCode].
         *
         * Unlike [shippingDestinationCountryCode], this method doesn't throw if the JSON field has
         * an unexpected type.
         */
        @JsonProperty("shipping_destination_country_code")
        @ExcludeMissing
        fun _shippingDestinationCountryCode(): JsonField<String> = shippingDestinationCountryCode

        /**
         * Returns the raw JSON value of [shippingDestinationPostalCode].
         *
         * Unlike [shippingDestinationPostalCode], this method doesn't throw if the JSON field has
         * an unexpected type.
         */
        @JsonProperty("shipping_destination_postal_code")
        @ExcludeMissing
        fun _shippingDestinationPostalCode(): JsonField<String> = shippingDestinationPostalCode

        /**
         * Returns the raw JSON value of [shippingSourcePostalCode].
         *
         * Unlike [shippingSourcePostalCode], this method doesn't throw if the JSON field has an
         * unexpected type.
         */
        @JsonProperty("shipping_source_postal_code")
        @ExcludeMissing
        fun _shippingSourcePostalCode(): JsonField<String> = shippingSourcePostalCode

        /**
         * Returns the raw JSON value of [shippingTaxAmount].
         *
         * Unlike [shippingTaxAmount], this method doesn't throw if the JSON field has an unexpected
         * type.
         */
        @JsonProperty("shipping_tax_amount")
        @ExcludeMissing
        fun _shippingTaxAmount(): JsonField<Long> = shippingTaxAmount

        /**
         * Returns the raw JSON value of [shippingTaxCurrency].
         *
         * Unlike [shippingTaxCurrency], this method doesn't throw if the JSON field has an
         * unexpected type.
         */
        @JsonProperty("shipping_tax_currency")
        @ExcludeMissing
        fun _shippingTaxCurrency(): JsonField<String> = shippingTaxCurrency

        /**
         * Returns the raw JSON value of [shippingTaxRate].
         *
         * Unlike [shippingTaxRate], this method doesn't throw if the JSON field has an unexpected
         * type.
         */
        @JsonProperty("shipping_tax_rate")
        @ExcludeMissing
        fun _shippingTaxRate(): JsonField<String> = shippingTaxRate

        /**
         * Returns the raw JSON value of [taxTreatments].
         *
         * Unlike [taxTreatments], this method doesn't throw if the JSON field has an unexpected
         * type.
         */
        @JsonProperty("tax_treatments")
        @ExcludeMissing
        fun _taxTreatments(): JsonField<TaxTreatments> = taxTreatments

        /**
         * Returns the raw JSON value of [uniqueValueAddedTaxInvoiceReference].
         *
         * Unlike [uniqueValueAddedTaxInvoiceReference], this method doesn't throw if the JSON field
         * has an unexpected type.
         */
        @JsonProperty("unique_value_added_tax_invoice_reference")
        @ExcludeMissing
        fun _uniqueValueAddedTaxInvoiceReference(): JsonField<String> =
            uniqueValueAddedTaxInvoiceReference

        @JsonAnySetter
        private fun putAdditionalProperty(key: String, value: JsonValue) {
            additionalProperties.put(key, value)
        }

        @JsonAnyGetter
        @ExcludeMissing
        fun _additionalProperties(): Map<String, JsonValue> =
            Collections.unmodifiableMap(additionalProperties)

        fun toBuilder() = Builder().from(this)

        companion object {

            /**
             * Returns a mutable builder for constructing an instance of [Invoice].
             *
             * The following fields are required:
             * ```java
             * .discountAmount()
             * .discountCurrency()
             * .discountTreatmentCode()
             * .dutyTaxAmount()
             * .dutyTaxCurrency()
             * .orderDate()
             * .shippingAmount()
             * .shippingCurrency()
             * .shippingDestinationCountryCode()
             * .shippingDestinationPostalCode()
             * .shippingSourcePostalCode()
             * .shippingTaxAmount()
             * .shippingTaxCurrency()
             * .shippingTaxRate()
             * .taxTreatments()
             * .uniqueValueAddedTaxInvoiceReference()
             * ```
             */
            @JvmStatic fun builder() = Builder()
        }

        /** A builder for [Invoice]. */
        class Builder internal constructor() {

            private var discountAmount: JsonField<Long>? = null
            private var discountCurrency: JsonField<String>? = null
            private var discountTreatmentCode: JsonField<DiscountTreatmentCode>? = null
            private var dutyTaxAmount: JsonField<Long>? = null
            private var dutyTaxCurrency: JsonField<String>? = null
            private var orderDate: JsonField<LocalDate>? = null
            private var shippingAmount: JsonField<Long>? = null
            private var shippingCurrency: JsonField<String>? = null
            private var shippingDestinationCountryCode: JsonField<String>? = null
            private var shippingDestinationPostalCode: JsonField<String>? = null
            private var shippingSourcePostalCode: JsonField<String>? = null
            private var shippingTaxAmount: JsonField<Long>? = null
            private var shippingTaxCurrency: JsonField<String>? = null
            private var shippingTaxRate: JsonField<String>? = null
            private var taxTreatments: JsonField<TaxTreatments>? = null
            private var uniqueValueAddedTaxInvoiceReference: JsonField<String>? = null
            private var additionalProperties: MutableMap<String, JsonValue> = mutableMapOf()

            @JvmSynthetic
            internal fun from(invoice: Invoice) = apply {
                discountAmount = invoice.discountAmount
                discountCurrency = invoice.discountCurrency
                discountTreatmentCode = invoice.discountTreatmentCode
                dutyTaxAmount = invoice.dutyTaxAmount
                dutyTaxCurrency = invoice.dutyTaxCurrency
                orderDate = invoice.orderDate
                shippingAmount = invoice.shippingAmount
                shippingCurrency = invoice.shippingCurrency
                shippingDestinationCountryCode = invoice.shippingDestinationCountryCode
                shippingDestinationPostalCode = invoice.shippingDestinationPostalCode
                shippingSourcePostalCode = invoice.shippingSourcePostalCode
                shippingTaxAmount = invoice.shippingTaxAmount
                shippingTaxCurrency = invoice.shippingTaxCurrency
                shippingTaxRate = invoice.shippingTaxRate
                taxTreatments = invoice.taxTreatments
                uniqueValueAddedTaxInvoiceReference = invoice.uniqueValueAddedTaxInvoiceReference
                additionalProperties = invoice.additionalProperties.toMutableMap()
            }

            /** Discount given to cardholder. */
            fun discountAmount(discountAmount: Long?) =
                discountAmount(JsonField.ofNullable(discountAmount))

            /**
             * Alias for [Builder.discountAmount].
             *
             * This unboxed primitive overload exists for backwards compatibility.
             */
            fun discountAmount(discountAmount: Long) = discountAmount(discountAmount as Long?)

            /** Alias for calling [Builder.discountAmount] with `discountAmount.orElse(null)`. */
            fun discountAmount(discountAmount: Optional<Long>) =
                discountAmount(discountAmount.getOrNull())

            /**
             * Sets [Builder.discountAmount] to an arbitrary JSON value.
             *
             * You should usually call [Builder.discountAmount] with a well-typed [Long] value
             * instead. This method is primarily for setting the field to an undocumented or not yet
             * supported value.
             */
            fun discountAmount(discountAmount: JsonField<Long>) = apply {
                this.discountAmount = discountAmount
            }

            /** The [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217) code for the discount. */
            fun discountCurrency(discountCurrency: String?) =
                discountCurrency(JsonField.ofNullable(discountCurrency))

            /**
             * Alias for calling [Builder.discountCurrency] with `discountCurrency.orElse(null)`.
             */
            fun discountCurrency(discountCurrency: Optional<String>) =
                discountCurrency(discountCurrency.getOrNull())

            /**
             * Sets [Builder.discountCurrency] to an arbitrary JSON value.
             *
             * You should usually call [Builder.discountCurrency] with a well-typed [String] value
             * instead. This method is primarily for setting the field to an undocumented or not yet
             * supported value.
             */
            fun discountCurrency(discountCurrency: JsonField<String>) = apply {
                this.discountCurrency = discountCurrency
            }

            /** Indicates how the merchant applied the discount. */
            fun discountTreatmentCode(discountTreatmentCode: DiscountTreatmentCode?) =
                discountTreatmentCode(JsonField.ofNullable(discountTreatmentCode))

            /**
             * Alias for calling [Builder.discountTreatmentCode] with
             * `discountTreatmentCode.orElse(null)`.
             */
            fun discountTreatmentCode(discountTreatmentCode: Optional<DiscountTreatmentCode>) =
                discountTreatmentCode(discountTreatmentCode.getOrNull())

            /**
             * Sets [Builder.discountTreatmentCode] to an arbitrary JSON value.
             *
             * You should usually call [Builder.discountTreatmentCode] with a well-typed
             * [DiscountTreatmentCode] value instead. This method is primarily for setting the field
             * to an undocumented or not yet supported value.
             */
            fun discountTreatmentCode(discountTreatmentCode: JsonField<DiscountTreatmentCode>) =
                apply {
                    this.discountTreatmentCode = discountTreatmentCode
                }

            /** Amount of duty taxes. */
            fun dutyTaxAmount(dutyTaxAmount: Long?) =
                dutyTaxAmount(JsonField.ofNullable(dutyTaxAmount))

            /**
             * Alias for [Builder.dutyTaxAmount].
             *
             * This unboxed primitive overload exists for backwards compatibility.
             */
            fun dutyTaxAmount(dutyTaxAmount: Long) = dutyTaxAmount(dutyTaxAmount as Long?)

            /** Alias for calling [Builder.dutyTaxAmount] with `dutyTaxAmount.orElse(null)`. */
            fun dutyTaxAmount(dutyTaxAmount: Optional<Long>) =
                dutyTaxAmount(dutyTaxAmount.getOrNull())

            /**
             * Sets [Builder.dutyTaxAmount] to an arbitrary JSON value.
             *
             * You should usually call [Builder.dutyTaxAmount] with a well-typed [Long] value
             * instead. This method is primarily for setting the field to an undocumented or not yet
             * supported value.
             */
            fun dutyTaxAmount(dutyTaxAmount: JsonField<Long>) = apply {
                this.dutyTaxAmount = dutyTaxAmount
            }

            /** The [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217) code for the duty tax. */
            fun dutyTaxCurrency(dutyTaxCurrency: String?) =
                dutyTaxCurrency(JsonField.ofNullable(dutyTaxCurrency))

            /** Alias for calling [Builder.dutyTaxCurrency] with `dutyTaxCurrency.orElse(null)`. */
            fun dutyTaxCurrency(dutyTaxCurrency: Optional<String>) =
                dutyTaxCurrency(dutyTaxCurrency.getOrNull())

            /**
             * Sets [Builder.dutyTaxCurrency] to an arbitrary JSON value.
             *
             * You should usually call [Builder.dutyTaxCurrency] with a well-typed [String] value
             * instead. This method is primarily for setting the field to an undocumented or not yet
             * supported value.
             */
            fun dutyTaxCurrency(dutyTaxCurrency: JsonField<String>) = apply {
                this.dutyTaxCurrency = dutyTaxCurrency
            }

            /** Date the order was taken. */
            fun orderDate(orderDate: LocalDate?) = orderDate(JsonField.ofNullable(orderDate))

            /** Alias for calling [Builder.orderDate] with `orderDate.orElse(null)`. */
            fun orderDate(orderDate: Optional<LocalDate>) = orderDate(orderDate.getOrNull())

            /**
             * Sets [Builder.orderDate] to an arbitrary JSON value.
             *
             * You should usually call [Builder.orderDate] with a well-typed [LocalDate] value
             * instead. This method is primarily for setting the field to an undocumented or not yet
             * supported value.
             */
            fun orderDate(orderDate: JsonField<LocalDate>) = apply { this.orderDate = orderDate }

            /** The shipping cost. */
            fun shippingAmount(shippingAmount: Long?) =
                shippingAmount(JsonField.ofNullable(shippingAmount))

            /**
             * Alias for [Builder.shippingAmount].
             *
             * This unboxed primitive overload exists for backwards compatibility.
             */
            fun shippingAmount(shippingAmount: Long) = shippingAmount(shippingAmount as Long?)

            /** Alias for calling [Builder.shippingAmount] with `shippingAmount.orElse(null)`. */
            fun shippingAmount(shippingAmount: Optional<Long>) =
                shippingAmount(shippingAmount.getOrNull())

            /**
             * Sets [Builder.shippingAmount] to an arbitrary JSON value.
             *
             * You should usually call [Builder.shippingAmount] with a well-typed [Long] value
             * instead. This method is primarily for setting the field to an undocumented or not yet
             * supported value.
             */
            fun shippingAmount(shippingAmount: JsonField<Long>) = apply {
                this.shippingAmount = shippingAmount
            }

            /**
             * The [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217) code for the shipping cost.
             */
            fun shippingCurrency(shippingCurrency: String?) =
                shippingCurrency(JsonField.ofNullable(shippingCurrency))

            /**
             * Alias for calling [Builder.shippingCurrency] with `shippingCurrency.orElse(null)`.
             */
            fun shippingCurrency(shippingCurrency: Optional<String>) =
                shippingCurrency(shippingCurrency.getOrNull())

            /**
             * Sets [Builder.shippingCurrency] to an arbitrary JSON value.
             *
             * You should usually call [Builder.shippingCurrency] with a well-typed [String] value
             * instead. This method is primarily for setting the field to an undocumented or not yet
             * supported value.
             */
            fun shippingCurrency(shippingCurrency: JsonField<String>) = apply {
                this.shippingCurrency = shippingCurrency
            }

            /** Country code of the shipping destination. */
            fun shippingDestinationCountryCode(shippingDestinationCountryCode: String?) =
                shippingDestinationCountryCode(JsonField.ofNullable(shippingDestinationCountryCode))

            /**
             * Alias for calling [Builder.shippingDestinationCountryCode] with
             * `shippingDestinationCountryCode.orElse(null)`.
             */
            fun shippingDestinationCountryCode(shippingDestinationCountryCode: Optional<String>) =
                shippingDestinationCountryCode(shippingDestinationCountryCode.getOrNull())

            /**
             * Sets [Builder.shippingDestinationCountryCode] to an arbitrary JSON value.
             *
             * You should usually call [Builder.shippingDestinationCountryCode] with a well-typed
             * [String] value instead. This method is primarily for setting the field to an
             * undocumented or not yet supported value.
             */
            fun shippingDestinationCountryCode(shippingDestinationCountryCode: JsonField<String>) =
                apply {
                    this.shippingDestinationCountryCode = shippingDestinationCountryCode
                }

            /** Postal code of the shipping destination. */
            fun shippingDestinationPostalCode(shippingDestinationPostalCode: String?) =
                shippingDestinationPostalCode(JsonField.ofNullable(shippingDestinationPostalCode))

            /**
             * Alias for calling [Builder.shippingDestinationPostalCode] with
             * `shippingDestinationPostalCode.orElse(null)`.
             */
            fun shippingDestinationPostalCode(shippingDestinationPostalCode: Optional<String>) =
                shippingDestinationPostalCode(shippingDestinationPostalCode.getOrNull())

            /**
             * Sets [Builder.shippingDestinationPostalCode] to an arbitrary JSON value.
             *
             * You should usually call [Builder.shippingDestinationPostalCode] with a well-typed
             * [String] value instead. This method is primarily for setting the field to an
             * undocumented or not yet supported value.
             */
            fun shippingDestinationPostalCode(shippingDestinationPostalCode: JsonField<String>) =
                apply {
                    this.shippingDestinationPostalCode = shippingDestinationPostalCode
                }

            /** Postal code of the location being shipped from. */
            fun shippingSourcePostalCode(shippingSourcePostalCode: String?) =
                shippingSourcePostalCode(JsonField.ofNullable(shippingSourcePostalCode))

            /**
             * Alias for calling [Builder.shippingSourcePostalCode] with
             * `shippingSourcePostalCode.orElse(null)`.
             */
            fun shippingSourcePostalCode(shippingSourcePostalCode: Optional<String>) =
                shippingSourcePostalCode(shippingSourcePostalCode.getOrNull())

            /**
             * Sets [Builder.shippingSourcePostalCode] to an arbitrary JSON value.
             *
             * You should usually call [Builder.shippingSourcePostalCode] with a well-typed [String]
             * value instead. This method is primarily for setting the field to an undocumented or
             * not yet supported value.
             */
            fun shippingSourcePostalCode(shippingSourcePostalCode: JsonField<String>) = apply {
                this.shippingSourcePostalCode = shippingSourcePostalCode
            }

            /** Taxes paid for freight and shipping. */
            fun shippingTaxAmount(shippingTaxAmount: Long?) =
                shippingTaxAmount(JsonField.ofNullable(shippingTaxAmount))

            /**
             * Alias for [Builder.shippingTaxAmount].
             *
             * This unboxed primitive overload exists for backwards compatibility.
             */
            fun shippingTaxAmount(shippingTaxAmount: Long) =
                shippingTaxAmount(shippingTaxAmount as Long?)

            /**
             * Alias for calling [Builder.shippingTaxAmount] with `shippingTaxAmount.orElse(null)`.
             */
            fun shippingTaxAmount(shippingTaxAmount: Optional<Long>) =
                shippingTaxAmount(shippingTaxAmount.getOrNull())

            /**
             * Sets [Builder.shippingTaxAmount] to an arbitrary JSON value.
             *
             * You should usually call [Builder.shippingTaxAmount] with a well-typed [Long] value
             * instead. This method is primarily for setting the field to an undocumented or not yet
             * supported value.
             */
            fun shippingTaxAmount(shippingTaxAmount: JsonField<Long>) = apply {
                this.shippingTaxAmount = shippingTaxAmount
            }

            /** The [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217) code for the shipping tax. */
            fun shippingTaxCurrency(shippingTaxCurrency: String?) =
                shippingTaxCurrency(JsonField.ofNullable(shippingTaxCurrency))

            /**
             * Alias for calling [Builder.shippingTaxCurrency] with
             * `shippingTaxCurrency.orElse(null)`.
             */
            fun shippingTaxCurrency(shippingTaxCurrency: Optional<String>) =
                shippingTaxCurrency(shippingTaxCurrency.getOrNull())

            /**
             * Sets [Builder.shippingTaxCurrency] to an arbitrary JSON value.
             *
             * You should usually call [Builder.shippingTaxCurrency] with a well-typed [String]
             * value instead. This method is primarily for setting the field to an undocumented or
             * not yet supported value.
             */
            fun shippingTaxCurrency(shippingTaxCurrency: JsonField<String>) = apply {
                this.shippingTaxCurrency = shippingTaxCurrency
            }

            /** Tax rate for freight and shipping. */
            fun shippingTaxRate(shippingTaxRate: String?) =
                shippingTaxRate(JsonField.ofNullable(shippingTaxRate))

            /** Alias for calling [Builder.shippingTaxRate] with `shippingTaxRate.orElse(null)`. */
            fun shippingTaxRate(shippingTaxRate: Optional<String>) =
                shippingTaxRate(shippingTaxRate.getOrNull())

            /**
             * Sets [Builder.shippingTaxRate] to an arbitrary JSON value.
             *
             * You should usually call [Builder.shippingTaxRate] with a well-typed [String] value
             * instead. This method is primarily for setting the field to an undocumented or not yet
             * supported value.
             */
            fun shippingTaxRate(shippingTaxRate: JsonField<String>) = apply {
                this.shippingTaxRate = shippingTaxRate
            }

            /** Indicates how the merchant applied taxes. */
            fun taxTreatments(taxTreatments: TaxTreatments?) =
                taxTreatments(JsonField.ofNullable(taxTreatments))

            /** Alias for calling [Builder.taxTreatments] with `taxTreatments.orElse(null)`. */
            fun taxTreatments(taxTreatments: Optional<TaxTreatments>) =
                taxTreatments(taxTreatments.getOrNull())

            /**
             * Sets [Builder.taxTreatments] to an arbitrary JSON value.
             *
             * You should usually call [Builder.taxTreatments] with a well-typed [TaxTreatments]
             * value instead. This method is primarily for setting the field to an undocumented or
             * not yet supported value.
             */
            fun taxTreatments(taxTreatments: JsonField<TaxTreatments>) = apply {
                this.taxTreatments = taxTreatments
            }

            /** Value added tax invoice reference number. */
            fun uniqueValueAddedTaxInvoiceReference(uniqueValueAddedTaxInvoiceReference: String?) =
                uniqueValueAddedTaxInvoiceReference(
                    JsonField.ofNullable(uniqueValueAddedTaxInvoiceReference)
                )

            /**
             * Alias for calling [Builder.uniqueValueAddedTaxInvoiceReference] with
             * `uniqueValueAddedTaxInvoiceReference.orElse(null)`.
             */
            fun uniqueValueAddedTaxInvoiceReference(
                uniqueValueAddedTaxInvoiceReference: Optional<String>
            ) = uniqueValueAddedTaxInvoiceReference(uniqueValueAddedTaxInvoiceReference.getOrNull())

            /**
             * Sets [Builder.uniqueValueAddedTaxInvoiceReference] to an arbitrary JSON value.
             *
             * You should usually call [Builder.uniqueValueAddedTaxInvoiceReference] with a
             * well-typed [String] value instead. This method is primarily for setting the field to
             * an undocumented or not yet supported value.
             */
            fun uniqueValueAddedTaxInvoiceReference(
                uniqueValueAddedTaxInvoiceReference: JsonField<String>
            ) = apply {
                this.uniqueValueAddedTaxInvoiceReference = uniqueValueAddedTaxInvoiceReference
            }

            fun additionalProperties(additionalProperties: Map<String, JsonValue>) = apply {
                this.additionalProperties.clear()
                putAllAdditionalProperties(additionalProperties)
            }

            fun putAdditionalProperty(key: String, value: JsonValue) = apply {
                additionalProperties.put(key, value)
            }

            fun putAllAdditionalProperties(additionalProperties: Map<String, JsonValue>) = apply {
                this.additionalProperties.putAll(additionalProperties)
            }

            fun removeAdditionalProperty(key: String) = apply { additionalProperties.remove(key) }

            fun removeAllAdditionalProperties(keys: Set<String>) = apply {
                keys.forEach(::removeAdditionalProperty)
            }

            /**
             * Returns an immutable instance of [Invoice].
             *
             * Further updates to this [Builder] will not mutate the returned instance.
             *
             * The following fields are required:
             * ```java
             * .discountAmount()
             * .discountCurrency()
             * .discountTreatmentCode()
             * .dutyTaxAmount()
             * .dutyTaxCurrency()
             * .orderDate()
             * .shippingAmount()
             * .shippingCurrency()
             * .shippingDestinationCountryCode()
             * .shippingDestinationPostalCode()
             * .shippingSourcePostalCode()
             * .shippingTaxAmount()
             * .shippingTaxCurrency()
             * .shippingTaxRate()
             * .taxTreatments()
             * .uniqueValueAddedTaxInvoiceReference()
             * ```
             *
             * @throws IllegalStateException if any required field is unset.
             */
            fun build(): Invoice =
                Invoice(
                    checkRequired("discountAmount", discountAmount),
                    checkRequired("discountCurrency", discountCurrency),
                    checkRequired("discountTreatmentCode", discountTreatmentCode),
                    checkRequired("dutyTaxAmount", dutyTaxAmount),
                    checkRequired("dutyTaxCurrency", dutyTaxCurrency),
                    checkRequired("orderDate", orderDate),
                    checkRequired("shippingAmount", shippingAmount),
                    checkRequired("shippingCurrency", shippingCurrency),
                    checkRequired("shippingDestinationCountryCode", shippingDestinationCountryCode),
                    checkRequired("shippingDestinationPostalCode", shippingDestinationPostalCode),
                    checkRequired("shippingSourcePostalCode", shippingSourcePostalCode),
                    checkRequired("shippingTaxAmount", shippingTaxAmount),
                    checkRequired("shippingTaxCurrency", shippingTaxCurrency),
                    checkRequired("shippingTaxRate", shippingTaxRate),
                    checkRequired("taxTreatments", taxTreatments),
                    checkRequired(
                        "uniqueValueAddedTaxInvoiceReference",
                        uniqueValueAddedTaxInvoiceReference,
                    ),
                    additionalProperties.toMutableMap(),
                )
        }

        private var validated: Boolean = false

        /**
         * Validates that the types of all values in this object match their expected types
         * recursively.
         *
         * This method is _not_ forwards compatible with new types from the API for existing fields.
         *
         * @throws IncreaseInvalidDataException if any value type in this object doesn't match its
         *   expected type.
         */
        fun validate(): Invoice = apply {
            if (validated) {
                return@apply
            }

            discountAmount()
            discountCurrency()
            discountTreatmentCode().ifPresent { it.validate() }
            dutyTaxAmount()
            dutyTaxCurrency()
            orderDate()
            shippingAmount()
            shippingCurrency()
            shippingDestinationCountryCode()
            shippingDestinationPostalCode()
            shippingSourcePostalCode()
            shippingTaxAmount()
            shippingTaxCurrency()
            shippingTaxRate()
            taxTreatments().ifPresent { it.validate() }
            uniqueValueAddedTaxInvoiceReference()
            validated = true
        }

        fun isValid(): Boolean =
            try {
                validate()
                true
            } catch (e: IncreaseInvalidDataException) {
                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 (discountAmount.asKnown().isPresent) 1 else 0) +
                (if (discountCurrency.asKnown().isPresent) 1 else 0) +
                (discountTreatmentCode.asKnown().getOrNull()?.validity() ?: 0) +
                (if (dutyTaxAmount.asKnown().isPresent) 1 else 0) +
                (if (dutyTaxCurrency.asKnown().isPresent) 1 else 0) +
                (if (orderDate.asKnown().isPresent) 1 else 0) +
                (if (shippingAmount.asKnown().isPresent) 1 else 0) +
                (if (shippingCurrency.asKnown().isPresent) 1 else 0) +
                (if (shippingDestinationCountryCode.asKnown().isPresent) 1 else 0) +
                (if (shippingDestinationPostalCode.asKnown().isPresent) 1 else 0) +
                (if (shippingSourcePostalCode.asKnown().isPresent) 1 else 0) +
                (if (shippingTaxAmount.asKnown().isPresent) 1 else 0) +
                (if (shippingTaxCurrency.asKnown().isPresent) 1 else 0) +
                (if (shippingTaxRate.asKnown().isPresent) 1 else 0) +
                (taxTreatments.asKnown().getOrNull()?.validity() ?: 0) +
                (if (uniqueValueAddedTaxInvoiceReference.asKnown().isPresent) 1 else 0)

        /** Indicates how the merchant applied the discount. */
        class DiscountTreatmentCode
        @JsonCreator
        private constructor(private val value: JsonField<String>) : 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<String> = value

            companion object {

                /** No invoice level discount provided */
                @JvmField
                val NO_INVOICE_LEVEL_DISCOUNT_PROVIDED = of("no_invoice_level_discount_provided")

                /** Tax calculated on post discount invoice total */
                @JvmField
                val TAX_CALCULATED_ON_POST_DISCOUNT_INVOICE_TOTAL =
                    of("tax_calculated_on_post_discount_invoice_total")

                /** Tax calculated on pre discount invoice total */
                @JvmField
                val TAX_CALCULATED_ON_PRE_DISCOUNT_INVOICE_TOTAL =
                    of("tax_calculated_on_pre_discount_invoice_total")

                @JvmStatic fun of(value: String) = DiscountTreatmentCode(JsonField.of(value))
            }

            /** An enum containing [DiscountTreatmentCode]'s known values. */
            enum class Known {
                /** No invoice level discount provided */
                NO_INVOICE_LEVEL_DISCOUNT_PROVIDED,
                /** Tax calculated on post discount invoice total */
                TAX_CALCULATED_ON_POST_DISCOUNT_INVOICE_TOTAL,
                /** Tax calculated on pre discount invoice total */
                TAX_CALCULATED_ON_PRE_DISCOUNT_INVOICE_TOTAL,
            }

            /**
             * An enum containing [DiscountTreatmentCode]'s known values, as well as an [_UNKNOWN]
             * member.
             *
             * An instance of [DiscountTreatmentCode] 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 {
                /** No invoice level discount provided */
                NO_INVOICE_LEVEL_DISCOUNT_PROVIDED,
                /** Tax calculated on post discount invoice total */
                TAX_CALCULATED_ON_POST_DISCOUNT_INVOICE_TOTAL,
                /** Tax calculated on pre discount invoice total */
                TAX_CALCULATED_ON_PRE_DISCOUNT_INVOICE_TOTAL,
                /**
                 * An enum member indicating that [DiscountTreatmentCode] 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) {
                    NO_INVOICE_LEVEL_DISCOUNT_PROVIDED -> Value.NO_INVOICE_LEVEL_DISCOUNT_PROVIDED
                    TAX_CALCULATED_ON_POST_DISCOUNT_INVOICE_TOTAL ->
                        Value.TAX_CALCULATED_ON_POST_DISCOUNT_INVOICE_TOTAL
                    TAX_CALCULATED_ON_PRE_DISCOUNT_INVOICE_TOTAL ->
                        Value.TAX_CALCULATED_ON_PRE_DISCOUNT_INVOICE_TOTAL
                    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 IncreaseInvalidDataException if this class instance's value is a not a known
             *   member.
             */
            fun known(): Known =
                when (this) {
                    NO_INVOICE_LEVEL_DISCOUNT_PROVIDED -> Known.NO_INVOICE_LEVEL_DISCOUNT_PROVIDED
                    TAX_CALCULATED_ON_POST_DISCOUNT_INVOICE_TOTAL ->
                        Known.TAX_CALCULATED_ON_POST_DISCOUNT_INVOICE_TOTAL
                    TAX_CALCULATED_ON_PRE_DISCOUNT_INVOICE_TOTAL ->
                        Known.TAX_CALCULATED_ON_PRE_DISCOUNT_INVOICE_TOTAL
                    else ->
                        throw IncreaseInvalidDataException("Unknown DiscountTreatmentCode: $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 IncreaseInvalidDataException if this class instance's value does not have the
             *   expected primitive type.
             */
            fun asString(): String =
                _value().asString().orElseThrow {
                    IncreaseInvalidDataException("Value is not a String")
                }

            private var validated: Boolean = false

            /**
             * Validates that the types of all values in this object match their expected types
             * recursively.
             *
             * This method is _not_ forwards compatible with new types from the API for existing
             * fields.
             *
             * @throws IncreaseInvalidDataException if any value type in this object doesn't match
             *   its expected type.
             */
            fun validate(): DiscountTreatmentCode = apply {
                if (validated) {
                    return@apply
                }

                known()
                validated = true
            }

            fun isValid(): Boolean =
                try {
                    validate()
                    true
                } catch (e: IncreaseInvalidDataException) {
                    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 DiscountTreatmentCode && value == other.value
            }

            override fun hashCode() = value.hashCode()

            override fun toString() = value.toString()
        }

        /** Indicates how the merchant applied taxes. */
        class TaxTreatments @JsonCreator private constructor(private val value: JsonField<String>) :
            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<String> = value

            companion object {

                /** No tax applies */
                @JvmField val NO_TAX_APPLIES = of("no_tax_applies")

                /** Net price line item level */
                @JvmField val NET_PRICE_LINE_ITEM_LEVEL = of("net_price_line_item_level")

                /** Net price invoice level */
                @JvmField val NET_PRICE_INVOICE_LEVEL = of("net_price_invoice_level")

                /** Gross price line item level */
                @JvmField val GROSS_PRICE_LINE_ITEM_LEVEL = of("gross_price_line_item_level")

                /** Gross price invoice level */
                @JvmField val GROSS_PRICE_INVOICE_LEVEL = of("gross_price_invoice_level")

                @JvmStatic fun of(value: String) = TaxTreatments(JsonField.of(value))
            }

            /** An enum containing [TaxTreatments]'s known values. */
            enum class Known {
                /** No tax applies */
                NO_TAX_APPLIES,
                /** Net price line item level */
                NET_PRICE_LINE_ITEM_LEVEL,
                /** Net price invoice level */
                NET_PRICE_INVOICE_LEVEL,
                /** Gross price line item level */
                GROSS_PRICE_LINE_ITEM_LEVEL,
                /** Gross price invoice level */
                GROSS_PRICE_INVOICE_LEVEL,
            }

            /**
             * An enum containing [TaxTreatments]'s known values, as well as an [_UNKNOWN] member.
             *
             * An instance of [TaxTreatments] 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 {
                /** No tax applies */
                NO_TAX_APPLIES,
                /** Net price line item level */
                NET_PRICE_LINE_ITEM_LEVEL,
                /** Net price invoice level */
                NET_PRICE_INVOICE_LEVEL,
                /** Gross price line item level */
                GROSS_PRICE_LINE_ITEM_LEVEL,
                /** Gross price invoice level */
                GROSS_PRICE_INVOICE_LEVEL,
                /**
                 * An enum member indicating that [TaxTreatments] 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) {
                    NO_TAX_APPLIES -> Value.NO_TAX_APPLIES
                    NET_PRICE_LINE_ITEM_LEVEL -> Value.NET_PRICE_LINE_ITEM_LEVEL
                    NET_PRICE_INVOICE_LEVEL -> Value.NET_PRICE_INVOICE_LEVEL
                    GROSS_PRICE_LINE_ITEM_LEVEL -> Value.GROSS_PRICE_LINE_ITEM_LEVEL
                    GROSS_PRICE_INVOICE_LEVEL -> Value.GROSS_PRICE_INVOICE_LEVEL
                    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 IncreaseInvalidDataException if this class instance's value is a not a known
             *   member.
             */
            fun known(): Known =
                when (this) {
                    NO_TAX_APPLIES -> Known.NO_TAX_APPLIES
                    NET_PRICE_LINE_ITEM_LEVEL -> Known.NET_PRICE_LINE_ITEM_LEVEL
                    NET_PRICE_INVOICE_LEVEL -> Known.NET_PRICE_INVOICE_LEVEL
                    GROSS_PRICE_LINE_ITEM_LEVEL -> Known.GROSS_PRICE_LINE_ITEM_LEVEL
                    GROSS_PRICE_INVOICE_LEVEL -> Known.GROSS_PRICE_INVOICE_LEVEL
                    else -> throw IncreaseInvalidDataException("Unknown TaxTreatments: $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 IncreaseInvalidDataException if this class instance's value does not have the
             *   expected primitive type.
             */
            fun asString(): String =
                _value().asString().orElseThrow {
                    IncreaseInvalidDataException("Value is not a String")
                }

            private var validated: Boolean = false

            /**
             * Validates that the types of all values in this object match their expected types
             * recursively.
             *
             * This method is _not_ forwards compatible with new types from the API for existing
             * fields.
             *
             * @throws IncreaseInvalidDataException if any value type in this object doesn't match
             *   its expected type.
             */
            fun validate(): TaxTreatments = apply {
                if (validated) {
                    return@apply
                }

                known()
                validated = true
            }

            fun isValid(): Boolean =
                try {
                    validate()
                    true
                } catch (e: IncreaseInvalidDataException) {
                    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 TaxTreatments && 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 Invoice &&
                discountAmount == other.discountAmount &&
                discountCurrency == other.discountCurrency &&
                discountTreatmentCode == other.discountTreatmentCode &&
                dutyTaxAmount == other.dutyTaxAmount &&
                dutyTaxCurrency == other.dutyTaxCurrency &&
                orderDate == other.orderDate &&
                shippingAmount == other.shippingAmount &&
                shippingCurrency == other.shippingCurrency &&
                shippingDestinationCountryCode == other.shippingDestinationCountryCode &&
                shippingDestinationPostalCode == other.shippingDestinationPostalCode &&
                shippingSourcePostalCode == other.shippingSourcePostalCode &&
                shippingTaxAmount == other.shippingTaxAmount &&
                shippingTaxCurrency == other.shippingTaxCurrency &&
                shippingTaxRate == other.shippingTaxRate &&
                taxTreatments == other.taxTreatments &&
                uniqueValueAddedTaxInvoiceReference == other.uniqueValueAddedTaxInvoiceReference &&
                additionalProperties == other.additionalProperties
        }

        private val hashCode: Int by lazy {
            Objects.hash(
                discountAmount,
                discountCurrency,
                discountTreatmentCode,
                dutyTaxAmount,
                dutyTaxCurrency,
                orderDate,
                shippingAmount,
                shippingCurrency,
                shippingDestinationCountryCode,
                shippingDestinationPostalCode,
                shippingSourcePostalCode,
                shippingTaxAmount,
                shippingTaxCurrency,
                shippingTaxRate,
                taxTreatments,
                uniqueValueAddedTaxInvoiceReference,
                additionalProperties,
            )
        }

        override fun hashCode(): Int = hashCode

        override fun toString() =
            "Invoice{discountAmount=$discountAmount, discountCurrency=$discountCurrency, discountTreatmentCode=$discountTreatmentCode, dutyTaxAmount=$dutyTaxAmount, dutyTaxCurrency=$dutyTaxCurrency, orderDate=$orderDate, shippingAmount=$shippingAmount, shippingCurrency=$shippingCurrency, shippingDestinationCountryCode=$shippingDestinationCountryCode, shippingDestinationPostalCode=$shippingDestinationPostalCode, shippingSourcePostalCode=$shippingSourcePostalCode, shippingTaxAmount=$shippingTaxAmount, shippingTaxCurrency=$shippingTaxCurrency, shippingTaxRate=$shippingTaxRate, taxTreatments=$taxTreatments, uniqueValueAddedTaxInvoiceReference=$uniqueValueAddedTaxInvoiceReference, additionalProperties=$additionalProperties}"
    }

    class LineItem
    @JsonCreator(mode = JsonCreator.Mode.DISABLED)
    private constructor(
        private val id: JsonField<String>,
        private val detailIndicator: JsonField<DetailIndicator>,
        private val discountAmount: JsonField<Long>,
        private val discountCurrency: JsonField<String>,
        private val discountTreatmentCode: JsonField<DiscountTreatmentCode>,
        private val itemCommodityCode: JsonField<String>,
        private val itemDescriptor: JsonField<String>,
        private val itemQuantity: JsonField<String>,
        private val productCode: JsonField<String>,
        private val salesTaxAmount: JsonField<Long>,
        private val salesTaxCurrency: JsonField<String>,
        private val salesTaxRate: JsonField<String>,
        private val totalAmount: JsonField<Long>,
        private val totalAmountCurrency: JsonField<String>,
        private val unitCost: JsonField<String>,
        private val unitCostCurrency: JsonField<String>,
        private val unitOfMeasureCode: JsonField<String>,
        private val additionalProperties: MutableMap<String, JsonValue>,
    ) {

        @JsonCreator
        private constructor(
            @JsonProperty("id") @ExcludeMissing id: JsonField<String> = JsonMissing.of(),
            @JsonProperty("detail_indicator")
            @ExcludeMissing
            detailIndicator: JsonField<DetailIndicator> = JsonMissing.of(),
            @JsonProperty("discount_amount")
            @ExcludeMissing
            discountAmount: JsonField<Long> = JsonMissing.of(),
            @JsonProperty("discount_currency")
            @ExcludeMissing
            discountCurrency: JsonField<String> = JsonMissing.of(),
            @JsonProperty("discount_treatment_code")
            @ExcludeMissing
            discountTreatmentCode: JsonField<DiscountTreatmentCode> = JsonMissing.of(),
            @JsonProperty("item_commodity_code")
            @ExcludeMissing
            itemCommodityCode: JsonField<String> = JsonMissing.of(),
            @JsonProperty("item_descriptor")
            @ExcludeMissing
            itemDescriptor: JsonField<String> = JsonMissing.of(),
            @JsonProperty("item_quantity")
            @ExcludeMissing
            itemQuantity: JsonField<String> = JsonMissing.of(),
            @JsonProperty("product_code")
            @ExcludeMissing
            productCode: JsonField<String> = JsonMissing.of(),
            @JsonProperty("sales_tax_amount")
            @ExcludeMissing
            salesTaxAmount: JsonField<Long> = JsonMissing.of(),
            @JsonProperty("sales_tax_currency")
            @ExcludeMissing
            salesTaxCurrency: JsonField<String> = JsonMissing.of(),
            @JsonProperty("sales_tax_rate")
            @ExcludeMissing
            salesTaxRate: JsonField<String> = JsonMissing.of(),
            @JsonProperty("total_amount")
            @ExcludeMissing
            totalAmount: JsonField<Long> = JsonMissing.of(),
            @JsonProperty("total_amount_currency")
            @ExcludeMissing
            totalAmountCurrency: JsonField<String> = JsonMissing.of(),
            @JsonProperty("unit_cost")
            @ExcludeMissing
            unitCost: JsonField<String> = JsonMissing.of(),
            @JsonProperty("unit_cost_currency")
            @ExcludeMissing
            unitCostCurrency: JsonField<String> = JsonMissing.of(),
            @JsonProperty("unit_of_measure_code")
            @ExcludeMissing
            unitOfMeasureCode: JsonField<String> = JsonMissing.of(),
        ) : this(
            id,
            detailIndicator,
            discountAmount,
            discountCurrency,
            discountTreatmentCode,
            itemCommodityCode,
            itemDescriptor,
            itemQuantity,
            productCode,
            salesTaxAmount,
            salesTaxCurrency,
            salesTaxRate,
            totalAmount,
            totalAmountCurrency,
            unitCost,
            unitCostCurrency,
            unitOfMeasureCode,
            mutableMapOf(),
        )

        /**
         * The Card Purchase Supplement Line Item identifier.
         *
         * @throws IncreaseInvalidDataException 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 id(): String = id.getRequired("id")

        /**
         * Indicates the type of line item.
         *
         * @throws IncreaseInvalidDataException if the JSON field has an unexpected type (e.g. if
         *   the server responded with an unexpected value).
         */
        fun detailIndicator(): Optional<DetailIndicator> =
            detailIndicator.getOptional("detail_indicator")

        /**
         * Discount amount for this specific line item.
         *
         * @throws IncreaseInvalidDataException if the JSON field has an unexpected type (e.g. if
         *   the server responded with an unexpected value).
         */
        fun discountAmount(): Optional<Long> = discountAmount.getOptional("discount_amount")

        /**
         * The [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217) code for the discount.
         *
         * @throws IncreaseInvalidDataException if the JSON field has an unexpected type (e.g. if
         *   the server responded with an unexpected value).
         */
        fun discountCurrency(): Optional<String> = discountCurrency.getOptional("discount_currency")

        /**
         * Indicates how the merchant applied the discount for this specific line item.
         *
         * @throws IncreaseInvalidDataException if the JSON field has an unexpected type (e.g. if
         *   the server responded with an unexpected value).
         */
        fun discountTreatmentCode(): Optional<DiscountTreatmentCode> =
            discountTreatmentCode.getOptional("discount_treatment_code")

        /**
         * Code used to categorize the purchase item.
         *
         * @throws IncreaseInvalidDataException if the JSON field has an unexpected type (e.g. if
         *   the server responded with an unexpected value).
         */
        fun itemCommodityCode(): Optional<String> =
            itemCommodityCode.getOptional("item_commodity_code")

        /**
         * Description of the purchase item.
         *
         * @throws IncreaseInvalidDataException if the JSON field has an unexpected type (e.g. if
         *   the server responded with an unexpected value).
         */
        fun itemDescriptor(): Optional<String> = itemDescriptor.getOptional("item_descriptor")

        /**
         * The number of units of the product being purchased.
         *
         * @throws IncreaseInvalidDataException if the JSON field has an unexpected type (e.g. if
         *   the server responded with an unexpected value).
         */
        fun itemQuantity(): Optional<String> = itemQuantity.getOptional("item_quantity")

        /**
         * Code used to categorize the product being purchased.
         *
         * @throws IncreaseInvalidDataException if the JSON field has an unexpected type (e.g. if
         *   the server responded with an unexpected value).
         */
        fun productCode(): Optional<String> = productCode.getOptional("product_code")

        /**
         * Sales tax amount for this line item.
         *
         * @throws IncreaseInvalidDataException if the JSON field has an unexpected type (e.g. if
         *   the server responded with an unexpected value).
         */
        fun salesTaxAmount(): Optional<Long> = salesTaxAmount.getOptional("sales_tax_amount")

        /**
         * The [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217) code for the sales tax assessed.
         *
         * @throws IncreaseInvalidDataException if the JSON field has an unexpected type (e.g. if
         *   the server responded with an unexpected value).
         */
        fun salesTaxCurrency(): Optional<String> =
            salesTaxCurrency.getOptional("sales_tax_currency")

        /**
         * Sales tax rate for this line item.
         *
         * @throws IncreaseInvalidDataException if the JSON field has an unexpected type (e.g. if
         *   the server responded with an unexpected value).
         */
        fun salesTaxRate(): Optional<String> = salesTaxRate.getOptional("sales_tax_rate")

        /**
         * Total amount of all line items.
         *
         * @throws IncreaseInvalidDataException if the JSON field has an unexpected type (e.g. if
         *   the server responded with an unexpected value).
         */
        fun totalAmount(): Optional<Long> = totalAmount.getOptional("total_amount")

        /**
         * The [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217) code for the total amount.
         *
         * @throws IncreaseInvalidDataException if the JSON field has an unexpected type (e.g. if
         *   the server responded with an unexpected value).
         */
        fun totalAmountCurrency(): Optional<String> =
            totalAmountCurrency.getOptional("total_amount_currency")

        /**
         * Cost of line item per unit of measure, in major units.
         *
         * @throws IncreaseInvalidDataException if the JSON field has an unexpected type (e.g. if
         *   the server responded with an unexpected value).
         */
        fun unitCost(): Optional<String> = unitCost.getOptional("unit_cost")

        /**
         * The [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217) code for the unit cost.
         *
         * @throws IncreaseInvalidDataException if the JSON field has an unexpected type (e.g. if
         *   the server responded with an unexpected value).
         */
        fun unitCostCurrency(): Optional<String> =
            unitCostCurrency.getOptional("unit_cost_currency")

        /**
         * Code indicating unit of measure (gallons, etc.).
         *
         * @throws IncreaseInvalidDataException if the JSON field has an unexpected type (e.g. if
         *   the server responded with an unexpected value).
         */
        fun unitOfMeasureCode(): Optional<String> =
            unitOfMeasureCode.getOptional("unit_of_measure_code")

        /**
         * Returns the raw JSON value of [id].
         *
         * Unlike [id], this method doesn't throw if the JSON field has an unexpected type.
         */
        @JsonProperty("id") @ExcludeMissing fun _id(): JsonField<String> = id

        /**
         * Returns the raw JSON value of [detailIndicator].
         *
         * Unlike [detailIndicator], this method doesn't throw if the JSON field has an unexpected
         * type.
         */
        @JsonProperty("detail_indicator")
        @ExcludeMissing
        fun _detailIndicator(): JsonField<DetailIndicator> = detailIndicator

        /**
         * Returns the raw JSON value of [discountAmount].
         *
         * Unlike [discountAmount], this method doesn't throw if the JSON field has an unexpected
         * type.
         */
        @JsonProperty("discount_amount")
        @ExcludeMissing
        fun _discountAmount(): JsonField<Long> = discountAmount

        /**
         * Returns the raw JSON value of [discountCurrency].
         *
         * Unlike [discountCurrency], this method doesn't throw if the JSON field has an unexpected
         * type.
         */
        @JsonProperty("discount_currency")
        @ExcludeMissing
        fun _discountCurrency(): JsonField<String> = discountCurrency

        /**
         * Returns the raw JSON value of [discountTreatmentCode].
         *
         * Unlike [discountTreatmentCode], this method doesn't throw if the JSON field has an
         * unexpected type.
         */
        @JsonProperty("discount_treatment_code")
        @ExcludeMissing
        fun _discountTreatmentCode(): JsonField<DiscountTreatmentCode> = discountTreatmentCode

        /**
         * Returns the raw JSON value of [itemCommodityCode].
         *
         * Unlike [itemCommodityCode], this method doesn't throw if the JSON field has an unexpected
         * type.
         */
        @JsonProperty("item_commodity_code")
        @ExcludeMissing
        fun _itemCommodityCode(): JsonField<String> = itemCommodityCode

        /**
         * Returns the raw JSON value of [itemDescriptor].
         *
         * Unlike [itemDescriptor], this method doesn't throw if the JSON field has an unexpected
         * type.
         */
        @JsonProperty("item_descriptor")
        @ExcludeMissing
        fun _itemDescriptor(): JsonField<String> = itemDescriptor

        /**
         * Returns the raw JSON value of [itemQuantity].
         *
         * Unlike [itemQuantity], this method doesn't throw if the JSON field has an unexpected
         * type.
         */
        @JsonProperty("item_quantity")
        @ExcludeMissing
        fun _itemQuantity(): JsonField<String> = itemQuantity

        /**
         * 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<String> = productCode

        /**
         * Returns the raw JSON value of [salesTaxAmount].
         *
         * Unlike [salesTaxAmount], this method doesn't throw if the JSON field has an unexpected
         * type.
         */
        @JsonProperty("sales_tax_amount")
        @ExcludeMissing
        fun _salesTaxAmount(): JsonField<Long> = salesTaxAmount

        /**
         * Returns the raw JSON value of [salesTaxCurrency].
         *
         * Unlike [salesTaxCurrency], this method doesn't throw if the JSON field has an unexpected
         * type.
         */
        @JsonProperty("sales_tax_currency")
        @ExcludeMissing
        fun _salesTaxCurrency(): JsonField<String> = salesTaxCurrency

        /**
         * Returns the raw JSON value of [salesTaxRate].
         *
         * Unlike [salesTaxRate], this method doesn't throw if the JSON field has an unexpected
         * type.
         */
        @JsonProperty("sales_tax_rate")
        @ExcludeMissing
        fun _salesTaxRate(): JsonField<String> = salesTaxRate

        /**
         * Returns the raw JSON value of [totalAmount].
         *
         * Unlike [totalAmount], this method doesn't throw if the JSON field has an unexpected type.
         */
        @JsonProperty("total_amount")
        @ExcludeMissing
        fun _totalAmount(): JsonField<Long> = totalAmount

        /**
         * Returns the raw JSON value of [totalAmountCurrency].
         *
         * Unlike [totalAmountCurrency], this method doesn't throw if the JSON field has an
         * unexpected type.
         */
        @JsonProperty("total_amount_currency")
        @ExcludeMissing
        fun _totalAmountCurrency(): JsonField<String> = totalAmountCurrency

        /**
         * Returns the raw JSON value of [unitCost].
         *
         * Unlike [unitCost], this method doesn't throw if the JSON field has an unexpected type.
         */
        @JsonProperty("unit_cost") @ExcludeMissing fun _unitCost(): JsonField<String> = unitCost

        /**
         * Returns the raw JSON value of [unitCostCurrency].
         *
         * Unlike [unitCostCurrency], this method doesn't throw if the JSON field has an unexpected
         * type.
         */
        @JsonProperty("unit_cost_currency")
        @ExcludeMissing
        fun _unitCostCurrency(): JsonField<String> = unitCostCurrency

        /**
         * Returns the raw JSON value of [unitOfMeasureCode].
         *
         * Unlike [unitOfMeasureCode], this method doesn't throw if the JSON field has an unexpected
         * type.
         */
        @JsonProperty("unit_of_measure_code")
        @ExcludeMissing
        fun _unitOfMeasureCode(): JsonField<String> = unitOfMeasureCode

        @JsonAnySetter
        private fun putAdditionalProperty(key: String, value: JsonValue) {
            additionalProperties.put(key, value)
        }

        @JsonAnyGetter
        @ExcludeMissing
        fun _additionalProperties(): Map<String, JsonValue> =
            Collections.unmodifiableMap(additionalProperties)

        fun toBuilder() = Builder().from(this)

        companion object {

            /**
             * Returns a mutable builder for constructing an instance of [LineItem].
             *
             * The following fields are required:
             * ```java
             * .id()
             * .detailIndicator()
             * .discountAmount()
             * .discountCurrency()
             * .discountTreatmentCode()
             * .itemCommodityCode()
             * .itemDescriptor()
             * .itemQuantity()
             * .productCode()
             * .salesTaxAmount()
             * .salesTaxCurrency()
             * .salesTaxRate()
             * .totalAmount()
             * .totalAmountCurrency()
             * .unitCost()
             * .unitCostCurrency()
             * .unitOfMeasureCode()
             * ```
             */
            @JvmStatic fun builder() = Builder()
        }

        /** A builder for [LineItem]. */
        class Builder internal constructor() {

            private var id: JsonField<String>? = null
            private var detailIndicator: JsonField<DetailIndicator>? = null
            private var discountAmount: JsonField<Long>? = null
            private var discountCurrency: JsonField<String>? = null
            private var discountTreatmentCode: JsonField<DiscountTreatmentCode>? = null
            private var itemCommodityCode: JsonField<String>? = null
            private var itemDescriptor: JsonField<String>? = null
            private var itemQuantity: JsonField<String>? = null
            private var productCode: JsonField<String>? = null
            private var salesTaxAmount: JsonField<Long>? = null
            private var salesTaxCurrency: JsonField<String>? = null
            private var salesTaxRate: JsonField<String>? = null
            private var totalAmount: JsonField<Long>? = null
            private var totalAmountCurrency: JsonField<String>? = null
            private var unitCost: JsonField<String>? = null
            private var unitCostCurrency: JsonField<String>? = null
            private var unitOfMeasureCode: JsonField<String>? = null
            private var additionalProperties: MutableMap<String, JsonValue> = mutableMapOf()

            @JvmSynthetic
            internal fun from(lineItem: LineItem) = apply {
                id = lineItem.id
                detailIndicator = lineItem.detailIndicator
                discountAmount = lineItem.discountAmount
                discountCurrency = lineItem.discountCurrency
                discountTreatmentCode = lineItem.discountTreatmentCode
                itemCommodityCode = lineItem.itemCommodityCode
                itemDescriptor = lineItem.itemDescriptor
                itemQuantity = lineItem.itemQuantity
                productCode = lineItem.productCode
                salesTaxAmount = lineItem.salesTaxAmount
                salesTaxCurrency = lineItem.salesTaxCurrency
                salesTaxRate = lineItem.salesTaxRate
                totalAmount = lineItem.totalAmount
                totalAmountCurrency = lineItem.totalAmountCurrency
                unitCost = lineItem.unitCost
                unitCostCurrency = lineItem.unitCostCurrency
                unitOfMeasureCode = lineItem.unitOfMeasureCode
                additionalProperties = lineItem.additionalProperties.toMutableMap()
            }

            /** The Card Purchase Supplement Line Item identifier. */
            fun id(id: String) = id(JsonField.of(id))

            /**
             * Sets [Builder.id] to an arbitrary JSON value.
             *
             * You should usually call [Builder.id] with a well-typed [String] value instead. This
             * method is primarily for setting the field to an undocumented or not yet supported
             * value.
             */
            fun id(id: JsonField<String>) = apply { this.id = id }

            /** Indicates the type of line item. */
            fun detailIndicator(detailIndicator: DetailIndicator?) =
                detailIndicator(JsonField.ofNullable(detailIndicator))

            /** Alias for calling [Builder.detailIndicator] with `detailIndicator.orElse(null)`. */
            fun detailIndicator(detailIndicator: Optional<DetailIndicator>) =
                detailIndicator(detailIndicator.getOrNull())

            /**
             * Sets [Builder.detailIndicator] to an arbitrary JSON value.
             *
             * You should usually call [Builder.detailIndicator] with a well-typed [DetailIndicator]
             * value instead. This method is primarily for setting the field to an undocumented or
             * not yet supported value.
             */
            fun detailIndicator(detailIndicator: JsonField<DetailIndicator>) = apply {
                this.detailIndicator = detailIndicator
            }

            /** Discount amount for this specific line item. */
            fun discountAmount(discountAmount: Long?) =
                discountAmount(JsonField.ofNullable(discountAmount))

            /**
             * Alias for [Builder.discountAmount].
             *
             * This unboxed primitive overload exists for backwards compatibility.
             */
            fun discountAmount(discountAmount: Long) = discountAmount(discountAmount as Long?)

            /** Alias for calling [Builder.discountAmount] with `discountAmount.orElse(null)`. */
            fun discountAmount(discountAmount: Optional<Long>) =
                discountAmount(discountAmount.getOrNull())

            /**
             * Sets [Builder.discountAmount] to an arbitrary JSON value.
             *
             * You should usually call [Builder.discountAmount] with a well-typed [Long] value
             * instead. This method is primarily for setting the field to an undocumented or not yet
             * supported value.
             */
            fun discountAmount(discountAmount: JsonField<Long>) = apply {
                this.discountAmount = discountAmount
            }

            /** The [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217) code for the discount. */
            fun discountCurrency(discountCurrency: String?) =
                discountCurrency(JsonField.ofNullable(discountCurrency))

            /**
             * Alias for calling [Builder.discountCurrency] with `discountCurrency.orElse(null)`.
             */
            fun discountCurrency(discountCurrency: Optional<String>) =
                discountCurrency(discountCurrency.getOrNull())

            /**
             * Sets [Builder.discountCurrency] to an arbitrary JSON value.
             *
             * You should usually call [Builder.discountCurrency] with a well-typed [String] value
             * instead. This method is primarily for setting the field to an undocumented or not yet
             * supported value.
             */
            fun discountCurrency(discountCurrency: JsonField<String>) = apply {
                this.discountCurrency = discountCurrency
            }

            /** Indicates how the merchant applied the discount for this specific line item. */
            fun discountTreatmentCode(discountTreatmentCode: DiscountTreatmentCode?) =
                discountTreatmentCode(JsonField.ofNullable(discountTreatmentCode))

            /**
             * Alias for calling [Builder.discountTreatmentCode] with
             * `discountTreatmentCode.orElse(null)`.
             */
            fun discountTreatmentCode(discountTreatmentCode: Optional<DiscountTreatmentCode>) =
                discountTreatmentCode(discountTreatmentCode.getOrNull())

            /**
             * Sets [Builder.discountTreatmentCode] to an arbitrary JSON value.
             *
             * You should usually call [Builder.discountTreatmentCode] with a well-typed
             * [DiscountTreatmentCode] value instead. This method is primarily for setting the field
             * to an undocumented or not yet supported value.
             */
            fun discountTreatmentCode(discountTreatmentCode: JsonField<DiscountTreatmentCode>) =
                apply {
                    this.discountTreatmentCode = discountTreatmentCode
                }

            /** Code used to categorize the purchase item. */
            fun itemCommodityCode(itemCommodityCode: String?) =
                itemCommodityCode(JsonField.ofNullable(itemCommodityCode))

            /**
             * Alias for calling [Builder.itemCommodityCode] with `itemCommodityCode.orElse(null)`.
             */
            fun itemCommodityCode(itemCommodityCode: Optional<String>) =
                itemCommodityCode(itemCommodityCode.getOrNull())

            /**
             * Sets [Builder.itemCommodityCode] to an arbitrary JSON value.
             *
             * You should usually call [Builder.itemCommodityCode] with a well-typed [String] value
             * instead. This method is primarily for setting the field to an undocumented or not yet
             * supported value.
             */
            fun itemCommodityCode(itemCommodityCode: JsonField<String>) = apply {
                this.itemCommodityCode = itemCommodityCode
            }

            /** Description of the purchase item. */
            fun itemDescriptor(itemDescriptor: String?) =
                itemDescriptor(JsonField.ofNullable(itemDescriptor))

            /** Alias for calling [Builder.itemDescriptor] with `itemDescriptor.orElse(null)`. */
            fun itemDescriptor(itemDescriptor: Optional<String>) =
                itemDescriptor(itemDescriptor.getOrNull())

            /**
             * Sets [Builder.itemDescriptor] to an arbitrary JSON value.
             *
             * You should usually call [Builder.itemDescriptor] with a well-typed [String] value
             * instead. This method is primarily for setting the field to an undocumented or not yet
             * supported value.
             */
            fun itemDescriptor(itemDescriptor: JsonField<String>) = apply {
                this.itemDescriptor = itemDescriptor
            }

            /** The number of units of the product being purchased. */
            fun itemQuantity(itemQuantity: String?) =
                itemQuantity(JsonField.ofNullable(itemQuantity))

            /** Alias for calling [Builder.itemQuantity] with `itemQuantity.orElse(null)`. */
            fun itemQuantity(itemQuantity: Optional<String>) =
                itemQuantity(itemQuantity.getOrNull())

            /**
             * Sets [Builder.itemQuantity] to an arbitrary JSON value.
             *
             * You should usually call [Builder.itemQuantity] with a well-typed [String] value
             * instead. This method is primarily for setting the field to an undocumented or not yet
             * supported value.
             */
            fun itemQuantity(itemQuantity: JsonField<String>) = apply {
                this.itemQuantity = itemQuantity
            }

            /** Code used to categorize the product being purchased. */
            fun productCode(productCode: String?) = productCode(JsonField.ofNullable(productCode))

            /** Alias for calling [Builder.productCode] with `productCode.orElse(null)`. */
            fun productCode(productCode: Optional<String>) = 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<String>) = apply {
                this.productCode = productCode
            }

            /** Sales tax amount for this line item. */
            fun salesTaxAmount(salesTaxAmount: Long?) =
                salesTaxAmount(JsonField.ofNullable(salesTaxAmount))

            /**
             * Alias for [Builder.salesTaxAmount].
             *
             * This unboxed primitive overload exists for backwards compatibility.
             */
            fun salesTaxAmount(salesTaxAmount: Long) = salesTaxAmount(salesTaxAmount as Long?)

            /** Alias for calling [Builder.salesTaxAmount] with `salesTaxAmount.orElse(null)`. */
            fun salesTaxAmount(salesTaxAmount: Optional<Long>) =
                salesTaxAmount(salesTaxAmount.getOrNull())

            /**
             * Sets [Builder.salesTaxAmount] to an arbitrary JSON value.
             *
             * You should usually call [Builder.salesTaxAmount] with a well-typed [Long] value
             * instead. This method is primarily for setting the field to an undocumented or not yet
             * supported value.
             */
            fun salesTaxAmount(salesTaxAmount: JsonField<Long>) = apply {
                this.salesTaxAmount = salesTaxAmount
            }

            /**
             * The [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217) code for the sales tax
             * assessed.
             */
            fun salesTaxCurrency(salesTaxCurrency: String?) =
                salesTaxCurrency(JsonField.ofNullable(salesTaxCurrency))

            /**
             * Alias for calling [Builder.salesTaxCurrency] with `salesTaxCurrency.orElse(null)`.
             */
            fun salesTaxCurrency(salesTaxCurrency: Optional<String>) =
                salesTaxCurrency(salesTaxCurrency.getOrNull())

            /**
             * Sets [Builder.salesTaxCurrency] to an arbitrary JSON value.
             *
             * You should usually call [Builder.salesTaxCurrency] with a well-typed [String] value
             * instead. This method is primarily for setting the field to an undocumented or not yet
             * supported value.
             */
            fun salesTaxCurrency(salesTaxCurrency: JsonField<String>) = apply {
                this.salesTaxCurrency = salesTaxCurrency
            }

            /** Sales tax rate for this line item. */
            fun salesTaxRate(salesTaxRate: String?) =
                salesTaxRate(JsonField.ofNullable(salesTaxRate))

            /** Alias for calling [Builder.salesTaxRate] with `salesTaxRate.orElse(null)`. */
            fun salesTaxRate(salesTaxRate: Optional<String>) =
                salesTaxRate(salesTaxRate.getOrNull())

            /**
             * Sets [Builder.salesTaxRate] to an arbitrary JSON value.
             *
             * You should usually call [Builder.salesTaxRate] with a well-typed [String] value
             * instead. This method is primarily for setting the field to an undocumented or not yet
             * supported value.
             */
            fun salesTaxRate(salesTaxRate: JsonField<String>) = apply {
                this.salesTaxRate = salesTaxRate
            }

            /** Total amount of all line items. */
            fun totalAmount(totalAmount: Long?) = totalAmount(JsonField.ofNullable(totalAmount))

            /**
             * Alias for [Builder.totalAmount].
             *
             * This unboxed primitive overload exists for backwards compatibility.
             */
            fun totalAmount(totalAmount: Long) = totalAmount(totalAmount as Long?)

            /** Alias for calling [Builder.totalAmount] with `totalAmount.orElse(null)`. */
            fun totalAmount(totalAmount: Optional<Long>) = totalAmount(totalAmount.getOrNull())

            /**
             * Sets [Builder.totalAmount] to an arbitrary JSON value.
             *
             * You should usually call [Builder.totalAmount] with a well-typed [Long] value instead.
             * This method is primarily for setting the field to an undocumented or not yet
             * supported value.
             */
            fun totalAmount(totalAmount: JsonField<Long>) = apply { this.totalAmount = totalAmount }

            /** The [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217) code for the total amount. */
            fun totalAmountCurrency(totalAmountCurrency: String?) =
                totalAmountCurrency(JsonField.ofNullable(totalAmountCurrency))

            /**
             * Alias for calling [Builder.totalAmountCurrency] with
             * `totalAmountCurrency.orElse(null)`.
             */
            fun totalAmountCurrency(totalAmountCurrency: Optional<String>) =
                totalAmountCurrency(totalAmountCurrency.getOrNull())

            /**
             * Sets [Builder.totalAmountCurrency] to an arbitrary JSON value.
             *
             * You should usually call [Builder.totalAmountCurrency] with a well-typed [String]
             * value instead. This method is primarily for setting the field to an undocumented or
             * not yet supported value.
             */
            fun totalAmountCurrency(totalAmountCurrency: JsonField<String>) = apply {
                this.totalAmountCurrency = totalAmountCurrency
            }

            /** Cost of line item per unit of measure, in major units. */
            fun unitCost(unitCost: String?) = unitCost(JsonField.ofNullable(unitCost))

            /** Alias for calling [Builder.unitCost] with `unitCost.orElse(null)`. */
            fun unitCost(unitCost: Optional<String>) = unitCost(unitCost.getOrNull())

            /**
             * Sets [Builder.unitCost] to an arbitrary JSON value.
             *
             * You should usually call [Builder.unitCost] with a well-typed [String] value instead.
             * This method is primarily for setting the field to an undocumented or not yet
             * supported value.
             */
            fun unitCost(unitCost: JsonField<String>) = apply { this.unitCost = unitCost }

            /** The [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217) code for the unit cost. */
            fun unitCostCurrency(unitCostCurrency: String?) =
                unitCostCurrency(JsonField.ofNullable(unitCostCurrency))

            /**
             * Alias for calling [Builder.unitCostCurrency] with `unitCostCurrency.orElse(null)`.
             */
            fun unitCostCurrency(unitCostCurrency: Optional<String>) =
                unitCostCurrency(unitCostCurrency.getOrNull())

            /**
             * Sets [Builder.unitCostCurrency] to an arbitrary JSON value.
             *
             * You should usually call [Builder.unitCostCurrency] with a well-typed [String] value
             * instead. This method is primarily for setting the field to an undocumented or not yet
             * supported value.
             */
            fun unitCostCurrency(unitCostCurrency: JsonField<String>) = apply {
                this.unitCostCurrency = unitCostCurrency
            }

            /** Code indicating unit of measure (gallons, etc.). */
            fun unitOfMeasureCode(unitOfMeasureCode: String?) =
                unitOfMeasureCode(JsonField.ofNullable(unitOfMeasureCode))

            /**
             * Alias for calling [Builder.unitOfMeasureCode] with `unitOfMeasureCode.orElse(null)`.
             */
            fun unitOfMeasureCode(unitOfMeasureCode: Optional<String>) =
                unitOfMeasureCode(unitOfMeasureCode.getOrNull())

            /**
             * Sets [Builder.unitOfMeasureCode] to an arbitrary JSON value.
             *
             * You should usually call [Builder.unitOfMeasureCode] with a well-typed [String] value
             * instead. This method is primarily for setting the field to an undocumented or not yet
             * supported value.
             */
            fun unitOfMeasureCode(unitOfMeasureCode: JsonField<String>) = apply {
                this.unitOfMeasureCode = unitOfMeasureCode
            }

            fun additionalProperties(additionalProperties: Map<String, JsonValue>) = apply {
                this.additionalProperties.clear()
                putAllAdditionalProperties(additionalProperties)
            }

            fun putAdditionalProperty(key: String, value: JsonValue) = apply {
                additionalProperties.put(key, value)
            }

            fun putAllAdditionalProperties(additionalProperties: Map<String, JsonValue>) = apply {
                this.additionalProperties.putAll(additionalProperties)
            }

            fun removeAdditionalProperty(key: String) = apply { additionalProperties.remove(key) }

            fun removeAllAdditionalProperties(keys: Set<String>) = apply {
                keys.forEach(::removeAdditionalProperty)
            }

            /**
             * Returns an immutable instance of [LineItem].
             *
             * Further updates to this [Builder] will not mutate the returned instance.
             *
             * The following fields are required:
             * ```java
             * .id()
             * .detailIndicator()
             * .discountAmount()
             * .discountCurrency()
             * .discountTreatmentCode()
             * .itemCommodityCode()
             * .itemDescriptor()
             * .itemQuantity()
             * .productCode()
             * .salesTaxAmount()
             * .salesTaxCurrency()
             * .salesTaxRate()
             * .totalAmount()
             * .totalAmountCurrency()
             * .unitCost()
             * .unitCostCurrency()
             * .unitOfMeasureCode()
             * ```
             *
             * @throws IllegalStateException if any required field is unset.
             */
            fun build(): LineItem =
                LineItem(
                    checkRequired("id", id),
                    checkRequired("detailIndicator", detailIndicator),
                    checkRequired("discountAmount", discountAmount),
                    checkRequired("discountCurrency", discountCurrency),
                    checkRequired("discountTreatmentCode", discountTreatmentCode),
                    checkRequired("itemCommodityCode", itemCommodityCode),
                    checkRequired("itemDescriptor", itemDescriptor),
                    checkRequired("itemQuantity", itemQuantity),
                    checkRequired("productCode", productCode),
                    checkRequired("salesTaxAmount", salesTaxAmount),
                    checkRequired("salesTaxCurrency", salesTaxCurrency),
                    checkRequired("salesTaxRate", salesTaxRate),
                    checkRequired("totalAmount", totalAmount),
                    checkRequired("totalAmountCurrency", totalAmountCurrency),
                    checkRequired("unitCost", unitCost),
                    checkRequired("unitCostCurrency", unitCostCurrency),
                    checkRequired("unitOfMeasureCode", unitOfMeasureCode),
                    additionalProperties.toMutableMap(),
                )
        }

        private var validated: Boolean = false

        /**
         * Validates that the types of all values in this object match their expected types
         * recursively.
         *
         * This method is _not_ forwards compatible with new types from the API for existing fields.
         *
         * @throws IncreaseInvalidDataException if any value type in this object doesn't match its
         *   expected type.
         */
        fun validate(): LineItem = apply {
            if (validated) {
                return@apply
            }

            id()
            detailIndicator().ifPresent { it.validate() }
            discountAmount()
            discountCurrency()
            discountTreatmentCode().ifPresent { it.validate() }
            itemCommodityCode()
            itemDescriptor()
            itemQuantity()
            productCode()
            salesTaxAmount()
            salesTaxCurrency()
            salesTaxRate()
            totalAmount()
            totalAmountCurrency()
            unitCost()
            unitCostCurrency()
            unitOfMeasureCode()
            validated = true
        }

        fun isValid(): Boolean =
            try {
                validate()
                true
            } catch (e: IncreaseInvalidDataException) {
                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 (id.asKnown().isPresent) 1 else 0) +
                (detailIndicator.asKnown().getOrNull()?.validity() ?: 0) +
                (if (discountAmount.asKnown().isPresent) 1 else 0) +
                (if (discountCurrency.asKnown().isPresent) 1 else 0) +
                (discountTreatmentCode.asKnown().getOrNull()?.validity() ?: 0) +
                (if (itemCommodityCode.asKnown().isPresent) 1 else 0) +
                (if (itemDescriptor.asKnown().isPresent) 1 else 0) +
                (if (itemQuantity.asKnown().isPresent) 1 else 0) +
                (if (productCode.asKnown().isPresent) 1 else 0) +
                (if (salesTaxAmount.asKnown().isPresent) 1 else 0) +
                (if (salesTaxCurrency.asKnown().isPresent) 1 else 0) +
                (if (salesTaxRate.asKnown().isPresent) 1 else 0) +
                (if (totalAmount.asKnown().isPresent) 1 else 0) +
                (if (totalAmountCurrency.asKnown().isPresent) 1 else 0) +
                (if (unitCost.asKnown().isPresent) 1 else 0) +
                (if (unitCostCurrency.asKnown().isPresent) 1 else 0) +
                (if (unitOfMeasureCode.asKnown().isPresent) 1 else 0)

        /** Indicates the type of line item. */
        class DetailIndicator
        @JsonCreator
        private constructor(private val value: JsonField<String>) : 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<String> = value

            companion object {

                /** Normal */
                @JvmField val NORMAL = of("normal")

                /** Credit */
                @JvmField val CREDIT = of("credit")

                /** Purchase */
                @JvmField val PAYMENT = of("payment")

                @JvmStatic fun of(value: String) = DetailIndicator(JsonField.of(value))
            }

            /** An enum containing [DetailIndicator]'s known values. */
            enum class Known {
                /** Normal */
                NORMAL,
                /** Credit */
                CREDIT,
                /** Purchase */
                PAYMENT,
            }

            /**
             * An enum containing [DetailIndicator]'s known values, as well as an [_UNKNOWN] member.
             *
             * An instance of [DetailIndicator] 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 {
                /** Normal */
                NORMAL,
                /** Credit */
                CREDIT,
                /** Purchase */
                PAYMENT,
                /**
                 * An enum member indicating that [DetailIndicator] 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) {
                    NORMAL -> Value.NORMAL
                    CREDIT -> Value.CREDIT
                    PAYMENT -> Value.PAYMENT
                    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 IncreaseInvalidDataException if this class instance's value is a not a known
             *   member.
             */
            fun known(): Known =
                when (this) {
                    NORMAL -> Known.NORMAL
                    CREDIT -> Known.CREDIT
                    PAYMENT -> Known.PAYMENT
                    else -> throw IncreaseInvalidDataException("Unknown DetailIndicator: $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 IncreaseInvalidDataException if this class instance's value does not have the
             *   expected primitive type.
             */
            fun asString(): String =
                _value().asString().orElseThrow {
                    IncreaseInvalidDataException("Value is not a String")
                }

            private var validated: Boolean = false

            /**
             * Validates that the types of all values in this object match their expected types
             * recursively.
             *
             * This method is _not_ forwards compatible with new types from the API for existing
             * fields.
             *
             * @throws IncreaseInvalidDataException if any value type in this object doesn't match
             *   its expected type.
             */
            fun validate(): DetailIndicator = apply {
                if (validated) {
                    return@apply
                }

                known()
                validated = true
            }

            fun isValid(): Boolean =
                try {
                    validate()
                    true
                } catch (e: IncreaseInvalidDataException) {
                    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 DetailIndicator && value == other.value
            }

            override fun hashCode() = value.hashCode()

            override fun toString() = value.toString()
        }

        /** Indicates how the merchant applied the discount for this specific line item. */
        class DiscountTreatmentCode
        @JsonCreator
        private constructor(private val value: JsonField<String>) : 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<String> = value

            companion object {

                /** No line item level discount provided */
                @JvmField
                val NO_LINE_ITEM_LEVEL_DISCOUNT_PROVIDED =
                    of("no_line_item_level_discount_provided")

                /** Tax calculated on post discount line item total */
                @JvmField
                val TAX_CALCULATED_ON_POST_DISCOUNT_LINE_ITEM_TOTAL =
                    of("tax_calculated_on_post_discount_line_item_total")

                /** Tax calculated on pre discount line item total */
                @JvmField
                val TAX_CALCULATED_ON_PRE_DISCOUNT_LINE_ITEM_TOTAL =
                    of("tax_calculated_on_pre_discount_line_item_total")

                @JvmStatic fun of(value: String) = DiscountTreatmentCode(JsonField.of(value))
            }

            /** An enum containing [DiscountTreatmentCode]'s known values. */
            enum class Known {
                /** No line item level discount provided */
                NO_LINE_ITEM_LEVEL_DISCOUNT_PROVIDED,
                /** Tax calculated on post discount line item total */
                TAX_CALCULATED_ON_POST_DISCOUNT_LINE_ITEM_TOTAL,
                /** Tax calculated on pre discount line item total */
                TAX_CALCULATED_ON_PRE_DISCOUNT_LINE_ITEM_TOTAL,
            }

            /**
             * An enum containing [DiscountTreatmentCode]'s known values, as well as an [_UNKNOWN]
             * member.
             *
             * An instance of [DiscountTreatmentCode] 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 {
                /** No line item level discount provided */
                NO_LINE_ITEM_LEVEL_DISCOUNT_PROVIDED,
                /** Tax calculated on post discount line item total */
                TAX_CALCULATED_ON_POST_DISCOUNT_LINE_ITEM_TOTAL,
                /** Tax calculated on pre discount line item total */
                TAX_CALCULATED_ON_PRE_DISCOUNT_LINE_ITEM_TOTAL,
                /**
                 * An enum member indicating that [DiscountTreatmentCode] 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) {
                    NO_LINE_ITEM_LEVEL_DISCOUNT_PROVIDED ->
                        Value.NO_LINE_ITEM_LEVEL_DISCOUNT_PROVIDED
                    TAX_CALCULATED_ON_POST_DISCOUNT_LINE_ITEM_TOTAL ->
                        Value.TAX_CALCULATED_ON_POST_DISCOUNT_LINE_ITEM_TOTAL
                    TAX_CALCULATED_ON_PRE_DISCOUNT_LINE_ITEM_TOTAL ->
                        Value.TAX_CALCULATED_ON_PRE_DISCOUNT_LINE_ITEM_TOTAL
                    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 IncreaseInvalidDataException if this class instance's value is a not a known
             *   member.
             */
            fun known(): Known =
                when (this) {
                    NO_LINE_ITEM_LEVEL_DISCOUNT_PROVIDED ->
                        Known.NO_LINE_ITEM_LEVEL_DISCOUNT_PROVIDED
                    TAX_CALCULATED_ON_POST_DISCOUNT_LINE_ITEM_TOTAL ->
                        Known.TAX_CALCULATED_ON_POST_DISCOUNT_LINE_ITEM_TOTAL
                    TAX_CALCULATED_ON_PRE_DISCOUNT_LINE_ITEM_TOTAL ->
                        Known.TAX_CALCULATED_ON_PRE_DISCOUNT_LINE_ITEM_TOTAL
                    else ->
                        throw IncreaseInvalidDataException("Unknown DiscountTreatmentCode: $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 IncreaseInvalidDataException if this class instance's value does not have the
             *   expected primitive type.
             */
            fun asString(): String =
                _value().asString().orElseThrow {
                    IncreaseInvalidDataException("Value is not a String")
                }

            private var validated: Boolean = false

            /**
             * Validates that the types of all values in this object match their expected types
             * recursively.
             *
             * This method is _not_ forwards compatible with new types from the API for existing
             * fields.
             *
             * @throws IncreaseInvalidDataException if any value type in this object doesn't match
             *   its expected type.
             */
            fun validate(): DiscountTreatmentCode = apply {
                if (validated) {
                    return@apply
                }

                known()
                validated = true
            }

            fun isValid(): Boolean =
                try {
                    validate()
                    true
                } catch (e: IncreaseInvalidDataException) {
                    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 DiscountTreatmentCode && 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 LineItem &&
                id == other.id &&
                detailIndicator == other.detailIndicator &&
                discountAmount == other.discountAmount &&
                discountCurrency == other.discountCurrency &&
                discountTreatmentCode == other.discountTreatmentCode &&
                itemCommodityCode == other.itemCommodityCode &&
                itemDescriptor == other.itemDescriptor &&
                itemQuantity == other.itemQuantity &&
                productCode == other.productCode &&
                salesTaxAmount == other.salesTaxAmount &&
                salesTaxCurrency == other.salesTaxCurrency &&
                salesTaxRate == other.salesTaxRate &&
                totalAmount == other.totalAmount &&
                totalAmountCurrency == other.totalAmountCurrency &&
                unitCost == other.unitCost &&
                unitCostCurrency == other.unitCostCurrency &&
                unitOfMeasureCode == other.unitOfMeasureCode &&
                additionalProperties == other.additionalProperties
        }

        private val hashCode: Int by lazy {
            Objects.hash(
                id,
                detailIndicator,
                discountAmount,
                discountCurrency,
                discountTreatmentCode,
                itemCommodityCode,
                itemDescriptor,
                itemQuantity,
                productCode,
                salesTaxAmount,
                salesTaxCurrency,
                salesTaxRate,
                totalAmount,
                totalAmountCurrency,
                unitCost,
                unitCostCurrency,
                unitOfMeasureCode,
                additionalProperties,
            )
        }

        override fun hashCode(): Int = hashCode

        override fun toString() =
            "LineItem{id=$id, detailIndicator=$detailIndicator, discountAmount=$discountAmount, discountCurrency=$discountCurrency, discountTreatmentCode=$discountTreatmentCode, itemCommodityCode=$itemCommodityCode, itemDescriptor=$itemDescriptor, itemQuantity=$itemQuantity, productCode=$productCode, salesTaxAmount=$salesTaxAmount, salesTaxCurrency=$salesTaxCurrency, salesTaxRate=$salesTaxRate, totalAmount=$totalAmount, totalAmountCurrency=$totalAmountCurrency, unitCost=$unitCost, unitCostCurrency=$unitCostCurrency, unitOfMeasureCode=$unitOfMeasureCode, additionalProperties=$additionalProperties}"
    }

    /** Shipping information for the purchase. */
    class Shipping
    @JsonCreator(mode = JsonCreator.Mode.DISABLED)
    private constructor(
        private val customerReferenceNumber: JsonField<String>,
        private val destinationAddress: JsonField<String>,
        private val destinationCountryCode: JsonField<String>,
        private val destinationPostalCode: JsonField<String>,
        private val destinationReceiverName: JsonField<String>,
        private val discountAmount: JsonField<Long>,
        private val netAmount: JsonField<Long>,
        private val numberOfPackages: JsonField<Long>,
        private val originAddress: JsonField<String>,
        private val originCountryCode: JsonField<String>,
        private val originPostalCode: JsonField<String>,
        private val originSenderName: JsonField<String>,
        private val pickUpDate: JsonField<LocalDate>,
        private val serviceDescription: JsonField<String>,
        private val serviceLevelCode: JsonField<String>,
        private val shippingCourierName: JsonField<String>,
        private val taxAmount: JsonField<Long>,
        private val trackingNumber: JsonField<String>,
        private val unitOfMeasure: JsonField<String>,
        private val weight: JsonField<String>,
        private val additionalProperties: MutableMap<String, JsonValue>,
    ) {

        @JsonCreator
        private constructor(
            @JsonProperty("customer_reference_number")
            @ExcludeMissing
            customerReferenceNumber: JsonField<String> = JsonMissing.of(),
            @JsonProperty("destination_address")
            @ExcludeMissing
            destinationAddress: JsonField<String> = JsonMissing.of(),
            @JsonProperty("destination_country_code")
            @ExcludeMissing
            destinationCountryCode: JsonField<String> = JsonMissing.of(),
            @JsonProperty("destination_postal_code")
            @ExcludeMissing
            destinationPostalCode: JsonField<String> = JsonMissing.of(),
            @JsonProperty("destination_receiver_name")
            @ExcludeMissing
            destinationReceiverName: JsonField<String> = JsonMissing.of(),
            @JsonProperty("discount_amount")
            @ExcludeMissing
            discountAmount: JsonField<Long> = JsonMissing.of(),
            @JsonProperty("net_amount")
            @ExcludeMissing
            netAmount: JsonField<Long> = JsonMissing.of(),
            @JsonProperty("number_of_packages")
            @ExcludeMissing
            numberOfPackages: JsonField<Long> = JsonMissing.of(),
            @JsonProperty("origin_address")
            @ExcludeMissing
            originAddress: JsonField<String> = JsonMissing.of(),
            @JsonProperty("origin_country_code")
            @ExcludeMissing
            originCountryCode: JsonField<String> = JsonMissing.of(),
            @JsonProperty("origin_postal_code")
            @ExcludeMissing
            originPostalCode: JsonField<String> = JsonMissing.of(),
            @JsonProperty("origin_sender_name")
            @ExcludeMissing
            originSenderName: JsonField<String> = JsonMissing.of(),
            @JsonProperty("pick_up_date")
            @ExcludeMissing
            pickUpDate: JsonField<LocalDate> = JsonMissing.of(),
            @JsonProperty("service_description")
            @ExcludeMissing
            serviceDescription: JsonField<String> = JsonMissing.of(),
            @JsonProperty("service_level_code")
            @ExcludeMissing
            serviceLevelCode: JsonField<String> = JsonMissing.of(),
            @JsonProperty("shipping_courier_name")
            @ExcludeMissing
            shippingCourierName: JsonField<String> = JsonMissing.of(),
            @JsonProperty("tax_amount")
            @ExcludeMissing
            taxAmount: JsonField<Long> = JsonMissing.of(),
            @JsonProperty("tracking_number")
            @ExcludeMissing
            trackingNumber: JsonField<String> = JsonMissing.of(),
            @JsonProperty("unit_of_measure")
            @ExcludeMissing
            unitOfMeasure: JsonField<String> = JsonMissing.of(),
            @JsonProperty("weight") @ExcludeMissing weight: JsonField<String> = JsonMissing.of(),
        ) : this(
            customerReferenceNumber,
            destinationAddress,
            destinationCountryCode,
            destinationPostalCode,
            destinationReceiverName,
            discountAmount,
            netAmount,
            numberOfPackages,
            originAddress,
            originCountryCode,
            originPostalCode,
            originSenderName,
            pickUpDate,
            serviceDescription,
            serviceLevelCode,
            shippingCourierName,
            taxAmount,
            trackingNumber,
            unitOfMeasure,
            weight,
            mutableMapOf(),
        )

        /**
         * The customer reference number.
         *
         * @throws IncreaseInvalidDataException if the JSON field has an unexpected type (e.g. if
         *   the server responded with an unexpected value).
         */
        fun customerReferenceNumber(): Optional<String> =
            customerReferenceNumber.getOptional("customer_reference_number")

        /**
         * Address of the destination.
         *
         * @throws IncreaseInvalidDataException if the JSON field has an unexpected type (e.g. if
         *   the server responded with an unexpected value).
         */
        fun destinationAddress(): Optional<String> =
            destinationAddress.getOptional("destination_address")

        /**
         * Country code of the destination.
         *
         * @throws IncreaseInvalidDataException if the JSON field has an unexpected type (e.g. if
         *   the server responded with an unexpected value).
         */
        fun destinationCountryCode(): Optional<String> =
            destinationCountryCode.getOptional("destination_country_code")

        /**
         * Postal code of the destination.
         *
         * @throws IncreaseInvalidDataException if the JSON field has an unexpected type (e.g. if
         *   the server responded with an unexpected value).
         */
        fun destinationPostalCode(): Optional<String> =
            destinationPostalCode.getOptional("destination_postal_code")

        /**
         * Name of the receiver at the destination.
         *
         * @throws IncreaseInvalidDataException if the JSON field has an unexpected type (e.g. if
         *   the server responded with an unexpected value).
         */
        fun destinationReceiverName(): Optional<String> =
            destinationReceiverName.getOptional("destination_receiver_name")

        /**
         * Discount amount for the shipment.
         *
         * @throws IncreaseInvalidDataException if the JSON field has an unexpected type (e.g. if
         *   the server responded with an unexpected value).
         */
        fun discountAmount(): Optional<Long> = discountAmount.getOptional("discount_amount")

        /**
         * Net shipping amount.
         *
         * @throws IncreaseInvalidDataException if the JSON field has an unexpected type (e.g. if
         *   the server responded with an unexpected value).
         */
        fun netAmount(): Optional<Long> = netAmount.getOptional("net_amount")

        /**
         * Number of packages shipped.
         *
         * @throws IncreaseInvalidDataException if the JSON field has an unexpected type (e.g. if
         *   the server responded with an unexpected value).
         */
        fun numberOfPackages(): Optional<Long> = numberOfPackages.getOptional("number_of_packages")

        /**
         * Address of the origin.
         *
         * @throws IncreaseInvalidDataException if the JSON field has an unexpected type (e.g. if
         *   the server responded with an unexpected value).
         */
        fun originAddress(): Optional<String> = originAddress.getOptional("origin_address")

        /**
         * Country code of the origin.
         *
         * @throws IncreaseInvalidDataException if the JSON field has an unexpected type (e.g. if
         *   the server responded with an unexpected value).
         */
        fun originCountryCode(): Optional<String> =
            originCountryCode.getOptional("origin_country_code")

        /**
         * Postal code of the origin.
         *
         * @throws IncreaseInvalidDataException if the JSON field has an unexpected type (e.g. if
         *   the server responded with an unexpected value).
         */
        fun originPostalCode(): Optional<String> =
            originPostalCode.getOptional("origin_postal_code")

        /**
         * Name of the sender at the origin.
         *
         * @throws IncreaseInvalidDataException if the JSON field has an unexpected type (e.g. if
         *   the server responded with an unexpected value).
         */
        fun originSenderName(): Optional<String> =
            originSenderName.getOptional("origin_sender_name")

        /**
         * Date the shipment should be picked up.
         *
         * @throws IncreaseInvalidDataException if the JSON field has an unexpected type (e.g. if
         *   the server responded with an unexpected value).
         */
        fun pickUpDate(): Optional<LocalDate> = pickUpDate.getOptional("pick_up_date")

        /**
         * Description of the shipping service.
         *
         * @throws IncreaseInvalidDataException if the JSON field has an unexpected type (e.g. if
         *   the server responded with an unexpected value).
         */
        fun serviceDescription(): Optional<String> =
            serviceDescription.getOptional("service_description")

        /**
         * Service level code for the shipment.
         *
         * @throws IncreaseInvalidDataException if the JSON field has an unexpected type (e.g. if
         *   the server responded with an unexpected value).
         */
        fun serviceLevelCode(): Optional<String> =
            serviceLevelCode.getOptional("service_level_code")

        /**
         * Name of the shipping courier.
         *
         * @throws IncreaseInvalidDataException if the JSON field has an unexpected type (e.g. if
         *   the server responded with an unexpected value).
         */
        fun shippingCourierName(): Optional<String> =
            shippingCourierName.getOptional("shipping_courier_name")

        /**
         * Tax amount for the shipment.
         *
         * @throws IncreaseInvalidDataException if the JSON field has an unexpected type (e.g. if
         *   the server responded with an unexpected value).
         */
        fun taxAmount(): Optional<Long> = taxAmount.getOptional("tax_amount")

        /**
         * Tracking number for the shipment.
         *
         * @throws IncreaseInvalidDataException if the JSON field has an unexpected type (e.g. if
         *   the server responded with an unexpected value).
         */
        fun trackingNumber(): Optional<String> = trackingNumber.getOptional("tracking_number")

        /**
         * Unit of measure for the shipment weight.
         *
         * @throws IncreaseInvalidDataException if the JSON field has an unexpected type (e.g. if
         *   the server responded with an unexpected value).
         */
        fun unitOfMeasure(): Optional<String> = unitOfMeasure.getOptional("unit_of_measure")

        /**
         * Weight of the shipment.
         *
         * @throws IncreaseInvalidDataException if the JSON field has an unexpected type (e.g. if
         *   the server responded with an unexpected value).
         */
        fun weight(): Optional<String> = weight.getOptional("weight")

        /**
         * Returns the raw JSON value of [customerReferenceNumber].
         *
         * Unlike [customerReferenceNumber], this method doesn't throw if the JSON field has an
         * unexpected type.
         */
        @JsonProperty("customer_reference_number")
        @ExcludeMissing
        fun _customerReferenceNumber(): JsonField<String> = customerReferenceNumber

        /**
         * Returns the raw JSON value of [destinationAddress].
         *
         * Unlike [destinationAddress], this method doesn't throw if the JSON field has an
         * unexpected type.
         */
        @JsonProperty("destination_address")
        @ExcludeMissing
        fun _destinationAddress(): JsonField<String> = destinationAddress

        /**
         * Returns the raw JSON value of [destinationCountryCode].
         *
         * Unlike [destinationCountryCode], this method doesn't throw if the JSON field has an
         * unexpected type.
         */
        @JsonProperty("destination_country_code")
        @ExcludeMissing
        fun _destinationCountryCode(): JsonField<String> = destinationCountryCode

        /**
         * Returns the raw JSON value of [destinationPostalCode].
         *
         * Unlike [destinationPostalCode], this method doesn't throw if the JSON field has an
         * unexpected type.
         */
        @JsonProperty("destination_postal_code")
        @ExcludeMissing
        fun _destinationPostalCode(): JsonField<String> = destinationPostalCode

        /**
         * Returns the raw JSON value of [destinationReceiverName].
         *
         * Unlike [destinationReceiverName], this method doesn't throw if the JSON field has an
         * unexpected type.
         */
        @JsonProperty("destination_receiver_name")
        @ExcludeMissing
        fun _destinationReceiverName(): JsonField<String> = destinationReceiverName

        /**
         * Returns the raw JSON value of [discountAmount].
         *
         * Unlike [discountAmount], this method doesn't throw if the JSON field has an unexpected
         * type.
         */
        @JsonProperty("discount_amount")
        @ExcludeMissing
        fun _discountAmount(): JsonField<Long> = discountAmount

        /**
         * Returns the raw JSON value of [netAmount].
         *
         * Unlike [netAmount], this method doesn't throw if the JSON field has an unexpected type.
         */
        @JsonProperty("net_amount") @ExcludeMissing fun _netAmount(): JsonField<Long> = netAmount

        /**
         * Returns the raw JSON value of [numberOfPackages].
         *
         * Unlike [numberOfPackages], this method doesn't throw if the JSON field has an unexpected
         * type.
         */
        @JsonProperty("number_of_packages")
        @ExcludeMissing
        fun _numberOfPackages(): JsonField<Long> = numberOfPackages

        /**
         * Returns the raw JSON value of [originAddress].
         *
         * Unlike [originAddress], this method doesn't throw if the JSON field has an unexpected
         * type.
         */
        @JsonProperty("origin_address")
        @ExcludeMissing
        fun _originAddress(): JsonField<String> = originAddress

        /**
         * Returns the raw JSON value of [originCountryCode].
         *
         * Unlike [originCountryCode], this method doesn't throw if the JSON field has an unexpected
         * type.
         */
        @JsonProperty("origin_country_code")
        @ExcludeMissing
        fun _originCountryCode(): JsonField<String> = originCountryCode

        /**
         * Returns the raw JSON value of [originPostalCode].
         *
         * Unlike [originPostalCode], this method doesn't throw if the JSON field has an unexpected
         * type.
         */
        @JsonProperty("origin_postal_code")
        @ExcludeMissing
        fun _originPostalCode(): JsonField<String> = originPostalCode

        /**
         * Returns the raw JSON value of [originSenderName].
         *
         * Unlike [originSenderName], this method doesn't throw if the JSON field has an unexpected
         * type.
         */
        @JsonProperty("origin_sender_name")
        @ExcludeMissing
        fun _originSenderName(): JsonField<String> = originSenderName

        /**
         * Returns the raw JSON value of [pickUpDate].
         *
         * Unlike [pickUpDate], this method doesn't throw if the JSON field has an unexpected type.
         */
        @JsonProperty("pick_up_date")
        @ExcludeMissing
        fun _pickUpDate(): JsonField<LocalDate> = pickUpDate

        /**
         * Returns the raw JSON value of [serviceDescription].
         *
         * Unlike [serviceDescription], this method doesn't throw if the JSON field has an
         * unexpected type.
         */
        @JsonProperty("service_description")
        @ExcludeMissing
        fun _serviceDescription(): JsonField<String> = serviceDescription

        /**
         * Returns the raw JSON value of [serviceLevelCode].
         *
         * Unlike [serviceLevelCode], this method doesn't throw if the JSON field has an unexpected
         * type.
         */
        @JsonProperty("service_level_code")
        @ExcludeMissing
        fun _serviceLevelCode(): JsonField<String> = serviceLevelCode

        /**
         * Returns the raw JSON value of [shippingCourierName].
         *
         * Unlike [shippingCourierName], this method doesn't throw if the JSON field has an
         * unexpected type.
         */
        @JsonProperty("shipping_courier_name")
        @ExcludeMissing
        fun _shippingCourierName(): JsonField<String> = shippingCourierName

        /**
         * Returns the raw JSON value of [taxAmount].
         *
         * Unlike [taxAmount], this method doesn't throw if the JSON field has an unexpected type.
         */
        @JsonProperty("tax_amount") @ExcludeMissing fun _taxAmount(): JsonField<Long> = taxAmount

        /**
         * Returns the raw JSON value of [trackingNumber].
         *
         * Unlike [trackingNumber], this method doesn't throw if the JSON field has an unexpected
         * type.
         */
        @JsonProperty("tracking_number")
        @ExcludeMissing
        fun _trackingNumber(): JsonField<String> = trackingNumber

        /**
         * Returns the raw JSON value of [unitOfMeasure].
         *
         * Unlike [unitOfMeasure], this method doesn't throw if the JSON field has an unexpected
         * type.
         */
        @JsonProperty("unit_of_measure")
        @ExcludeMissing
        fun _unitOfMeasure(): JsonField<String> = unitOfMeasure

        /**
         * Returns the raw JSON value of [weight].
         *
         * Unlike [weight], this method doesn't throw if the JSON field has an unexpected type.
         */
        @JsonProperty("weight") @ExcludeMissing fun _weight(): JsonField<String> = weight

        @JsonAnySetter
        private fun putAdditionalProperty(key: String, value: JsonValue) {
            additionalProperties.put(key, value)
        }

        @JsonAnyGetter
        @ExcludeMissing
        fun _additionalProperties(): Map<String, JsonValue> =
            Collections.unmodifiableMap(additionalProperties)

        fun toBuilder() = Builder().from(this)

        companion object {

            /**
             * Returns a mutable builder for constructing an instance of [Shipping].
             *
             * The following fields are required:
             * ```java
             * .customerReferenceNumber()
             * .destinationAddress()
             * .destinationCountryCode()
             * .destinationPostalCode()
             * .destinationReceiverName()
             * .discountAmount()
             * .netAmount()
             * .numberOfPackages()
             * .originAddress()
             * .originCountryCode()
             * .originPostalCode()
             * .originSenderName()
             * .pickUpDate()
             * .serviceDescription()
             * .serviceLevelCode()
             * .shippingCourierName()
             * .taxAmount()
             * .trackingNumber()
             * .unitOfMeasure()
             * .weight()
             * ```
             */
            @JvmStatic fun builder() = Builder()
        }

        /** A builder for [Shipping]. */
        class Builder internal constructor() {

            private var customerReferenceNumber: JsonField<String>? = null
            private var destinationAddress: JsonField<String>? = null
            private var destinationCountryCode: JsonField<String>? = null
            private var destinationPostalCode: JsonField<String>? = null
            private var destinationReceiverName: JsonField<String>? = null
            private var discountAmount: JsonField<Long>? = null
            private var netAmount: JsonField<Long>? = null
            private var numberOfPackages: JsonField<Long>? = null
            private var originAddress: JsonField<String>? = null
            private var originCountryCode: JsonField<String>? = null
            private var originPostalCode: JsonField<String>? = null
            private var originSenderName: JsonField<String>? = null
            private var pickUpDate: JsonField<LocalDate>? = null
            private var serviceDescription: JsonField<String>? = null
            private var serviceLevelCode: JsonField<String>? = null
            private var shippingCourierName: JsonField<String>? = null
            private var taxAmount: JsonField<Long>? = null
            private var trackingNumber: JsonField<String>? = null
            private var unitOfMeasure: JsonField<String>? = null
            private var weight: JsonField<String>? = null
            private var additionalProperties: MutableMap<String, JsonValue> = mutableMapOf()

            @JvmSynthetic
            internal fun from(shipping: Shipping) = apply {
                customerReferenceNumber = shipping.customerReferenceNumber
                destinationAddress = shipping.destinationAddress
                destinationCountryCode = shipping.destinationCountryCode
                destinationPostalCode = shipping.destinationPostalCode
                destinationReceiverName = shipping.destinationReceiverName
                discountAmount = shipping.discountAmount
                netAmount = shipping.netAmount
                numberOfPackages = shipping.numberOfPackages
                originAddress = shipping.originAddress
                originCountryCode = shipping.originCountryCode
                originPostalCode = shipping.originPostalCode
                originSenderName = shipping.originSenderName
                pickUpDate = shipping.pickUpDate
                serviceDescription = shipping.serviceDescription
                serviceLevelCode = shipping.serviceLevelCode
                shippingCourierName = shipping.shippingCourierName
                taxAmount = shipping.taxAmount
                trackingNumber = shipping.trackingNumber
                unitOfMeasure = shipping.unitOfMeasure
                weight = shipping.weight
                additionalProperties = shipping.additionalProperties.toMutableMap()
            }

            /** The customer reference number. */
            fun customerReferenceNumber(customerReferenceNumber: String?) =
                customerReferenceNumber(JsonField.ofNullable(customerReferenceNumber))

            /**
             * Alias for calling [Builder.customerReferenceNumber] with
             * `customerReferenceNumber.orElse(null)`.
             */
            fun customerReferenceNumber(customerReferenceNumber: Optional<String>) =
                customerReferenceNumber(customerReferenceNumber.getOrNull())

            /**
             * Sets [Builder.customerReferenceNumber] to an arbitrary JSON value.
             *
             * You should usually call [Builder.customerReferenceNumber] with a well-typed [String]
             * value instead. This method is primarily for setting the field to an undocumented or
             * not yet supported value.
             */
            fun customerReferenceNumber(customerReferenceNumber: JsonField<String>) = apply {
                this.customerReferenceNumber = customerReferenceNumber
            }

            /** Address of the destination. */
            fun destinationAddress(destinationAddress: String?) =
                destinationAddress(JsonField.ofNullable(destinationAddress))

            /**
             * Alias for calling [Builder.destinationAddress] with
             * `destinationAddress.orElse(null)`.
             */
            fun destinationAddress(destinationAddress: Optional<String>) =
                destinationAddress(destinationAddress.getOrNull())

            /**
             * Sets [Builder.destinationAddress] to an arbitrary JSON value.
             *
             * You should usually call [Builder.destinationAddress] with a well-typed [String] value
             * instead. This method is primarily for setting the field to an undocumented or not yet
             * supported value.
             */
            fun destinationAddress(destinationAddress: JsonField<String>) = apply {
                this.destinationAddress = destinationAddress
            }

            /** Country code of the destination. */
            fun destinationCountryCode(destinationCountryCode: String?) =
                destinationCountryCode(JsonField.ofNullable(destinationCountryCode))

            /**
             * Alias for calling [Builder.destinationCountryCode] with
             * `destinationCountryCode.orElse(null)`.
             */
            fun destinationCountryCode(destinationCountryCode: Optional<String>) =
                destinationCountryCode(destinationCountryCode.getOrNull())

            /**
             * Sets [Builder.destinationCountryCode] to an arbitrary JSON value.
             *
             * You should usually call [Builder.destinationCountryCode] with a well-typed [String]
             * value instead. This method is primarily for setting the field to an undocumented or
             * not yet supported value.
             */
            fun destinationCountryCode(destinationCountryCode: JsonField<String>) = apply {
                this.destinationCountryCode = destinationCountryCode
            }

            /** Postal code of the destination. */
            fun destinationPostalCode(destinationPostalCode: String?) =
                destinationPostalCode(JsonField.ofNullable(destinationPostalCode))

            /**
             * Alias for calling [Builder.destinationPostalCode] with
             * `destinationPostalCode.orElse(null)`.
             */
            fun destinationPostalCode(destinationPostalCode: Optional<String>) =
                destinationPostalCode(destinationPostalCode.getOrNull())

            /**
             * Sets [Builder.destinationPostalCode] to an arbitrary JSON value.
             *
             * You should usually call [Builder.destinationPostalCode] with a well-typed [String]
             * value instead. This method is primarily for setting the field to an undocumented or
             * not yet supported value.
             */
            fun destinationPostalCode(destinationPostalCode: JsonField<String>) = apply {
                this.destinationPostalCode = destinationPostalCode
            }

            /** Name of the receiver at the destination. */
            fun destinationReceiverName(destinationReceiverName: String?) =
                destinationReceiverName(JsonField.ofNullable(destinationReceiverName))

            /**
             * Alias for calling [Builder.destinationReceiverName] with
             * `destinationReceiverName.orElse(null)`.
             */
            fun destinationReceiverName(destinationReceiverName: Optional<String>) =
                destinationReceiverName(destinationReceiverName.getOrNull())

            /**
             * Sets [Builder.destinationReceiverName] to an arbitrary JSON value.
             *
             * You should usually call [Builder.destinationReceiverName] with a well-typed [String]
             * value instead. This method is primarily for setting the field to an undocumented or
             * not yet supported value.
             */
            fun destinationReceiverName(destinationReceiverName: JsonField<String>) = apply {
                this.destinationReceiverName = destinationReceiverName
            }

            /** Discount amount for the shipment. */
            fun discountAmount(discountAmount: Long?) =
                discountAmount(JsonField.ofNullable(discountAmount))

            /**
             * Alias for [Builder.discountAmount].
             *
             * This unboxed primitive overload exists for backwards compatibility.
             */
            fun discountAmount(discountAmount: Long) = discountAmount(discountAmount as Long?)

            /** Alias for calling [Builder.discountAmount] with `discountAmount.orElse(null)`. */
            fun discountAmount(discountAmount: Optional<Long>) =
                discountAmount(discountAmount.getOrNull())

            /**
             * Sets [Builder.discountAmount] to an arbitrary JSON value.
             *
             * You should usually call [Builder.discountAmount] with a well-typed [Long] value
             * instead. This method is primarily for setting the field to an undocumented or not yet
             * supported value.
             */
            fun discountAmount(discountAmount: JsonField<Long>) = apply {
                this.discountAmount = discountAmount
            }

            /** Net shipping amount. */
            fun netAmount(netAmount: Long?) = netAmount(JsonField.ofNullable(netAmount))

            /**
             * Alias for [Builder.netAmount].
             *
             * This unboxed primitive overload exists for backwards compatibility.
             */
            fun netAmount(netAmount: Long) = netAmount(netAmount as Long?)

            /** Alias for calling [Builder.netAmount] with `netAmount.orElse(null)`. */
            fun netAmount(netAmount: Optional<Long>) = netAmount(netAmount.getOrNull())

            /**
             * Sets [Builder.netAmount] to an arbitrary JSON value.
             *
             * You should usually call [Builder.netAmount] with a well-typed [Long] value instead.
             * This method is primarily for setting the field to an undocumented or not yet
             * supported value.
             */
            fun netAmount(netAmount: JsonField<Long>) = apply { this.netAmount = netAmount }

            /** Number of packages shipped. */
            fun numberOfPackages(numberOfPackages: Long?) =
                numberOfPackages(JsonField.ofNullable(numberOfPackages))

            /**
             * Alias for [Builder.numberOfPackages].
             *
             * This unboxed primitive overload exists for backwards compatibility.
             */
            fun numberOfPackages(numberOfPackages: Long) =
                numberOfPackages(numberOfPackages as Long?)

            /**
             * Alias for calling [Builder.numberOfPackages] with `numberOfPackages.orElse(null)`.
             */
            fun numberOfPackages(numberOfPackages: Optional<Long>) =
                numberOfPackages(numberOfPackages.getOrNull())

            /**
             * Sets [Builder.numberOfPackages] to an arbitrary JSON value.
             *
             * You should usually call [Builder.numberOfPackages] with a well-typed [Long] value
             * instead. This method is primarily for setting the field to an undocumented or not yet
             * supported value.
             */
            fun numberOfPackages(numberOfPackages: JsonField<Long>) = apply {
                this.numberOfPackages = numberOfPackages
            }

            /** Address of the origin. */
            fun originAddress(originAddress: String?) =
                originAddress(JsonField.ofNullable(originAddress))

            /** Alias for calling [Builder.originAddress] with `originAddress.orElse(null)`. */
            fun originAddress(originAddress: Optional<String>) =
                originAddress(originAddress.getOrNull())

            /**
             * Sets [Builder.originAddress] to an arbitrary JSON value.
             *
             * You should usually call [Builder.originAddress] with a well-typed [String] value
             * instead. This method is primarily for setting the field to an undocumented or not yet
             * supported value.
             */
            fun originAddress(originAddress: JsonField<String>) = apply {
                this.originAddress = originAddress
            }

            /** Country code of the origin. */
            fun originCountryCode(originCountryCode: String?) =
                originCountryCode(JsonField.ofNullable(originCountryCode))

            /**
             * Alias for calling [Builder.originCountryCode] with `originCountryCode.orElse(null)`.
             */
            fun originCountryCode(originCountryCode: Optional<String>) =
                originCountryCode(originCountryCode.getOrNull())

            /**
             * Sets [Builder.originCountryCode] to an arbitrary JSON value.
             *
             * You should usually call [Builder.originCountryCode] with a well-typed [String] value
             * instead. This method is primarily for setting the field to an undocumented or not yet
             * supported value.
             */
            fun originCountryCode(originCountryCode: JsonField<String>) = apply {
                this.originCountryCode = originCountryCode
            }

            /** Postal code of the origin. */
            fun originPostalCode(originPostalCode: String?) =
                originPostalCode(JsonField.ofNullable(originPostalCode))

            /**
             * Alias for calling [Builder.originPostalCode] with `originPostalCode.orElse(null)`.
             */
            fun originPostalCode(originPostalCode: Optional<String>) =
                originPostalCode(originPostalCode.getOrNull())

            /**
             * Sets [Builder.originPostalCode] to an arbitrary JSON value.
             *
             * You should usually call [Builder.originPostalCode] with a well-typed [String] value
             * instead. This method is primarily for setting the field to an undocumented or not yet
             * supported value.
             */
            fun originPostalCode(originPostalCode: JsonField<String>) = apply {
                this.originPostalCode = originPostalCode
            }

            /** Name of the sender at the origin. */
            fun originSenderName(originSenderName: String?) =
                originSenderName(JsonField.ofNullable(originSenderName))

            /**
             * Alias for calling [Builder.originSenderName] with `originSenderName.orElse(null)`.
             */
            fun originSenderName(originSenderName: Optional<String>) =
                originSenderName(originSenderName.getOrNull())

            /**
             * Sets [Builder.originSenderName] to an arbitrary JSON value.
             *
             * You should usually call [Builder.originSenderName] with a well-typed [String] value
             * instead. This method is primarily for setting the field to an undocumented or not yet
             * supported value.
             */
            fun originSenderName(originSenderName: JsonField<String>) = apply {
                this.originSenderName = originSenderName
            }

            /** Date the shipment should be picked up. */
            fun pickUpDate(pickUpDate: LocalDate?) = pickUpDate(JsonField.ofNullable(pickUpDate))

            /** Alias for calling [Builder.pickUpDate] with `pickUpDate.orElse(null)`. */
            fun pickUpDate(pickUpDate: Optional<LocalDate>) = pickUpDate(pickUpDate.getOrNull())

            /**
             * Sets [Builder.pickUpDate] to an arbitrary JSON value.
             *
             * You should usually call [Builder.pickUpDate] with a well-typed [LocalDate] value
             * instead. This method is primarily for setting the field to an undocumented or not yet
             * supported value.
             */
            fun pickUpDate(pickUpDate: JsonField<LocalDate>) = apply {
                this.pickUpDate = pickUpDate
            }

            /** Description of the shipping service. */
            fun serviceDescription(serviceDescription: String?) =
                serviceDescription(JsonField.ofNullable(serviceDescription))

            /**
             * Alias for calling [Builder.serviceDescription] with
             * `serviceDescription.orElse(null)`.
             */
            fun serviceDescription(serviceDescription: Optional<String>) =
                serviceDescription(serviceDescription.getOrNull())

            /**
             * Sets [Builder.serviceDescription] to an arbitrary JSON value.
             *
             * You should usually call [Builder.serviceDescription] with a well-typed [String] value
             * instead. This method is primarily for setting the field to an undocumented or not yet
             * supported value.
             */
            fun serviceDescription(serviceDescription: JsonField<String>) = apply {
                this.serviceDescription = serviceDescription
            }

            /** Service level code for the shipment. */
            fun serviceLevelCode(serviceLevelCode: String?) =
                serviceLevelCode(JsonField.ofNullable(serviceLevelCode))

            /**
             * Alias for calling [Builder.serviceLevelCode] with `serviceLevelCode.orElse(null)`.
             */
            fun serviceLevelCode(serviceLevelCode: Optional<String>) =
                serviceLevelCode(serviceLevelCode.getOrNull())

            /**
             * Sets [Builder.serviceLevelCode] to an arbitrary JSON value.
             *
             * You should usually call [Builder.serviceLevelCode] with a well-typed [String] value
             * instead. This method is primarily for setting the field to an undocumented or not yet
             * supported value.
             */
            fun serviceLevelCode(serviceLevelCode: JsonField<String>) = apply {
                this.serviceLevelCode = serviceLevelCode
            }

            /** Name of the shipping courier. */
            fun shippingCourierName(shippingCourierName: String?) =
                shippingCourierName(JsonField.ofNullable(shippingCourierName))

            /**
             * Alias for calling [Builder.shippingCourierName] with
             * `shippingCourierName.orElse(null)`.
             */
            fun shippingCourierName(shippingCourierName: Optional<String>) =
                shippingCourierName(shippingCourierName.getOrNull())

            /**
             * Sets [Builder.shippingCourierName] to an arbitrary JSON value.
             *
             * You should usually call [Builder.shippingCourierName] with a well-typed [String]
             * value instead. This method is primarily for setting the field to an undocumented or
             * not yet supported value.
             */
            fun shippingCourierName(shippingCourierName: JsonField<String>) = apply {
                this.shippingCourierName = shippingCourierName
            }

            /** Tax amount for the shipment. */
            fun taxAmount(taxAmount: Long?) = taxAmount(JsonField.ofNullable(taxAmount))

            /**
             * Alias for [Builder.taxAmount].
             *
             * This unboxed primitive overload exists for backwards compatibility.
             */
            fun taxAmount(taxAmount: Long) = taxAmount(taxAmount as Long?)

            /** Alias for calling [Builder.taxAmount] with `taxAmount.orElse(null)`. */
            fun taxAmount(taxAmount: Optional<Long>) = taxAmount(taxAmount.getOrNull())

            /**
             * Sets [Builder.taxAmount] to an arbitrary JSON value.
             *
             * You should usually call [Builder.taxAmount] with a well-typed [Long] value instead.
             * This method is primarily for setting the field to an undocumented or not yet
             * supported value.
             */
            fun taxAmount(taxAmount: JsonField<Long>) = apply { this.taxAmount = taxAmount }

            /** Tracking number for the shipment. */
            fun trackingNumber(trackingNumber: String?) =
                trackingNumber(JsonField.ofNullable(trackingNumber))

            /** Alias for calling [Builder.trackingNumber] with `trackingNumber.orElse(null)`. */
            fun trackingNumber(trackingNumber: Optional<String>) =
                trackingNumber(trackingNumber.getOrNull())

            /**
             * Sets [Builder.trackingNumber] to an arbitrary JSON value.
             *
             * You should usually call [Builder.trackingNumber] with a well-typed [String] value
             * instead. This method is primarily for setting the field to an undocumented or not yet
             * supported value.
             */
            fun trackingNumber(trackingNumber: JsonField<String>) = apply {
                this.trackingNumber = trackingNumber
            }

            /** Unit of measure for the shipment weight. */
            fun unitOfMeasure(unitOfMeasure: String?) =
                unitOfMeasure(JsonField.ofNullable(unitOfMeasure))

            /** Alias for calling [Builder.unitOfMeasure] with `unitOfMeasure.orElse(null)`. */
            fun unitOfMeasure(unitOfMeasure: Optional<String>) =
                unitOfMeasure(unitOfMeasure.getOrNull())

            /**
             * Sets [Builder.unitOfMeasure] to an arbitrary JSON value.
             *
             * You should usually call [Builder.unitOfMeasure] with a well-typed [String] value
             * instead. This method is primarily for setting the field to an undocumented or not yet
             * supported value.
             */
            fun unitOfMeasure(unitOfMeasure: JsonField<String>) = apply {
                this.unitOfMeasure = unitOfMeasure
            }

            /** Weight of the shipment. */
            fun weight(weight: String?) = weight(JsonField.ofNullable(weight))

            /** Alias for calling [Builder.weight] with `weight.orElse(null)`. */
            fun weight(weight: Optional<String>) = weight(weight.getOrNull())

            /**
             * Sets [Builder.weight] to an arbitrary JSON value.
             *
             * You should usually call [Builder.weight] with a well-typed [String] value instead.
             * This method is primarily for setting the field to an undocumented or not yet
             * supported value.
             */
            fun weight(weight: JsonField<String>) = apply { this.weight = weight }

            fun additionalProperties(additionalProperties: Map<String, JsonValue>) = apply {
                this.additionalProperties.clear()
                putAllAdditionalProperties(additionalProperties)
            }

            fun putAdditionalProperty(key: String, value: JsonValue) = apply {
                additionalProperties.put(key, value)
            }

            fun putAllAdditionalProperties(additionalProperties: Map<String, JsonValue>) = apply {
                this.additionalProperties.putAll(additionalProperties)
            }

            fun removeAdditionalProperty(key: String) = apply { additionalProperties.remove(key) }

            fun removeAllAdditionalProperties(keys: Set<String>) = apply {
                keys.forEach(::removeAdditionalProperty)
            }

            /**
             * Returns an immutable instance of [Shipping].
             *
             * Further updates to this [Builder] will not mutate the returned instance.
             *
             * The following fields are required:
             * ```java
             * .customerReferenceNumber()
             * .destinationAddress()
             * .destinationCountryCode()
             * .destinationPostalCode()
             * .destinationReceiverName()
             * .discountAmount()
             * .netAmount()
             * .numberOfPackages()
             * .originAddress()
             * .originCountryCode()
             * .originPostalCode()
             * .originSenderName()
             * .pickUpDate()
             * .serviceDescription()
             * .serviceLevelCode()
             * .shippingCourierName()
             * .taxAmount()
             * .trackingNumber()
             * .unitOfMeasure()
             * .weight()
             * ```
             *
             * @throws IllegalStateException if any required field is unset.
             */
            fun build(): Shipping =
                Shipping(
                    checkRequired("customerReferenceNumber", customerReferenceNumber),
                    checkRequired("destinationAddress", destinationAddress),
                    checkRequired("destinationCountryCode", destinationCountryCode),
                    checkRequired("destinationPostalCode", destinationPostalCode),
                    checkRequired("destinationReceiverName", destinationReceiverName),
                    checkRequired("discountAmount", discountAmount),
                    checkRequired("netAmount", netAmount),
                    checkRequired("numberOfPackages", numberOfPackages),
                    checkRequired("originAddress", originAddress),
                    checkRequired("originCountryCode", originCountryCode),
                    checkRequired("originPostalCode", originPostalCode),
                    checkRequired("originSenderName", originSenderName),
                    checkRequired("pickUpDate", pickUpDate),
                    checkRequired("serviceDescription", serviceDescription),
                    checkRequired("serviceLevelCode", serviceLevelCode),
                    checkRequired("shippingCourierName", shippingCourierName),
                    checkRequired("taxAmount", taxAmount),
                    checkRequired("trackingNumber", trackingNumber),
                    checkRequired("unitOfMeasure", unitOfMeasure),
                    checkRequired("weight", weight),
                    additionalProperties.toMutableMap(),
                )
        }

        private var validated: Boolean = false

        /**
         * Validates that the types of all values in this object match their expected types
         * recursively.
         *
         * This method is _not_ forwards compatible with new types from the API for existing fields.
         *
         * @throws IncreaseInvalidDataException if any value type in this object doesn't match its
         *   expected type.
         */
        fun validate(): Shipping = apply {
            if (validated) {
                return@apply
            }

            customerReferenceNumber()
            destinationAddress()
            destinationCountryCode()
            destinationPostalCode()
            destinationReceiverName()
            discountAmount()
            netAmount()
            numberOfPackages()
            originAddress()
            originCountryCode()
            originPostalCode()
            originSenderName()
            pickUpDate()
            serviceDescription()
            serviceLevelCode()
            shippingCourierName()
            taxAmount()
            trackingNumber()
            unitOfMeasure()
            weight()
            validated = true
        }

        fun isValid(): Boolean =
            try {
                validate()
                true
            } catch (e: IncreaseInvalidDataException) {
                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 (customerReferenceNumber.asKnown().isPresent) 1 else 0) +
                (if (destinationAddress.asKnown().isPresent) 1 else 0) +
                (if (destinationCountryCode.asKnown().isPresent) 1 else 0) +
                (if (destinationPostalCode.asKnown().isPresent) 1 else 0) +
                (if (destinationReceiverName.asKnown().isPresent) 1 else 0) +
                (if (discountAmount.asKnown().isPresent) 1 else 0) +
                (if (netAmount.asKnown().isPresent) 1 else 0) +
                (if (numberOfPackages.asKnown().isPresent) 1 else 0) +
                (if (originAddress.asKnown().isPresent) 1 else 0) +
                (if (originCountryCode.asKnown().isPresent) 1 else 0) +
                (if (originPostalCode.asKnown().isPresent) 1 else 0) +
                (if (originSenderName.asKnown().isPresent) 1 else 0) +
                (if (pickUpDate.asKnown().isPresent) 1 else 0) +
                (if (serviceDescription.asKnown().isPresent) 1 else 0) +
                (if (serviceLevelCode.asKnown().isPresent) 1 else 0) +
                (if (shippingCourierName.asKnown().isPresent) 1 else 0) +
                (if (taxAmount.asKnown().isPresent) 1 else 0) +
                (if (trackingNumber.asKnown().isPresent) 1 else 0) +
                (if (unitOfMeasure.asKnown().isPresent) 1 else 0) +
                (if (weight.asKnown().isPresent) 1 else 0)

        override fun equals(other: Any?): Boolean {
            if (this === other) {
                return true
            }

            return other is Shipping &&
                customerReferenceNumber == other.customerReferenceNumber &&
                destinationAddress == other.destinationAddress &&
                destinationCountryCode == other.destinationCountryCode &&
                destinationPostalCode == other.destinationPostalCode &&
                destinationReceiverName == other.destinationReceiverName &&
                discountAmount == other.discountAmount &&
                netAmount == other.netAmount &&
                numberOfPackages == other.numberOfPackages &&
                originAddress == other.originAddress &&
                originCountryCode == other.originCountryCode &&
                originPostalCode == other.originPostalCode &&
                originSenderName == other.originSenderName &&
                pickUpDate == other.pickUpDate &&
                serviceDescription == other.serviceDescription &&
                serviceLevelCode == other.serviceLevelCode &&
                shippingCourierName == other.shippingCourierName &&
                taxAmount == other.taxAmount &&
                trackingNumber == other.trackingNumber &&
                unitOfMeasure == other.unitOfMeasure &&
                weight == other.weight &&
                additionalProperties == other.additionalProperties
        }

        private val hashCode: Int by lazy {
            Objects.hash(
                customerReferenceNumber,
                destinationAddress,
                destinationCountryCode,
                destinationPostalCode,
                destinationReceiverName,
                discountAmount,
                netAmount,
                numberOfPackages,
                originAddress,
                originCountryCode,
                originPostalCode,
                originSenderName,
                pickUpDate,
                serviceDescription,
                serviceLevelCode,
                shippingCourierName,
                taxAmount,
                trackingNumber,
                unitOfMeasure,
                weight,
                additionalProperties,
            )
        }

        override fun hashCode(): Int = hashCode

        override fun toString() =
            "Shipping{customerReferenceNumber=$customerReferenceNumber, destinationAddress=$destinationAddress, destinationCountryCode=$destinationCountryCode, destinationPostalCode=$destinationPostalCode, destinationReceiverName=$destinationReceiverName, discountAmount=$discountAmount, netAmount=$netAmount, numberOfPackages=$numberOfPackages, originAddress=$originAddress, originCountryCode=$originCountryCode, originPostalCode=$originPostalCode, originSenderName=$originSenderName, pickUpDate=$pickUpDate, serviceDescription=$serviceDescription, serviceLevelCode=$serviceLevelCode, shippingCourierName=$shippingCourierName, taxAmount=$taxAmount, trackingNumber=$trackingNumber, unitOfMeasure=$unitOfMeasure, weight=$weight, additionalProperties=$additionalProperties}"
    }

    /**
     * A constant representing the object's type. For this resource it will always be
     * `card_purchase_supplement`.
     */
    class Type @JsonCreator private constructor(private val value: JsonField<String>) : 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<String> = value

        companion object {

            @JvmField val CARD_PURCHASE_SUPPLEMENT = of("card_purchase_supplement")

            @JvmStatic fun of(value: String) = Type(JsonField.of(value))
        }

        /** An enum containing [Type]'s known values. */
        enum class Known {
            CARD_PURCHASE_SUPPLEMENT
        }

        /**
         * An enum containing [Type]'s known values, as well as an [_UNKNOWN] member.
         *
         * An instance of [Type] 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 {
            CARD_PURCHASE_SUPPLEMENT,
            /** An enum member indicating that [Type] 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) {
                CARD_PURCHASE_SUPPLEMENT -> Value.CARD_PURCHASE_SUPPLEMENT
                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 IncreaseInvalidDataException if this class instance's value is a not a known
         *   member.
         */
        fun known(): Known =
            when (this) {
                CARD_PURCHASE_SUPPLEMENT -> Known.CARD_PURCHASE_SUPPLEMENT
                else -> throw IncreaseInvalidDataException("Unknown Type: $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 IncreaseInvalidDataException if this class instance's value does not have the
         *   expected primitive type.
         */
        fun asString(): String =
            _value().asString().orElseThrow {
                IncreaseInvalidDataException("Value is not a String")
            }

        private var validated: Boolean = false

        /**
         * Validates that the types of all values in this object match their expected types
         * recursively.
         *
         * This method is _not_ forwards compatible with new types from the API for existing fields.
         *
         * @throws IncreaseInvalidDataException if any value type in this object doesn't match its
         *   expected type.
         */
        fun validate(): Type = apply {
            if (validated) {
                return@apply
            }

            known()
            validated = true
        }

        fun isValid(): Boolean =
            try {
                validate()
                true
            } catch (e: IncreaseInvalidDataException) {
                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 Type && 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 CardPurchaseSupplement &&
            id == other.id &&
            cardPaymentId == other.cardPaymentId &&
            invoice == other.invoice &&
            lineItems == other.lineItems &&
            shipping == other.shipping &&
            transactionId == other.transactionId &&
            type == other.type &&
            additionalProperties == other.additionalProperties
    }

    private val hashCode: Int by lazy {
        Objects.hash(
            id,
            cardPaymentId,
            invoice,
            lineItems,
            shipping,
            transactionId,
            type,
            additionalProperties,
        )
    }

    override fun hashCode(): Int = hashCode

    override fun toString() =
        "CardPurchaseSupplement{id=$id, cardPaymentId=$cardPaymentId, invoice=$invoice, lineItems=$lineItems, shipping=$shipping, transactionId=$transactionId, type=$type, additionalProperties=$additionalProperties}"
}
