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

import typing
from ..core.client_wrapper import SyncClientWrapper
from .raw_client import RawOrdersClient
from .custom_attribute_definitions.client import CustomAttributeDefinitionsClient
from .custom_attributes.client import CustomAttributesClient
from ..requests.order import OrderParams
from ..core.request_options import RequestOptions
from ..types.create_order_response import CreateOrderResponse
from ..types.batch_get_orders_response import BatchGetOrdersResponse
from ..requests.order_reward import OrderRewardParams
from ..types.calculate_order_response import CalculateOrderResponse
from ..types.clone_order_response import CloneOrderResponse
from ..requests.search_orders_query import SearchOrdersQueryParams
from ..types.search_orders_response import SearchOrdersResponse
from ..types.get_order_response import GetOrderResponse
from ..types.update_order_response import UpdateOrderResponse
from ..types.pay_order_response import PayOrderResponse
from ..core.client_wrapper import AsyncClientWrapper
from .raw_client import AsyncRawOrdersClient
from .custom_attribute_definitions.client import AsyncCustomAttributeDefinitionsClient
from .custom_attributes.client import AsyncCustomAttributesClient

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


class OrdersClient:
    def __init__(self, *, client_wrapper: SyncClientWrapper):
        self._raw_client = RawOrdersClient(client_wrapper=client_wrapper)
        self.custom_attribute_definitions = CustomAttributeDefinitionsClient(client_wrapper=client_wrapper)

        self.custom_attributes = CustomAttributesClient(client_wrapper=client_wrapper)

    @property
    def with_raw_response(self) -> RawOrdersClient:
        """
        Retrieves a raw implementation of this client that returns raw responses.

        Returns
        -------
        RawOrdersClient
        """
        return self._raw_client

    def create(
        self,
        *,
        order: typing.Optional[OrderParams] = OMIT,
        idempotency_key: typing.Optional[str] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> CreateOrderResponse:
        """
        Creates a new [order](entity:Order) that can include information about products for
        purchase and settings to apply to the purchase.

        To pay for a created order, see
        [Pay for Orders](https://developer.squareup.com/docs/orders-api/pay-for-orders).

        You can modify open orders using the [UpdateOrder](api-endpoint:Orders-UpdateOrder) endpoint.

        Parameters
        ----------
        order : typing.Optional[OrderParams]
            The order to create. If this field is set, the only other top-level field that can be
            set is the `idempotency_key`.

        idempotency_key : typing.Optional[str]
            A value you specify that uniquely identifies this
            order among orders you have created.

            If you are unsure whether a particular order was created successfully,
            you can try it again with the same idempotency key without
            worrying about creating duplicate orders.

            For more information, see [Idempotency](https://developer.squareup.com/docs/build-basics/common-api-patterns/idempotency).

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

        Returns
        -------
        CreateOrderResponse
            Success

        Examples
        --------
        from square import Square

        client = Square(
            token="YOUR_TOKEN",
        )
        client.orders.create(
            order={
                "location_id": "057P5VYJ4A5X1",
                "reference_id": "my-order-001",
                "line_items": [
                    {
                        "name": "New York Strip Steak",
                        "quantity": "1",
                        "base_price_money": {"amount": 1599, "currency": "USD"},
                    },
                    {
                        "quantity": "2",
                        "catalog_object_id": "BEMYCSMIJL46OCDV4KYIKXIB",
                        "modifiers": [
                            {"catalog_object_id": "CHQX7Y4KY6N5KINJKZCFURPZ"}
                        ],
                        "applied_discounts": [{"discount_uid": "one-dollar-off"}],
                    },
                ],
                "taxes": [
                    {
                        "uid": "state-sales-tax",
                        "name": "State Sales Tax",
                        "percentage": "9",
                        "scope": "ORDER",
                    }
                ],
                "discounts": [
                    {
                        "uid": "labor-day-sale",
                        "name": "Labor Day Sale",
                        "percentage": "5",
                        "scope": "ORDER",
                    },
                    {
                        "uid": "membership-discount",
                        "catalog_object_id": "DB7L55ZH2BGWI4H23ULIWOQ7",
                        "scope": "ORDER",
                    },
                    {
                        "uid": "one-dollar-off",
                        "name": "Sale - $1.00 off",
                        "amount_money": {"amount": 100, "currency": "USD"},
                        "scope": "LINE_ITEM",
                    },
                ],
            },
            idempotency_key="8193148c-9586-11e6-99f9-28cfe92138cf",
        )
        """
        response = self._raw_client.create(
            order=order, idempotency_key=idempotency_key, request_options=request_options
        )
        return response.data

    def batch_get(
        self,
        *,
        order_ids: typing.Sequence[str],
        location_id: typing.Optional[str] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> BatchGetOrdersResponse:
        """
        Retrieves a set of [orders](entity:Order) by their IDs.

        If a given order ID does not exist, the ID is ignored instead of generating an error.

        Parameters
        ----------
        order_ids : typing.Sequence[str]
            The IDs of the orders to retrieve. A maximum of 100 orders can be retrieved per request.

        location_id : typing.Optional[str]
            The ID of the location for these orders. This field is optional: omit it to retrieve
            orders within the scope of the current authorization's merchant ID.

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

        Returns
        -------
        BatchGetOrdersResponse
            Success

        Examples
        --------
        from square import Square

        client = Square(
            token="YOUR_TOKEN",
        )
        client.orders.batch_get(
            location_id="057P5VYJ4A5X1",
            order_ids=["CAISEM82RcpmcFBM0TfOyiHV3es", "CAISENgvlJ6jLWAzERDzjyHVybY"],
        )
        """
        response = self._raw_client.batch_get(
            order_ids=order_ids, location_id=location_id, request_options=request_options
        )
        return response.data

    def calculate(
        self,
        *,
        order: OrderParams,
        proposed_rewards: typing.Optional[typing.Sequence[OrderRewardParams]] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> CalculateOrderResponse:
        """
        Enables applications to preview order pricing without creating an order.

        Parameters
        ----------
        order : OrderParams
            The order to be calculated. Expects the entire order, not a sparse update.

        proposed_rewards : typing.Optional[typing.Sequence[OrderRewardParams]]
            Identifies one or more loyalty reward tiers to apply during the order calculation.
            The discounts defined by the reward tiers are added to the order only to preview the
            effect of applying the specified rewards. The rewards do not correspond to actual
            redemptions; that is, no `reward`s are created. Therefore, the reward `id`s are
            random strings used only to reference the reward tier.

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

        Returns
        -------
        CalculateOrderResponse
            Success

        Examples
        --------
        from square import Square

        client = Square(
            token="YOUR_TOKEN",
        )
        client.orders.calculate(
            order={
                "location_id": "D7AVYMEAPJ3A3",
                "line_items": [
                    {
                        "name": "Item 1",
                        "quantity": "1",
                        "base_price_money": {"amount": 500, "currency": "USD"},
                    },
                    {
                        "name": "Item 2",
                        "quantity": "2",
                        "base_price_money": {"amount": 300, "currency": "USD"},
                    },
                ],
                "discounts": [
                    {"name": "50% Off", "percentage": "50", "scope": "ORDER"}
                ],
            },
        )
        """
        response = self._raw_client.calculate(
            order=order, proposed_rewards=proposed_rewards, request_options=request_options
        )
        return response.data

    def clone(
        self,
        *,
        order_id: str,
        version: typing.Optional[int] = OMIT,
        idempotency_key: typing.Optional[str] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> CloneOrderResponse:
        """
        Creates a new order, in the `DRAFT` state, by duplicating an existing order. The newly created order has
        only the core fields (such as line items, taxes, and discounts) copied from the original order.

        Parameters
        ----------
        order_id : str
            The ID of the order to clone.

        version : typing.Optional[int]
            An optional order version for concurrency protection.

            If a version is provided, it must match the latest stored version of the order to clone.
            If a version is not provided, the API clones the latest version.

        idempotency_key : typing.Optional[str]
            A value you specify that uniquely identifies this clone request.

            If you are unsure whether a particular order was cloned successfully,
            you can reattempt the call with the same idempotency key without
            worrying about creating duplicate cloned orders.
            The originally cloned order is returned.

            For more information, see [Idempotency](https://developer.squareup.com/docs/build-basics/common-api-patterns/idempotency).

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

        Returns
        -------
        CloneOrderResponse
            Success

        Examples
        --------
        from square import Square

        client = Square(
            token="YOUR_TOKEN",
        )
        client.orders.clone(
            order_id="ZAISEM52YcpmcWAzERDOyiWS123",
            version=3,
            idempotency_key="UNIQUE_STRING",
        )
        """
        response = self._raw_client.clone(
            order_id=order_id, version=version, idempotency_key=idempotency_key, request_options=request_options
        )
        return response.data

    def search(
        self,
        *,
        location_ids: typing.Optional[typing.Sequence[str]] = OMIT,
        cursor: typing.Optional[str] = OMIT,
        query: typing.Optional[SearchOrdersQueryParams] = OMIT,
        limit: typing.Optional[int] = OMIT,
        return_entries: typing.Optional[bool] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> SearchOrdersResponse:
        """
        Search all orders for one or more locations. Orders include all sales,
        returns, and exchanges regardless of how or when they entered the Square
        ecosystem (such as Point of Sale, Invoices, and Connect APIs).

        `SearchOrders` requests need to specify which locations to search and define a
        [SearchOrdersQuery](entity:SearchOrdersQuery) object that controls
        how to sort or filter the results. Your `SearchOrdersQuery` can:

          Set filter criteria.
          Set the sort order.
          Determine whether to return results as complete `Order` objects or as
        [OrderEntry](entity:OrderEntry) objects.

        Note that details for orders processed with Square Point of Sale while in
        offline mode might not be transmitted to Square for up to 72 hours. Offline
        orders have a `created_at` value that reflects the time the order was created,
        not the time it was subsequently transmitted to Square.

        Parameters
        ----------
        location_ids : typing.Optional[typing.Sequence[str]]
            The location IDs for the orders to query. All locations must belong to
            the same merchant.

            Max: 10 location IDs.

        cursor : typing.Optional[str]
            A pagination cursor returned by a previous call to this endpoint.
            Provide this cursor to retrieve the next set of results for your original query.
            For more information, see [Pagination](https://developer.squareup.com/docs/build-basics/common-api-patterns/pagination).

        query : typing.Optional[SearchOrdersQueryParams]
            Query conditions used to filter or sort the results. Note that when
            retrieving additional pages using a cursor, you must use the original query.

        limit : typing.Optional[int]
            The maximum number of results to be returned in a single page.

            Default: `500`
            Max: `1000`

        return_entries : typing.Optional[bool]
            A Boolean that controls the format of the search results. If `true`,
            `SearchOrders` returns [OrderEntry](entity:OrderEntry) objects. If `false`, `SearchOrders`
            returns complete order objects.

            Default: `false`.

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

        Returns
        -------
        SearchOrdersResponse
            Success

        Examples
        --------
        from square import Square

        client = Square(
            token="YOUR_TOKEN",
        )
        client.orders.search(
            location_ids=["057P5VYJ4A5X1", "18YC4JDH91E1H"],
            query={
                "filter": {
                    "state_filter": {"states": ["COMPLETED"]},
                    "date_time_filter": {
                        "closed_at": {
                            "start_at": "2018-03-03T20:00:00+00:00",
                            "end_at": "2019-03-04T21:54:45+00:00",
                        }
                    },
                },
                "sort": {"sort_field": "CLOSED_AT", "sort_order": "DESC"},
            },
            limit=3,
            return_entries=True,
        )
        """
        response = self._raw_client.search(
            location_ids=location_ids,
            cursor=cursor,
            query=query,
            limit=limit,
            return_entries=return_entries,
            request_options=request_options,
        )
        return response.data

    def get(self, order_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> GetOrderResponse:
        """
        Retrieves an [Order](entity:Order) by ID.

        Parameters
        ----------
        order_id : str
            The ID of the order to retrieve.

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

        Returns
        -------
        GetOrderResponse
            Success

        Examples
        --------
        from square import Square

        client = Square(
            token="YOUR_TOKEN",
        )
        client.orders.get(
            order_id="order_id",
        )
        """
        response = self._raw_client.get(order_id, request_options=request_options)
        return response.data

    def update(
        self,
        order_id: str,
        *,
        order: typing.Optional[OrderParams] = OMIT,
        fields_to_clear: typing.Optional[typing.Sequence[str]] = OMIT,
        idempotency_key: typing.Optional[str] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> UpdateOrderResponse:
        """
        Updates an open [order](entity:Order) by adding, replacing, or deleting
        fields. Orders with a `COMPLETED` or `CANCELED` state cannot be updated.

        An `UpdateOrder` request requires the following:

        - The `order_id` in the endpoint path, identifying the order to update.
        - The latest `version` of the order to update.
        - The [sparse order](https://developer.squareup.com/docs/orders-api/manage-orders/update-orders#sparse-order-objects)
        containing only the fields to update and the version to which the update is
        being applied.
        - If deleting fields, the [dot notation paths](https://developer.squareup.com/docs/orders-api/manage-orders/update-orders#identifying-fields-to-delete)
        identifying the fields to clear.

        To pay for an order, see
        [Pay for Orders](https://developer.squareup.com/docs/orders-api/pay-for-orders).

        Parameters
        ----------
        order_id : str
            The ID of the order to update.

        order : typing.Optional[OrderParams]
            The [sparse order](https://developer.squareup.com/docs/orders-api/manage-orders/update-orders#sparse-order-objects)
            containing only the fields to update and the version to which the update is
            being applied.

        fields_to_clear : typing.Optional[typing.Sequence[str]]
            The [dot notation paths](https://developer.squareup.com/docs/orders-api/manage-orders/update-orders#identifying-fields-to-delete)
            fields to clear. For example, `line_items[uid].note`.
            For more information, see [Deleting fields](https://developer.squareup.com/docs/orders-api/manage-orders/update-orders#deleting-fields).

        idempotency_key : typing.Optional[str]
            A value you specify that uniquely identifies this update request.

            If you are unsure whether a particular update was applied to an order successfully,
            you can reattempt it with the same idempotency key without
            worrying about creating duplicate updates to the order.
            The latest order version is returned.

            For more information, see [Idempotency](https://developer.squareup.com/docs/build-basics/common-api-patterns/idempotency).

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

        Returns
        -------
        UpdateOrderResponse
            Success

        Examples
        --------
        from square import Square

        client = Square(
            token="YOUR_TOKEN",
        )
        client.orders.update(
            order_id="order_id",
            order={
                "location_id": "location_id",
                "line_items": [
                    {
                        "uid": "cookie_uid",
                        "name": "COOKIE",
                        "quantity": "2",
                        "base_price_money": {"amount": 200, "currency": "USD"},
                    }
                ],
                "version": 1,
            },
            fields_to_clear=["discounts"],
            idempotency_key="UNIQUE_STRING",
        )
        """
        response = self._raw_client.update(
            order_id,
            order=order,
            fields_to_clear=fields_to_clear,
            idempotency_key=idempotency_key,
            request_options=request_options,
        )
        return response.data

    def pay(
        self,
        order_id: str,
        *,
        idempotency_key: str,
        order_version: typing.Optional[int] = OMIT,
        payment_ids: typing.Optional[typing.Sequence[str]] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> PayOrderResponse:
        """
        Pay for an [order](entity:Order) using one or more approved [payments](entity:Payment)
        or settle an order with a total of `0`.

        The total of the `payment_ids` listed in the request must be equal to the order
        total. Orders with a total amount of `0` can be marked as paid by specifying an empty
        array of `payment_ids` in the request.

        To be used with `PayOrder`, a payment must:

        - Reference the order by specifying the `order_id` when [creating the payment](api-endpoint:Payments-CreatePayment).
        Any approved payments that reference the same `order_id` not specified in the
        `payment_ids` is canceled.
        - Be approved with [delayed capture](https://developer.squareup.com/docs/payments-api/take-payments/card-payments/delayed-capture).
        Using a delayed capture payment with `PayOrder` completes the approved payment.

        Parameters
        ----------
        order_id : str
            The ID of the order being paid.

        idempotency_key : str
            A value you specify that uniquely identifies this request among requests you have sent. If
            you are unsure whether a particular payment request was completed successfully, you can reattempt
            it with the same idempotency key without worrying about duplicate payments.

            For more information, see [Idempotency](https://developer.squareup.com/docs/working-with-apis/idempotency).

        order_version : typing.Optional[int]
            The version of the order being paid. If not supplied, the latest version will be paid.

        payment_ids : typing.Optional[typing.Sequence[str]]
            The IDs of the [payments](entity:Payment) to collect.
            The payment total must match the order total.

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

        Returns
        -------
        PayOrderResponse
            Success

        Examples
        --------
        from square import Square

        client = Square(
            token="YOUR_TOKEN",
        )
        client.orders.pay(
            order_id="order_id",
            idempotency_key="c043a359-7ad9-4136-82a9-c3f1d66dcbff",
            payment_ids=["EnZdNAlWCmfh6Mt5FMNST1o7taB", "0LRiVlbXVwe8ozu4KbZxd12mvaB"],
        )
        """
        response = self._raw_client.pay(
            order_id,
            idempotency_key=idempotency_key,
            order_version=order_version,
            payment_ids=payment_ids,
            request_options=request_options,
        )
        return response.data


class AsyncOrdersClient:
    def __init__(self, *, client_wrapper: AsyncClientWrapper):
        self._raw_client = AsyncRawOrdersClient(client_wrapper=client_wrapper)
        self.custom_attribute_definitions = AsyncCustomAttributeDefinitionsClient(client_wrapper=client_wrapper)

        self.custom_attributes = AsyncCustomAttributesClient(client_wrapper=client_wrapper)

    @property
    def with_raw_response(self) -> AsyncRawOrdersClient:
        """
        Retrieves a raw implementation of this client that returns raw responses.

        Returns
        -------
        AsyncRawOrdersClient
        """
        return self._raw_client

    async def create(
        self,
        *,
        order: typing.Optional[OrderParams] = OMIT,
        idempotency_key: typing.Optional[str] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> CreateOrderResponse:
        """
        Creates a new [order](entity:Order) that can include information about products for
        purchase and settings to apply to the purchase.

        To pay for a created order, see
        [Pay for Orders](https://developer.squareup.com/docs/orders-api/pay-for-orders).

        You can modify open orders using the [UpdateOrder](api-endpoint:Orders-UpdateOrder) endpoint.

        Parameters
        ----------
        order : typing.Optional[OrderParams]
            The order to create. If this field is set, the only other top-level field that can be
            set is the `idempotency_key`.

        idempotency_key : typing.Optional[str]
            A value you specify that uniquely identifies this
            order among orders you have created.

            If you are unsure whether a particular order was created successfully,
            you can try it again with the same idempotency key without
            worrying about creating duplicate orders.

            For more information, see [Idempotency](https://developer.squareup.com/docs/build-basics/common-api-patterns/idempotency).

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

        Returns
        -------
        CreateOrderResponse
            Success

        Examples
        --------
        import asyncio

        from square import AsyncSquare

        client = AsyncSquare(
            token="YOUR_TOKEN",
        )


        async def main() -> None:
            await client.orders.create(
                order={
                    "location_id": "057P5VYJ4A5X1",
                    "reference_id": "my-order-001",
                    "line_items": [
                        {
                            "name": "New York Strip Steak",
                            "quantity": "1",
                            "base_price_money": {"amount": 1599, "currency": "USD"},
                        },
                        {
                            "quantity": "2",
                            "catalog_object_id": "BEMYCSMIJL46OCDV4KYIKXIB",
                            "modifiers": [
                                {"catalog_object_id": "CHQX7Y4KY6N5KINJKZCFURPZ"}
                            ],
                            "applied_discounts": [{"discount_uid": "one-dollar-off"}],
                        },
                    ],
                    "taxes": [
                        {
                            "uid": "state-sales-tax",
                            "name": "State Sales Tax",
                            "percentage": "9",
                            "scope": "ORDER",
                        }
                    ],
                    "discounts": [
                        {
                            "uid": "labor-day-sale",
                            "name": "Labor Day Sale",
                            "percentage": "5",
                            "scope": "ORDER",
                        },
                        {
                            "uid": "membership-discount",
                            "catalog_object_id": "DB7L55ZH2BGWI4H23ULIWOQ7",
                            "scope": "ORDER",
                        },
                        {
                            "uid": "one-dollar-off",
                            "name": "Sale - $1.00 off",
                            "amount_money": {"amount": 100, "currency": "USD"},
                            "scope": "LINE_ITEM",
                        },
                    ],
                },
                idempotency_key="8193148c-9586-11e6-99f9-28cfe92138cf",
            )


        asyncio.run(main())
        """
        response = await self._raw_client.create(
            order=order, idempotency_key=idempotency_key, request_options=request_options
        )
        return response.data

    async def batch_get(
        self,
        *,
        order_ids: typing.Sequence[str],
        location_id: typing.Optional[str] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> BatchGetOrdersResponse:
        """
        Retrieves a set of [orders](entity:Order) by their IDs.

        If a given order ID does not exist, the ID is ignored instead of generating an error.

        Parameters
        ----------
        order_ids : typing.Sequence[str]
            The IDs of the orders to retrieve. A maximum of 100 orders can be retrieved per request.

        location_id : typing.Optional[str]
            The ID of the location for these orders. This field is optional: omit it to retrieve
            orders within the scope of the current authorization's merchant ID.

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

        Returns
        -------
        BatchGetOrdersResponse
            Success

        Examples
        --------
        import asyncio

        from square import AsyncSquare

        client = AsyncSquare(
            token="YOUR_TOKEN",
        )


        async def main() -> None:
            await client.orders.batch_get(
                location_id="057P5VYJ4A5X1",
                order_ids=[
                    "CAISEM82RcpmcFBM0TfOyiHV3es",
                    "CAISENgvlJ6jLWAzERDzjyHVybY",
                ],
            )


        asyncio.run(main())
        """
        response = await self._raw_client.batch_get(
            order_ids=order_ids, location_id=location_id, request_options=request_options
        )
        return response.data

    async def calculate(
        self,
        *,
        order: OrderParams,
        proposed_rewards: typing.Optional[typing.Sequence[OrderRewardParams]] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> CalculateOrderResponse:
        """
        Enables applications to preview order pricing without creating an order.

        Parameters
        ----------
        order : OrderParams
            The order to be calculated. Expects the entire order, not a sparse update.

        proposed_rewards : typing.Optional[typing.Sequence[OrderRewardParams]]
            Identifies one or more loyalty reward tiers to apply during the order calculation.
            The discounts defined by the reward tiers are added to the order only to preview the
            effect of applying the specified rewards. The rewards do not correspond to actual
            redemptions; that is, no `reward`s are created. Therefore, the reward `id`s are
            random strings used only to reference the reward tier.

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

        Returns
        -------
        CalculateOrderResponse
            Success

        Examples
        --------
        import asyncio

        from square import AsyncSquare

        client = AsyncSquare(
            token="YOUR_TOKEN",
        )


        async def main() -> None:
            await client.orders.calculate(
                order={
                    "location_id": "D7AVYMEAPJ3A3",
                    "line_items": [
                        {
                            "name": "Item 1",
                            "quantity": "1",
                            "base_price_money": {"amount": 500, "currency": "USD"},
                        },
                        {
                            "name": "Item 2",
                            "quantity": "2",
                            "base_price_money": {"amount": 300, "currency": "USD"},
                        },
                    ],
                    "discounts": [
                        {"name": "50% Off", "percentage": "50", "scope": "ORDER"}
                    ],
                },
            )


        asyncio.run(main())
        """
        response = await self._raw_client.calculate(
            order=order, proposed_rewards=proposed_rewards, request_options=request_options
        )
        return response.data

    async def clone(
        self,
        *,
        order_id: str,
        version: typing.Optional[int] = OMIT,
        idempotency_key: typing.Optional[str] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> CloneOrderResponse:
        """
        Creates a new order, in the `DRAFT` state, by duplicating an existing order. The newly created order has
        only the core fields (such as line items, taxes, and discounts) copied from the original order.

        Parameters
        ----------
        order_id : str
            The ID of the order to clone.

        version : typing.Optional[int]
            An optional order version for concurrency protection.

            If a version is provided, it must match the latest stored version of the order to clone.
            If a version is not provided, the API clones the latest version.

        idempotency_key : typing.Optional[str]
            A value you specify that uniquely identifies this clone request.

            If you are unsure whether a particular order was cloned successfully,
            you can reattempt the call with the same idempotency key without
            worrying about creating duplicate cloned orders.
            The originally cloned order is returned.

            For more information, see [Idempotency](https://developer.squareup.com/docs/build-basics/common-api-patterns/idempotency).

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

        Returns
        -------
        CloneOrderResponse
            Success

        Examples
        --------
        import asyncio

        from square import AsyncSquare

        client = AsyncSquare(
            token="YOUR_TOKEN",
        )


        async def main() -> None:
            await client.orders.clone(
                order_id="ZAISEM52YcpmcWAzERDOyiWS123",
                version=3,
                idempotency_key="UNIQUE_STRING",
            )


        asyncio.run(main())
        """
        response = await self._raw_client.clone(
            order_id=order_id, version=version, idempotency_key=idempotency_key, request_options=request_options
        )
        return response.data

    async def search(
        self,
        *,
        location_ids: typing.Optional[typing.Sequence[str]] = OMIT,
        cursor: typing.Optional[str] = OMIT,
        query: typing.Optional[SearchOrdersQueryParams] = OMIT,
        limit: typing.Optional[int] = OMIT,
        return_entries: typing.Optional[bool] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> SearchOrdersResponse:
        """
        Search all orders for one or more locations. Orders include all sales,
        returns, and exchanges regardless of how or when they entered the Square
        ecosystem (such as Point of Sale, Invoices, and Connect APIs).

        `SearchOrders` requests need to specify which locations to search and define a
        [SearchOrdersQuery](entity:SearchOrdersQuery) object that controls
        how to sort or filter the results. Your `SearchOrdersQuery` can:

          Set filter criteria.
          Set the sort order.
          Determine whether to return results as complete `Order` objects or as
        [OrderEntry](entity:OrderEntry) objects.

        Note that details for orders processed with Square Point of Sale while in
        offline mode might not be transmitted to Square for up to 72 hours. Offline
        orders have a `created_at` value that reflects the time the order was created,
        not the time it was subsequently transmitted to Square.

        Parameters
        ----------
        location_ids : typing.Optional[typing.Sequence[str]]
            The location IDs for the orders to query. All locations must belong to
            the same merchant.

            Max: 10 location IDs.

        cursor : typing.Optional[str]
            A pagination cursor returned by a previous call to this endpoint.
            Provide this cursor to retrieve the next set of results for your original query.
            For more information, see [Pagination](https://developer.squareup.com/docs/build-basics/common-api-patterns/pagination).

        query : typing.Optional[SearchOrdersQueryParams]
            Query conditions used to filter or sort the results. Note that when
            retrieving additional pages using a cursor, you must use the original query.

        limit : typing.Optional[int]
            The maximum number of results to be returned in a single page.

            Default: `500`
            Max: `1000`

        return_entries : typing.Optional[bool]
            A Boolean that controls the format of the search results. If `true`,
            `SearchOrders` returns [OrderEntry](entity:OrderEntry) objects. If `false`, `SearchOrders`
            returns complete order objects.

            Default: `false`.

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

        Returns
        -------
        SearchOrdersResponse
            Success

        Examples
        --------
        import asyncio

        from square import AsyncSquare

        client = AsyncSquare(
            token="YOUR_TOKEN",
        )


        async def main() -> None:
            await client.orders.search(
                location_ids=["057P5VYJ4A5X1", "18YC4JDH91E1H"],
                query={
                    "filter": {
                        "state_filter": {"states": ["COMPLETED"]},
                        "date_time_filter": {
                            "closed_at": {
                                "start_at": "2018-03-03T20:00:00+00:00",
                                "end_at": "2019-03-04T21:54:45+00:00",
                            }
                        },
                    },
                    "sort": {"sort_field": "CLOSED_AT", "sort_order": "DESC"},
                },
                limit=3,
                return_entries=True,
            )


        asyncio.run(main())
        """
        response = await self._raw_client.search(
            location_ids=location_ids,
            cursor=cursor,
            query=query,
            limit=limit,
            return_entries=return_entries,
            request_options=request_options,
        )
        return response.data

    async def get(self, order_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> GetOrderResponse:
        """
        Retrieves an [Order](entity:Order) by ID.

        Parameters
        ----------
        order_id : str
            The ID of the order to retrieve.

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

        Returns
        -------
        GetOrderResponse
            Success

        Examples
        --------
        import asyncio

        from square import AsyncSquare

        client = AsyncSquare(
            token="YOUR_TOKEN",
        )


        async def main() -> None:
            await client.orders.get(
                order_id="order_id",
            )


        asyncio.run(main())
        """
        response = await self._raw_client.get(order_id, request_options=request_options)
        return response.data

    async def update(
        self,
        order_id: str,
        *,
        order: typing.Optional[OrderParams] = OMIT,
        fields_to_clear: typing.Optional[typing.Sequence[str]] = OMIT,
        idempotency_key: typing.Optional[str] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> UpdateOrderResponse:
        """
        Updates an open [order](entity:Order) by adding, replacing, or deleting
        fields. Orders with a `COMPLETED` or `CANCELED` state cannot be updated.

        An `UpdateOrder` request requires the following:

        - The `order_id` in the endpoint path, identifying the order to update.
        - The latest `version` of the order to update.
        - The [sparse order](https://developer.squareup.com/docs/orders-api/manage-orders/update-orders#sparse-order-objects)
        containing only the fields to update and the version to which the update is
        being applied.
        - If deleting fields, the [dot notation paths](https://developer.squareup.com/docs/orders-api/manage-orders/update-orders#identifying-fields-to-delete)
        identifying the fields to clear.

        To pay for an order, see
        [Pay for Orders](https://developer.squareup.com/docs/orders-api/pay-for-orders).

        Parameters
        ----------
        order_id : str
            The ID of the order to update.

        order : typing.Optional[OrderParams]
            The [sparse order](https://developer.squareup.com/docs/orders-api/manage-orders/update-orders#sparse-order-objects)
            containing only the fields to update and the version to which the update is
            being applied.

        fields_to_clear : typing.Optional[typing.Sequence[str]]
            The [dot notation paths](https://developer.squareup.com/docs/orders-api/manage-orders/update-orders#identifying-fields-to-delete)
            fields to clear. For example, `line_items[uid].note`.
            For more information, see [Deleting fields](https://developer.squareup.com/docs/orders-api/manage-orders/update-orders#deleting-fields).

        idempotency_key : typing.Optional[str]
            A value you specify that uniquely identifies this update request.

            If you are unsure whether a particular update was applied to an order successfully,
            you can reattempt it with the same idempotency key without
            worrying about creating duplicate updates to the order.
            The latest order version is returned.

            For more information, see [Idempotency](https://developer.squareup.com/docs/build-basics/common-api-patterns/idempotency).

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

        Returns
        -------
        UpdateOrderResponse
            Success

        Examples
        --------
        import asyncio

        from square import AsyncSquare

        client = AsyncSquare(
            token="YOUR_TOKEN",
        )


        async def main() -> None:
            await client.orders.update(
                order_id="order_id",
                order={
                    "location_id": "location_id",
                    "line_items": [
                        {
                            "uid": "cookie_uid",
                            "name": "COOKIE",
                            "quantity": "2",
                            "base_price_money": {"amount": 200, "currency": "USD"},
                        }
                    ],
                    "version": 1,
                },
                fields_to_clear=["discounts"],
                idempotency_key="UNIQUE_STRING",
            )


        asyncio.run(main())
        """
        response = await self._raw_client.update(
            order_id,
            order=order,
            fields_to_clear=fields_to_clear,
            idempotency_key=idempotency_key,
            request_options=request_options,
        )
        return response.data

    async def pay(
        self,
        order_id: str,
        *,
        idempotency_key: str,
        order_version: typing.Optional[int] = OMIT,
        payment_ids: typing.Optional[typing.Sequence[str]] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> PayOrderResponse:
        """
        Pay for an [order](entity:Order) using one or more approved [payments](entity:Payment)
        or settle an order with a total of `0`.

        The total of the `payment_ids` listed in the request must be equal to the order
        total. Orders with a total amount of `0` can be marked as paid by specifying an empty
        array of `payment_ids` in the request.

        To be used with `PayOrder`, a payment must:

        - Reference the order by specifying the `order_id` when [creating the payment](api-endpoint:Payments-CreatePayment).
        Any approved payments that reference the same `order_id` not specified in the
        `payment_ids` is canceled.
        - Be approved with [delayed capture](https://developer.squareup.com/docs/payments-api/take-payments/card-payments/delayed-capture).
        Using a delayed capture payment with `PayOrder` completes the approved payment.

        Parameters
        ----------
        order_id : str
            The ID of the order being paid.

        idempotency_key : str
            A value you specify that uniquely identifies this request among requests you have sent. If
            you are unsure whether a particular payment request was completed successfully, you can reattempt
            it with the same idempotency key without worrying about duplicate payments.

            For more information, see [Idempotency](https://developer.squareup.com/docs/working-with-apis/idempotency).

        order_version : typing.Optional[int]
            The version of the order being paid. If not supplied, the latest version will be paid.

        payment_ids : typing.Optional[typing.Sequence[str]]
            The IDs of the [payments](entity:Payment) to collect.
            The payment total must match the order total.

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

        Returns
        -------
        PayOrderResponse
            Success

        Examples
        --------
        import asyncio

        from square import AsyncSquare

        client = AsyncSquare(
            token="YOUR_TOKEN",
        )


        async def main() -> None:
            await client.orders.pay(
                order_id="order_id",
                idempotency_key="c043a359-7ad9-4136-82a9-c3f1d66dcbff",
                payment_ids=[
                    "EnZdNAlWCmfh6Mt5FMNST1o7taB",
                    "0LRiVlbXVwe8ozu4KbZxd12mvaB",
                ],
            )


        asyncio.run(main())
        """
        response = await self._raw_client.pay(
            order_id,
            idempotency_key=idempotency_key,
            order_version=order_version,
            payment_ids=payment_ids,
            request_options=request_options,
        )
        return response.data
