"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT."""
# @generated-id: ebc52c8aa67f

from __future__ import annotations
from .mode import Mode
from .sales_invoice_discount_response import (
    SalesInvoiceDiscountResponse,
    SalesInvoiceDiscountResponseTypedDict,
)
from .sales_invoice_email_details import (
    SalesInvoiceEmailDetails,
    SalesInvoiceEmailDetailsTypedDict,
)
from .sales_invoice_line_item_response import (
    SalesInvoiceLineItemResponse,
    SalesInvoiceLineItemResponseTypedDict,
)
from .sales_invoice_payment_details_response import (
    SalesInvoicePaymentDetailsResponse,
    SalesInvoicePaymentDetailsResponseTypedDict,
)
from .sales_invoice_payment_term_response import SalesInvoicePaymentTermResponse
from .sales_invoice_recipient_response import (
    SalesInvoiceRecipientResponse,
    SalesInvoiceRecipientResponseTypedDict,
)
from .sales_invoice_status_response import SalesInvoiceStatusResponse
from .sales_invoice_vat_mode_response import SalesInvoiceVatModeResponse
from .sales_invoice_vat_scheme_response import SalesInvoiceVatSchemeResponse
from .url import URL, URLTypedDict
from mollie import models
from mollie.types import BaseModel, Nullable, OptionalNullable, UNSET, UNSET_SENTINEL
import pydantic
from pydantic import field_serializer, model_serializer
from typing import List, Optional
from typing_extensions import Annotated, NotRequired, TypedDict


class ListSalesInvoiceResponseMetadataTypedDict(TypedDict):
    r"""Provide any data you like as a JSON object. We will save the data alongside the entity. Whenever
    you fetch the entity with our API, we will also include the metadata. You can use up to approximately 1kB.
    """


class ListSalesInvoiceResponseMetadata(BaseModel):
    r"""Provide any data you like as a JSON object. We will save the data alongside the entity. Whenever
    you fetch the entity with our API, we will also include the metadata. You can use up to approximately 1kB.
    """


class ListSalesInvoiceResponseAmountDueTypedDict(TypedDict):
    r"""The amount that is left to be paid."""

    currency: str
    r"""A three-character ISO 4217 currency code."""
    value: str
    r"""A string containing an exact monetary amount in the given currency."""


class ListSalesInvoiceResponseAmountDue(BaseModel):
    r"""The amount that is left to be paid."""

    currency: str
    r"""A three-character ISO 4217 currency code."""

    value: str
    r"""A string containing an exact monetary amount in the given currency."""


class ListSalesInvoiceResponseSubtotalAmountTypedDict(TypedDict):
    r"""The total amount without VAT before discounts."""

    currency: str
    r"""A three-character ISO 4217 currency code."""
    value: str
    r"""A string containing an exact monetary amount in the given currency."""


class ListSalesInvoiceResponseSubtotalAmount(BaseModel):
    r"""The total amount without VAT before discounts."""

    currency: str
    r"""A three-character ISO 4217 currency code."""

    value: str
    r"""A string containing an exact monetary amount in the given currency."""


class ListSalesInvoiceResponseTotalAmountTypedDict(TypedDict):
    r"""The total amount with VAT."""

    currency: str
    r"""A three-character ISO 4217 currency code."""
    value: str
    r"""A string containing an exact monetary amount in the given currency."""


class ListSalesInvoiceResponseTotalAmount(BaseModel):
    r"""The total amount with VAT."""

    currency: str
    r"""A three-character ISO 4217 currency code."""

    value: str
    r"""A string containing an exact monetary amount in the given currency."""


class ListSalesInvoiceResponseTotalVatAmountTypedDict(TypedDict):
    r"""The total VAT amount."""

    currency: str
    r"""A three-character ISO 4217 currency code."""
    value: str
    r"""A string containing an exact monetary amount in the given currency."""


class ListSalesInvoiceResponseTotalVatAmount(BaseModel):
    r"""The total VAT amount."""

    currency: str
    r"""A three-character ISO 4217 currency code."""

    value: str
    r"""A string containing an exact monetary amount in the given currency."""


class ListSalesInvoiceResponseDiscountedSubtotalAmountTypedDict(TypedDict):
    r"""The total amount without VAT after discounts."""

    currency: str
    r"""A three-character ISO 4217 currency code."""
    value: str
    r"""A string containing an exact monetary amount in the given currency."""


class ListSalesInvoiceResponseDiscountedSubtotalAmount(BaseModel):
    r"""The total amount without VAT after discounts."""

    currency: str
    r"""A three-character ISO 4217 currency code."""

    value: str
    r"""A string containing an exact monetary amount in the given currency."""


