# This file was auto-generated by Fern from our API Definition.

import typing
from ..core.client_wrapper import SyncClientWrapper
from ..core.request_options import RequestOptions
from .types.get_id_transactions_response import GetIdTransactionsResponse
from ..core.jsonable_encoder import jsonable_encoder
from ..core.pydantic_utilities import parse_obj_as
from ..errors.not_found_error import NotFoundError
from ..types.error import Error
from json.decoder import JSONDecodeError
from ..core.api_error import ApiError
import datetime as dt
from ..types.transaction_status import TransactionStatus
from ..types.transaction_transaction_type import TransactionTransactionType
from ..types.transaction_ledger_type import TransactionLedgerType
from ..types.transaction_direction import TransactionDirection
from ..types.transaction_categorization_status import TransactionCategorizationStatus
from ..types.transaction import Transaction
from ..errors.bad_request_error import BadRequestError
from .types.export_transaction_request_format import ExportTransactionRequestFormat
from .types.export_transaction_response import ExportTransactionResponse
from .types.get_transactions_by_month_response import GetTransactionsByMonthResponse
from ..core.serialization import convert_and_respect_annotation_metadata
from .types.suggest_transaction_categories_response_item import SuggestTransactionCategoriesResponseItem
from ..core.client_wrapper import AsyncClientWrapper

# this is used as the default value for optional parameters
OMIT = typing.cast(typing.Any, ...)


