producteca 2.0.14__py3-none-any.whl → 2.0.16__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- producteca/__init__.py +3 -0
- producteca/abstract/abstract_dataclass.py +13 -1
- producteca/client.py +2 -0
- producteca/payments/tests/test_payments.py +18 -2
- producteca/products/products.py +161 -39
- producteca/products/search_products.py +71 -74
- producteca/products/tests/test_products.py +96 -11
- producteca/products/tests/test_search_products.py +10 -10
- producteca/sales_orders/sales_orders.py +140 -97
- producteca/sales_orders/search_sale_orders.py +21 -21
- producteca/sales_orders/tests/test_sales_orders.py +49 -19
- producteca/sales_orders/tests/test_search_so.py +2 -4
- producteca/shipments/tests/test_shipment.py +19 -7
- {producteca-2.0.14.dist-info → producteca-2.0.16.dist-info}/METADATA +5 -5
- producteca-2.0.16.dist-info/RECORD +31 -0
- producteca-2.0.14.dist-info/RECORD +0 -31
- {producteca-2.0.14.dist-info → producteca-2.0.16.dist-info}/WHEEL +0 -0
- {producteca-2.0.14.dist-info → producteca-2.0.16.dist-info}/entry_points.txt +0 -0
@@ -13,6 +13,33 @@ class TestProduct(unittest.TestCase):
|
|
13
13
|
code="TEST001",
|
14
14
|
category="Test"
|
15
15
|
)
|
16
|
+
self.product_to_create_payload = {
|
17
|
+
"sku": "9817234",
|
18
|
+
"code": "871234",
|
19
|
+
"name": "Hola test",
|
20
|
+
"buyingPrice": 0,
|
21
|
+
"deals": [
|
22
|
+
{
|
23
|
+
"campaign": "string",
|
24
|
+
"regularPrice": 0,
|
25
|
+
"dealPrice": 0
|
26
|
+
}
|
27
|
+
],
|
28
|
+
"prices": [
|
29
|
+
{
|
30
|
+
"amount": 10,
|
31
|
+
"currency": "Local",
|
32
|
+
"priceList": "Default"
|
33
|
+
}
|
34
|
+
],
|
35
|
+
"stocks": [
|
36
|
+
{
|
37
|
+
"quantity": 2,
|
38
|
+
"availableQuantity": 2,
|
39
|
+
"warehouse": "Default"
|
40
|
+
}
|
41
|
+
],
|
42
|
+
}
|
16
43
|
|
17
44
|
@patch('requests.post')
|
18
45
|
def test_create_product_success(self, mock_post):
|
@@ -22,7 +49,7 @@ class TestProduct(unittest.TestCase):
|
|
22
49
|
mock_response.json.return_value = self.test_product.model_dump()
|
23
50
|
mock_post.return_value = mock_response
|
24
51
|
|
25
|
-
response = self.client.Product(**self.test_product.model_dump()).
|
52
|
+
response = self.client.Product(**self.test_product.model_dump()).synchronize(self.product_to_create_payload)
|
26
53
|
|
27
54
|
self.assertEqual(response.sku, "TEST001")
|
28
55
|
|
@@ -34,17 +61,17 @@ class TestProduct(unittest.TestCase):
|
|
34
61
|
mock_post.return_value = mock_response
|
35
62
|
|
36
63
|
with self.assertRaises(Exception):
|
37
|
-
self.client.Product.
|
64
|
+
self.client.Product.synchronize(self.product_to_create_payload)
|
38
65
|
|
39
66
|
@patch('requests.post')
|
40
67
|
def test_update_product_success(self, mock_post):
|
41
|
-
|
68
|
+
payload = self.product_to_create_payload
|
42
69
|
mock_response = Mock()
|
43
70
|
mock_response.status_code = 200
|
44
71
|
mock_response.json.return_value = self.test_product.model_dump()
|
45
72
|
mock_post.return_value = mock_response
|
46
73
|
|
47
|
-
response = self.client.Product(**self.test_product.model_dump()).
|
74
|
+
response = self.client.Product(**self.test_product.model_dump()).synchronize(payload)
|
48
75
|
|
49
76
|
self.assertEqual(response.name, "Test Product")
|
50
77
|
|
@@ -65,28 +92,86 @@ class TestProduct(unittest.TestCase):
|
|
65
92
|
# Mock get bundle response
|
66
93
|
mock_response = Mock()
|
67
94
|
mock_response.status_code = 200
|
68
|
-
test_prod =
|
69
|
-
|
95
|
+
test_prod = {
|
96
|
+
"results": [
|
97
|
+
{
|
98
|
+
"companyId": 0,
|
99
|
+
"productId": 0,
|
100
|
+
"variations": [
|
101
|
+
{
|
102
|
+
"variationId": 0,
|
103
|
+
"components": [
|
104
|
+
{
|
105
|
+
"quantity": 0,
|
106
|
+
"variationId": 0,
|
107
|
+
"productId": 0
|
108
|
+
}
|
109
|
+
]
|
110
|
+
}
|
111
|
+
],
|
112
|
+
"id": "string"
|
113
|
+
}
|
114
|
+
],
|
115
|
+
"count": 0
|
116
|
+
}
|
70
117
|
mock_response.json.return_value = test_prod
|
71
118
|
mock_get.return_value = mock_response
|
72
119
|
|
73
120
|
product = self.client.Product.get_bundle(1)
|
74
121
|
|
75
|
-
self.assertEqual(product.
|
122
|
+
self.assertEqual(product.count, 0)
|
76
123
|
|
77
124
|
@patch('requests.get')
|
78
125
|
def test_get_ml_integration(self, mock_get):
|
79
126
|
# Mock ML integration response
|
80
127
|
mock_response = Mock()
|
81
128
|
mock_response.status_code = 200
|
82
|
-
|
83
|
-
|
84
|
-
|
129
|
+
meli_product = {
|
130
|
+
"hasCustomShippingCosts": True,
|
131
|
+
"productId": 0,
|
132
|
+
"shipping": {
|
133
|
+
"localPickup": True,
|
134
|
+
"mode": "string",
|
135
|
+
"freeShipping": True,
|
136
|
+
"freeShippingCost": 0,
|
137
|
+
"mandatoryFreeShipping": True,
|
138
|
+
"freeShippingMethod": "string"
|
139
|
+
},
|
140
|
+
"mShopsShipping": {
|
141
|
+
"enabled": True
|
142
|
+
},
|
143
|
+
"addFreeShippingCostToPrice": True,
|
144
|
+
"category": {
|
145
|
+
"meliId": "string",
|
146
|
+
"acceptsMercadoenvios": True,
|
147
|
+
"suggest": True,
|
148
|
+
"fixed": True
|
149
|
+
},
|
150
|
+
"attributeCompletion": {
|
151
|
+
"productIdentifierStatus": "Complete",
|
152
|
+
"dataSheetStatus": "Complete",
|
153
|
+
"status": "Complete",
|
154
|
+
"count": 0,
|
155
|
+
"total": 0
|
156
|
+
},
|
157
|
+
"catalogProducts": [
|
158
|
+
"string"
|
159
|
+
],
|
160
|
+
"warranty": "string",
|
161
|
+
"domain": "string",
|
162
|
+
"listingTypeId": "GoldSpecial",
|
163
|
+
"catalogProductsStatus": "Unlinked",
|
164
|
+
"tags": [
|
165
|
+
"string"
|
166
|
+
]
|
167
|
+
}
|
168
|
+
|
169
|
+
mock_response.json.return_value = meli_product
|
85
170
|
mock_get.return_value = mock_response
|
86
171
|
|
87
172
|
product = self.client.Product.get_ml_integration(1)
|
88
173
|
|
89
|
-
self.assertEqual(product.
|
174
|
+
self.assertEqual(product.listing_type_id, "GoldSpecial")
|
90
175
|
|
91
176
|
|
92
177
|
if __name__ == '__main__':
|
@@ -34,8 +34,8 @@ class TestSearchProduct(unittest.TestCase):
|
|
34
34
|
"results": [{
|
35
35
|
"@search.score": 1.0,
|
36
36
|
"id": 123,
|
37
|
-
"
|
38
|
-
"
|
37
|
+
"productId": 456,
|
38
|
+
"companyId": 789,
|
39
39
|
"name": "Test Product",
|
40
40
|
"code": "TEST-001",
|
41
41
|
"skus": ["SKU001"],
|
@@ -47,18 +47,18 @@ class TestSearchProduct(unittest.TestCase):
|
|
47
47
|
"quantity": 10,
|
48
48
|
"reserved": 0
|
49
49
|
}],
|
50
|
-
"
|
51
|
-
"
|
52
|
-
"
|
53
|
-
"
|
50
|
+
"warehousesWithStock": ["Main"],
|
51
|
+
"totalStock": 10,
|
52
|
+
"hasPictures": True,
|
53
|
+
"buyingPrice": 100.0,
|
54
54
|
"prices": [{
|
55
|
-
"
|
56
|
-
"
|
55
|
+
"priceListId": 1,
|
56
|
+
"priceList": "Default",
|
57
57
|
"amount": 200.0,
|
58
58
|
"currency": "USD"
|
59
59
|
}],
|
60
|
-
"
|
61
|
-
"
|
60
|
+
"integrationIds": ["INT001"],
|
61
|
+
"integrationApps": ["APP1"],
|
62
62
|
"integrations": [],
|
63
63
|
"campaigns": [],
|
64
64
|
"app": None,
|
@@ -11,56 +11,56 @@ _logger = logging.getLogger(__name__)
|
|
11
11
|
|
12
12
|
|
13
13
|
class SaleOrderLocation(BaseModel):
|
14
|
-
|
15
|
-
|
16
|
-
|
14
|
+
street_name: Optional[str] = Field(None, alias="streetName")
|
15
|
+
street_number: Optional[str] = Field(None, alias="streetNumber")
|
16
|
+
address_notes: Optional[str] = Field(None, alias="addressNotes")
|
17
17
|
state: Optional[str] = None
|
18
18
|
city: Optional[str] = None
|
19
19
|
neighborhood: Optional[str] = None
|
20
|
-
|
20
|
+
zip_code: Optional[str] = Field(None, alias="zipCode")
|
21
21
|
|
22
22
|
|
23
23
|
class SaleOrderBillingInfo(BaseModel):
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
24
|
+
doc_type: Optional[str] = Field(None, alias="docType")
|
25
|
+
doc_number: Optional[str] = Field(None, alias="docNumber")
|
26
|
+
street_name: Optional[str] = Field(None, alias="streetName")
|
27
|
+
street_number: Optional[str] = Field(None, alias="streetNumber")
|
28
28
|
comment: Optional[str] = None
|
29
|
-
|
29
|
+
zip_code: Optional[str] = Field(None, alias="zipCode")
|
30
30
|
city: Optional[str] = None
|
31
31
|
state: Optional[str] = None
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
32
|
+
state_registration: Optional[str] = Field(None, alias="stateRegistration")
|
33
|
+
tax_payer_type: Optional[str] = Field(None, alias="taxPayerType")
|
34
|
+
first_name: Optional[str] = Field(None, alias="firstName")
|
35
|
+
last_name: Optional[str] = Field(None, alias="lastName")
|
36
|
+
business_name: Optional[str] = Field(None, alias="businessName")
|
37
37
|
|
38
38
|
|
39
39
|
class SaleOrderProfile(BaseModel):
|
40
40
|
app: int
|
41
|
-
|
41
|
+
integration_id: str = Field(alias="integrationId")
|
42
42
|
nickname: Optional[str] = None
|
43
43
|
|
44
44
|
|
45
45
|
class SaleOrderContact(BaseModel):
|
46
46
|
id: int
|
47
47
|
name: str
|
48
|
-
|
48
|
+
contact_person: Optional[str] = Field(None, alias="contactPerson")
|
49
49
|
mail: Optional[str] = None
|
50
|
-
|
51
|
-
|
50
|
+
phone_number: Optional[str] = Field(None, alias="phoneNumber")
|
51
|
+
tax_id: Optional[str] = Field(None, alias="taxId")
|
52
52
|
location: Optional[SaleOrderLocation] = None
|
53
53
|
notes: Optional[str] = None
|
54
54
|
type: Optional[str] = None
|
55
|
-
|
56
|
-
|
55
|
+
price_list: Optional[str] = Field(None, alias="priceList")
|
56
|
+
price_list_id: Optional[str] = Field(None, alias="priceListId")
|
57
57
|
profile: Optional[SaleOrderProfile] = None
|
58
|
-
|
58
|
+
billing_info: Optional[SaleOrderBillingInfo] = Field(None, alias="billingInfo")
|
59
59
|
|
60
60
|
|
61
61
|
class SaleOrderIntegrationId(BaseModel):
|
62
|
-
|
63
|
-
|
62
|
+
alternate_id: Optional[str] = Field(None, alias="alternateId")
|
63
|
+
integration_id: str = Field(alias="integrationId")
|
64
64
|
app: int
|
65
65
|
|
66
66
|
|
@@ -70,11 +70,11 @@ class SaleOrderVariationPicture(BaseModel):
|
|
70
70
|
|
71
71
|
|
72
72
|
class SaleOrderVariationStock(BaseModel):
|
73
|
-
|
73
|
+
warehouse_id: Optional[int] = Field(None, alias="warehouseId")
|
74
74
|
warehouse: str
|
75
75
|
quantity: int
|
76
76
|
reserved: int
|
77
|
-
|
77
|
+
last_modified: Optional[str] = Field(None, alias="lastModified")
|
78
78
|
available: int
|
79
79
|
|
80
80
|
|
@@ -84,13 +84,13 @@ class SaleOrderVariationAttribute(BaseModel):
|
|
84
84
|
|
85
85
|
|
86
86
|
class SaleOrderVariation(BaseModel):
|
87
|
-
|
87
|
+
supplier_code: Optional[str] = Field(None, alias="supplierCode")
|
88
88
|
pictures: Optional[List[SaleOrderVariationPicture]] = None
|
89
89
|
stocks: Optional[List[SaleOrderVariationStock]] = None
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
90
|
+
integration_id: Optional[int] = Field(None, alias="integrationId")
|
91
|
+
attributes_hash: Optional[str] = Field(None, alias="attributesHash")
|
92
|
+
primary_color: Optional[str] = Field(None, alias="primaryColor")
|
93
|
+
secondary_color: Optional[str] = Field(None, alias="secondaryColor")
|
94
94
|
size: Optional[str] = None
|
95
95
|
thumbnail: Optional[str] = None
|
96
96
|
attributes: Optional[List[SaleOrderVariationAttribute]] = None
|
@@ -113,11 +113,11 @@ class SaleOrderConversation(BaseModel):
|
|
113
113
|
|
114
114
|
class SaleOrderLine(BaseModel):
|
115
115
|
price: float
|
116
|
-
|
117
|
-
|
116
|
+
original_price: Optional[float] = Field(None, alias="originalPrice")
|
117
|
+
transaction_fee: Optional[float] = Field(None, alias="transactionFee")
|
118
118
|
product: SaleOrderProduct
|
119
119
|
variation: SaleOrderVariation
|
120
|
-
|
120
|
+
order_variation_integration_id: Optional[str] = Field(None, alias="orderVariationIntegrationId")
|
121
121
|
quantity: int
|
122
122
|
conversation: Optional[SaleOrderConversation] = None
|
123
123
|
reserved: Optional[int] = None
|
@@ -125,38 +125,38 @@ class SaleOrderLine(BaseModel):
|
|
125
125
|
|
126
126
|
|
127
127
|
class SaleOrderCard(BaseModel):
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
128
|
+
payment_network: Optional[str] = Field(None, alias="paymentNetwork")
|
129
|
+
first_six_digits: Optional[int] = Field(None, alias="firstSixDigits")
|
130
|
+
last_four_digits: Optional[int] = Field(None, alias="lastFourDigits")
|
131
|
+
cardholder_identification_number: Optional[str] = Field(None, alias="cardholderIdentificationNumber")
|
132
|
+
cardholder_identification_type: Optional[str] = Field(None, alias="cardholderIdentificationType")
|
133
|
+
cardholder_name: Optional[str] = Field(None, alias="cardholderName")
|
134
134
|
|
135
135
|
|
136
136
|
class SaleOrderPaymentIntegration(BaseModel):
|
137
|
-
|
137
|
+
integration_id: str = Field(alias="integrationId")
|
138
138
|
app: int
|
139
139
|
|
140
140
|
|
141
141
|
class SaleOrderPayment(BaseModel):
|
142
142
|
date: Optional[str] = None
|
143
143
|
amount: float
|
144
|
-
|
144
|
+
coupon_amount: Optional[float] = Field(None, alias="couponAmount")
|
145
145
|
status: Optional[str] = None
|
146
146
|
method: Optional[str] = None
|
147
147
|
integration: Optional[SaleOrderPaymentIntegration] = None
|
148
|
-
|
148
|
+
transaction_fee: Optional[float] = Field(None, alias="transactionFee")
|
149
149
|
installments: Optional[int] = None
|
150
150
|
card: Optional[SaleOrderCard] = None
|
151
151
|
notes: Optional[str] = None
|
152
|
-
|
153
|
-
|
152
|
+
authorization_code: Optional[str] = Field(None, alias="authorizationCode")
|
153
|
+
has_cancelable_status: Optional[bool] = Field(None, alias="hasCancelableStatus")
|
154
154
|
id: Optional[int] = None
|
155
155
|
|
156
156
|
|
157
157
|
class SaleOrderShipmentMethod(BaseModel):
|
158
|
-
|
159
|
-
|
158
|
+
tracking_number: Optional[str] = Field(None, alias="trackingNumber")
|
159
|
+
tracking_url: Optional[str] = Field(None, alias="trackingUrl")
|
160
160
|
courier: Optional[str] = None
|
161
161
|
mode: Optional[str] = None
|
162
162
|
cost: Optional[float] = None
|
@@ -173,7 +173,7 @@ class SaleOrderShipmentProduct(BaseModel):
|
|
173
173
|
|
174
174
|
class SaleOrderShipmentIntegration(BaseModel):
|
175
175
|
app: int
|
176
|
-
|
176
|
+
integration_id: str = Field(alias="integrationId")
|
177
177
|
status: str
|
178
178
|
id: int
|
179
179
|
|
@@ -187,70 +187,101 @@ class SaleOrderShipment(BaseModel):
|
|
187
187
|
id: int
|
188
188
|
|
189
189
|
|
190
|
-
class
|
191
|
-
id:
|
192
|
-
|
193
|
-
app:
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
190
|
+
class SaleOrderInvoiceIntegrationAbstract(BaseModel):
|
191
|
+
id: int
|
192
|
+
integration_id: str = Field(alias="integrationId")
|
193
|
+
app: int
|
194
|
+
created_at: str = Field(alias="createdAt")
|
195
|
+
decrease_stock: bool = Field(alias="decreaseStock")
|
196
|
+
|
197
|
+
|
198
|
+
class SaleOrderInvoiceIntegration(SaleOrderInvoiceIntegrationAbstract):
|
199
|
+
document_url: Optional[str] = Field(None, alias="documentUrl")
|
200
|
+
xml_url: Optional[str] = Field(None, alias="xmlUrl")
|
201
|
+
|
202
|
+
|
203
|
+
class SaleOrderInvoiceIntegrationPut(SaleOrderInvoiceIntegrationAbstract):
|
204
|
+
document_url: str = Field(alias="documentUrl")
|
205
|
+
xml_url: str = Field(alias="xmlUrl")
|
198
206
|
|
199
207
|
|
200
208
|
class SaleOrder(BaseModel):
|
201
209
|
tags: Optional[List[str]] = None
|
202
210
|
integrations: Optional[List[SaleOrderIntegrationId]] = None
|
203
|
-
|
211
|
+
invoice_integration: SaleOrderInvoiceIntegration = Field(alias="invoiceIntegration")
|
204
212
|
channel: Optional[str] = None
|
205
|
-
|
213
|
+
pii_expired: Optional[bool] = Field(None, alias="piiExpired")
|
206
214
|
contact: Optional[SaleOrderContact] = None
|
207
215
|
lines: Optional[List[SaleOrderLine]] = None
|
208
216
|
warehouse: Optional[str] = None
|
209
|
-
|
210
|
-
|
211
|
-
|
217
|
+
warehouse_id: Optional[int] = Field(None, alias="warehouseId")
|
218
|
+
warehouse_integration: Optional[str] = Field(None, alias="warehouseIntegration")
|
219
|
+
pick_up_store: Optional[str] = Field(None, alias="pickUpStore")
|
212
220
|
payments: Optional[List[SaleOrderPayment]] = None
|
213
221
|
shipments: Optional[List[SaleOrderShipment]] = None
|
214
222
|
amount: Optional[float] = None
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
223
|
+
shipping_cost: Optional[float] = Field(None, alias="shippingCost")
|
224
|
+
financial_cost: Optional[float] = Field(None, alias="financialCost")
|
225
|
+
paid_approved: Optional[float] = Field(None, alias="paidApproved")
|
226
|
+
payment_status: Optional[str] = Field(None, alias="paymentStatus")
|
227
|
+
delivery_status: Optional[str] = Field(None, alias="deliveryStatus")
|
228
|
+
payment_fulfillment_status: Optional[str] = Field(None, alias="paymentFulfillmentStatus")
|
229
|
+
delivery_fulfillment_status: Optional[str] = Field(None, alias="deliveryFulfillmentStatus")
|
230
|
+
delivery_method: Optional[str] = Field(None, alias="deliveryMethod")
|
231
|
+
payment_term: Optional[str] = Field(None, alias="paymentTerm")
|
224
232
|
currency: Optional[str] = None
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
233
|
+
custom_id: Optional[str] = Field(None, alias="customId")
|
234
|
+
is_open: Optional[bool] = Field(None, alias="isOpen")
|
235
|
+
is_canceled: Optional[bool] = Field(None, alias="isCanceled")
|
236
|
+
cart_id: Optional[str] = Field(None, alias="cartId")
|
229
237
|
draft: Optional[bool] = None
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
238
|
+
promise_delivery_date: Optional[str] = Field(None, alias="promiseDeliveryDate")
|
239
|
+
promise_dispatch_date: Optional[str] = Field(None, alias="promiseDispatchDate")
|
240
|
+
has_any_shipments: Optional[bool] = Field(None, alias="hasAnyShipments")
|
241
|
+
has_any_payments: Optional[bool] = Field(None, alias="hasAnyPayments")
|
234
242
|
date: Optional[str] = None
|
235
243
|
notes: Optional[str] = None
|
236
244
|
id: int
|
237
245
|
|
238
246
|
|
247
|
+
class SaleOrderSynchronize(BaseModel):
|
248
|
+
id: int
|
249
|
+
invoice_integration: SaleOrderInvoiceIntegration = Field(alias="invoiceIntegration")
|
250
|
+
notes: Optional[str] = None
|
251
|
+
tags: Optional[List[str]] = None
|
252
|
+
|
253
|
+
|
254
|
+
class UpdateStatus(BaseModel):
|
255
|
+
updated: bool = False
|
256
|
+
|
257
|
+
|
258
|
+
class SaleOrderSyncResponse(BaseModel):
|
259
|
+
basic: UpdateStatus = Field(default_factory=UpdateStatus)
|
260
|
+
contact: UpdateStatus = Field(default_factory=UpdateStatus)
|
261
|
+
shipments: UpdateStatus = Field(default_factory=UpdateStatus)
|
262
|
+
payments: UpdateStatus = Field(default_factory=UpdateStatus)
|
263
|
+
invoice_integration: UpdateStatus = Field(alias="invoiceIntegration", default_factory=UpdateStatus)
|
264
|
+
|
265
|
+
|
239
266
|
@dataclass
|
240
267
|
class SaleOrderService(BaseService[SaleOrder]):
|
241
|
-
endpoint: str =
|
268
|
+
endpoint: str = 'salesorders'
|
242
269
|
|
243
270
|
def __call__(self, **payload):
|
244
271
|
self._record = SaleOrder(**payload)
|
245
272
|
return self
|
246
273
|
|
247
|
-
def
|
274
|
+
def __repr__(self):
|
275
|
+
return repr(self._record)
|
276
|
+
|
277
|
+
def get(self, sale_order_id: int) -> "SaleOrderService":
|
248
278
|
endpoint = f'{self.endpoint}/{sale_order_id}'
|
249
279
|
url = self.config.get_endpoint(endpoint)
|
250
280
|
response = requests.get(url, headers=self.config.headers)
|
251
281
|
if not response.ok:
|
252
282
|
raise Exception("Order could not be fetched")
|
253
|
-
|
283
|
+
response_data = response.json()
|
284
|
+
return self(**response_data)
|
254
285
|
|
255
286
|
def get_shipping_labels(self):
|
256
287
|
if not self._record:
|
@@ -278,25 +309,32 @@ class SaleOrderService(BaseService[SaleOrder]):
|
|
278
309
|
url = self.config.get_endpoint(endpoint)
|
279
310
|
response = requests.post(url, headers=self.config.headers)
|
280
311
|
if not response.ok:
|
281
|
-
raise Exception("Order could not be
|
312
|
+
raise Exception("Order could not be cancelled")
|
282
313
|
|
283
|
-
def synchronize(self
|
314
|
+
def synchronize(self) -> "SaleOrderService":
|
315
|
+
if not self._record:
|
316
|
+
raise Exception("You need to add a record by calling the resource and adding info")
|
284
317
|
endpoint = f'{self.endpoint}/synchronize'
|
285
318
|
url = self.config.get_endpoint(endpoint)
|
286
|
-
|
319
|
+
# TODO: Check what can we sync, and what can we not sync
|
320
|
+
sync_body = SaleOrderSynchronize(**self._record.model_dump(by_alias=True))
|
321
|
+
response = requests.post(url, json=sync_body.model_dump(by_alias=True), headers=self.config.headers)
|
287
322
|
if not response.ok:
|
288
|
-
raise Exception(f"Synchronize error {response.text}")
|
289
|
-
|
323
|
+
raise Exception(f"Synchronize error {response.status_code} {response.text}")
|
324
|
+
sync_res = SaleOrderSyncResponse(**response.json()) # noqa
|
325
|
+
return self
|
290
326
|
|
291
327
|
def invoice_integration(self):
|
292
328
|
if not self._record:
|
293
329
|
raise Exception("You need to add a record id")
|
294
330
|
endpoint = f'{self.endpoint}/{self._record.id}/invoiceIntegration'
|
295
331
|
url = self.config.get_endpoint(endpoint)
|
296
|
-
response = requests.put(url, headers=self.config.headers,
|
332
|
+
response = requests.put(url, headers=self.config.headers,
|
333
|
+
json={"id": self._record.id,
|
334
|
+
"invoiceIntegration": SaleOrderInvoiceIntegrationPut(**self._record.invoice_integration.model_dump(by_alias=True)).model_dump()})
|
297
335
|
if not response.ok:
|
298
336
|
raise Exception(f"Error on resposne {response.text}")
|
299
|
-
return
|
337
|
+
return response.ok
|
300
338
|
|
301
339
|
def search(self, params: SearchSalesOrderParams):
|
302
340
|
endpoint: str = f"search/{self.endpoint}"
|
@@ -308,41 +346,46 @@ class SaleOrderService(BaseService[SaleOrder]):
|
|
308
346
|
headers=headers,
|
309
347
|
)
|
310
348
|
if not response.ok:
|
311
|
-
raise Exception(f"Error on resposne {response.text}")
|
312
|
-
|
349
|
+
raise Exception(f"Error on resposne {response.status_code} - {response.text}")
|
350
|
+
response_data = response.json()
|
351
|
+
return SearchSalesOrder(**response_data)
|
313
352
|
|
314
|
-
def add_payment(self, payload
|
353
|
+
def add_payment(self, payload) -> Payment:
|
315
354
|
if not self._record:
|
316
355
|
raise Exception("You need to add a record id")
|
356
|
+
payment = Payment(**payload)
|
317
357
|
url = self.config.get_endpoint(f"{self.endpoint}/{self._record.id}/payments")
|
318
|
-
res = requests.post(url,
|
358
|
+
res = requests.post(url, json=payment.model_dump(by_alias=True, exclude_none=True), headers=self.config.headers)
|
319
359
|
if not res.ok:
|
320
360
|
raise Exception(f"Error on resposne {res.text}")
|
321
361
|
return Payment(**res.json())
|
322
362
|
|
323
|
-
def update_payment(self, payment_id: int, payload
|
363
|
+
def update_payment(self, payment_id: int, payload) -> "Payment":
|
324
364
|
if not self._record:
|
325
365
|
raise Exception("You need to add a record id")
|
366
|
+
payment = Payment(**payload)
|
326
367
|
url = self.config.get_endpoint(f"{self.endpoint}/{self._record.id}/payments/{payment_id}")
|
327
|
-
res = requests.put(url,
|
368
|
+
res = requests.put(url, json=payment.model_dump(by_alias=True, exclude_none=True), headers=self.config.headers)
|
328
369
|
if not res.ok:
|
329
370
|
raise Exception(f"Error on payment update {res.text}")
|
330
371
|
return Payment(**res.json())
|
331
372
|
|
332
|
-
def add_shipment(self, payload
|
373
|
+
def add_shipment(self, payload) -> "Shipment":
|
333
374
|
if not self._record:
|
334
375
|
raise Exception("You need to add a record id")
|
376
|
+
shipment = Shipment(**payload)
|
335
377
|
url = self.config.get_endpoint(f"{self.endpoint}/{self._record.id}/shipments")
|
336
|
-
res = requests.post(url,
|
378
|
+
res = requests.post(url, json=shipment.model_dump(by_alias=True, exclude_none=True), headers=self.config.headers)
|
337
379
|
if not res.ok:
|
338
380
|
raise Exception(f"Error on shipment add {res.text}")
|
339
381
|
return Shipment(**res.json())
|
340
382
|
|
341
|
-
def update_shipment(self, shipment_id: str, payload
|
383
|
+
def update_shipment(self, shipment_id: str, payload) -> "Shipment":
|
342
384
|
if not self._record:
|
343
385
|
raise Exception("You need to add a record id")
|
386
|
+
shipment = Shipment(**payload)
|
344
387
|
url = self.config.get_endpoint(f"{self.endpoint}/{self._record.id}/shipments/{shipment_id}")
|
345
|
-
res = requests.put(url,
|
388
|
+
res = requests.put(url, json=shipment.model_dump(by_alias=True, exclude_none=True), headers=self.config.headers)
|
346
389
|
if not res.ok:
|
347
390
|
raise Exception(f"Error on shipment update {res.text}")
|
348
391
|
return Shipment(**res.json())
|