/
invoice.py
120 lines (92 loc) · 3.71 KB
/
invoice.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
from __future__ import annotations
from . import Model, Order, OrderItem, Product, Customer
from typing import TYPE_CHECKING, Optional, List, Union
from functools import cached_property
if TYPE_CHECKING:
from magento import Client
from magento.search import SearchQuery
class Invoice(Model):
"""Wrapper for the ``invoices`` endpoint"""
DOCUMENTATION = 'https://adobe-commerce.redoc.ly/2.3.7-admin/tag/invoices'
IDENTIFIER = 'entity_id'
def __init__(self, data: dict, client: Client):
"""Initialize an Invoice object using an API response from the ``invoices`` endpoint
:param data: API response from the ``invoices`` endpoint
:param client: an initialized :class:`~.Client` object
"""
super().__init__(
data=data,
client=client,
endpoint='invoices',
private_keys=True
)
def __repr__(self):
return f'<Magento Invoice: #{self.number}> for {self.order}'
@property
def excluded_keys(self) -> List[str]:
return ['items']
@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 order(self) -> Order:
"""The corresponding :class:`~.Order`"""
return self.client.orders.by_id(self.order_id)
@cached_property
def customer(self) -> Customer:
"""The corresponding :class:`~.Customer`"""
return self.client.customers.by_invoice(self)
@cached_property
def items(self) -> List[InvoiceItem]:
"""The invoiced items, returned as a list of :class:`InvoiceItem` objects"""
return [InvoiceItem(item, self) for item in self.__items
if item['order_item_id'] in self.order.item_ids]
class InvoiceItem(Model):
"""Wraps an item entry of an :class:`Invoice`"""
DOCUMENTATION = "https://adobe-commerce.redoc.ly/2.3.7-admin/tag/invoicesid"
IDENTIFIER = 'entity_id'
def __init__(self, item: dict, invoice: Invoice):
"""Initialize an InvoiceItem of an :class:`Invoice`
:param item: API response to use as source data
:param invoice: the :class:`Invoice` that this is an item of
"""
super().__init__(
data=item,
client=invoice.client,
endpoint=f'invoices/{invoice.id}'
)
self.invoice = invoice
def __repr__(self):
return f"<InvoiceItem ({self.sku})> from {self.invoice}"
def data_endpoint(self, scope: Optional[str] = None) -> None:
"""No data endpoint exists for invoice items"""
return self.logger.info("There is no API endpoint for individual invoice items")
def query_endpoint(self) -> None:
"""No search endpoint exists for invoice items"""
return self.logger.info("There is no API endpoint for querying invoice items")
@property
def excluded_keys(self) -> List[str]:
return ['product_id']
@property
def order(self) -> Order:
"""The :class:`~.Order` this item is from"""
return self.invoice.order
@cached_property
def order_item(self) -> OrderItem:
"""The item's corresponding :class:`~.OrderItem`"""
for item in self.order.items:
if item.item_id == self.order_item_id:
return item
@property
def product(self) -> Product:
"""The item's corresponding simple :class:`~.Product`"""
return self.order_item.product
@property
def product_id(self) -> int:
"""Id of the corresponding simple :class:`~.Product`"""
return self.order_item.product_id