class TransactionsClient:
    def __init__(self, *, client_wrapper: SyncClientWrapper):
        self._client_wrapper = client_wrapper

    def get_transactions_by_company(
        self, id: str, *, request_options: typing.Optional[RequestOptions] = None
    ) -> GetIdTransactionsResponse:
        """
        Parameters
        ----------
        id : str
            Company ID

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        GetIdTransactionsResponse
            List of transactions

        Examples
        --------
        from openledger import OpenLedgerClient

        client = OpenLedgerClient(
            token="YOUR_TOKEN",
        )
        client.transactions.get_transactions_by_company(
            id="id",
        )
        """
        _response = self._client_wrapper.httpx_client.request(
            f"{jsonable_encoder(id)}/transactions",
            method="GET",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                return typing.cast(
                    GetIdTransactionsResponse,
                    parse_obj_as(
                        type_=GetIdTransactionsResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
            if _response.status_code == 404:
                raise NotFoundError(
                    typing.cast(
                        Error,
                        parse_obj_as(
                            type_=Error,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    def create_a_new_transaction(
        self,
        id_: str,
        *,
        id: typing.Optional[str] = OMIT,
        date: typing.Optional[dt.datetime] = OMIT,
        amount: typing.Optional[float] = OMIT,
        currency: typing.Optional[str] = OMIT,
        description: typing.Optional[str] = OMIT,
        status: typing.Optional[TransactionStatus] = OMIT,
        created_by: typing.Optional[int] = OMIT,
        updated_by: typing.Optional[int] = OMIT,
        created_at: typing.Optional[dt.datetime] = OMIT,
        updated_at: typing.Optional[dt.datetime] = OMIT,
        bank_transaction_id: typing.Optional[str] = OMIT,
        transaction_type: typing.Optional[TransactionTransactionType] = OMIT,
        ledger_type: typing.Optional[TransactionLedgerType] = OMIT,
        bank_account_id: typing.Optional[str] = OMIT,
        business_id: typing.Optional[str] = OMIT,
        direction: typing.Optional[TransactionDirection] = OMIT,
        balance: typing.Optional[float] = OMIT,
        counterparty_name: typing.Optional[str] = OMIT,
        categorization_status: typing.Optional[TransactionCategorizationStatus] = OMIT,
        category_id: typing.Optional[int] = OMIT,
        company_id: typing.Optional[str] = OMIT,
        metadata: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> Transaction:
        """
        Parameters
        ----------
        id_ : str
            Company ID

        id : typing.Optional[str]
            Unique identifier for the transaction

        date : typing.Optional[dt.datetime]
            Date of the transaction

        amount : typing.Optional[float]
            Amount of the transaction

        currency : typing.Optional[str]
            Currency of the transaction

        description : typing.Optional[str]
            Description of the transaction

        status : typing.Optional[TransactionStatus]
            Status of the transaction

        created_by : typing.Optional[int]
            ID of the user who created the transaction

        updated_by : typing.Optional[int]
            ID of the user who last updated the transaction

        created_at : typing.Optional[dt.datetime]
            Date when the transaction was created

        updated_at : typing.Optional[dt.datetime]
            Date when the transaction was last updated

        bank_transaction_id : typing.Optional[str]
            ID of the bank transaction

        transaction_type : typing.Optional[TransactionTransactionType]
            Type of transaction

        ledger_type : typing.Optional[TransactionLedgerType]
            Ledger type of the transaction

        bank_account_id : typing.Optional[str]
            ID of the bank account

        business_id : typing.Optional[str]
            ID of the business

        direction : typing.Optional[TransactionDirection]
            Direction of the transaction

        balance : typing.Optional[float]
            Balance after the transaction

        counterparty_name : typing.Optional[str]
            Name of the counterparty

        categorization_status : typing.Optional[TransactionCategorizationStatus]
            Status of categorization

        category_id : typing.Optional[int]
            ID of the category

        company_id : typing.Optional[str]
            ID of the company

        metadata : typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]]
            Additional metadata for the transaction

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        Transaction
            Transaction created successfully

        Examples
        --------
        from openledger import OpenLedgerClient

        client = OpenLedgerClient(
            token="YOUR_TOKEN",
        )
        client.transactions.create_a_new_transaction(
            id_="id",
        )
        """
        _response = self._client_wrapper.httpx_client.request(
            f"{jsonable_encoder(id_)}/transactions",
            method="POST",
            json={
                "id": id,
                "date": date,
                "amount": amount,
                "currency": currency,
                "description": description,
                "status": status,
                "created_by": created_by,
                "updated_by": updated_by,
                "created_at": created_at,
                "updated_at": updated_at,
                "bank_transaction_id": bank_transaction_id,
                "transaction_type": transaction_type,
                "ledger_type": ledger_type,
                "bank_account_id": bank_account_id,
                "business_id": business_id,
                "direction": direction,
                "balance": balance,
                "counterparty_name": counterparty_name,
                "categorizationStatus": categorization_status,
                "category_id": category_id,
                "company_id": company_id,
                "metadata": metadata,
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                return typing.cast(
                    Transaction,
                    parse_obj_as(
                        type_=Transaction,  # type: ignore
                        object_=_response.json(),
                    ),
                )
            if _response.status_code == 400:
                raise BadRequestError(
                    typing.cast(
                        Error,
                        parse_obj_as(
                            type_=Error,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 404:
                raise NotFoundError(
                    typing.cast(
                        Error,
                        parse_obj_as(
                            type_=Error,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    def edit_a_transaction(
        self,
        id_: str,
        transaction_id: str,
        *,
        id: typing.Optional[str] = OMIT,
        date: typing.Optional[dt.datetime] = OMIT,
        amount: typing.Optional[float] = OMIT,
        currency: typing.Optional[str] = OMIT,
        description: typing.Optional[str] = OMIT,
        status: typing.Optional[TransactionStatus] = OMIT,
        created_by: typing.Optional[int] = OMIT,
        updated_by: typing.Optional[int] = OMIT,
        created_at: typing.Optional[dt.datetime] = OMIT,
        updated_at: typing.Optional[dt.datetime] = OMIT,
        bank_transaction_id: typing.Optional[str] = OMIT,
        transaction_type: typing.Optional[TransactionTransactionType] = OMIT,
        ledger_type: typing.Optional[TransactionLedgerType] = OMIT,
        bank_account_id: typing.Optional[str] = OMIT,
        business_id: typing.Optional[str] = OMIT,
        direction: typing.Optional[TransactionDirection] = OMIT,
        balance: typing.Optional[float] = OMIT,
        counterparty_name: typing.Optional[str] = OMIT,
        categorization_status: typing.Optional[TransactionCategorizationStatus] = OMIT,
        category_id: typing.Optional[int] = OMIT,
        company_id: typing.Optional[str] = OMIT,
        metadata: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> Transaction:
        """
        Parameters
        ----------
        id_ : str
            Company ID

        transaction_id : str
            Transaction ID

        id : typing.Optional[str]
            Unique identifier for the transaction

        date : typing.Optional[dt.datetime]
            Date of the transaction

        amount : typing.Optional[float]
            Amount of the transaction

        currency : typing.Optional[str]
            Currency of the transaction

        description : typing.Optional[str]
            Description of the transaction

        status : typing.Optional[TransactionStatus]
            Status of the transaction

        created_by : typing.Optional[int]
            ID of the user who created the transaction

        updated_by : typing.Optional[int]
            ID of the user who last updated the transaction

        created_at : typing.Optional[dt.datetime]
            Date when the transaction was created

        updated_at : typing.Optional[dt.datetime]
            Date when the transaction was last updated

        bank_transaction_id : typing.Optional[str]
            ID of the bank transaction

        transaction_type : typing.Optional[TransactionTransactionType]
            Type of transaction

        ledger_type : typing.Optional[TransactionLedgerType]
            Ledger type of the transaction

        bank_account_id : typing.Optional[str]
            ID of the bank account

        business_id : typing.Optional[str]
            ID of the business

        direction : typing.Optional[TransactionDirection]
            Direction of the transaction

        balance : typing.Optional[float]
            Balance after the transaction

        counterparty_name : typing.Optional[str]
            Name of the counterparty

        categorization_status : typing.Optional[TransactionCategorizationStatus]
            Status of categorization

        category_id : typing.Optional[int]
            ID of the category

        company_id : typing.Optional[str]
            ID of the company

        metadata : typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]]
            Additional metadata for the transaction

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        Transaction
            Transaction updated successfully

        Examples
        --------
        from openledger import OpenLedgerClient

        client = OpenLedgerClient(
            token="YOUR_TOKEN",
        )
        client.transactions.edit_a_transaction(
            id_="id",
            transaction_id="transactionId",
        )
        """
        _response = self._client_wrapper.httpx_client.request(
            f"{jsonable_encoder(id_)}/transactions/{jsonable_encoder(transaction_id)}",
            method="PUT",
            json={
                "id": id,
                "date": date,
                "amount": amount,
                "currency": currency,
                "description": description,
                "status": status,
                "created_by": created_by,
                "updated_by": updated_by,
                "created_at": created_at,
                "updated_at": updated_at,
                "bank_transaction_id": bank_transaction_id,
                "transaction_type": transaction_type,
                "ledger_type": ledger_type,
                "bank_account_id": bank_account_id,
                "business_id": business_id,
                "direction": direction,
                "balance": balance,
                "counterparty_name": counterparty_name,
                "categorizationStatus": categorization_status,
                "category_id": category_id,
                "company_id": company_id,
                "metadata": metadata,
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                return typing.cast(
                    Transaction,
                    parse_obj_as(
                        type_=Transaction,  # type: ignore
                        object_=_response.json(),
                    ),
                )
            if _response.status_code == 400:
                raise BadRequestError(
                    typing.cast(
                        Error,
                        parse_obj_as(
                            type_=Error,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 404:
                raise NotFoundError(
                    typing.cast(
                        Error,
                        parse_obj_as(
                            type_=Error,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    def export_transaction(
        self,
        id: str,
        *,
        format: typing.Optional[ExportTransactionRequestFormat] = None,
        start_date: typing.Optional[str] = None,
        end_date: typing.Optional[str] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> ExportTransactionResponse:
        """
        Parameters
        ----------
        id : str
            Company ID

        format : typing.Optional[ExportTransactionRequestFormat]
            Export format

        start_date : typing.Optional[str]
            Start date for filtering transactions

        end_date : typing.Optional[str]
            End date for filtering transactions

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        ExportTransactionResponse
            Transactions exported successfully

        Examples
        --------
        from openledger import OpenLedgerClient

        client = OpenLedgerClient(
            token="YOUR_TOKEN",
        )
        client.transactions.export_transaction(
            id="id",
        )
        """
        _response = self._client_wrapper.httpx_client.request(
            f"{jsonable_encoder(id)}/transactions/export",
            method="GET",
            params={
                "format": format,
                "startDate": start_date,
                "endDate": end_date,
            },
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                return typing.cast(
                    ExportTransactionResponse,
                    parse_obj_as(
                        type_=ExportTransactionResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
            if _response.status_code == 400:
                raise BadRequestError(
                    typing.cast(
                        Error,
                        parse_obj_as(
                            type_=Error,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 404:
                raise NotFoundError(
                    typing.cast(
                        Error,
                        parse_obj_as(
                            type_=Error,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    def get_transactions_by_month(
        self, id: str, month: str, *, request_options: typing.Optional[RequestOptions] = None
    ) -> GetTransactionsByMonthResponse:
        """
        Parameters
        ----------
        id : str
            Company ID

        month : str
            Month in YYYY-MM format

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        GetTransactionsByMonthResponse
            List of transactions for the specified month

        Examples
        --------
        from openledger import OpenLedgerClient

        client = OpenLedgerClient(
            token="YOUR_TOKEN",
        )
        client.transactions.get_transactions_by_month(
            id="id",
            month="month",
        )
        """
        _response = self._client_wrapper.httpx_client.request(
            f"{jsonable_encoder(id)}/transactions/month/{jsonable_encoder(month)}",
            method="GET",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                return typing.cast(
                    GetTransactionsByMonthResponse,
                    parse_obj_as(
                        type_=GetTransactionsByMonthResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
            if _response.status_code == 400:
                raise BadRequestError(
                    typing.cast(
                        Error,
                        parse_obj_as(
                            type_=Error,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 404:
                raise NotFoundError(
                    typing.cast(
                        Error,
                        parse_obj_as(
                            type_=Error,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    def prompt_transaction(
        self, id: str, *, request_options: typing.Optional[RequestOptions] = None
    ) -> typing.Dict[str, typing.Optional[typing.Any]]:
        """
        Parameters
        ----------
        id : str
            Company ID

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        typing.Dict[str, typing.Optional[typing.Any]]
            Transaction prompt successful

        Examples
        --------
        from openledger import OpenLedgerClient

        client = OpenLedgerClient(
            token="YOUR_TOKEN",
        )
        client.transactions.prompt_transaction(
            id="id",
        )
        """
        _response = self._client_wrapper.httpx_client.request(
            f"{jsonable_encoder(id)}/transactions/prompt",
            method="GET",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                return typing.cast(
                    typing.Dict[str, typing.Optional[typing.Any]],
                    parse_obj_as(
                        type_=typing.Dict[str, typing.Optional[typing.Any]],  # type: ignore
                        object_=_response.json(),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    def classify_transaction(
        self, id: str, *, request_options: typing.Optional[RequestOptions] = None
    ) -> typing.List[Transaction]:
        """
        Parameters
        ----------
        id : str
            Company ID

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        typing.List[Transaction]
            Transactions classified successfully

        Examples
        --------
        from openledger import OpenLedgerClient

        client = OpenLedgerClient(
            token="YOUR_TOKEN",
        )
        client.transactions.classify_transaction(
            id="id",
        )
        """
        _response = self._client_wrapper.httpx_client.request(
            f"{jsonable_encoder(id)}/transactions/classify",
            method="GET",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                return typing.cast(
                    typing.List[Transaction],
                    parse_obj_as(
                        type_=typing.List[Transaction],  # type: ignore
                        object_=_response.json(),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    def generate_general_ledger(
        self, id: str, *, request_options: typing.Optional[RequestOptions] = None
    ) -> typing.Dict[str, typing.Optional[typing.Any]]:
        """
        Parameters
        ----------
        id : str
            Company ID

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        typing.Dict[str, typing.Optional[typing.Any]]
            General ledger generated successfully

        Examples
        --------
        from openledger import OpenLedgerClient

        client = OpenLedgerClient(
            token="YOUR_TOKEN",
        )
        client.transactions.generate_general_ledger(
            id="id",
        )
        """
        _response = self._client_wrapper.httpx_client.request(
            f"{jsonable_encoder(id)}/transactions/general-ledger",
            method="GET",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                return typing.cast(
                    typing.Dict[str, typing.Optional[typing.Any]],
                    parse_obj_as(
                        type_=typing.Dict[str, typing.Optional[typing.Any]],  # type: ignore
                        object_=_response.json(),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    def bulk_create_transactions(
        self, id: str, *, request: typing.Sequence[Transaction], request_options: typing.Optional[RequestOptions] = None
    ) -> typing.List[Transaction]:
        """
        Parameters
        ----------
        id : str
            Company ID

        request : typing.Sequence[Transaction]

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        typing.List[Transaction]
            Transactions created successfully

        Examples
        --------
        from openledger import OpenLedgerClient, Transaction

        client = OpenLedgerClient(
            token="YOUR_TOKEN",
        )
        client.transactions.bulk_create_transactions(
            id="id",
            request=[Transaction()],
        )
        """
        _response = self._client_wrapper.httpx_client.request(
            f"{jsonable_encoder(id)}/transactions/bulk",
            method="POST",
            json=convert_and_respect_annotation_metadata(
                object_=request, annotation=typing.Sequence[Transaction], direction="write"
            ),
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                return typing.cast(
                    typing.List[Transaction],
                    parse_obj_as(
                        type_=typing.List[Transaction],  # type: ignore
                        object_=_response.json(),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    def suggest_transaction_categories(
        self,
        id: str,
        *,
        transactions: typing.Optional[typing.Sequence[Transaction]] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> typing.List[SuggestTransactionCategoriesResponseItem]:
        """
        Parameters
        ----------
        id : str
            Company ID

        transactions : typing.Optional[typing.Sequence[Transaction]]

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        typing.List[SuggestTransactionCategoriesResponseItem]
            Categories suggested successfully

        Examples
        --------
        from openledger import OpenLedgerClient

        client = OpenLedgerClient(
            token="YOUR_TOKEN",
        )
        client.transactions.suggest_transaction_categories(
            id="id",
        )
        """
        _response = self._client_wrapper.httpx_client.request(
            f"{jsonable_encoder(id)}/transactions/suggest-categories",
            method="POST",
            json={
                "transactions": convert_and_respect_annotation_metadata(
                    object_=transactions, annotation=typing.Sequence[Transaction], direction="write"
                ),
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                return typing.cast(
                    typing.List[SuggestTransactionCategoriesResponseItem],
                    parse_obj_as(
                        type_=typing.List[SuggestTransactionCategoriesResponseItem],  # type: ignore
                        object_=_response.json(),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)


class AsyncTransactionsClient:
    def __init__(self, *, client_wrapper: AsyncClientWrapper):
        self._client_wrapper = client_wrapper

    async def get_transactions_by_company(
        self, id: str, *, request_options: typing.Optional[RequestOptions] = None
    ) -> GetIdTransactionsResponse:
        """
        Parameters
        ----------
        id : str
            Company ID

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        GetIdTransactionsResponse
            List of transactions

        Examples
        --------
        import asyncio

        from openledger import AsyncOpenLedgerClient

        client = AsyncOpenLedgerClient(
            token="YOUR_TOKEN",
        )


        async def main() -> None:
            await client.transactions.get_transactions_by_company(
                id="id",
            )


        asyncio.run(main())
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"{jsonable_encoder(id)}/transactions",
            method="GET",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                return typing.cast(
                    GetIdTransactionsResponse,
                    parse_obj_as(
                        type_=GetIdTransactionsResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
            if _response.status_code == 404:
                raise NotFoundError(
                    typing.cast(
                        Error,
                        parse_obj_as(
                            type_=Error,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    async def create_a_new_transaction(
        self,
        id_: str,
        *,
        id: typing.Optional[str] = OMIT,
        date: typing.Optional[dt.datetime] = OMIT,
        amount: typing.Optional[float] = OMIT,
        currency: typing.Optional[str] = OMIT,
        description: typing.Optional[str] = OMIT,
        status: typing.Optional[TransactionStatus] = OMIT,
        created_by: typing.Optional[int] = OMIT,
        updated_by: typing.Optional[int] = OMIT,
        created_at: typing.Optional[dt.datetime] = OMIT,
        updated_at: typing.Optional[dt.datetime] = OMIT,
        bank_transaction_id: typing.Optional[str] = OMIT,
        transaction_type: typing.Optional[TransactionTransactionType] = OMIT,
        ledger_type: typing.Optional[TransactionLedgerType] = OMIT,
        bank_account_id: typing.Optional[str] = OMIT,
        business_id: typing.Optional[str] = OMIT,
        direction: typing.Optional[TransactionDirection] = OMIT,
        balance: typing.Optional[float] = OMIT,
        counterparty_name: typing.Optional[str] = OMIT,
        categorization_status: typing.Optional[TransactionCategorizationStatus] = OMIT,
        category_id: typing.Optional[int] = OMIT,
        company_id: typing.Optional[str] = OMIT,
        metadata: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> Transaction:
        """
        Parameters
        ----------
        id_ : str
            Company ID

        id : typing.Optional[str]
            Unique identifier for the transaction

        date : typing.Optional[dt.datetime]
            Date of the transaction

        amount : typing.Optional[float]
            Amount of the transaction

        currency : typing.Optional[str]
            Currency of the transaction

        description : typing.Optional[str]
            Description of the transaction

        status : typing.Optional[TransactionStatus]
            Status of the transaction

        created_by : typing.Optional[int]
            ID of the user who created the transaction

        updated_by : typing.Optional[int]
            ID of the user who last updated the transaction

        created_at : typing.Optional[dt.datetime]
            Date when the transaction was created

        updated_at : typing.Optional[dt.datetime]
            Date when the transaction was last updated

        bank_transaction_id : typing.Optional[str]
            ID of the bank transaction

        transaction_type : typing.Optional[TransactionTransactionType]
            Type of transaction

        ledger_type : typing.Optional[TransactionLedgerType]
            Ledger type of the transaction

        bank_account_id : typing.Optional[str]
            ID of the bank account

        business_id : typing.Optional[str]
            ID of the business

        direction : typing.Optional[TransactionDirection]
            Direction of the transaction

        balance : typing.Optional[float]
            Balance after the transaction

        counterparty_name : typing.Optional[str]
            Name of the counterparty

        categorization_status : typing.Optional[TransactionCategorizationStatus]
            Status of categorization

        category_id : typing.Optional[int]
            ID of the category

        company_id : typing.Optional[str]
            ID of the company

        metadata : typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]]
            Additional metadata for the transaction

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        Transaction
            Transaction created successfully

        Examples
        --------
        import asyncio

        from openledger import AsyncOpenLedgerClient

        client = AsyncOpenLedgerClient(
            token="YOUR_TOKEN",
        )


        async def main() -> None:
            await client.transactions.create_a_new_transaction(
                id_="id",
            )


        asyncio.run(main())
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"{jsonable_encoder(id_)}/transactions",
            method="POST",
            json={
                "id": id,
                "date": date,
                "amount": amount,
                "currency": currency,
                "description": description,
                "status": status,
                "created_by": created_by,
                "updated_by": updated_by,
                "created_at": created_at,
                "updated_at": updated_at,
                "bank_transaction_id": bank_transaction_id,
                "transaction_type": transaction_type,
                "ledger_type": ledger_type,
                "bank_account_id": bank_account_id,
                "business_id": business_id,
                "direction": direction,
                "balance": balance,
                "counterparty_name": counterparty_name,
                "categorizationStatus": categorization_status,
                "category_id": category_id,
                "company_id": company_id,
                "metadata": metadata,
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                return typing.cast(
                    Transaction,
                    parse_obj_as(
                        type_=Transaction,  # type: ignore
                        object_=_response.json(),
                    ),
                )
            if _response.status_code == 400:
                raise BadRequestError(
                    typing.cast(
                        Error,
                        parse_obj_as(
                            type_=Error,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 404:
                raise NotFoundError(
                    typing.cast(
                        Error,
                        parse_obj_as(
                            type_=Error,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    async def edit_a_transaction(
        self,
        id_: str,
        transaction_id: str,
        *,
        id: typing.Optional[str] = OMIT,
        date: typing.Optional[dt.datetime] = OMIT,
        amount: typing.Optional[float] = OMIT,
        currency: typing.Optional[str] = OMIT,
        description: typing.Optional[str] = OMIT,
        status: typing.Optional[TransactionStatus] = OMIT,
        created_by: typing.Optional[int] = OMIT,
        updated_by: typing.Optional[int] = OMIT,
        created_at: typing.Optional[dt.datetime] = OMIT,
        updated_at: typing.Optional[dt.datetime] = OMIT,
        bank_transaction_id: typing.Optional[str] = OMIT,
        transaction_type: typing.Optional[TransactionTransactionType] = OMIT,
        ledger_type: typing.Optional[TransactionLedgerType] = OMIT,
        bank_account_id: typing.Optional[str] = OMIT,
        business_id: typing.Optional[str] = OMIT,
        direction: typing.Optional[TransactionDirection] = OMIT,
        balance: typing.Optional[float] = OMIT,
        counterparty_name: typing.Optional[str] = OMIT,
        categorization_status: typing.Optional[TransactionCategorizationStatus] = OMIT,
        category_id: typing.Optional[int] = OMIT,
        company_id: typing.Optional[str] = OMIT,
        metadata: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> Transaction:
        """
        Parameters
        ----------
        id_ : str
            Company ID

        transaction_id : str
            Transaction ID

        id : typing.Optional[str]
            Unique identifier for the transaction

        date : typing.Optional[dt.datetime]
            Date of the transaction

        amount : typing.Optional[float]
            Amount of the transaction

        currency : typing.Optional[str]
            Currency of the transaction

        description : typing.Optional[str]
            Description of the transaction

        status : typing.Optional[TransactionStatus]
            Status of the transaction

        created_by : typing.Optional[int]
            ID of the user who created the transaction

        updated_by : typing.Optional[int]
            ID of the user who last updated the transaction

        created_at : typing.Optional[dt.datetime]
            Date when the transaction was created

        updated_at : typing.Optional[dt.datetime]
            Date when the transaction was last updated

        bank_transaction_id : typing.Optional[str]
            ID of the bank transaction

        transaction_type : typing.Optional[TransactionTransactionType]
            Type of transaction

        ledger_type : typing.Optional[TransactionLedgerType]
            Ledger type of the transaction

        bank_account_id : typing.Optional[str]
            ID of the bank account

        business_id : typing.Optional[str]
            ID of the business

        direction : typing.Optional[TransactionDirection]
            Direction of the transaction

        balance : typing.Optional[float]
            Balance after the transaction

        counterparty_name : typing.Optional[str]
            Name of the counterparty

        categorization_status : typing.Optional[TransactionCategorizationStatus]
            Status of categorization

        category_id : typing.Optional[int]
            ID of the category

        company_id : typing.Optional[str]
            ID of the company

        metadata : typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]]
            Additional metadata for the transaction

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        Transaction
            Transaction updated successfully

        Examples
        --------
        import asyncio

        from openledger import AsyncOpenLedgerClient

        client = AsyncOpenLedgerClient(
            token="YOUR_TOKEN",
        )


        async def main() -> None:
            await client.transactions.edit_a_transaction(
                id_="id",
                transaction_id="transactionId",
            )


        asyncio.run(main())
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"{jsonable_encoder(id_)}/transactions/{jsonable_encoder(transaction_id)}",
            method="PUT",
            json={
                "id": id,
                "date": date,
                "amount": amount,
                "currency": currency,
                "description": description,
                "status": status,
                "created_by": created_by,
                "updated_by": updated_by,
                "created_at": created_at,
                "updated_at": updated_at,
                "bank_transaction_id": bank_transaction_id,
                "transaction_type": transaction_type,
                "ledger_type": ledger_type,
                "bank_account_id": bank_account_id,
                "business_id": business_id,
                "direction": direction,
                "balance": balance,
                "counterparty_name": counterparty_name,
                "categorizationStatus": categorization_status,
                "category_id": category_id,
                "company_id": company_id,
                "metadata": metadata,
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                return typing.cast(
                    Transaction,
                    parse_obj_as(
                        type_=Transaction,  # type: ignore
                        object_=_response.json(),
                    ),
                )
            if _response.status_code == 400:
                raise BadRequestError(
                    typing.cast(
                        Error,
                        parse_obj_as(
                            type_=Error,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 404:
                raise NotFoundError(
                    typing.cast(
                        Error,
                        parse_obj_as(
                            type_=Error,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    async def export_transaction(
        self,
        id: str,
        *,
        format: typing.Optional[ExportTransactionRequestFormat] = None,
        start_date: typing.Optional[str] = None,
        end_date: typing.Optional[str] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> ExportTransactionResponse:
        """
        Parameters
        ----------
        id : str
            Company ID

        format : typing.Optional[ExportTransactionRequestFormat]
            Export format

        start_date : typing.Optional[str]
            Start date for filtering transactions

        end_date : typing.Optional[str]
            End date for filtering transactions

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        ExportTransactionResponse
            Transactions exported successfully

        Examples
        --------
        import asyncio

        from openledger import AsyncOpenLedgerClient

        client = AsyncOpenLedgerClient(
            token="YOUR_TOKEN",
        )


        async def main() -> None:
            await client.transactions.export_transaction(
                id="id",
            )


        asyncio.run(main())
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"{jsonable_encoder(id)}/transactions/export",
            method="GET",
            params={
                "format": format,
                "startDate": start_date,
                "endDate": end_date,
            },
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                return typing.cast(
                    ExportTransactionResponse,
                    parse_obj_as(
                        type_=ExportTransactionResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
            if _response.status_code == 400:
                raise BadRequestError(
                    typing.cast(
                        Error,
                        parse_obj_as(
                            type_=Error,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 404:
                raise NotFoundError(
                    typing.cast(
                        Error,
                        parse_obj_as(
                            type_=Error,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    async def get_transactions_by_month(
        self, id: str, month: str, *, request_options: typing.Optional[RequestOptions] = None
    ) -> GetTransactionsByMonthResponse:
        """
        Parameters
        ----------
        id : str
            Company ID

        month : str
            Month in YYYY-MM format

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        GetTransactionsByMonthResponse
            List of transactions for the specified month

        Examples
        --------
        import asyncio

        from openledger import AsyncOpenLedgerClient

        client = AsyncOpenLedgerClient(
            token="YOUR_TOKEN",
        )


        async def main() -> None:
            await client.transactions.get_transactions_by_month(
                id="id",
                month="month",
            )


        asyncio.run(main())
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"{jsonable_encoder(id)}/transactions/month/{jsonable_encoder(month)}",
            method="GET",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                return typing.cast(
                    GetTransactionsByMonthResponse,
                    parse_obj_as(
                        type_=GetTransactionsByMonthResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
            if _response.status_code == 400:
                raise BadRequestError(
                    typing.cast(
                        Error,
                        parse_obj_as(
                            type_=Error,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 404:
                raise NotFoundError(
                    typing.cast(
                        Error,
                        parse_obj_as(
                            type_=Error,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    async def prompt_transaction(
        self, id: str, *, request_options: typing.Optional[RequestOptions] = None
    ) -> typing.Dict[str, typing.Optional[typing.Any]]:
        """
        Parameters
        ----------
        id : str
            Company ID

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        typing.Dict[str, typing.Optional[typing.Any]]
            Transaction prompt successful

        Examples
        --------
        import asyncio

        from openledger import AsyncOpenLedgerClient

        client = AsyncOpenLedgerClient(
            token="YOUR_TOKEN",
        )


        async def main() -> None:
            await client.transactions.prompt_transaction(
                id="id",
            )


        asyncio.run(main())
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"{jsonable_encoder(id)}/transactions/prompt",
            method="GET",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                return typing.cast(
                    typing.Dict[str, typing.Optional[typing.Any]],
                    parse_obj_as(
                        type_=typing.Dict[str, typing.Optional[typing.Any]],  # type: ignore
                        object_=_response.json(),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    async def classify_transaction(
        self, id: str, *, request_options: typing.Optional[RequestOptions] = None
    ) -> typing.List[Transaction]:
        """
        Parameters
        ----------
        id : str
            Company ID

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        typing.List[Transaction]
            Transactions classified successfully

        Examples
        --------
        import asyncio

        from openledger import AsyncOpenLedgerClient

        client = AsyncOpenLedgerClient(
            token="YOUR_TOKEN",
        )


        async def main() -> None:
            await client.transactions.classify_transaction(
                id="id",
            )


        asyncio.run(main())
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"{jsonable_encoder(id)}/transactions/classify",
            method="GET",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                return typing.cast(
                    typing.List[Transaction],
                    parse_obj_as(
                        type_=typing.List[Transaction],  # type: ignore
                        object_=_response.json(),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    async def generate_general_ledger(
        self, id: str, *, request_options: typing.Optional[RequestOptions] = None
    ) -> typing.Dict[str, typing.Optional[typing.Any]]:
        """
        Parameters
        ----------
        id : str
            Company ID

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        typing.Dict[str, typing.Optional[typing.Any]]
            General ledger generated successfully

        Examples
        --------
        import asyncio

        from openledger import AsyncOpenLedgerClient

        client = AsyncOpenLedgerClient(
            token="YOUR_TOKEN",
        )


        async def main() -> None:
            await client.transactions.generate_general_ledger(
                id="id",
            )


        asyncio.run(main())
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"{jsonable_encoder(id)}/transactions/general-ledger",
            method="GET",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                return typing.cast(
                    typing.Dict[str, typing.Optional[typing.Any]],
                    parse_obj_as(
                        type_=typing.Dict[str, typing.Optional[typing.Any]],  # type: ignore
                        object_=_response.json(),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    async def bulk_create_transactions(
        self, id: str, *, request: typing.Sequence[Transaction], request_options: typing.Optional[RequestOptions] = None
    ) -> typing.List[Transaction]:
        """
        Parameters
        ----------
        id : str
            Company ID

        request : typing.Sequence[Transaction]

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        typing.List[Transaction]
            Transactions created successfully

        Examples
        --------
        import asyncio

        from openledger import AsyncOpenLedgerClient, Transaction

        client = AsyncOpenLedgerClient(
            token="YOUR_TOKEN",
        )


        async def main() -> None:
            await client.transactions.bulk_create_transactions(
                id="id",
                request=[Transaction()],
            )


        asyncio.run(main())
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"{jsonable_encoder(id)}/transactions/bulk",
            method="POST",
            json=convert_and_respect_annotation_metadata(
                object_=request, annotation=typing.Sequence[Transaction], direction="write"
            ),
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                return typing.cast(
                    typing.List[Transaction],
                    parse_obj_as(
                        type_=typing.List[Transaction],  # type: ignore
                        object_=_response.json(),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    async def suggest_transaction_categories(
        self,
        id: str,
        *,
        transactions: typing.Optional[typing.Sequence[Transaction]] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> typing.List[SuggestTransactionCategoriesResponseItem]:
        """
        Parameters
        ----------
        id : str
            Company ID

        transactions : typing.Optional[typing.Sequence[Transaction]]

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        typing.List[SuggestTransactionCategoriesResponseItem]
            Categories suggested successfully

        Examples
        --------
        import asyncio

        from openledger import AsyncOpenLedgerClient

        client = AsyncOpenLedgerClient(
            token="YOUR_TOKEN",
        )


        async def main() -> None:
            await client.transactions.suggest_transaction_categories(
                id="id",
            )


        asyncio.run(main())
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"{jsonable_encoder(id)}/transactions/suggest-categories",
            method="POST",
            json={
                "transactions": convert_and_respect_annotation_metadata(
                    object_=transactions, annotation=typing.Sequence[Transaction], direction="write"
                ),
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                return typing.cast(
                    typing.List[SuggestTransactionCategoriesResponseItem],
                    parse_obj_as(
                        type_=typing.List[SuggestTransactionCategoriesResponseItem],  # type: ignore
                        object_=_response.json(),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)