class ListSalesInvoiceResponseLinksTypedDict(TypedDict):
    r"""An object with several relevant URLs. Every URL object will contain an `href` and a `type` field."""

    self_: NotRequired[URLTypedDict]
    r"""In v2 endpoints, URLs are commonly represented as objects with an `href` and `type` field."""
    invoice_payment: NotRequired[URLTypedDict]
    r"""In v2 endpoints, URLs are commonly represented as objects with an `href` and `type` field."""
    pdf_link: NotRequired[URLTypedDict]
    r"""In v2 endpoints, URLs are commonly represented as objects with an `href` and `type` field."""
    next: NotRequired[URLTypedDict]
    r"""In v2 endpoints, URLs are commonly represented as objects with an `href` and `type` field."""
    previous: NotRequired[URLTypedDict]
    r"""In v2 endpoints, URLs are commonly represented as objects with an `href` and `type` field."""


class ListSalesInvoiceResponseLinks(BaseModel):
    r"""An object with several relevant URLs. Every URL object will contain an `href` and a `type` field."""

    self_: Annotated[Optional[URL], pydantic.Field(alias="self")] = None
    r"""In v2 endpoints, URLs are commonly represented as objects with an `href` and `type` field."""

    invoice_payment: Annotated[
        Optional[URL], pydantic.Field(alias="invoicePayment")
    ] = None
    r"""In v2 endpoints, URLs are commonly represented as objects with an `href` and `type` field."""

    pdf_link: Annotated[Optional[URL], pydantic.Field(alias="pdfLink")] = None
    r"""In v2 endpoints, URLs are commonly represented as objects with an `href` and `type` field."""

    next: Optional[URL] = None
    r"""In v2 endpoints, URLs are commonly represented as objects with an `href` and `type` field."""

    previous: Optional[URL] = None
    r"""In v2 endpoints, URLs are commonly represented as objects with an `href` and `type` field."""

    @model_serializer(mode="wrap")
    def serialize_model(self, handler):
        optional_fields = set(["self", "invoicePayment", "pdfLink", "next", "previous"])
        serialized = handler(self)
        m = {}

        for n, f in type(self).model_fields.items():
            k = f.alias or n
            val = serialized.get(k, serialized.get(n))

            if val != UNSET_SENTINEL:
                if val is not None or k not in optional_fields:
                    m[k] = val

        return m


