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

from __future__ import annotations
from .amount import Amount, AmountTypedDict
from .amount_nullable import AmountNullable, AmountNullableTypedDict
from .payment_method import PaymentMethod
from .url import URL, URLTypedDict
from .url_nullable import URLNullable, URLNullableTypedDict
from enum import Enum
from mollie import models, utils
from mollie.types import BaseModel, Nullable, OptionalNullable, UNSET, UNSET_SENTINEL
import pydantic
from pydantic import field_serializer, model_serializer
from typing import Dict, List, Optional
from typing_extensions import Annotated, NotRequired, TypedDict


class EntitySettlementStatus(str, Enum, metaclass=utils.OpenEnumMeta):
    r"""The status of the settlement."""

    OPEN = "open"
    PENDING = "pending"
    PAIDOUT = "paidout"
    FAILED = "failed"


class EntitySettlementAmountTypedDict(TypedDict):
    r"""The total amount of the settlement."""

    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 EntitySettlementAmount(BaseModel):
    r"""The total amount of the settlement."""

    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 EntitySettlementRateTypedDict(TypedDict):
    r"""The service rates, further divided into `fixed` and `percentage` costs."""

    fixed: NotRequired[AmountTypedDict]
    r"""In v2 endpoints, monetary amounts are represented as objects with a `currency` and `value` field."""
    percentage: NotRequired[str]


class EntitySettlementRate(BaseModel):
    r"""The service rates, further divided into `fixed` and `percentage` costs."""

    fixed: Optional[Amount] = None
    r"""In v2 endpoints, monetary amounts are represented as objects with a `currency` and `value` field."""

    percentage: Optional[str] = None

    @model_serializer(mode="wrap")
    def serialize_model(self, handler):
        optional_fields = set(["fixed", "percentage"])
        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 EntitySettlementCostTypedDict(TypedDict):
    description: str
    r"""A description of the cost subtotal"""
    method: Nullable[PaymentMethod]
    r"""The payment method, if applicable"""
    count: int
    r"""The number of fees"""
    rate: EntitySettlementRateTypedDict
    r"""The service rates, further divided into `fixed` and `percentage` costs."""
    amount_net: AmountTypedDict
    r"""In v2 endpoints, monetary amounts are represented as objects with a `currency` and `value` field."""
    amount_vat: Nullable[AmountNullableTypedDict]
    r"""In v2 endpoints, monetary amounts are represented as objects with a `currency` and `value` field."""
    amount_gross: AmountTypedDict
    r"""In v2 endpoints, monetary amounts are represented as objects with a `currency` and `value` field."""


class EntitySettlementCost(BaseModel):
    description: str
    r"""A description of the cost subtotal"""

    method: Nullable[PaymentMethod]
    r"""The payment method, if applicable"""

    count: int
    r"""The number of fees"""

    rate: EntitySettlementRate
    r"""The service rates, further divided into `fixed` and `percentage` costs."""

    amount_net: Annotated[Amount, pydantic.Field(alias="amountNet")]
    r"""In v2 endpoints, monetary amounts are represented as objects with a `currency` and `value` field."""

    amount_vat: Annotated[Nullable[AmountNullable], pydantic.Field(alias="amountVat")]
    r"""In v2 endpoints, monetary amounts are represented as objects with a `currency` and `value` field."""

    amount_gross: Annotated[Amount, pydantic.Field(alias="amountGross")]
    r"""In v2 endpoints, monetary amounts are represented as objects with a `currency` and `value` field."""

    @field_serializer("method")
    def serialize_method(self, value):
        if isinstance(value, str):
            try:
                return models.PaymentMethod(value)
            except ValueError:
                return value
        return value

    @model_serializer(mode="wrap")
    def serialize_model(self, handler):
        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:
                m[k] = val

        return m


class EntitySettlementRevenueTypedDict(TypedDict):
    description: str
    r"""A description of the revenue subtotal"""
    method: Nullable[PaymentMethod]
    r"""The payment method, if applicable"""
    count: int
    r"""The number of payments"""
    amount_net: AmountTypedDict
    r"""In v2 endpoints, monetary amounts are represented as objects with a `currency` and `value` field."""
    amount_vat: Nullable[AmountNullableTypedDict]
    r"""In v2 endpoints, monetary amounts are represented as objects with a `currency` and `value` field."""
    amount_gross: AmountTypedDict
    r"""In v2 endpoints, monetary amounts are represented as objects with a `currency` and `value` field."""


