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

import typing
from json.decoder import JSONDecodeError

from ..core.api_error import ApiError
from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper
from ..core.http_response import AsyncHttpResponse, HttpResponse
from ..core.jsonable_encoder import jsonable_encoder
from ..core.pydantic_utilities import parse_obj_as
from ..core.request_options import RequestOptions
from ..errors.bad_request_error import BadRequestError
from ..errors.internal_server_error import InternalServerError
from ..errors.service_unavailable_error import ServiceUnavailableError
from ..errors.unauthorized_error import UnauthorizedError
from ..types.item_commodity_code import ItemCommodityCode
from ..types.item_description import ItemDescription
from ..types.item_product_code import ItemProductCode
from ..types.item_product_name import ItemProductName
from ..types.item_unitof_measure import ItemUnitofMeasure
from ..types.line_item_query_record import LineItemQueryRecord
from ..types.payabli_api_response import PayabliApiResponse
from ..types.payabli_api_response_6 import PayabliApiResponse6
from ..types.query_response_items import QueryResponseItems
from .types.delete_item_response import DeleteItemResponse

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


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

    def add_item(
        self,
        entry: str,
        *,
        item_cost: float,
        item_qty: int,
        idempotency_key: typing.Optional[str] = None,
        item_categories: typing.Optional[typing.Sequence[typing.Optional[str]]] = OMIT,
        item_commodity_code: typing.Optional[ItemCommodityCode] = OMIT,
        item_description: typing.Optional[ItemDescription] = OMIT,
        item_mode: typing.Optional[int] = OMIT,
        item_product_code: typing.Optional[ItemProductCode] = OMIT,
        item_product_name: typing.Optional[ItemProductName] = OMIT,
        item_unit_of_measure: typing.Optional[ItemUnitofMeasure] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> HttpResponse[PayabliApiResponse6]:
        """
        Adds products and services to an entrypoint's catalog. These are used as line items for invoicing and transactions. In the response, "responseData" displays the item's code.

        Parameters
        ----------
        entry : str
            The paypoint's entrypoint identifier. [Learn more](/api-reference/api-overview#entrypoint-vs-entry)

        item_cost : float
            Item or product price per unit.

        item_qty : int
            Quantity of item or product.

        idempotency_key : typing.Optional[str]
            A unique ID you can include to prevent duplicating objects or transactions if a request is sent more than once. This key isn't generated in Payabli, you must generate it yourself.

        item_categories : typing.Optional[typing.Sequence[typing.Optional[str]]]
            Array of tags classifying item or product.

        item_commodity_code : typing.Optional[ItemCommodityCode]

        item_description : typing.Optional[ItemDescription]

        item_mode : typing.Optional[int]
            Internal class of item or product: value '0' is only for invoices, '1' for bills, and '2' is common for both.

        item_product_code : typing.Optional[ItemProductCode]

        item_product_name : typing.Optional[ItemProductName]

        item_unit_of_measure : typing.Optional[ItemUnitofMeasure]

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

        Returns
        -------
        HttpResponse[PayabliApiResponse6]
            Success
        """
        _response = self._client_wrapper.httpx_client.request(
            f"LineItem/{jsonable_encoder(entry)}",
            method="POST",
            json={
                "itemCategories": item_categories,
                "itemCommodityCode": item_commodity_code,
                "itemCost": item_cost,
                "itemDescription": item_description,
                "itemMode": item_mode,
                "itemProductCode": item_product_code,
                "itemProductName": item_product_name,
                "itemQty": item_qty,
                "itemUnitOfMeasure": item_unit_of_measure,
            },
            headers={
                "content-type": "application/json",
                "idempotencyKey": str(idempotency_key) if idempotency_key is not None else None,
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    PayabliApiResponse6,
                    parse_obj_as(
                        type_=PayabliApiResponse6,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            if _response.status_code == 400:
                raise BadRequestError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 401:
                raise UnauthorizedError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 500:
                raise InternalServerError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 503:
                raise ServiceUnavailableError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        PayabliApiResponse,
                        parse_obj_as(
                            type_=PayabliApiResponse,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    def delete_item(
        self, line_item_id: int, *, request_options: typing.Optional[RequestOptions] = None
    ) -> HttpResponse[DeleteItemResponse]:
        """
        Deletes an item.

        Parameters
        ----------
        line_item_id : int
            ID for the line item (also known as a product, service, or item).

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

        Returns
        -------
        HttpResponse[DeleteItemResponse]
            Success
        """
        _response = self._client_wrapper.httpx_client.request(
            f"LineItem/{jsonable_encoder(line_item_id)}",
            method="DELETE",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    DeleteItemResponse,
                    parse_obj_as(
                        type_=DeleteItemResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            if _response.status_code == 400:
                raise BadRequestError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 401:
                raise UnauthorizedError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 500:
                raise InternalServerError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 503:
                raise ServiceUnavailableError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        PayabliApiResponse,
                        parse_obj_as(
                            type_=PayabliApiResponse,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    def get_item(
        self, line_item_id: int, *, request_options: typing.Optional[RequestOptions] = None
    ) -> HttpResponse[LineItemQueryRecord]:
        """
        Gets an item by ID.

        Parameters
        ----------
        line_item_id : int
            ID for the line item (also known as a product, service, or item).

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

        Returns
        -------
        HttpResponse[LineItemQueryRecord]
            Success
        """
        _response = self._client_wrapper.httpx_client.request(
            f"LineItem/{jsonable_encoder(line_item_id)}",
            method="GET",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    LineItemQueryRecord,
                    parse_obj_as(
                        type_=LineItemQueryRecord,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            if _response.status_code == 400:
                raise BadRequestError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 401:
                raise UnauthorizedError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 500:
                raise InternalServerError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 503:
                raise ServiceUnavailableError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        PayabliApiResponse,
                        parse_obj_as(
                            type_=PayabliApiResponse,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    def list_line_items(
        self,
        entry: str,
        *,
        from_record: typing.Optional[int] = None,
        limit_record: typing.Optional[int] = None,
        parameters: typing.Optional[typing.Dict[str, typing.Optional[str]]] = None,
        sort_by: typing.Optional[str] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> HttpResponse[QueryResponseItems]:
        """
        Retrieves a list of line items and their details from an entrypoint. Line items are also known as items, products, and services. Use filters to limit results.

        Parameters
        ----------
        entry : str
            The paypoint's entrypoint identifier. [Learn more](/api-reference/api-overview#entrypoint-vs-entry)

        from_record : typing.Optional[int]
            The number of records to skip before starting to collect the result set.

        limit_record : typing.Optional[int]
            Max number of records to return for the query. Use `0` or negative value to return all records.

        parameters : typing.Optional[typing.Dict[str, typing.Optional[str]]]

            Collection of field names, conditions, and values used to filter the query
            <Info>
              **You must remove `parameters=` from the request before you send it, otherwise Payabli will ignore the filters.**

              Because of a technical limitation, you can't make a request that includes filters from the API console on this page. The response won't be filtered. Instead, copy the request, remove `parameters=` and run the request in a different client.

              For example:

              --url https://api-sandbox.payabli.com/api/Query/transactions/org/236?parameters=totalAmount(gt)=1000&limitRecord=20

              should become:

              --url https://api-sandbox.payabli.com/api/Query/transactions/org/236?totalAmount(gt)=1000&limitRecord=20

            </Info>
            See [Filters and Conditions Reference](/developers/developer-guides/pay-ops-reporting-engine-overview#filters-and-conditions-reference) for help.

            List of field names accepted:

              - `categories` (ct, nct)
              - `code` (ne, eq, ct, nct)
              - `commodityCode` (ne, eq, ct, nct)
              - `createdDate` (gt, ge, lt, le, eq, ne)
              - `description` (ne, eq, ct, nct)
              - `externalPaypointID` (ct, nct, ne, eq)
              - `mode` (eq, ne)
              - `name` (ne, eq, ct, nct)
              - `orgName` (ne, eq, ct, nct)
              - `paypointDba` (ne, eq, ct, nct)
              - `paypointId` (ne, eq)
              - `paypointLegal` (ne, eq, ct, nct)
              - `quantity` (gt, ge, lt, le, eq, ne)
              - `uom` (ne, eq, ct, nct)
              - `updatedDate` (gt, ge, lt, le, eq, ne)
              - `value` (gt, ge, lt, le, eq, ne)

            List of comparison accepted - enclosed between parentheses:

            - eq or empty => equal
            - gt => greater than
            - ge => greater or equal
            - lt => less than
            - le => less or equal
            - ne => not equal
            - ct => contains
            - nct => not contains
            - in => inside array separated by "|"
            - nin => not inside array separated by "|"

            List of parameters accepted:
            - limitRecord : max number of records for query (default="20", "0" or negative value for all)
            - fromRecord : initial record in query

            Example: name(ct)=john return all records with name containing john

        sort_by : typing.Optional[str]
            The field name to use for sorting results. Use `desc(field_name)` to sort descending by `field_name`, and use `asc(field_name)` to sort ascending by `field_name`.

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

        Returns
        -------
        HttpResponse[QueryResponseItems]
            Success
        """
        _response = self._client_wrapper.httpx_client.request(
            f"Query/lineitems/{jsonable_encoder(entry)}",
            method="GET",
            params={
                "fromRecord": from_record,
                "limitRecord": limit_record,
                "parameters": parameters,
                "sortBy": sort_by,
            },
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    QueryResponseItems,
                    parse_obj_as(
                        type_=QueryResponseItems,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            if _response.status_code == 400:
                raise BadRequestError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 401:
                raise UnauthorizedError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 500:
                raise InternalServerError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 503:
                raise ServiceUnavailableError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        PayabliApiResponse,
                        parse_obj_as(
                            type_=PayabliApiResponse,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    def update_item(
        self,
        line_item_id: int,
        *,
        item_cost: float,
        item_qty: int,
        item_categories: typing.Optional[typing.Sequence[typing.Optional[str]]] = OMIT,
        item_commodity_code: typing.Optional[ItemCommodityCode] = OMIT,
        item_description: typing.Optional[ItemDescription] = OMIT,
        item_mode: typing.Optional[int] = OMIT,
        item_product_code: typing.Optional[ItemProductCode] = OMIT,
        item_product_name: typing.Optional[ItemProductName] = OMIT,
        item_unit_of_measure: typing.Optional[ItemUnitofMeasure] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> HttpResponse[PayabliApiResponse6]:
        """
        Updates an item.

        Parameters
        ----------
        line_item_id : int
            ID for the line item (also known as a product, service, or item).

        item_cost : float
            Item or product price per unit.

        item_qty : int
            Quantity of item or product.

        item_categories : typing.Optional[typing.Sequence[typing.Optional[str]]]
            Array of tags classifying item or product.

        item_commodity_code : typing.Optional[ItemCommodityCode]

        item_description : typing.Optional[ItemDescription]

        item_mode : typing.Optional[int]
            Internal class of item or product: value '0' is only for invoices, '1' for bills, and '2' is common for both.

        item_product_code : typing.Optional[ItemProductCode]

        item_product_name : typing.Optional[ItemProductName]

        item_unit_of_measure : typing.Optional[ItemUnitofMeasure]

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

        Returns
        -------
        HttpResponse[PayabliApiResponse6]
            Success
        """
        _response = self._client_wrapper.httpx_client.request(
            f"LineItem/{jsonable_encoder(line_item_id)}",
            method="PUT",
            json={
                "itemCategories": item_categories,
                "itemCommodityCode": item_commodity_code,
                "itemCost": item_cost,
                "itemDescription": item_description,
                "itemMode": item_mode,
                "itemProductCode": item_product_code,
                "itemProductName": item_product_name,
                "itemQty": item_qty,
                "itemUnitOfMeasure": item_unit_of_measure,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    PayabliApiResponse6,
                    parse_obj_as(
                        type_=PayabliApiResponse6,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            if _response.status_code == 400:
                raise BadRequestError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 401:
                raise UnauthorizedError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 500:
                raise InternalServerError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 503:
                raise ServiceUnavailableError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        PayabliApiResponse,
                        parse_obj_as(
                            type_=PayabliApiResponse,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)


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

    async def add_item(
        self,
        entry: str,
        *,
        item_cost: float,
        item_qty: int,
        idempotency_key: typing.Optional[str] = None,
        item_categories: typing.Optional[typing.Sequence[typing.Optional[str]]] = OMIT,
        item_commodity_code: typing.Optional[ItemCommodityCode] = OMIT,
        item_description: typing.Optional[ItemDescription] = OMIT,
        item_mode: typing.Optional[int] = OMIT,
        item_product_code: typing.Optional[ItemProductCode] = OMIT,
        item_product_name: typing.Optional[ItemProductName] = OMIT,
        item_unit_of_measure: typing.Optional[ItemUnitofMeasure] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AsyncHttpResponse[PayabliApiResponse6]:
        """
        Adds products and services to an entrypoint's catalog. These are used as line items for invoicing and transactions. In the response, "responseData" displays the item's code.

        Parameters
        ----------
        entry : str
            The paypoint's entrypoint identifier. [Learn more](/api-reference/api-overview#entrypoint-vs-entry)

        item_cost : float
            Item or product price per unit.

        item_qty : int
            Quantity of item or product.

        idempotency_key : typing.Optional[str]
            A unique ID you can include to prevent duplicating objects or transactions if a request is sent more than once. This key isn't generated in Payabli, you must generate it yourself.

        item_categories : typing.Optional[typing.Sequence[typing.Optional[str]]]
            Array of tags classifying item or product.

        item_commodity_code : typing.Optional[ItemCommodityCode]

        item_description : typing.Optional[ItemDescription]

        item_mode : typing.Optional[int]
            Internal class of item or product: value '0' is only for invoices, '1' for bills, and '2' is common for both.

        item_product_code : typing.Optional[ItemProductCode]

        item_product_name : typing.Optional[ItemProductName]

        item_unit_of_measure : typing.Optional[ItemUnitofMeasure]

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

        Returns
        -------
        AsyncHttpResponse[PayabliApiResponse6]
            Success
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"LineItem/{jsonable_encoder(entry)}",
            method="POST",
            json={
                "itemCategories": item_categories,
                "itemCommodityCode": item_commodity_code,
                "itemCost": item_cost,
                "itemDescription": item_description,
                "itemMode": item_mode,
                "itemProductCode": item_product_code,
                "itemProductName": item_product_name,
                "itemQty": item_qty,
                "itemUnitOfMeasure": item_unit_of_measure,
            },
            headers={
                "content-type": "application/json",
                "idempotencyKey": str(idempotency_key) if idempotency_key is not None else None,
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    PayabliApiResponse6,
                    parse_obj_as(
                        type_=PayabliApiResponse6,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            if _response.status_code == 400:
                raise BadRequestError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 401:
                raise UnauthorizedError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 500:
                raise InternalServerError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 503:
                raise ServiceUnavailableError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        PayabliApiResponse,
                        parse_obj_as(
                            type_=PayabliApiResponse,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    async def delete_item(
        self, line_item_id: int, *, request_options: typing.Optional[RequestOptions] = None
    ) -> AsyncHttpResponse[DeleteItemResponse]:
        """
        Deletes an item.

        Parameters
        ----------
        line_item_id : int
            ID for the line item (also known as a product, service, or item).

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

        Returns
        -------
        AsyncHttpResponse[DeleteItemResponse]
            Success
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"LineItem/{jsonable_encoder(line_item_id)}",
            method="DELETE",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    DeleteItemResponse,
                    parse_obj_as(
                        type_=DeleteItemResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            if _response.status_code == 400:
                raise BadRequestError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 401:
                raise UnauthorizedError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 500:
                raise InternalServerError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 503:
                raise ServiceUnavailableError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        PayabliApiResponse,
                        parse_obj_as(
                            type_=PayabliApiResponse,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    async def get_item(
        self, line_item_id: int, *, request_options: typing.Optional[RequestOptions] = None
    ) -> AsyncHttpResponse[LineItemQueryRecord]:
        """
        Gets an item by ID.

        Parameters
        ----------
        line_item_id : int
            ID for the line item (also known as a product, service, or item).

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

        Returns
        -------
        AsyncHttpResponse[LineItemQueryRecord]
            Success
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"LineItem/{jsonable_encoder(line_item_id)}",
            method="GET",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    LineItemQueryRecord,
                    parse_obj_as(
                        type_=LineItemQueryRecord,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            if _response.status_code == 400:
                raise BadRequestError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 401:
                raise UnauthorizedError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 500:
                raise InternalServerError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 503:
                raise ServiceUnavailableError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        PayabliApiResponse,
                        parse_obj_as(
                            type_=PayabliApiResponse,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    async def list_line_items(
        self,
        entry: str,
        *,
        from_record: typing.Optional[int] = None,
        limit_record: typing.Optional[int] = None,
        parameters: typing.Optional[typing.Dict[str, typing.Optional[str]]] = None,
        sort_by: typing.Optional[str] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AsyncHttpResponse[QueryResponseItems]:
        """
        Retrieves a list of line items and their details from an entrypoint. Line items are also known as items, products, and services. Use filters to limit results.

        Parameters
        ----------
        entry : str
            The paypoint's entrypoint identifier. [Learn more](/api-reference/api-overview#entrypoint-vs-entry)

        from_record : typing.Optional[int]
            The number of records to skip before starting to collect the result set.

        limit_record : typing.Optional[int]
            Max number of records to return for the query. Use `0` or negative value to return all records.

        parameters : typing.Optional[typing.Dict[str, typing.Optional[str]]]

            Collection of field names, conditions, and values used to filter the query
            <Info>
              **You must remove `parameters=` from the request before you send it, otherwise Payabli will ignore the filters.**

              Because of a technical limitation, you can't make a request that includes filters from the API console on this page. The response won't be filtered. Instead, copy the request, remove `parameters=` and run the request in a different client.

              For example:

              --url https://api-sandbox.payabli.com/api/Query/transactions/org/236?parameters=totalAmount(gt)=1000&limitRecord=20

              should become:

              --url https://api-sandbox.payabli.com/api/Query/transactions/org/236?totalAmount(gt)=1000&limitRecord=20

            </Info>
            See [Filters and Conditions Reference](/developers/developer-guides/pay-ops-reporting-engine-overview#filters-and-conditions-reference) for help.

            List of field names accepted:

              - `categories` (ct, nct)
              - `code` (ne, eq, ct, nct)
              - `commodityCode` (ne, eq, ct, nct)
              - `createdDate` (gt, ge, lt, le, eq, ne)
              - `description` (ne, eq, ct, nct)
              - `externalPaypointID` (ct, nct, ne, eq)
              - `mode` (eq, ne)
              - `name` (ne, eq, ct, nct)
              - `orgName` (ne, eq, ct, nct)
              - `paypointDba` (ne, eq, ct, nct)
              - `paypointId` (ne, eq)
              - `paypointLegal` (ne, eq, ct, nct)
              - `quantity` (gt, ge, lt, le, eq, ne)
              - `uom` (ne, eq, ct, nct)
              - `updatedDate` (gt, ge, lt, le, eq, ne)
              - `value` (gt, ge, lt, le, eq, ne)

            List of comparison accepted - enclosed between parentheses:

            - eq or empty => equal
            - gt => greater than
            - ge => greater or equal
            - lt => less than
            - le => less or equal
            - ne => not equal
            - ct => contains
            - nct => not contains
            - in => inside array separated by "|"
            - nin => not inside array separated by "|"

            List of parameters accepted:
            - limitRecord : max number of records for query (default="20", "0" or negative value for all)
            - fromRecord : initial record in query

            Example: name(ct)=john return all records with name containing john

        sort_by : typing.Optional[str]
            The field name to use for sorting results. Use `desc(field_name)` to sort descending by `field_name`, and use `asc(field_name)` to sort ascending by `field_name`.

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

        Returns
        -------
        AsyncHttpResponse[QueryResponseItems]
            Success
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"Query/lineitems/{jsonable_encoder(entry)}",
            method="GET",
            params={
                "fromRecord": from_record,
                "limitRecord": limit_record,
                "parameters": parameters,
                "sortBy": sort_by,
            },
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    QueryResponseItems,
                    parse_obj_as(
                        type_=QueryResponseItems,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            if _response.status_code == 400:
                raise BadRequestError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 401:
                raise UnauthorizedError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 500:
                raise InternalServerError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 503:
                raise ServiceUnavailableError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        PayabliApiResponse,
                        parse_obj_as(
                            type_=PayabliApiResponse,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    async def update_item(
        self,
        line_item_id: int,
        *,
        item_cost: float,
        item_qty: int,
        item_categories: typing.Optional[typing.Sequence[typing.Optional[str]]] = OMIT,
        item_commodity_code: typing.Optional[ItemCommodityCode] = OMIT,
        item_description: typing.Optional[ItemDescription] = OMIT,
        item_mode: typing.Optional[int] = OMIT,
        item_product_code: typing.Optional[ItemProductCode] = OMIT,
        item_product_name: typing.Optional[ItemProductName] = OMIT,
        item_unit_of_measure: typing.Optional[ItemUnitofMeasure] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AsyncHttpResponse[PayabliApiResponse6]:
        """
        Updates an item.

        Parameters
        ----------
        line_item_id : int
            ID for the line item (also known as a product, service, or item).

        item_cost : float
            Item or product price per unit.

        item_qty : int
            Quantity of item or product.

        item_categories : typing.Optional[typing.Sequence[typing.Optional[str]]]
            Array of tags classifying item or product.

        item_commodity_code : typing.Optional[ItemCommodityCode]

        item_description : typing.Optional[ItemDescription]

        item_mode : typing.Optional[int]
            Internal class of item or product: value '0' is only for invoices, '1' for bills, and '2' is common for both.

        item_product_code : typing.Optional[ItemProductCode]

        item_product_name : typing.Optional[ItemProductName]

        item_unit_of_measure : typing.Optional[ItemUnitofMeasure]

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

        Returns
        -------
        AsyncHttpResponse[PayabliApiResponse6]
            Success
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"LineItem/{jsonable_encoder(line_item_id)}",
            method="PUT",
            json={
                "itemCategories": item_categories,
                "itemCommodityCode": item_commodity_code,
                "itemCost": item_cost,
                "itemDescription": item_description,
                "itemMode": item_mode,
                "itemProductCode": item_product_code,
                "itemProductName": item_product_name,
                "itemQty": item_qty,
                "itemUnitOfMeasure": item_unit_of_measure,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    PayabliApiResponse6,
                    parse_obj_as(
                        type_=PayabliApiResponse6,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            if _response.status_code == 400:
                raise BadRequestError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 401:
                raise UnauthorizedError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 500:
                raise InternalServerError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 503:
                raise ServiceUnavailableError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        PayabliApiResponse,
                        parse_obj_as(
                            type_=PayabliApiResponse,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