class ListSalesInvoiceResponseTypedDict(TypedDict):
    resource: str
    r"""Indicates the response contains a sales invoice object. Will always contain the string `sales-invoice` for this
    endpoint.
    """
    id: str
    r"""The identifier uniquely referring to this invoice. Example: `invoice_4Y0eZitmBnQ6IDoMqZQKh`."""
    mode: Mode
    r"""Whether this entity was created in live mode or in test mode."""
    invoice_number: NotRequired[Nullable[str]]
    r"""When issued, an invoice number will be set for the sales invoice."""
    profile_id: NotRequired[Nullable[str]]
    r"""The identifier referring to the [profile](get-profile) this entity belongs to.

    Most API credentials are linked to a single profile. In these cases the `profileId` must not be sent in the creation
    request. For organization-level credentials such as OAuth access tokens however, the `profileId` parameter is
    required.
    """
    status: NotRequired[SalesInvoiceStatusResponse]
    r"""The status for the invoice to end up in.

    A `draft` invoice is not paid or not sent and can be updated after creation. Setting it to `issued` sends it to
    the recipient so they may then pay through our payment system. To skip our payment process, set this to `paid` to
    mark it as paid. It can then subsequently be sent as well, same as with `issued`.

    A status value that cannot be set but can be returned is `canceled`, for invoices which were
    issued, but then canceled. Currently this can only be done for invoices created in the dashboard.

    Dependent parameters:
    - `paymentDetails` is required if invoice should be set directly to `paid`
    - `customerId` and `mandateId` are required if a recurring payment should be used to set the invoice to `paid`
    - `emailDetails` optional for `issued` and `paid` to send the invoice by email
    """
    vat_scheme: NotRequired[SalesInvoiceVatSchemeResponse]
    r"""The VAT scheme to create the invoice for. You must be enrolled with One Stop Shop enabled to use it."""
    vat_mode: NotRequired[SalesInvoiceVatModeResponse]
    r"""The VAT mode to use for VAT calculation. `exclusive` mode means we will apply the relevant VAT on top of the
    price. `inclusive` means the prices you are providing to us already contain the VAT you want to apply.
    """
    memo: NotRequired[Nullable[str]]
    r"""A free-form memo you can set on the invoice, and will be shown on the invoice PDF."""
    metadata: NotRequired[Nullable[ListSalesInvoiceResponseMetadataTypedDict]]
    r"""Provide any data you like as a JSON object. We will save the data alongside the entity. Whenever
    you fetch the entity with our API, we will also include the metadata. You can use up to approximately 1kB.
    """
    payment_term: NotRequired[Nullable[SalesInvoicePaymentTermResponse]]
    r"""The payment term to be set on the invoice."""
    payment_details: NotRequired[SalesInvoicePaymentDetailsResponseTypedDict]
    email_details: NotRequired[Nullable[SalesInvoiceEmailDetailsTypedDict]]
    customer_id: NotRequired[str]
    r"""The identifier referring to the [customer](get-customer) you want to attempt an automated payment for. If
    provided, `mandateId` becomes required as well. Only allowed for invoices with status `paid`.
    """
    mandate_id: NotRequired[str]
    r"""The identifier referring to the [mandate](get-mandate) you want to use for the automated payment. If provided,
    `customerId` becomes required as well. Only allowed for invoices with status `paid`.
    """
    recipient_identifier: NotRequired[str]
    r"""An identifier tied to the recipient data. This should be a unique value based on data your system contains,
    so that both you and us know who we're referring to. It is a value you provide to us so that recipient management
    is not required to send a first invoice to a recipient.
    """
    recipient: NotRequired[Nullable[SalesInvoiceRecipientResponseTypedDict]]
    lines: NotRequired[Nullable[List[SalesInvoiceLineItemResponseTypedDict]]]
    r"""Provide the line items for the invoice. Each line contains details such as a description of the item
    ordered and its price.

    All lines must have the same currency as the invoice.
    """
    discount: NotRequired[Nullable[SalesInvoiceDiscountResponseTypedDict]]
    is_e_invoice: NotRequired[bool]
    r"""This indicates whether the invoice is an e-invoice. The default value is `false` and can't be changed
    after the invoice has been issued. When `emailDetails` is provided, an additional email is sent to the
    recipient.

    E-invoicing is only available for merchants based in Belgium, Germany, and the Netherlands, and only when
    the recipient is also located in one of these countries.
    """
    amount_due: NotRequired[ListSalesInvoiceResponseAmountDueTypedDict]
    r"""The amount that is left to be paid."""
    subtotal_amount: NotRequired[ListSalesInvoiceResponseSubtotalAmountTypedDict]
    r"""The total amount without VAT before discounts."""
    total_amount: NotRequired[ListSalesInvoiceResponseTotalAmountTypedDict]
    r"""The total amount with VAT."""
    total_vat_amount: NotRequired[ListSalesInvoiceResponseTotalVatAmountTypedDict]
    r"""The total VAT amount."""
    discounted_subtotal_amount: NotRequired[
        ListSalesInvoiceResponseDiscountedSubtotalAmountTypedDict
    ]
    r"""The total amount without VAT after discounts."""
    created_at: NotRequired[str]
    r"""The entity's date and time of creation, in [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) format."""
    issued_at: NotRequired[Nullable[str]]
    r"""If issued, the date when the sales invoice was issued, in [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601)
    format.
    """
    paid_at: NotRequired[Nullable[str]]
    r"""If paid, the date when the sales invoice was paid, in [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601)
    format.
    """
    due_at: NotRequired[Nullable[str]]
    r"""If issued, the date when the sales invoice payment is due, in [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601)
    format.
    """
    links: NotRequired[ListSalesInvoiceResponseLinksTypedDict]
    r"""An object with several relevant URLs. Every URL object will contain an `href` and a `type` field."""