class EntitySettlementRevenue(BaseModel):
    description: str
    r"""A description of the revenue subtotal"""

    method: Nullable[PaymentMethod]
    r"""The payment method, if applicable"""

    count: int
    r"""The number of payments"""

    amount_net: Annotated[Amount, pydantic.Field(alias="amountNet")]
    r"""In v2 endpoints, monetary amounts are represented as objects with a `currency` and `value` field."""

    amount_vat: Annotated[Nullable[AmountNullable], pydantic.Field(alias="amountVat")]
    r"""In v2 endpoints, monetary amounts are represented as objects with a `currency` and `value` field."""

    amount_gross: Annotated[Amount, pydantic.Field(alias="amountGross")]
    r"""In v2 endpoints, monetary amounts are represented as objects with a `currency` and `value` field."""

    @field_serializer("method")
    def serialize_method(self, value):
        if isinstance(value, str):
            try:
                return models.PaymentMethod(value)
            except ValueError:
                return value
        return value

    @model_serializer(mode="wrap")
    def serialize_model(self, handler):
        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:
                m[k] = val

        return m


class EntitySettlementPeriodsTypedDict(TypedDict):
    costs: NotRequired[List[EntitySettlementCostTypedDict]]
    r"""An array of cost objects, describing the fees withheld for each payment method during this period."""
    revenue: NotRequired[List[EntitySettlementRevenueTypedDict]]
    r"""An array of revenue objects containing the total revenue for each payment method during this period."""
    invoice_id: NotRequired[str]
    invoice_reference: NotRequired[Nullable[str]]
    r"""The invoice reference, if the invoice has been created already."""


class EntitySettlementPeriods(BaseModel):
    costs: Optional[List[EntitySettlementCost]] = None
    r"""An array of cost objects, describing the fees withheld for each payment method during this period."""

    revenue: Optional[List[EntitySettlementRevenue]] = None
    r"""An array of revenue objects containing the total revenue for each payment method during this period."""

    invoice_id: Annotated[Optional[str], pydantic.Field(alias="invoiceId")] = None

    invoice_reference: Annotated[
        OptionalNullable[str], pydantic.Field(alias="invoiceReference")
    ] = UNSET
    r"""The invoice reference, if the invoice has been created already."""

    @model_serializer(mode="wrap")
    def serialize_model(self, handler):
        optional_fields = set(["costs", "revenue", "invoiceId", "invoiceReference"])
        nullable_fields = set(["invoiceReference"])
        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


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

    self_: URLTypedDict
    r"""In v2 endpoints, URLs are commonly represented as objects with an `href` and `type` field."""
    payments: NotRequired[URLTypedDict]
    r"""In v2 endpoints, URLs are commonly represented as objects with an `href` and `type` field."""
    captures: NotRequired[URLTypedDict]
    r"""In v2 endpoints, URLs are commonly represented as objects with an `href` and `type` field."""
    refunds: NotRequired[URLTypedDict]
    r"""In v2 endpoints, URLs are commonly represented as objects with an `href` and `type` field."""
    chargebacks: NotRequired[URLTypedDict]
    r"""In v2 endpoints, URLs are commonly represented as objects with an `href` and `type` field."""
    invoice: NotRequired[Nullable[URLNullableTypedDict]]
    r"""In v2 endpoints, URLs are commonly represented as objects with an `href` and `type` field."""
    documentation: NotRequired[URLTypedDict]
    r"""In v2 endpoints, URLs are commonly represented as objects with an `href` and `type` field."""


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

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

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

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

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

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

    invoice: OptionalNullable[URLNullable] = UNSET
    r"""In v2 endpoints, URLs are commonly represented as objects with an `href` and `type` field."""

    documentation: 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(
            [
                "payments",
                "captures",
                "refunds",
                "chargebacks",
                "invoice",
                "documentation",
            ]
        )
        nullable_fields = set(["invoice"])
        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


