channel-app 0.0.131__py3-none-any.whl → 0.0.135__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.
- channel_app/app/product/service.py +16 -0
- channel_app/core/commands.py +3 -1
- channel_app/core/tests.py +15 -164
- channel_app/omnitron/commands/tests/test_products.py +494 -0
- {channel_app-0.0.131.dist-info → channel_app-0.0.135.dist-info}/METADATA +1 -1
- channel_app-0.0.135.dist-info/RECORD +60 -0
- {channel_app-0.0.131.dist-info → channel_app-0.0.135.dist-info}/WHEEL +1 -1
- channel_app/channel_app/app/__init__.py +0 -0
- channel_app/channel_app/app/order/__init__.py +0 -0
- channel_app/channel_app/app/order/service.py +0 -230
- channel_app/channel_app/app/product/__init__.py +0 -0
- channel_app/channel_app/app/product/service.py +0 -237
- channel_app/channel_app/app/product_price/__init__.py +0 -0
- channel_app/channel_app/app/product_price/service.py +0 -254
- channel_app/channel_app/app/product_stock/__init__.py +0 -0
- channel_app/channel_app/app/product_stock/service.py +0 -258
- channel_app/channel_app/app/setup/__init__.py +0 -0
- channel_app/channel_app/app/setup/service.py +0 -61
- channel_app/channel_app/channel/__init__.py +0 -0
- channel_app/channel_app/channel/commands/__init__.py +0 -0
- channel_app/channel_app/channel/commands/orders/__init__.py +0 -0
- channel_app/channel_app/channel/commands/orders/orders.py +0 -329
- channel_app/channel_app/channel/commands/product_categories.py +0 -1
- channel_app/channel_app/channel/commands/product_images.py +0 -1
- channel_app/channel_app/channel/commands/product_prices.py +0 -148
- channel_app/channel_app/channel/commands/product_stocks.py +0 -220
- channel_app/channel_app/channel/commands/products.py +0 -161
- channel_app/channel_app/channel/commands/setup.py +0 -948
- channel_app/channel_app/channel/integration.py +0 -84
- channel_app/channel_app/core/__init__.py +0 -0
- channel_app/channel_app/core/clients.py +0 -12
- channel_app/channel_app/core/commands.py +0 -364
- channel_app/channel_app/core/data.py +0 -227
- channel_app/channel_app/core/integration.py +0 -74
- channel_app/channel_app/core/products.py +0 -64
- channel_app/channel_app/core/settings.py +0 -28
- channel_app/channel_app/core/utilities.py +0 -99
- channel_app/channel_app/omnitron/__init__.py +0 -0
- channel_app/channel_app/omnitron/batch_request.py +0 -82
- channel_app/channel_app/omnitron/commands/__init__.py +0 -0
- channel_app/channel_app/omnitron/commands/batch_requests.py +0 -281
- channel_app/channel_app/omnitron/commands/error_reports.py +0 -86
- channel_app/channel_app/omnitron/commands/integration_actions.py +0 -200
- channel_app/channel_app/omnitron/commands/orders/__init__.py +0 -0
- channel_app/channel_app/omnitron/commands/orders/addresses.py +0 -242
- channel_app/channel_app/omnitron/commands/orders/cargo_companies.py +0 -40
- channel_app/channel_app/omnitron/commands/orders/customers.py +0 -72
- channel_app/channel_app/omnitron/commands/orders/orders.py +0 -450
- channel_app/channel_app/omnitron/commands/product_categories.py +0 -1
- channel_app/channel_app/omnitron/commands/product_images.py +0 -1
- channel_app/channel_app/omnitron/commands/product_prices.py +0 -192
- channel_app/channel_app/omnitron/commands/product_stocks.py +0 -229
- channel_app/channel_app/omnitron/commands/products.py +0 -735
- channel_app/channel_app/omnitron/commands/setup.py +0 -839
- channel_app/channel_app/omnitron/constants.py +0 -98
- channel_app/channel_app/omnitron/exceptions.py +0 -42
- channel_app/channel_app/omnitron/integration.py +0 -159
- channel_app/setup.py +0 -21
- channel_app-0.0.131.dist-info/RECORD +0 -110
- /channel_app/{channel_app → omnitron/commands/tests}/__init__.py +0 -0
- {channel_app-0.0.131.dist-info → channel_app-0.0.135.dist-info}/top_level.txt +0 -0
@@ -1,450 +0,0 @@
|
|
1
|
-
from typing import List
|
2
|
-
|
3
|
-
from omnisdk.omnitron.endpoints import (ChannelCreateOrderEndpoint,
|
4
|
-
ChannelIntegrationActionEndpoint,
|
5
|
-
ChannelOrderShippingInfoEndpoint,
|
6
|
-
ChannelOrderItemEndpoint,
|
7
|
-
ChannelBatchRequestEndpoint,
|
8
|
-
ChannelOrderEndpoint,
|
9
|
-
ChannelCargoEndpoint,
|
10
|
-
ChannelCancellationRequestEndpoint)
|
11
|
-
from omnisdk.omnitron.models import Order, OrderShippingInfo, \
|
12
|
-
CancellationRequest
|
13
|
-
|
14
|
-
from channel_app.core.commands import OmnitronCommandInterface
|
15
|
-
from channel_app.core.data import (OrderBatchRequestResponseDto,
|
16
|
-
OmnitronCreateOrderDto, OmnitronOrderDto,
|
17
|
-
OrderItemDto, CancelOrderDto, ErrorReportDto)
|
18
|
-
from channel_app.core.utilities import split_list
|
19
|
-
from channel_app.omnitron.batch_request import ClientBatchRequest
|
20
|
-
from channel_app.omnitron.commands.batch_requests import ProcessBatchRequests
|
21
|
-
from channel_app.omnitron.constants import (ContentType, BatchRequestStatus)
|
22
|
-
|
23
|
-
|
24
|
-
class GetOrders(OmnitronCommandInterface):
|
25
|
-
endpoint = ChannelOrderEndpoint
|
26
|
-
batch_service = ClientBatchRequest
|
27
|
-
content_type = ContentType.order.value
|
28
|
-
path = "updates"
|
29
|
-
BATCH_SIZE = 100
|
30
|
-
|
31
|
-
def get_data(self) -> List[Order]:
|
32
|
-
orders = self.get_orders()
|
33
|
-
return orders
|
34
|
-
|
35
|
-
def get_orders(self) -> List[Order]:
|
36
|
-
orders = self.endpoint(
|
37
|
-
path=self.path, channel_id=self.integration.channel_id
|
38
|
-
).list(
|
39
|
-
params={
|
40
|
-
"limit": self.BATCH_SIZE
|
41
|
-
}
|
42
|
-
)
|
43
|
-
orders = orders[:self.BATCH_SIZE]
|
44
|
-
|
45
|
-
objects_data = self.create_batch_objects(
|
46
|
-
data=orders, content_type=self.content_type)
|
47
|
-
self.update_batch_request(objects_data=objects_data)
|
48
|
-
|
49
|
-
return orders
|
50
|
-
|
51
|
-
|
52
|
-
class GetOrderItems(OmnitronCommandInterface):
|
53
|
-
endpoint = ChannelOrderItemEndpoint
|
54
|
-
|
55
|
-
def get_data(self):
|
56
|
-
order = self.objects
|
57
|
-
order_items = self.get_order_items(order)
|
58
|
-
for order_item in order_items:
|
59
|
-
order_item.content_type = ContentType.order_item.value
|
60
|
-
self.integration.do_action(key="get_integration_with_object_id",
|
61
|
-
objects=order_items)
|
62
|
-
return order_items
|
63
|
-
|
64
|
-
|
65
|
-
class ProcessOrderBatchRequests(OmnitronCommandInterface, ProcessBatchRequests):
|
66
|
-
"""
|
67
|
-
Not finalized batch requests with content type `order` is managed in this command
|
68
|
-
"""
|
69
|
-
endpoint = ChannelBatchRequestEndpoint
|
70
|
-
content_type = ContentType.order.value
|
71
|
-
BATCH_SIZE = 100
|
72
|
-
CHUNK_SIZE = 50
|
73
|
-
|
74
|
-
def validated_data(self, data: List[OrderBatchRequestResponseDto]):
|
75
|
-
for item in data:
|
76
|
-
assert isinstance(item, OrderBatchRequestResponseDto)
|
77
|
-
return data
|
78
|
-
|
79
|
-
def send(self, validated_data):
|
80
|
-
result = self.process_item(validated_data)
|
81
|
-
return result
|
82
|
-
|
83
|
-
@property
|
84
|
-
def update_state(self, *args, **kwargs) -> BatchRequestStatus:
|
85
|
-
return BatchRequestStatus.done
|
86
|
-
|
87
|
-
def get_remote_order_number(self, obj, integration_actions):
|
88
|
-
for integration_action in integration_actions:
|
89
|
-
content_type = integration_action.content_type["model"]
|
90
|
-
if content_type != "order":
|
91
|
-
continue
|
92
|
-
if integration_action.object_id == obj.pk:
|
93
|
-
return integration_action.remote_id
|
94
|
-
|
95
|
-
def get_channel_items_by_reference_object_ids(self, channel_response,
|
96
|
-
model_items_by_content,
|
97
|
-
integration_actions):
|
98
|
-
channel_items_by_order_id = {}
|
99
|
-
for order_id, order in model_items_by_content["order"].items():
|
100
|
-
for channel_item in channel_response:
|
101
|
-
# TODO: comment
|
102
|
-
number = self.get_remote_order_number(obj=order,
|
103
|
-
integration_actions=integration_actions)
|
104
|
-
if channel_item.number != number:
|
105
|
-
continue
|
106
|
-
remote_item = channel_item
|
107
|
-
channel_items_by_order_id[order_id] = remote_item
|
108
|
-
break
|
109
|
-
return channel_items_by_order_id
|
110
|
-
|
111
|
-
def get_orders(self, id_list) -> dict:
|
112
|
-
if not id_list:
|
113
|
-
return {}
|
114
|
-
|
115
|
-
end_point = ChannelOrderEndpoint(
|
116
|
-
channel_id=self.integration.channel_id)
|
117
|
-
orders = []
|
118
|
-
for chunk_id_list in split_list(id_list, self.CHUNK_SIZE):
|
119
|
-
orders_batch = end_point.list(
|
120
|
-
params={"id__in": ",".join(chunk_id_list),
|
121
|
-
"limit": len(chunk_id_list)})
|
122
|
-
orders.extend(orders_batch)
|
123
|
-
return {order.pk: order for order in orders}
|
124
|
-
|
125
|
-
def group_model_items_by_content_type(self, items_by_content):
|
126
|
-
batch_items = {}
|
127
|
-
for model, model_pks in items_by_content.items():
|
128
|
-
if model != "order":
|
129
|
-
continue
|
130
|
-
group_items = self.get_orders(model_pks)
|
131
|
-
batch_items[model] = group_items
|
132
|
-
return batch_items
|
133
|
-
|
134
|
-
|
135
|
-
class CreateOrders(OmnitronCommandInterface):
|
136
|
-
endpoint = ChannelCreateOrderEndpoint
|
137
|
-
content_type = ContentType.order.value
|
138
|
-
CHUNK_SIZE = 50
|
139
|
-
|
140
|
-
def get_data(self) -> dict:
|
141
|
-
assert isinstance(self.objects, OmnitronCreateOrderDto)
|
142
|
-
|
143
|
-
order = self.objects.order
|
144
|
-
order_item = self.objects.order_item
|
145
|
-
order_items = self.prepare_order_items(order_items=order_item)
|
146
|
-
extra_field = self.get_extra_field(order)
|
147
|
-
data = {
|
148
|
-
"order_item": order_items,
|
149
|
-
"order": {
|
150
|
-
"number": order.number[:128],
|
151
|
-
"channel": self.integration.channel_id,
|
152
|
-
"customer": order.customer,
|
153
|
-
"shipping_address": order.shipping_address,
|
154
|
-
"billing_address": order.billing_address,
|
155
|
-
"currency": order.currency,
|
156
|
-
"amount": order.amount,
|
157
|
-
"shipping_amount": order.shipping_amount,
|
158
|
-
"shipping_tax_rate": order.shipping_tax_rate,
|
159
|
-
"extra_field": extra_field,
|
160
|
-
"delivery_type": order.delivery_type,
|
161
|
-
"cargo_company": order.cargo_company,
|
162
|
-
"discount_amount": order.discount_amount or 0,
|
163
|
-
"net_shipping_amount": order.net_shipping_amount,
|
164
|
-
"tracking_number": order.tracking_number[:256],
|
165
|
-
"carrier_shipping_code": order.carrier_shipping_code[:256],
|
166
|
-
"remote_addr": order.remote_addr,
|
167
|
-
"has_gift_box": order.has_gift_box,
|
168
|
-
"gift_box_note": order.gift_box_note[:160],
|
169
|
-
"client_type": "default",
|
170
|
-
"language_code": order.language_code,
|
171
|
-
"notes": order.notes[:320],
|
172
|
-
"delivery_range": order.delivery_type,
|
173
|
-
"shipping_option_slug": order.shipping_option_slug[:128],
|
174
|
-
"date_placed": str(order.created_at)
|
175
|
-
}
|
176
|
-
}
|
177
|
-
return data
|
178
|
-
|
179
|
-
def get_extra_field(self, order: OmnitronOrderDto):
|
180
|
-
extra_field = order.extra_field or {}
|
181
|
-
if "id" not in extra_field and order.remote_id:
|
182
|
-
extra_field.update({"id": order.remote_id})
|
183
|
-
return extra_field
|
184
|
-
|
185
|
-
def send(self, validated_data) -> object:
|
186
|
-
order_obj = Order(**validated_data)
|
187
|
-
order = self.endpoint(channel_id=self.integration.channel_id).create(
|
188
|
-
item=order_obj)
|
189
|
-
self._update_batch_request(order)
|
190
|
-
return order
|
191
|
-
|
192
|
-
def normalize_response(self, data, response) -> List[object]:
|
193
|
-
return [data]
|
194
|
-
|
195
|
-
def _update_batch_request(self, order):
|
196
|
-
order.remote_id = order.extra_field.get("id")
|
197
|
-
objects_data_order = self.create_batch_objects(data=[order],
|
198
|
-
content_type=ContentType.order.value)
|
199
|
-
order_items = self.get_order_items(order_pk=order.pk)
|
200
|
-
for item in order_items:
|
201
|
-
item.remote_id = item.extra_field["id"]
|
202
|
-
objects_data_order_items = self.create_batch_objects(
|
203
|
-
data=order_items,
|
204
|
-
content_type=ContentType.order_item.value)
|
205
|
-
objects_data = []
|
206
|
-
objects_data.extend(objects_data_order)
|
207
|
-
objects_data.extend(objects_data_order_items)
|
208
|
-
self.update_batch_request(objects_data=objects_data)
|
209
|
-
|
210
|
-
def get_order_items(self, order_pk):
|
211
|
-
params = {"order": order_pk}
|
212
|
-
endpoint = ChannelOrderItemEndpoint(
|
213
|
-
channel_id=self.integration.channel_id)
|
214
|
-
order_items = endpoint.list(params=params)
|
215
|
-
for item in endpoint.iterator:
|
216
|
-
if not item:
|
217
|
-
break
|
218
|
-
order_items.extend(item)
|
219
|
-
return order_items
|
220
|
-
|
221
|
-
@property
|
222
|
-
def update_state(self, *args, **kwargs) -> BatchRequestStatus:
|
223
|
-
return BatchRequestStatus.done
|
224
|
-
|
225
|
-
def prepare_order_items(self, order_items: List[OrderItemDto]):
|
226
|
-
product_dict = self.get_products(order_items)
|
227
|
-
items = []
|
228
|
-
for item in order_items:
|
229
|
-
price_list = self.integration.catalog.price_list
|
230
|
-
stock_list = self.integration.catalog.stock_list
|
231
|
-
order_item_data = {
|
232
|
-
"product": product_dict[item.product],
|
233
|
-
"status": item.status or "400",
|
234
|
-
"price_currency": item.price_currency,
|
235
|
-
"price": item.price,
|
236
|
-
"tax_rate": item.tax_rate,
|
237
|
-
"extra_field": {
|
238
|
-
"id": item.remote_id
|
239
|
-
},
|
240
|
-
"price_list": item.price_list or price_list,
|
241
|
-
"stock_list": item.stock_list or stock_list,
|
242
|
-
"tracking_number": item.tracking_number,
|
243
|
-
"carrier_shipping_code": item.carrier_shipping_code[:256],
|
244
|
-
"discount_amount": item.discount_amount,
|
245
|
-
"retail_price": item.retail_price,
|
246
|
-
"attributes": item.attributes or {},
|
247
|
-
"attributes_kwargs": item.attributes_kwargs or {},
|
248
|
-
"parent": item.parent,
|
249
|
-
"delivered_date": item.delivered_date,
|
250
|
-
"estimated_delivery_date": item.delivered_date,
|
251
|
-
}
|
252
|
-
items.append(order_item_data)
|
253
|
-
return items
|
254
|
-
|
255
|
-
def get_order_item_extra_field(self, order_item: OrderItemDto):
|
256
|
-
extra_field = order_item.extra_field
|
257
|
-
if "id" not in extra_field and order_item.remote_id:
|
258
|
-
extra_field.update({"id": order_item.remote_id})
|
259
|
-
return extra_field
|
260
|
-
|
261
|
-
def get_products(self, order_items: List[OrderItemDto]) -> dict:
|
262
|
-
product_remote_ids = self.get_product_remote_id_list(order_items)
|
263
|
-
endpoint = ChannelIntegrationActionEndpoint(
|
264
|
-
channel_id=self.integration.channel_id)
|
265
|
-
product_integration_actions = []
|
266
|
-
for chunk in split_list(product_remote_ids, self.CHUNK_SIZE):
|
267
|
-
params = {"channel": self.integration.channel_id,
|
268
|
-
"content_type_model": ContentType.product.value,
|
269
|
-
"remote_id__in": ",".join(chunk)}
|
270
|
-
ia = endpoint.list(params=params)
|
271
|
-
product_integration_actions.extend(ia)
|
272
|
-
return {ia.remote_id: ia.object_id for ia in
|
273
|
-
product_integration_actions}
|
274
|
-
|
275
|
-
def get_product_remote_id_list(self, order_items: List[OrderItemDto]):
|
276
|
-
product_remote_ids = [item.product for item in order_items]
|
277
|
-
return product_remote_ids
|
278
|
-
|
279
|
-
|
280
|
-
class CreateOrderShippingInfo(OmnitronCommandInterface):
|
281
|
-
endpoint = ChannelOrderShippingInfoEndpoint
|
282
|
-
|
283
|
-
def get_data(self) -> dict:
|
284
|
-
order: Order = self.objects
|
285
|
-
cargo_is_send = self.integration.channel.conf.get(
|
286
|
-
"send_shipping_info", False)
|
287
|
-
shipping_company = self.get_shipping_company(
|
288
|
-
cargo_company_id=order.cargo_company)
|
289
|
-
data = {
|
290
|
-
"order": order.pk,
|
291
|
-
"order_number": order.number,
|
292
|
-
"shipping_company": shipping_company,
|
293
|
-
"is_send": cargo_is_send
|
294
|
-
}
|
295
|
-
return data
|
296
|
-
|
297
|
-
def get_shipping_company(self, cargo_company_id):
|
298
|
-
endpoint = ChannelCargoEndpoint(channel_id=self.integration.channel_id)
|
299
|
-
cargo_company = endpoint.retrieve(id=cargo_company_id)
|
300
|
-
return cargo_company
|
301
|
-
|
302
|
-
def send(self, validated_data) -> object:
|
303
|
-
"""
|
304
|
-
:param validated_data: data for order
|
305
|
-
:return: order objects
|
306
|
-
"""
|
307
|
-
order_shipping_info_obj = OrderShippingInfo(**validated_data)
|
308
|
-
order = self.endpoint(channel_id=self.integration.channel_id).create(
|
309
|
-
item=order_shipping_info_obj)
|
310
|
-
return order
|
311
|
-
|
312
|
-
def check_run(self, is_ok, formatted_data):
|
313
|
-
if not is_ok:
|
314
|
-
return False
|
315
|
-
return True
|
316
|
-
|
317
|
-
|
318
|
-
class CreateOrderCancel(OmnitronCommandInterface):
|
319
|
-
endpoint = ChannelOrderEndpoint
|
320
|
-
path = "{pk}/cancel"
|
321
|
-
|
322
|
-
def get_data(self):
|
323
|
-
assert isinstance(self.objects, CancelOrderDto)
|
324
|
-
cancel_data = self.objects
|
325
|
-
order_pk = self.get_order_pk(order_remote_id=cancel_data.order)
|
326
|
-
order_item_dict = self.get_order_item_dict(
|
327
|
-
cancel_items=cancel_data.cancel_items)
|
328
|
-
order_item_pk_list = []
|
329
|
-
for key, pk_list in order_item_dict.items():
|
330
|
-
order_item_pk_list.extend(pk_list)
|
331
|
-
|
332
|
-
reasons = self.get_reasons_data(order_item_dict=order_item_dict,
|
333
|
-
reasons=cancel_data.reasons)
|
334
|
-
|
335
|
-
data = {
|
336
|
-
"cancel_items": order_item_pk_list,
|
337
|
-
"order": order_pk,
|
338
|
-
"reasons": reasons
|
339
|
-
}
|
340
|
-
return data
|
341
|
-
|
342
|
-
def get_order_pk(self, order_remote_id):
|
343
|
-
end_point = ChannelIntegrationActionEndpoint(
|
344
|
-
channel_id=self.integration.channel_id)
|
345
|
-
params = {"channel": self.integration.channel_id,
|
346
|
-
"content_type_model": ContentType.order.value,
|
347
|
-
"remote_id": order_remote_id}
|
348
|
-
integration_actions = end_point.list(params=params)
|
349
|
-
if not integration_actions:
|
350
|
-
raise Exception(
|
351
|
-
"Order not found: number={}".format(order_remote_id))
|
352
|
-
if len(integration_actions) != 1:
|
353
|
-
raise Exception(
|
354
|
-
"CancelOrder.get_order_pk query incorrect: params={}".format(
|
355
|
-
params))
|
356
|
-
|
357
|
-
integration_action = integration_actions[0]
|
358
|
-
object_id = integration_action.object_id
|
359
|
-
return object_id
|
360
|
-
|
361
|
-
def get_order_item_dict(self, cancel_items: List[str]) -> dict:
|
362
|
-
"""
|
363
|
-
cancel_items: ["121", "232"] -> omnitron orderitem remote_id list
|
364
|
-
:return: dict
|
365
|
-
{orderitem_remote_id: [omnitron_id1, omnitronid2]}
|
366
|
-
{"121": [1001]}
|
367
|
-
{"232": [1002, 1003]}
|
368
|
-
"""
|
369
|
-
end_point = ChannelIntegrationActionEndpoint(
|
370
|
-
channel_id=self.integration.channel_id)
|
371
|
-
|
372
|
-
object_ids = {}
|
373
|
-
for order_item_remote_id in cancel_items:
|
374
|
-
params = {"channel": self.integration.channel_id,
|
375
|
-
"content_type_model": ContentType.order_item.value,
|
376
|
-
"remote_id": order_item_remote_id}
|
377
|
-
integration_actions = end_point.list(params=params)
|
378
|
-
for item in end_point.iterator:
|
379
|
-
if not item:
|
380
|
-
break
|
381
|
-
integration_actions.extend(item)
|
382
|
-
|
383
|
-
if not integration_actions:
|
384
|
-
raise Exception(
|
385
|
-
"CreateOrderCancel: OrderItem not found, number={}".format(
|
386
|
-
order_item_remote_id))
|
387
|
-
ids = [integration_action.object_id
|
388
|
-
for integration_action in integration_actions]
|
389
|
-
|
390
|
-
object_ids[order_item_remote_id] = ids
|
391
|
-
|
392
|
-
return object_ids
|
393
|
-
|
394
|
-
def get_reasons_data(self, order_item_dict: dict, reasons: dict):
|
395
|
-
"""
|
396
|
-
order_item_dict: dict # {remote_basketitem_id: [id1,id2]}
|
397
|
-
reasons: dict # {order_item_remote_id: remote_reason_code}
|
398
|
-
"""
|
399
|
-
reasons_dict = {} # order_item_id: reason_id
|
400
|
-
for order_item_remote_id, reason_remote_code in reasons.items():
|
401
|
-
order_item_id_list = order_item_dict[order_item_remote_id]
|
402
|
-
reason_mapping = self.integration.channel.conf.get(
|
403
|
-
"reason_mapping", {})
|
404
|
-
try:
|
405
|
-
cancellation_reason_id = reason_mapping[reason_remote_code]
|
406
|
-
except KeyError:
|
407
|
-
cancellation_reason_id = self.integration.channel.conf.get(
|
408
|
-
"cancellation_reason_id")
|
409
|
-
|
410
|
-
for order_item_id in order_item_id_list:
|
411
|
-
reasons_dict[order_item_id] = cancellation_reason_id
|
412
|
-
return reasons_dict
|
413
|
-
|
414
|
-
def send(self, validated_data) -> Order:
|
415
|
-
path = self.path.format(validated_data["order"])
|
416
|
-
endpoint = self.endpoint(path=path,
|
417
|
-
channel_id=self.integration.channel_id,
|
418
|
-
raw=True)
|
419
|
-
response = endpoint.create(item=validated_data)
|
420
|
-
return response
|
421
|
-
|
422
|
-
def normalize_response(self, data, response) -> List[object]:
|
423
|
-
return [data]
|
424
|
-
|
425
|
-
|
426
|
-
class GetCancellationRequest(OmnitronCommandInterface):
|
427
|
-
endpoint = ChannelCancellationRequestEndpoint
|
428
|
-
content_type = ContentType.cancellation_request.value
|
429
|
-
CHUNK_SIZE = 50
|
430
|
-
|
431
|
-
def get_data(self):
|
432
|
-
"""
|
433
|
-
{"status": "approved", "cancellation_type": "refund or cancel", "order_item": 3212}
|
434
|
-
"""
|
435
|
-
assert isinstance(self.objects, dict)
|
436
|
-
query_params = self.objects
|
437
|
-
if not query_params.get("limit", None):
|
438
|
-
query_params["limit"] = self.CHUNK_SIZE
|
439
|
-
return self.get_cancellation_requests(query_params=query_params)
|
440
|
-
|
441
|
-
def get_cancellation_requests(self, query_params={}) -> List[
|
442
|
-
CancellationRequest]:
|
443
|
-
endpoint = self.endpoint(path=self.path,
|
444
|
-
channel_id=self.integration.channel_id)
|
445
|
-
cancellation_requests = endpoint.list(query_params)
|
446
|
-
for batch in endpoint.iterator:
|
447
|
-
if not batch:
|
448
|
-
break
|
449
|
-
cancellation_requests.extend(batch)
|
450
|
-
return cancellation_requests
|
@@ -1 +0,0 @@
|
|
1
|
-
#TODO omnitron product category integration
|
@@ -1 +0,0 @@
|
|
1
|
-
#TODO omnitron image integration
|
@@ -1,192 +0,0 @@
|
|
1
|
-
from typing import List
|
2
|
-
|
3
|
-
from omnisdk.omnitron.endpoints import ChannelIntegrationActionEndpoint, \
|
4
|
-
ChannelProductPriceEndpoint, ChannelBatchRequestEndpoint, \
|
5
|
-
ChannelExtraProductPriceEndpoint
|
6
|
-
from omnisdk.omnitron.models import ProductPrice
|
7
|
-
|
8
|
-
from channel_app.core.commands import OmnitronCommandInterface
|
9
|
-
from channel_app.core.data import BatchRequestResponseDto
|
10
|
-
from channel_app.omnitron.commands.batch_requests import ProcessBatchRequests
|
11
|
-
from channel_app.omnitron.constants import (ContentType, BatchRequestStatus,
|
12
|
-
IntegrationActionStatus,
|
13
|
-
FailedReasonType)
|
14
|
-
|
15
|
-
|
16
|
-
class GetUpdatedProductPrices(OmnitronCommandInterface):
|
17
|
-
endpoint = ChannelProductPriceEndpoint
|
18
|
-
path = "updates"
|
19
|
-
BATCH_SIZE = 100
|
20
|
-
content_type = ContentType.product_price.value
|
21
|
-
|
22
|
-
def get_data(self) -> List[ProductPrice]:
|
23
|
-
prices = self.get_product_prices()
|
24
|
-
prices = self.get_integration_actions(prices)
|
25
|
-
return prices
|
26
|
-
|
27
|
-
def get_product_prices(self) -> List[ProductPrice]:
|
28
|
-
prices = self.endpoint(
|
29
|
-
path=self.path,
|
30
|
-
channel_id=self.integration.channel_id
|
31
|
-
).list(
|
32
|
-
params={
|
33
|
-
"limit": self.BATCH_SIZE
|
34
|
-
}
|
35
|
-
)
|
36
|
-
prices = prices[:self.BATCH_SIZE]
|
37
|
-
objects_data = self.create_batch_objects(data=prices,
|
38
|
-
content_type=self.content_type)
|
39
|
-
self.update_batch_request(objects_data=objects_data)
|
40
|
-
return prices
|
41
|
-
|
42
|
-
def get_integration_actions(self, prices: List[ProductPrice]):
|
43
|
-
if not prices:
|
44
|
-
return []
|
45
|
-
endpoint = ChannelIntegrationActionEndpoint(
|
46
|
-
channel_id=self.integration.channel_id)
|
47
|
-
price_integration_actions = endpoint.list(
|
48
|
-
params={
|
49
|
-
"local_batch_id": self.integration.batch_request.local_batch_id,
|
50
|
-
"status": IntegrationActionStatus.processing,
|
51
|
-
"channel_id": self.integration.channel_id
|
52
|
-
})
|
53
|
-
for price_batch in endpoint.iterator:
|
54
|
-
price_integration_actions.extend(price_batch)
|
55
|
-
price_ia_dict = {ia.object_id: ia for ia in price_integration_actions}
|
56
|
-
for price in prices:
|
57
|
-
price_ia = price_ia_dict[price.pk]
|
58
|
-
price.remote_id = price_ia.remote_id
|
59
|
-
return prices
|
60
|
-
|
61
|
-
|
62
|
-
class GetInsertedProductPrices(GetUpdatedProductPrices):
|
63
|
-
path = "inserts"
|
64
|
-
|
65
|
-
def get_integration_actions(self, prices: List[ProductPrice]):
|
66
|
-
if not prices:
|
67
|
-
return []
|
68
|
-
endpoint = ChannelIntegrationActionEndpoint(
|
69
|
-
channel_id=self.integration.channel_id)
|
70
|
-
product_ids = [str(price.product) for price in prices]
|
71
|
-
product_ias = endpoint.list(
|
72
|
-
params={"object_id__in": ",".join(product_ids),
|
73
|
-
"content_type_name": ContentType.product.value,
|
74
|
-
"status": IntegrationActionStatus.success,
|
75
|
-
"channel_id": self.integration.channel_id
|
76
|
-
})
|
77
|
-
for product_batch in endpoint.iterator:
|
78
|
-
product_ias.extend(product_batch)
|
79
|
-
product_integrations_by_id = {ia.object_id: ia for ia in product_ias}
|
80
|
-
|
81
|
-
for price in prices:
|
82
|
-
if price.product in product_integrations_by_id:
|
83
|
-
product_ia = product_integrations_by_id[price.product]
|
84
|
-
price.remote_id = product_ia.remote_id
|
85
|
-
else:
|
86
|
-
price.failed_reason_type = FailedReasonType.channel_app.value
|
87
|
-
self.failed_object_list.append(
|
88
|
-
(price, ContentType.product_price.value,
|
89
|
-
"Product has not been sent"))
|
90
|
-
return prices
|
91
|
-
|
92
|
-
|
93
|
-
class GetInsertedProductPricesFromExtraPriceList(OmnitronCommandInterface):
|
94
|
-
endpoint = ChannelExtraProductPriceEndpoint
|
95
|
-
path = "inserts"
|
96
|
-
BATCH_SIZE = 100
|
97
|
-
content_type = ContentType.product_price.value
|
98
|
-
|
99
|
-
def get_data(self) -> List[ProductPrice]:
|
100
|
-
self.price_list_id = self.objects
|
101
|
-
prices = self.get_product_prices()
|
102
|
-
prices = self.get_integration_actions(prices)
|
103
|
-
return prices
|
104
|
-
|
105
|
-
def get_product_prices(self) -> List[ProductPrice]:
|
106
|
-
endpoint = self.endpoint(path=self.path,
|
107
|
-
channel_id=self.integration.channel_id)
|
108
|
-
prices = endpoint.list(
|
109
|
-
params={"price_list": self.price_list_id}
|
110
|
-
)
|
111
|
-
for price_batch in endpoint.iterator:
|
112
|
-
prices.extend(price_batch)
|
113
|
-
if len(prices) >= self.BATCH_SIZE:
|
114
|
-
break
|
115
|
-
prices = prices[:self.BATCH_SIZE]
|
116
|
-
objects_data = self.create_batch_objects(data=prices,
|
117
|
-
content_type=self.content_type)
|
118
|
-
self.update_batch_request(objects_data=objects_data)
|
119
|
-
return prices
|
120
|
-
|
121
|
-
def get_integration_actions(self, prices: List[ProductPrice]):
|
122
|
-
if not prices:
|
123
|
-
return []
|
124
|
-
endpoint = ChannelIntegrationActionEndpoint(
|
125
|
-
channel_id=self.integration.channel_id)
|
126
|
-
price_integration_actions = endpoint.list(
|
127
|
-
params={
|
128
|
-
"local_batch_id": self.integration.batch_request.local_batch_id,
|
129
|
-
"status": IntegrationActionStatus.processing
|
130
|
-
})
|
131
|
-
for price_batch in endpoint.iterator:
|
132
|
-
price_integration_actions.extend(price_batch)
|
133
|
-
price_ia_dict = {ia.object_id: ia for ia in price_integration_actions}
|
134
|
-
for price in prices:
|
135
|
-
price_ia = price_ia_dict[price.pk]
|
136
|
-
price.remote_id = price_ia.remote_id
|
137
|
-
return prices
|
138
|
-
|
139
|
-
|
140
|
-
class GetUpdatedProductPricesFromExtraPriceList(
|
141
|
-
GetInsertedProductPricesFromExtraPriceList):
|
142
|
-
path = "updates"
|
143
|
-
|
144
|
-
|
145
|
-
class ProcessPriceBatchRequests(OmnitronCommandInterface, ProcessBatchRequests):
|
146
|
-
endpoint = ChannelBatchRequestEndpoint
|
147
|
-
content_type = ContentType.product_price.value
|
148
|
-
CHUNK_SIZE = 50
|
149
|
-
BATCH_SIZE = 100
|
150
|
-
|
151
|
-
def get_data(self):
|
152
|
-
return self.objects
|
153
|
-
|
154
|
-
def validated_data(self, data: List[BatchRequestResponseDto]):
|
155
|
-
for item in data:
|
156
|
-
assert isinstance(item, BatchRequestResponseDto)
|
157
|
-
return data
|
158
|
-
|
159
|
-
def send(self, validated_data):
|
160
|
-
result = self.process_item(validated_data)
|
161
|
-
return result
|
162
|
-
|
163
|
-
@property
|
164
|
-
def update_state(self, *args, **kwargs) -> BatchRequestStatus:
|
165
|
-
return BatchRequestStatus.done
|
166
|
-
|
167
|
-
def check_run(self, is_ok, formatted_data):
|
168
|
-
if not is_ok and self.is_batch_request:
|
169
|
-
self.integration.batch_request.objects = None
|
170
|
-
self.batch_service(self.integration.channel_id).to_fail(
|
171
|
-
self.integration.batch_request)
|
172
|
-
return False
|
173
|
-
|
174
|
-
def get_channel_items_by_reference_object_ids(self, channel_response,
|
175
|
-
model_items_by_content,
|
176
|
-
integration_actions):
|
177
|
-
product_ids = [str(item) for item in
|
178
|
-
model_items_by_content["productprice"]]
|
179
|
-
|
180
|
-
model_items_by_content_product = self.get_products(product_ids)
|
181
|
-
|
182
|
-
channel_items_by_product_id = {}
|
183
|
-
for product_id, product in model_items_by_content_product.items():
|
184
|
-
for channel_item in channel_response:
|
185
|
-
# TODO: comment
|
186
|
-
sku = self.get_barcode(obj=product)
|
187
|
-
if channel_item.sku != sku:
|
188
|
-
continue
|
189
|
-
remote_item = channel_item
|
190
|
-
channel_items_by_product_id[product_id] = remote_item
|
191
|
-
break
|
192
|
-
return channel_items_by_product_id
|