class ListSalesInvoiceResponse(BaseModel):
    resource: str
    r"""Indicates the response contains a sales invoice object. Will always contain the string `sales-invoice` for this
    endpoint.
    """

    id: str
    r"""The identifier uniquely referring to this invoice. Example: `invoice_4Y0eZitmBnQ6IDoMqZQKh`."""

    mode: Mode
    r"""Whether this entity was created in live mode or in test mode."""

    invoice_number: Annotated[
        OptionalNullable[str], pydantic.Field(alias="invoiceNumber")
    ] = UNSET
    r"""When issued, an invoice number will be set for the sales invoice."""

    profile_id: Annotated[OptionalNullable[str], pydantic.Field(alias="profileId")] = (
        UNSET
    )
    r"""The identifier referring to the [profile](get-profile) this entity belongs to.

    Most API credentials are linked to a single profile. In these cases the `profileId` must not be sent in the creation
    request. For organization-level credentials such as OAuth access tokens however, the `profileId` parameter is
    required.
    """

    status: Optional[SalesInvoiceStatusResponse] = None
    r"""The status for the invoice to end up in.

    A `draft` invoice is not paid or not sent and can be updated after creation. Setting it to `issued` sends it to
    the recipient so they may then pay through our payment system. To skip our payment process, set this to `paid` to
    mark it as paid. It can then subsequently be sent as well, same as with `issued`.

    A status value that cannot be set but can be returned is `canceled`, for invoices which were
    issued, but then canceled. Currently this can only be done for invoices created in the dashboard.

    Dependent parameters:
    - `paymentDetails` is required if invoice should be set directly to `paid`
    - `customerId` and `mandateId` are required if a recurring payment should be used to set the invoice to `paid`
    - `emailDetails` optional for `issued` and `paid` to send the invoice by email
    """

    vat_scheme: Annotated[
        Optional[SalesInvoiceVatSchemeResponse], pydantic.Field(alias="vatScheme")
    ] = None
    r"""The VAT scheme to create the invoice for. You must be enrolled with One Stop Shop enabled to use it."""

    vat_mode: Annotated[
        Optional[SalesInvoiceVatModeResponse], pydantic.Field(alias="vatMode")
    ] = None
    r"""The VAT mode to use for VAT calculation. `exclusive` mode means we will apply the relevant VAT on top of the
    price. `inclusive` means the prices you are providing to us already contain the VAT you want to apply.
    """

    memo: OptionalNullable[str] = UNSET
    r"""A free-form memo you can set on the invoice, and will be shown on the invoice PDF."""

    metadata: OptionalNullable[ListSalesInvoiceResponseMetadata] = UNSET
    r"""Provide any data you like as a JSON object. We will save the data alongside the entity. Whenever
    you fetch the entity with our API, we will also include the metadata. You can use up to approximately 1kB.
    """

    payment_term: Annotated[
        OptionalNullable[SalesInvoicePaymentTermResponse],
        pydantic.Field(alias="paymentTerm"),
    ] = UNSET
    r"""The payment term to be set on the invoice."""

    payment_details: Annotated[
        Optional[SalesInvoicePaymentDetailsResponse],
        pydantic.Field(alias="paymentDetails"),
    ] = None

    email_details: Annotated[
        OptionalNullable[SalesInvoiceEmailDetails], pydantic.Field(alias="emailDetails")
    ] = UNSET

    customer_id: Annotated[Optional[str], pydantic.Field(alias="customerId")] = None
    r"""The identifier referring to the [customer](get-customer) you want to attempt an automated payment for. If
    provided, `mandateId` becomes required as well. Only allowed for invoices with status `paid`.
    """

    mandate_id: Annotated[Optional[str], pydantic.Field(alias="mandateId")] = None
    r"""The identifier referring to the [mandate](get-mandate) you want to use for the automated payment. If provided,
    `customerId` becomes required as well. Only allowed for invoices with status `paid`.
    """

    recipient_identifier: Annotated[
        Optional[str], pydantic.Field(alias="recipientIdentifier")
    ] = None
    r"""An identifier tied to the recipient data. This should be a unique value based on data your system contains,
    so that both you and us know who we're referring to. It is a value you provide to us so that recipient management
    is not required to send a first invoice to a recipient.
    """

    recipient: OptionalNullable[SalesInvoiceRecipientResponse] = UNSET

    lines: OptionalNullable[List[SalesInvoiceLineItemResponse]] = UNSET
    r"""Provide the line items for the invoice. Each line contains details such as a description of the item
    ordered and its price.

    All lines must have the same currency as the invoice.
    """

    discount: OptionalNullable[SalesInvoiceDiscountResponse] = UNSET

    is_e_invoice: Annotated[Optional[bool], pydantic.Field(alias="isEInvoice")] = None
    r"""This indicates whether the invoice is an e-invoice. The default value is `false` and can't be changed
    after the invoice has been issued. When `emailDetails` is provided, an additional email is sent to the
    recipient.

    E-invoicing is only available for merchants based in Belgium, Germany, and the Netherlands, and only when
    the recipient is also located in one of these countries.
    """

    amount_due: Annotated[
        Optional[ListSalesInvoiceResponseAmountDue], pydantic.Field(alias="amountDue")
    ] = None
    r"""The amount that is left to be paid."""

    subtotal_amount: Annotated[
        Optional[ListSalesInvoiceResponseSubtotalAmount],
        pydantic.Field(alias="subtotalAmount"),
    ] = None
    r"""The total amount without VAT before discounts."""

    total_amount: Annotated[
        Optional[ListSalesInvoiceResponseTotalAmount],
        pydantic.Field(alias="totalAmount"),
    ] = None
    r"""The total amount with VAT."""

    total_vat_amount: Annotated[
        Optional[ListSalesInvoiceResponseTotalVatAmount],
        pydantic.Field(alias="totalVatAmount"),
    ] = None
    r"""The total VAT amount."""

    discounted_subtotal_amount: Annotated[
        Optional[ListSalesInvoiceResponseDiscountedSubtotalAmount],
        pydantic.Field(alias="discountedSubtotalAmount"),
    ] = None
    r"""The total amount without VAT after discounts."""

    created_at: Annotated[Optional[str], pydantic.Field(alias="createdAt")] = None
    r"""The entity's date and time of creation, in [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) format."""

    issued_at: Annotated[OptionalNullable[str], pydantic.Field(alias="issuedAt")] = (
        UNSET
    )
    r"""If issued, the date when the sales invoice was issued, in [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601)
    format.
    """

    paid_at: Annotated[OptionalNullable[str], pydantic.Field(alias="paidAt")] = UNSET
    r"""If paid, the date when the sales invoice was paid, in [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601)
    format.
    """

    due_at: Annotated[OptionalNullable[str], pydantic.Field(alias="dueAt")] = UNSET
    r"""If issued, the date when the sales invoice payment is due, in [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601)
    format.
    """

    links: Annotated[
        Optional[ListSalesInvoiceResponseLinks], pydantic.Field(alias="_links")
    ] = None
    r"""An object with several relevant URLs. Every URL object will contain an `href` and a `type` field."""

    @field_serializer("mode")
    def serialize_mode(self, value):
        if isinstance(value, str):
            try:
                return models.Mode(value)
            except ValueError:
                return value
        return value

    @field_serializer("status")
    def serialize_status(self, value):
        if isinstance(value, str):
            try:
                return models.SalesInvoiceStatusResponse(value)
            except ValueError:
                return value
        return value

    @field_serializer("vat_scheme")
    def serialize_vat_scheme(self, value):
        if isinstance(value, str):
            try:
                return models.SalesInvoiceVatSchemeResponse(value)
            except ValueError:
                return value
        return value

    @field_serializer("vat_mode")
    def serialize_vat_mode(self, value):
        if isinstance(value, str):
            try:
                return models.SalesInvoiceVatModeResponse(value)
            except ValueError:
                return value
        return value

    @field_serializer("payment_term")
    def serialize_payment_term(self, value):
        if isinstance(value, str):
            try:
                return models.SalesInvoicePaymentTermResponse(value)
            except ValueError:
                return value
        return value

    @model_serializer(mode="wrap")
    def serialize_model(self, handler):
        optional_fields = set(
            [
                "invoiceNumber",
                "profileId",
                "status",
                "vatScheme",
                "vatMode",
                "memo",
                "metadata",
                "paymentTerm",
                "paymentDetails",
                "emailDetails",
                "customerId",
                "mandateId",
                "recipientIdentifier",
                "recipient",
                "lines",
                "discount",
                "isEInvoice",
                "amountDue",
                "subtotalAmount",
                "totalAmount",
                "totalVatAmount",
                "discountedSubtotalAmount",
                "createdAt",
                "issuedAt",
                "paidAt",
                "dueAt",
                "_links",
            ]
        )
        nullable_fields = set(
            [
                "invoiceNumber",
                "profileId",
                "memo",
                "metadata",
                "paymentTerm",
                "emailDetails",
                "recipient",
                "lines",
                "discount",
                "issuedAt",
                "paidAt",
                "dueAt",
            ]
        )
        serialized = handler(self)
        m = {}

        for n, f in type(self).model_fields.items():
            k = f.alias or n
            val = serialized.get(k, serialized.get(n))
            is_nullable_and_explicitly_set = (
                k in nullable_fields
                and (self.__pydantic_fields_set__.intersection({n}))  # pylint: disable=no-member
            )

            if val != UNSET_SENTINEL:
                if (
                    val is not None
                    or k not in optional_fields
                    or is_nullable_and_explicitly_set
                ):
                    m[k] = val

        return m


try:
    ListSalesInvoiceResponseLinks.model_rebuild()
except NameError:
    pass
try:
    ListSalesInvoiceResponse.model_rebuild()
except NameError:
    pass
