The order
module
-
class magento.models.order.Order(data, client)View on GitHub
View Source Code
class Order(Model): """Wrapper for the ``orders`` endpoint""" DOCUMENTATION = 'https://adobe-commerce.redoc.ly/2.3.7-admin/tag/orders' IDENTIFIER = 'entity_id'def __init__(self, data: dict, client: Client): """Initialize an Order object using an API response from the ``orders`` endpoint :param data: API response from the ``orders`` endpoint :param client: an initialized :class:`~.Client` object """ super().__init__( data=data, client=client, endpoint='orders', private_keys=True )def __repr__(self): return f'<Magento Order: #{self.number} placed on {self.created_at}>' @property def excluded_keys(self) -> List[str]: return ['items', 'payment'] @property def id(self) -> int: """Alias for ``entity_id``""" return getattr(self, 'entity_id', None) @property def number(self) -> str: """Alias for ``increment_id``""" return getattr(self, 'increment_id', None) @cached_property def items(self) -> List[OrderItem]: """The ordered items, returned as a list of :class:`OrderItem` objects .. note:: When a configurable :class:`~.Product` is ordered, the API returns data for both the configurable and simple product * The :class:`OrderItem` is initialized using the configurable product data, since the simple product data is incomplete * The :attr:`~.OrderItem.product` and :attr:`~.OrderItem.product_id` will still match the simple product though If both entries are needed, the unparsed response is in the :attr:`~.data` dict """ return [OrderItem(item, order=self) for item in self.__items if item.get('parent_item') is None] @cached_property def item_ids(self) -> List[int]: """The ``item_id`` s of the ordered :attr:`~.items`""" return [item.item_id for item in self.items] @cached_property def products(self) -> List[Product]: """The ordered :attr:`~items`, returned as their corresponding :class:`~.Product` objects""" return [item.product for item in self.items]def get_invoice(self) -> Invoice: """Retrieve the :class:`~.Invoice` of the Order""" return self.client.invoices.by_order(self)@property def customer(self) -> Customer: return self.client.customers.by_order(self) @property def shipping_address(self) -> dict: """Shipping details, from ``extension_attributes.shipping_assignments``""" return self.extension_attributes.get( 'shipping_assignments', [{}])[0].get( 'shipping', {}).get( 'address', {}) @property def bill_to(self) -> dict: """Condensed version of the ``billing_address`` dict""" if hasattr(self, 'billing_address'): return { 'firstname': self.billing_address.get('firstname', ''), 'lastname': self.billing_address.get('lastname', ''), 'email': self.billing_address.get('email', ''), 'address': self.bill_to_address } @property def bill_to_address(self) -> str: """The billing address, parsed into a single string""" return self._build_address('billing') @property def ship_to(self) -> dict: """Condensed version of the :attr:`~.shipping_address` dict""" return { 'firstname': self.shipping_address.get('firstname', ''), 'lastname': self.shipping_address.get('lastname', ''), 'email': self.shipping_address.get('email', ''), 'address': self.ship_to_address } @property def ship_to_address(self) -> str: """The shipping address, parsed into a single string""" return self._build_address('shipping') def _build_address(self, address_type: str) -> str: """Parses an address dict into a single string :param address_type: the address to parse; either ``shipping`` or ``billing`` """ address_dict = getattr(self, f'{address_type}_address') address = ' '.join(address_dict.get('street', [])) + ', ' for field in ('city', 'region_code', 'postcode', 'country_id'): if value := address_dict.get(field): address += value.replace('None', '') + ', ' return address.strip(', ') @cached_property def payment(self) -> dict: """Payment data""" data = copy.deepcopy(self.__payment) if additional_info := self.extension_attributes.get('payment_additional_info'): data.pop('additional_information', None) data.update(self.unpack_attributes(additional_info, key='key')) return data @property def net_tax(self) -> float: """Final tax amount, with refunds and cancellations taken into account""" return self.base_tax_amount - getattr(self, 'base_tax_refunded', 0) - getattr(self, 'base_tax_canceled', 0) @property def net_total(self) -> float: """Final Order value, with refunds and cancellations taken into account""" return self.base_grand_total - getattr(self, 'base_total_refunded', 0) - getattr(self, 'base_total_canceled', 0) @property def item_refunds(self) -> float: """Total amount refunded for items; excludes shipping and adjustment refunds/fees""" return sum(item.net_refund for item in self.items) @cached_property def total_qty_invoiced(self) -> int: """Total number of units invoiced""" return sum(item.qty_invoiced for item in self.items) @cached_property def total_qty_shipped(self) -> int: """Total number of units shipped""" return sum(item.qty_shipped for item in self.items) @cached_property def total_qty_refunded(self) -> int: """Total number of units refunded""" return sum(item.qty_refunded for item in self.items) @cached_property def total_qty_canceled(self) -> int: """Total number of units canceled""" return sum(item.qty_canceled for item in self.items) @cached_property def total_qty_outstanding(self) -> int: """Total number of units that haven't been shipped/fulfilled yet""" return sum(item.qty_outstanding for item in self.items) @cached_property def net_qty_ordered(self) -> int: """Total number of units ordered, after accounting for refunds and cancellations""" return sum(item.net_qty_ordered for item in self.items) Bases:
Model
Wrapper for the
orders
endpoint- DOCUMENTATION: str = 'https://adobe-commerce.redoc.ly/2.3.7-admin/tag/orders'
Link to the Official Magento 2 API documentation for the endpoint wrapped by the Model
-
__init__(data, client)View on GitHub
View Source Code
def __init__(self, data: dict, client: Client): """Initialize an Order object using an API response from the ``orders`` endpoint :param data: API response from the ``orders`` endpoint :param client: an initialized :class:`~.Client` object """ super().__init__( data=data, client=client, endpoint='orders', private_keys=True ) Initialize an Order object using an API response from the
orders
endpoint
- property excluded_keys: List[str]
API response keys that shouldn’t be set as object attributes by
set_attrs()
- Returns
list of API response keys that shouldn’t be set as attributes
- property items: List[OrderItem]
The ordered items, returned as a list of
OrderItem
objectsNote
When a configurable
Product
is ordered, the API returns data for both the configurable and simple productThe
OrderItem
is initialized using the configurable product data, since the simple product data is incompleteThe
product
andproduct_id
will still match the simple product though
If both entries are needed, the unparsed response is in the
data
dict
- property products: List[Product]
The ordered
items
, returned as their correspondingProduct
objects
-
get_invoice()View on GitHub
View Source Code
def get_invoice(self) -> Invoice: """Retrieve the :class:`~.Invoice` of the Order""" return self.client.invoices.by_order(self) Retrieve the
Invoice
of the Order- Return type
- property ship_to: dict
Condensed version of the
shipping_address
dict
-
class magento.models.order.OrderItem(item, client=None, order=None)View on GitHub
View Source Code
class OrderItem(Model): """Wrapper for the ``order/items`` endpoint""" DOCUMENTATION = "https://adobe-commerce.redoc.ly/2.3.7-admin/tag/ordersitems" IDENTIFIER = 'item_id'def __init__(self, item: dict, client: Optional[Client] = None, order: Optional[Order] = None): """Initialize an OrderItem using an API response from the ``orders/items`` endpoint .. note:: Initialization requires either a :class:`~.Client` or :class:`Order` object :param item: API response from the ``orders/items`` endpoint :param order: the :class:`Order` that this is an item of :param client: the :class:`~.Client` to use (if not initializing with an Order) :raise ValueError: if both the ``order`` and ``client`` aren't provided """ if client is None: if order is None: raise ValueError('An Order or Client object must be provided') if not isinstance(order, Order): raise TypeError(f'`order` must be of type {Order}') super().__init__( data=item, client=client if client else order.client, endpoint='orders/items' ) self.tax = item.get('base_tax_amount', item.get('tax_amount', 0)) self.refund = item.get('base_amount_refunded', item.get('amount_refunded', 0)) self.tax_refunded = item.get('base_tax_refunded', item.get('tax_refunded', 0)) self.line_total = item.get('base_row_total_incl_tax', item.get('row_total_incl_tax', 0)) self._order = orderdef __repr__(self): return f"<OrderItem ({self.sku})> from Order ID: {self.order_id}>" @property def excluded_keys(self) -> List[str]: return ['product_id'] @cached_property def order(self) -> Order: """The corresponding :class:`Order`""" if self._order is None: return self.client.orders.by_id(self.order_id) return self._order @cached_property def product(self) -> Product: """The item's corresponding :class:`~.Product` .. note:: **If the ordered item:** * Is a configurable product - the child simple product is returned * Has custom options - the base product is returned """ if self.product_type != 'configurable': return self.client.products.by_id(self.product_id) if not self.extension_attributes.get('custom_options'): return self.client.products.by_sku(self.sku) # Configurable + Custom Options -> configurable product id & unsearchable option sku for item in self.order.data['items']: # Get simple product id from response data if item.get('parent_item_id') == self.item_id: return self.client.products.by_id(item['product_id']) @cached_property def product_id(self) -> int: """Id of the corresponding simple :class:`~.Product`""" return self.__product_id if self.product_type != 'configurable' else self.product.id @cached_property def extension_attributes(self) -> dict: return getattr(self, 'product_option', {}).get('extension_attributes', {}) @cached_property def qty_outstanding(self) -> int: """Number of units that haven't been shipped/fulfilled yet""" return self.net_qty_ordered - self.qty_shipped @cached_property def net_qty_ordered(self) -> int: """Number of units ordered, after accounting for refunds and cancellations""" return self.qty_ordered - self.qty_refunded - self.qty_canceled @cached_property def net_tax(self) -> float: """Tax amount after accounting for refunds and cancellations""" return self.tax - self.tax_refunded - getattr(self, 'tax_canceled', 0) @cached_property def net_total(self) -> float: """Row total (incl. tax) after accounting for refunds and cancellations""" return self.line_total - self.net_refund - self.total_canceled @cached_property def net_refund(self) -> float: """Refund amount after accounting for tax and discount refunds""" return self.refund + self.tax_refunded - getattr(self, 'discount_refunded', 0) @cached_property def total_canceled(self) -> float: """Cancelled amount; note that partial cancellation is not possible""" if self.qty_canceled != 0: return self.line_total return 0 Bases:
Model
Wrapper for the
order/items
endpoint- DOCUMENTATION: str = 'https://adobe-commerce.redoc.ly/2.3.7-admin/tag/ordersitems'
Link to the Official Magento 2 API documentation for the endpoint wrapped by the Model
-
__init__(item, client=None, order=None)View on GitHub
View Source Code
def __init__(self, item: dict, client: Optional[Client] = None, order: Optional[Order] = None): """Initialize an OrderItem using an API response from the ``orders/items`` endpoint .. note:: Initialization requires either a :class:`~.Client` or :class:`Order` object :param item: API response from the ``orders/items`` endpoint :param order: the :class:`Order` that this is an item of :param client: the :class:`~.Client` to use (if not initializing with an Order) :raise ValueError: if both the ``order`` and ``client`` aren't provided """ if client is None: if order is None: raise ValueError('An Order or Client object must be provided') if not isinstance(order, Order): raise TypeError(f'`order` must be of type {Order}') super().__init__( data=item, client=client if client else order.client, endpoint='orders/items' ) self.tax = item.get('base_tax_amount', item.get('tax_amount', 0)) self.refund = item.get('base_amount_refunded', item.get('amount_refunded', 0)) self.tax_refunded = item.get('base_tax_refunded', item.get('tax_refunded', 0)) self.line_total = item.get('base_row_total_incl_tax', item.get('row_total_incl_tax', 0)) self._order = order Initialize an OrderItem using an API response from the
orders/items
endpoint
- property excluded_keys: List[str]
API response keys that shouldn’t be set as object attributes by
set_attrs()
- Returns
list of API response keys that shouldn’t be set as attributes
- property product: Product
The item’s corresponding
Product
Note
If the ordered item:
Is a configurable product - the child simple product is returned
Has custom options - the base product is returned