class EntitySettlementTypedDict(TypedDict):
    resource: str
    r"""Indicates the response contains a settlement object. Will always contain the string `settlement` for this
    endpoint.
    """
    id: str
    r"""The identifier uniquely referring to this settlement."""
    status: EntitySettlementStatus
    amount: EntitySettlementAmountTypedDict
    r"""The total amount of the settlement."""
    balance_id: str
    r"""The balance token that the settlement was settled to."""
    links: EntitySettlementLinksTypedDict
    r"""An object with several relevant URLs. Every URL object will contain an `href` and a `type` field."""
    created_at: NotRequired[str]
    r"""The entity's date and time of creation, in [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) format."""
    reference: NotRequired[Nullable[str]]
    r"""The settlement's bank reference, as found in your Mollie account and on your bank statement."""
    settled_at: NotRequired[Nullable[str]]
    r"""The date on which the settlement was settled, in ISO 8601 format.

    For an [open settlement](get-open-settlement) or for the [next settlement](get-next-settlement), no settlement
    date is available.
    """
    invoice_id: NotRequired[Nullable[str]]
    r"""The ID of the oldest invoice created for all the periods, if the invoice has been created yet."""
    periods: NotRequired[Dict[str, Dict[str, EntitySettlementPeriodsTypedDict]]]
    r"""For bookkeeping purposes, the settlement includes an overview of transactions included in the settlement. These
    transactions are grouped into 'period' objects — one for each calendar month.

    For example, if a settlement includes funds from 15 April until 4 May, it will include two period objects. One for
    all transactions processed between 15 April and 30 April, and one for all transactions between 1 May and 4 May.

    Period objects are grouped by year, and then by month. So in the above example, the full `periods` collection will
    look as follows: `{\"2024\": {\"04\": {...}, \"05\": {...}}}`. The year and month in this documentation are referred as `<year>` and `<month>`.

    The example response should give a good idea of what this looks like in practise.
    """


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

    id: str
    r"""The identifier uniquely referring to this settlement."""

    status: EntitySettlementStatus

    amount: EntitySettlementAmount
    r"""The total amount of the settlement."""

    balance_id: Annotated[str, pydantic.Field(alias="balanceId")]
    r"""The balance token that the settlement was settled to."""

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

    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."""

    reference: OptionalNullable[str] = UNSET
    r"""The settlement's bank reference, as found in your Mollie account and on your bank statement."""

    settled_at: Annotated[OptionalNullable[str], pydantic.Field(alias="settledAt")] = (
        UNSET
    )
    r"""The date on which the settlement was settled, in ISO 8601 format.

    For an [open settlement](get-open-settlement) or for the [next settlement](get-next-settlement), no settlement
    date is available.
    """

    invoice_id: Annotated[OptionalNullable[str], pydantic.Field(alias="invoiceId")] = (
        UNSET
    )
    r"""The ID of the oldest invoice created for all the periods, if the invoice has been created yet."""

    periods: Optional[Dict[str, Dict[str, EntitySettlementPeriods]]] = None
    r"""For bookkeeping purposes, the settlement includes an overview of transactions included in the settlement. These
    transactions are grouped into 'period' objects — one for each calendar month.

    For example, if a settlement includes funds from 15 April until 4 May, it will include two period objects. One for
    all transactions processed between 15 April and 30 April, and one for all transactions between 1 May and 4 May.

    Period objects are grouped by year, and then by month. So in the above example, the full `periods` collection will
    look as follows: `{\"2024\": {\"04\": {...}, \"05\": {...}}}`. The year and month in this documentation are referred as `<year>` and `<month>`.

    The example response should give a good idea of what this looks like in practise.
    """

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

    @model_serializer(mode="wrap")
    def serialize_model(self, handler):
        optional_fields = set(
            ["createdAt", "reference", "settledAt", "invoiceId", "periods"]
        )
        nullable_fields = set(["reference", "settledAt", "invoiceId"])
        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:
    EntitySettlementCost.model_rebuild()
except NameError:
    pass
try:
    EntitySettlementRevenue.model_rebuild()
except NameError:
    pass
try:
    EntitySettlementPeriods.model_rebuild()
except NameError:
    pass
try:
    EntitySettlementLinks.model_rebuild()
except NameError:
    pass
try:
    EntitySettlement.model_rebuild()
except NameError:
    pass
