channel-app 0.0.148__py3-none-any.whl → 0.0.150__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.
@@ -1,18 +1,27 @@
1
1
  from dataclasses import asdict
2
2
  from typing import List, Generator, Union
3
3
 
4
+ from requests import exceptions as requests_exceptions
5
+
4
6
  from omnisdk.omnitron.models import (Customer, Address, CargoCompany, Order,
5
- BatchRequest)
7
+ BatchRequest, CancellationRequest)
8
+ from omnisdk.omnitron.endpoints import ChannelIntegrationActionEndpoint
6
9
 
7
10
  from channel_app.core import settings
8
- from channel_app.core.data import (OmnitronCreateOrderDto, OmnitronOrderDto,
11
+ from channel_app.core.data import (BatchRequestResponseDto,
12
+ CancellationRequestDto,
13
+ ChannelCancellationRequestDto,
14
+ OmnitronCreateOrderDto,
15
+ OmnitronOrderDto,
9
16
  ChannelCreateOrderDto,
10
17
  ErrorReportDto,
11
- OrderBatchRequestResponseDto, CancelOrderDto,
18
+ OrderBatchRequestResponseDto,
19
+ CancelOrderDto,
12
20
  ChannelUpdateOrderItemDto)
13
21
  from channel_app.core.settings import OmnitronIntegration, ChannelIntegration
14
22
  from channel_app.omnitron.batch_request import ClientBatchRequest
15
- from channel_app.omnitron.constants import ContentType
23
+ from channel_app.omnitron.constants import (BatchRequestStatus, ContentType,
24
+ FailedReasonType)
16
25
  from channel_app.omnitron.exceptions import (CityException,
17
26
  TownshipException,
18
27
  DistrictException,
@@ -35,21 +44,21 @@ class OrderService(object):
35
44
  order_batch_objects = []
36
45
  while True:
37
46
  try:
38
- channel_create_order, report, _ = next(get_orders)
47
+ channel_create_order, report_list, _ = next(get_orders)
39
48
  except StopIteration:
40
49
  break
41
50
 
42
51
  # tips
43
52
  channel_create_order: ChannelCreateOrderDto
44
- report: ErrorReportDto
45
-
46
- if report and (is_success_log or not report.is_ok):
47
- report.error_code = \
48
- f"{omnitron_integration.batch_request.local_batch_id}" \
49
- f"_GetOrders_{channel_create_order.order.number}"
50
- omnitron_integration.do_action(
51
- key='create_error_report',
52
- objects=report)
53
+ report_list: List[ErrorReportDto]
54
+ for report in report_list:
55
+ if is_success_log or not report.is_ok:
56
+ report.error_code = \
57
+ f"{omnitron_integration.batch_request.local_batch_id}" \
58
+ f"-Channel-GetOrders_{channel_create_order.order.number}"
59
+ omnitron_integration.do_action(
60
+ key='create_error_report',
61
+ objects=report)
53
62
 
54
63
  order = self.create_order(omnitron_integration=omnitron_integration,
55
64
  channel_order=channel_create_order)
@@ -57,10 +66,15 @@ class OrderService(object):
57
66
  order_batch_objects.extend(omnitron_integration.batch_request.objects)
58
67
 
59
68
  omnitron_integration.batch_request.objects = order_batch_objects
60
-
61
- self.batch_service(settings.OMNITRON_CHANNEL_ID).to_done(
62
- batch_request=omnitron_integration.batch_request
63
- )
69
+ try:
70
+ self.batch_service(settings.OMNITRON_CHANNEL_ID).to_done(
71
+ batch_request=omnitron_integration.batch_request
72
+ )
73
+ except requests_exceptions.HTTPError as exc:
74
+ if exc.response.status_code == 406 and "batch_request_status_100_1" in exc.response.text:
75
+ pass
76
+ else:
77
+ raise exc
64
78
 
65
79
  def create_order(self, omnitron_integration: OmnitronIntegration,
66
80
  channel_order: ChannelCreateOrderDto
@@ -144,21 +158,21 @@ class OrderService(object):
144
158
  order_batch_objects = []
145
159
  while True:
146
160
  try:
147
- channel_update_order, report, _ = next(get_updated_orders)
161
+ channel_update_order, report_list, _ = next(get_updated_orders)
148
162
  except StopIteration:
149
163
  break
150
164
 
151
165
  # tips
152
166
  channel_update_order: ChannelUpdateOrderItemDto
153
- report: ErrorReportDto
154
-
155
- if report and (is_success_log or not report.is_ok):
156
- report.error_code = \
157
- f"{omnitron_integration.batch_request.local_batch_id}" \
158
- f"_GetUpdatedOrders_{channel_update_order.remote_id}"
159
- omnitron_integration.do_action(
160
- key='create_error_report',
161
- objects=report)
167
+ report_list: List[ErrorReportDto]
168
+ for report in report_list:
169
+ if report and (is_success_log or not report.is_ok):
170
+ report.error_code = \
171
+ f"{omnitron_integration.batch_request.local_batch_id}" \
172
+ f"_GetUpdatedOrders_{channel_update_order.remote_id}"
173
+ omnitron_integration.do_action(
174
+ key='create_error_report',
175
+ objects=report)
162
176
 
163
177
  omnitron_integration.do_action(
164
178
  key='update_order_items', objects=channel_update_order)
@@ -288,3 +302,166 @@ class OrderService(object):
288
302
  return success_data
289
303
  except IndexError:
290
304
  return
305
+
306
+ def fetch_and_create_cancellation_requests(self, is_success_log=True):
307
+ with OmnitronIntegration(
308
+ content_type=ContentType.cancellation_request.value) as omnitron_integration:
309
+ get_cancellation_requests = ChannelIntegration().do_action(
310
+ key='get_cancellation_requests',
311
+ batch_request=omnitron_integration.batch_request)
312
+ get_cancellation_requests: Generator
313
+ while True:
314
+ try:
315
+ cancellation_request, report_list, _ = next(get_cancellation_requests)
316
+ except StopIteration:
317
+ break
318
+
319
+ # tips
320
+ cancellation_request: CancellationRequestDto
321
+ report_list: List[ErrorReportDto]
322
+ for report in report_list:
323
+ if report and (is_success_log or not report.is_ok):
324
+ report.error_code = \
325
+ f"{omnitron_integration.batch_request.local_batch_id}" \
326
+ f"-Channel-GetCancellationRequests_{cancellation_request.order_item}"
327
+ omnitron_integration.do_action(
328
+ key='create_error_report',
329
+ objects=report)
330
+
331
+ # omnitron integration do action create_cancellation_request
332
+ cancellation_request_response = omnitron_integration.do_action(
333
+ key='create_cancellation_requests',
334
+ objects=cancellation_request)
335
+ try:
336
+ self.batch_service(settings.OMNITRON_CHANNEL_ID).to_done(
337
+ batch_request=omnitron_integration.batch_request
338
+ )
339
+ except requests_exceptions.HTTPError as exc:
340
+ if exc.response.status_code == 406 and "batch_request_status_100_1" in exc.response.text:
341
+ pass
342
+ else:
343
+ raise exc
344
+
345
+
346
+
347
+
348
+ def update_cancellation_requests(self, is_success_log=True):
349
+ with OmnitronIntegration(
350
+ content_type=ContentType.cancellation_request.value) as omnitron_integration:
351
+ cancellation_requests = omnitron_integration.do_action(
352
+ key='get_cancellation_requests_update', objects={})
353
+ cancellation_requests: List[CancellationRequest]
354
+
355
+ if not cancellation_requests:
356
+ omnitron_integration.batch_request.objects = None
357
+ self.batch_service(omnitron_integration.channel_id).to_fail(
358
+ omnitron_integration.batch_request)
359
+ return
360
+
361
+ batch_request_object_list = []
362
+
363
+ for cancellation_request in cancellation_requests:
364
+ remote_order_item = self.get_channel_order_item(
365
+ omnitron_integration, cancellation_request.order_item)
366
+ remote_reason = self.get_channel_reason(
367
+ omnitron_integration, cancellation_request.reason)
368
+ remote_cancellation_request = self.get_channel_cancellation_request(
369
+ omnitron_integration, cancellation_request.id)
370
+
371
+ channel_cancellation_request = ChannelCancellationRequestDto(
372
+ cancellation_type=cancellation_request.cancellation_type,
373
+ status=cancellation_request.status,
374
+ order_item=remote_order_item,
375
+ reason=remote_reason,
376
+ description=cancellation_request.description,
377
+ remote_id=remote_cancellation_request,
378
+ )
379
+ response_data, reports, data = ChannelIntegration().do_action(
380
+ key='update_cancellation_request',
381
+ objects=channel_cancellation_request,
382
+ batch_request=omnitron_integration.batch_request,
383
+ is_sync=True)
384
+
385
+ # tips
386
+ response_data: List[BatchRequestResponseDto]
387
+ reports: List[ErrorReportDto]
388
+ data: List[ChannelCancellationRequestDto]
389
+
390
+ if reports and (is_success_log or not reports[0].is_ok):
391
+ for report in reports:
392
+ omnitron_integration.do_action(
393
+ key='create_error_report',
394
+ objects=report)
395
+
396
+ if response_data:
397
+ failed_reason_type = None
398
+ else:
399
+ failed_reason_type = FailedReasonType.remote.value
400
+
401
+ batch_request_object_dto = dict(
402
+ pk=cancellation_request.id,
403
+ version_date=cancellation_request.modified_date,
404
+ content_type=ContentType.cancellation_request.value,
405
+ failed_reason_type=failed_reason_type,
406
+ remote_id=remote_cancellation_request)
407
+
408
+ batch_request_object_list.append(batch_request_object_dto)
409
+
410
+ status = BatchRequestStatus.fail.value
411
+ if any([br["failed_reason_type"] is None for br in batch_request_object_list]):
412
+ status = BatchRequestStatus.done.value
413
+
414
+ omnitron_integration.batch_request.objects = batch_request_object_list
415
+ service = self.batch_service(omnitron_integration.channel_id)
416
+
417
+ if status == BatchRequestStatus.done.value:
418
+ service.to_done(batch_request=omnitron_integration.batch_request)
419
+ else:
420
+ service.to_fail(batch_request=omnitron_integration.batch_request)
421
+
422
+ def get_channel_order_item(self, omnitron_integration, order_item):
423
+ channel_id = omnitron_integration.channel_id
424
+ end_point = ChannelIntegrationActionEndpoint(
425
+ channel_id=channel_id)
426
+ params = {
427
+ "channel": channel_id,
428
+ "content_type_name": ContentType.order_item.value,
429
+ "object_id": order_item
430
+ }
431
+ integration_action = end_point.list(params=params)
432
+ if not integration_action:
433
+ return Exception("Order item remote id not found: {}".format(order_item))
434
+ if len(integration_action) > 1:
435
+ return Exception("Multiple order item remote id found: {}".format(order_item))
436
+ return integration_action[0].remote_id
437
+
438
+ def get_channel_reason(self, omnitron_integration, omnitron_reason):
439
+ configuration = omnitron_integration.channel.conf
440
+ # configuration icinde yer alan reason_mapping anahtari bir json objesi,
441
+ # key channel_reason value omnitron_reason olan bir dict objesinden
442
+ # channel_reason'u döndürür
443
+ for channel_reason, omnitron_reason in configuration.get("reason_mapping", {}):
444
+ if omnitron_reason == omnitron_reason:
445
+ return channel_reason
446
+
447
+ return "10"
448
+
449
+ def get_channel_cancellation_request(self, omnitron_integration,
450
+ omnitron_cancel_request_pk):
451
+ channel_id = omnitron_integration.channel_id
452
+ end_point = ChannelIntegrationActionEndpoint(
453
+ channel_id=channel_id)
454
+ params = {
455
+ "channel": channel_id,
456
+ "content_type_name": ContentType.cancellation_request.value,
457
+ "object_id": omnitron_cancel_request_pk
458
+ }
459
+ integration_action = end_point.list(params=params)
460
+ if not integration_action:
461
+ return Exception("Cancellation request remote id not found: {}".format(
462
+ omnitron_cancel_request_pk))
463
+ if len(integration_action) > 1:
464
+ return Exception("Multiple cancellation request remote id found: {}".format(
465
+ omnitron_cancel_request_pk))
466
+ return integration_action[0].remote_id
467
+
@@ -5,9 +5,13 @@ from typing import Tuple, Any, List
5
5
  from omnisdk.omnitron.models import Order, BatchRequest
6
6
 
7
7
  from channel_app.core.commands import ChannelCommandInterface
8
- from channel_app.core.data import (ErrorReportDto, ChannelCreateOrderDto,
9
- AddressDto, CustomerDto, ChannelOrderDto,
10
- OrderItemDto, OrderBatchRequestResponseDto,
8
+ from channel_app.core.data import (BatchRequestResponseDto,
9
+ CancellationRequestDto,
10
+ ChannelCancellationRequestDto,
11
+ ErrorReportDto,
12
+ ChannelCreateOrderDto, AddressDto,
13
+ CustomerDto, ChannelOrderDto, OrderItemDto,
14
+ OrderBatchRequestResponseDto,
11
15
  CancelOrderDto, ChannelUpdateOrderItemDto)
12
16
  from channel_app.omnitron.constants import ResponseStatus
13
17
 
@@ -72,17 +76,19 @@ class GetOrders(ChannelCommandInterface):
72
76
  yield channel_create_order, report, None
73
77
 
74
78
  def __mocked_request(self, data):
79
+ number = str(int(random() * 1000000))
75
80
  return [{
76
81
  "order": {
77
- "remote_id": "123131",
78
- "number": "12331",
82
+ "status": "400",
83
+ "remote_id": number,
84
+ "number": number,
79
85
  "channel": "1",
80
86
  "currency": "try",
81
87
  "amount": "17",
82
88
  "shipping_amount": "0.0",
83
89
  "shipping_tax_rate": "18",
84
90
  "extra_field": {},
85
- "created_at": datetime.datetime.now(),
91
+ "created_at": str(datetime.datetime.now()),
86
92
  "customer": {
87
93
  "email": "dummy@dummy.com",
88
94
  "phone_number": None,
@@ -110,11 +116,11 @@ class GetOrders(ChannelCommandInterface):
110
116
  "city": "İstanbul",
111
117
  "line": "dummy 3 dummy cd"
112
118
  },
113
- "cargo_company": "aras kargo"
119
+ "cargo_company": "aras"
114
120
  },
115
121
  "order_items": [
116
122
  {
117
- "remote_id": "1234",
123
+ "remote_id": "1234567816",
118
124
  "product": "1234",
119
125
  "price_currency": "try",
120
126
  "price": "17.0",
@@ -351,21 +357,126 @@ class GetUpdatedOrderItems(ChannelCommandInterface):
351
357
  """
352
358
  Convert ChannelUpdateOrderItemDto to the format OmnitronIntegration
353
359
  """
354
- for response_order_data in response:
355
- order_items_data = response_order_data["order_items"]
356
-
357
- report = self.create_report(response_order_data)
358
- for order_item_data in order_items_data:
359
- channel_update_order_item = ChannelUpdateOrderItemDto(
360
- **order_item_data)
360
+ for order_item_data in response:
361
+ report = self.create_report(order_item_data)
362
+ channel_update_order_item = ChannelUpdateOrderItemDto(
363
+ **order_item_data)
361
364
 
362
- yield channel_update_order_item, report, None
365
+ yield channel_update_order_item, report, None
363
366
 
364
367
  def __mocked_request(self, data):
365
- return {
368
+ return [{
366
369
  "remote_id": "XYAD123213",
370
+ "order_remote_id": "1234",
371
+ "order_number": "1234",
367
372
  "status": "550",
368
373
  "invoice_number": "1234",
369
374
  "invoice_date": None,
370
- "tracking_number": "400"
375
+ "tracking_number": "400",
376
+ "extra_field": {"tracking_number": "1231"},
377
+ }]
378
+
379
+
380
+ class GetCancellationRequests(ChannelCommandInterface):
381
+ def get_data(self):
382
+ data = self.objects
383
+ return data
384
+
385
+ def validated_data(self, data) -> object:
386
+ return data
387
+
388
+ def transform_data(self, data) -> object:
389
+ return data
390
+
391
+ def send_request(self, transformed_data) -> object:
392
+ response = self.__mocked_request(data=transformed_data)
393
+ return response
394
+
395
+ def normalize_response(
396
+ self, data, validated_data, transformed_data,
397
+ response) -> Tuple[CancellationRequestDto, ErrorReportDto, Any]:
398
+ report = self.create_report(response)
399
+ for row in response:
400
+ obj = CancellationRequestDto(
401
+ order_item=row["order_item"],
402
+ reason=row["reason"],
403
+ cancellation_type=row["cancellation_type"],
404
+ remote_id=row["remote_id"]
405
+ )
406
+
407
+ yield obj, report, data
408
+
409
+ def __mocked_request(self, data):
410
+ """
411
+ Mock a request and response for the send operation to mimic actual
412
+ channel data
413
+
414
+ :return:
415
+
416
+ [{
417
+ "order_item": "remote_item_1",
418
+ "reason": "remote_reason_code",
419
+ "cancellation_type": "remote_cancellation_type"
420
+ },]
421
+ """
422
+ response_data = [
423
+ {
424
+ 'order_item': "1234567816",
425
+ 'reason': "iptal",
426
+ 'cancellation_type': "refund",
427
+ 'remote_id': "1234567816_1"
428
+ }
429
+ ]
430
+ return response_data
431
+
432
+
433
+ class UpdateCancellationRequest(ChannelCommandInterface):
434
+ def get_data(self) -> ChannelCancellationRequestDto:
435
+ isinstance(self.objects, ChannelCancellationRequestDto)
436
+ data = self.objects
437
+ return data
438
+
439
+ def validated_data(self, data) -> object:
440
+ return data
441
+
442
+ def transform_data(self, data) -> object:
443
+ return data
444
+
445
+ def send_request(self, transformed_data) -> object:
446
+ response = self.__mocked_request(data=transformed_data)
447
+ return response
448
+
449
+ def normalize_response(
450
+ self, data, validated_data, transformed_data,
451
+ response) -> Tuple[BatchRequestResponseDto, ErrorReportDto, Any]:
452
+
453
+ obj = BatchRequestResponseDto(
454
+ status=response["status"],
455
+ remote_id=response["remote_id"],
456
+ sku=response["sku"],
457
+ message=response["message"])
458
+
459
+ report = self.create_report(response)
460
+ return obj, report, data
461
+
462
+ def __mocked_request(self, data):
463
+ """
464
+ Mock a request and response for the send operation to mimic actual
465
+ channel data
466
+
467
+ :return:
468
+
469
+ {
470
+ "status": "SUCCESS",
471
+ "remote_id": "123a1",
472
+ "sku": "1234567",
473
+ "message": ""
474
+ }
475
+ """
476
+ return {
477
+ "status": ResponseStatus.success,
478
+ "remote_id": data.remote_id,
479
+ "sku": data.remote_id,
480
+ "message": data.status
371
481
  }
482
+
@@ -1006,6 +1006,11 @@ class GetChannelConfSchema(ChannelCommandInterface):
1006
1006
  data_type=ChannelConfSchemaDataTypes.text,
1007
1007
  key="setting_name_2",
1008
1008
  label="setting_name_2"),
1009
+ "reason_mapping": ChannelConfSchemaField(
1010
+ required=True,
1011
+ data_type=ChannelConfSchemaDataTypes.json,
1012
+ key="reason_mapping",
1013
+ label="reason_mapping"),
1009
1014
  }
1010
1015
 
1011
1016
  return schema, None, None
@@ -1,8 +1,8 @@
1
1
  import requests
2
2
 
3
3
  from channel_app.channel.commands.orders.orders import (
4
- GetOrders, CheckOrders, SendUpdatedOrders, GetCancelledOrders,
5
- GetUpdatedOrderItems)
4
+ GetCancellationRequests, GetOrders, CheckOrders, SendUpdatedOrders,
5
+ GetCancelledOrders, GetUpdatedOrderItems, UpdateCancellationRequest)
6
6
  from channel_app.channel.commands.product_images import (
7
7
  SendUpdatedImages, SendInsertedImages, CheckImages)
8
8
  from channel_app.channel.commands.product_prices import (
@@ -49,7 +49,9 @@ class ChannelIntegration(BaseIntegration):
49
49
  "get_updated_order_items": GetUpdatedOrderItems,
50
50
  "send_updated_orders": SendUpdatedOrders,
51
51
  "check_orders": CheckOrders,
52
- "get_cancelled_orders": GetCancelledOrders
52
+ "get_cancelled_orders": GetCancelledOrders,
53
+ "get_cancellation_requests": GetCancellationRequests,
54
+ "update_cancellation_request": UpdateCancellationRequest,
53
55
  }
54
56
 
55
57
  def __init__(self):
@@ -11,7 +11,7 @@ from channel_app.core.data import ErrorReportDto
11
11
  from channel_app.core.integration import BaseIntegration
12
12
  from channel_app.omnitron.batch_request import ClientBatchRequest
13
13
  from channel_app.omnitron.constants import BatchRequestStatus, ContentType
14
- from channel_app.omnitron.exceptions import (CountryException, CityException,
14
+ from channel_app.omnitron.exceptions import (AppException, CityException,
15
15
  TownshipException,
16
16
  DistrictException)
17
17
 
@@ -106,17 +106,24 @@ class ChannelCommandInterface(CommandInterface):
106
106
  if not self.is_batch_request:
107
107
  return
108
108
  name = self.__class__.__name__
109
+ if isinstance(response, Response):
110
+ raw_request = f"{response.request.method}-"
111
+ f"{response.request.url}-"
112
+ f"{response.request.body}"
113
+ raw_response = response.text
114
+ else:
115
+ raw_request = str("")
116
+ raw_response = str(response)
117
+
109
118
  report_list = []
110
119
  report = ErrorReportDto(
111
120
  action_content_type=ContentType.batch_request.value,
112
121
  action_object_id=self.batch_request.pk,
113
122
  modified_date=datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
114
- error_code=f"{self.batch_request.local_batch_id}-{name}-{datetime.now().timestamp()}",
115
- error_description=f"{self.batch_request.local_batch_id}-{name}",
116
- raw_request=f"{response.request.method}-"
117
- f"{response.request.url}-"
118
- f"{response.request.body}",
119
- raw_response=f"{response.text}"
123
+ error_code=f"{self.batch_request.local_batch_id}-Channel-{name}-{datetime.now().timestamp()}",
124
+ error_description=f"{name}",
125
+ raw_request=raw_request,
126
+ raw_response=raw_response
120
127
  )
121
128
  is_ok = self.check_response_is_ok(response=response)
122
129
  if is_ok:
@@ -130,7 +137,7 @@ class ChannelCommandInterface(CommandInterface):
130
137
  action_object_id=failed_obj[0].pk,
131
138
  modified_date=failed_obj[0].modified_date,
132
139
  error_code=f"{self.batch_request.local_batch_id}-{name}-{datetime.now().timestamp()}",
133
- error_description=f"{self.batch_request.local_batch_id}-{name}",
140
+ error_description=f"{name}",
134
141
  raw_request="",
135
142
  raw_response=f"{failed_obj[0].failed_reason_type}-{failed_obj[2]}",
136
143
  is_ok=False
@@ -139,7 +146,10 @@ class ChannelCommandInterface(CommandInterface):
139
146
  return report_list
140
147
 
141
148
  def check_response_is_ok(self, response):
142
- if str(response.status_code).startswith("2"):
149
+ is_response_obj = isinstance(response, Response)
150
+ if is_response_obj and str(response.status_code).startswith("2"):
151
+ return True
152
+ elif not is_response_obj and response:
143
153
  return True
144
154
  return False
145
155
 
@@ -209,15 +219,15 @@ class OmnitronCommandInterface(CommandInterface):
209
219
  raw_response = e.response.text
210
220
  is_ok = False
211
221
  logger.error(f"{raw_request}-/-{raw_response}")
212
- except CountryException as e:
213
- is_ok = False
214
- raw_response = str(e.params)
215
222
  except (CityException, TownshipException, DistrictException) as e:
216
223
  is_ok = False
217
224
  self.integration.do_action(
218
225
  key='create_address_error_report',
219
226
  objects=e.params)
220
227
  raw_response = str(e.params)
228
+ except AppException as e:
229
+ is_ok = False
230
+ raw_response = str(e.params)
221
231
  except Exception as e:
222
232
  is_ok = False
223
233
  raw_response = f"{str(e)} - {traceback.format_exc()}"
@@ -225,7 +235,6 @@ class OmnitronCommandInterface(CommandInterface):
225
235
  if request:
226
236
  raw_request = f"{request.method} - {request.url} - {request.body}"
227
237
  logger.error(f"{raw_request}-/-{raw_response}")
228
-
229
238
  finally:
230
239
  if not is_ok:
231
240
  self.send_error_report(raw_request, raw_response)
@@ -258,8 +267,8 @@ class OmnitronCommandInterface(CommandInterface):
258
267
  action_content_type=failed_obj[1],
259
268
  action_object_id=failed_obj[0].pk,
260
269
  modified_date=failed_obj[0].modified_date,
261
- error_code=f"{self.integration.batch_request.local_batch_id}-{name}",
262
- error_description=f"{self.integration.batch_request.local_batch_id}-{name}",
270
+ error_code=f"{self.integration.batch_request.local_batch_id}-Omnitron-{name}",
271
+ error_description=f"Omnitron-{name}",
263
272
  raw_request="",
264
273
  raw_response=f"{failed_obj[0].failed_reason_type}-{failed_obj[2]}",
265
274
  is_ok=False
@@ -278,7 +287,7 @@ class OmnitronCommandInterface(CommandInterface):
278
287
  action_object_id=self.integration.batch_request.pk,
279
288
  modified_date=datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
280
289
  error_code=f"{self.integration.batch_request.local_batch_id}-{name}-{datetime.now().microsecond}",
281
- error_description=f"{self.integration.batch_request.local_batch_id}-{name}",
290
+ error_description=f"Omnitron-{name}",
282
291
  raw_request=raw_request,
283
292
  raw_response=raw_response
284
293
  )
channel_app/core/data.py CHANGED
@@ -3,7 +3,7 @@ from dataclasses import dataclass
3
3
  from decimal import Decimal
4
4
  from typing import List, Optional
5
5
 
6
- from channel_app.omnitron.constants import ResponseStatus, \
6
+ from channel_app.omnitron.constants import CancellationType, ResponseStatus, \
7
7
  ChannelConfSchemaDataTypes
8
8
 
9
9
 
@@ -194,6 +194,14 @@ class CancelOrderDto:
194
194
  refund_invoice_number: Optional[str] = None
195
195
 
196
196
 
197
+ @dataclass
198
+ class CancellationRequestDto:
199
+ order_item: str # remote item number
200
+ reason: str # reason code
201
+ remote_id: str
202
+ cancellation_type: Optional[str] = "cancel"
203
+
204
+
197
205
  @dataclass
198
206
  class CustomerDto:
199
207
  email: str # "john.doe@akinon.com"
@@ -254,3 +262,13 @@ class ChannelUpdateOrderItemDto:
254
262
  invoice_date: Optional[str] = None
255
263
  tracking_number: Optional[str] = None
256
264
  extra_field: Optional[dict] = None
265
+
266
+
267
+ @dataclass
268
+ class ChannelCancellationRequestDto:
269
+ cancellation_type: CancellationType # cancel, refund
270
+ status: str # confirmed, waiting_approval, approved, rejected, completed
271
+ order_item: str # omnitron order item remote id
272
+ reason: str # omnitron reason code
273
+ description: Optional[str] # description for refund
274
+ remote_id: Optional[str] # remote id for cancellation request
@@ -1,5 +1,7 @@
1
1
  import importlib
2
2
  import os
3
+ from dotenv import load_dotenv
4
+ load_dotenv()
3
5
 
4
6
  env_variables = os.environ
5
7
 
@@ -21,8 +23,8 @@ DEFAULT_CONNECTION_POOL_MAX_SIZE = os.getenv("DEFAULT_CONNECTION_POOL_COUNT") or
21
23
  DEFAULT_CONNECTION_POOL_RETRY = os.getenv("DEFAULT_CONNECTION_POOL_RETRY") or 0
22
24
  REQUEST_LOG = os.getenv("REQUEST_LOG") or False
23
25
 
24
- omnitron_module = importlib.import_module(os.environ.get("OMNITRON_MODULE"))
26
+ omnitron_module = importlib.import_module(os.getenv("OMNITRON_MODULE"))
25
27
  OmnitronIntegration = omnitron_module.OmnitronIntegration
26
28
 
27
- channel_module = importlib.import_module(os.environ.get("CHANNEL_MODULE"))
29
+ channel_module = importlib.import_module(os.getenv("CHANNEL_MODULE"))
28
30
  ChannelIntegration = channel_module.ChannelIntegration
@@ -69,7 +69,7 @@ class GetOrCreateAddress(OmnitronCommandInterface):
69
69
  "district": district_pk,
70
70
  "title": address.title and address.title[:128],
71
71
  "line": address.line[:255],
72
- "postcode": address.postcode[:64],
72
+ "postcode": address.postcode and address.postcode[:64],
73
73
  "notes": address.notes and address.notes[:512],
74
74
  "company_name": address.company_name and address.company_name[:255],
75
75
  "tax_office": address.tax_office and address.tax_office[:64],
@@ -187,6 +187,10 @@ class GetOrCreateAddress(OmnitronCommandInterface):
187
187
  countries = endpoint.list(params=params)
188
188
  if len(countries) == 1:
189
189
  return countries[0]
190
+ params = {"name__exact": country_code, "is_active": True}
191
+ countries = endpoint.list(params=params)
192
+ if len(countries) == 1:
193
+ return countries[0]
190
194
  try:
191
195
  countries = self.get_mapping_object(country_code, endpoint)
192
196
  except IntegrationMappingException as exc:
@@ -4,6 +4,7 @@ from omnisdk.omnitron.endpoints import ChannelCargoEndpoint
4
4
  from omnisdk.omnitron.models import CargoCompany
5
5
 
6
6
  from channel_app.core.commands import OmnitronCommandInterface
7
+ from channel_app.omnitron.exceptions import CargoCompanyException
7
8
 
8
9
 
9
10
  class GetCargoCompany(OmnitronCommandInterface):
@@ -14,7 +15,7 @@ class GetCargoCompany(OmnitronCommandInterface):
14
15
  for cargo_company in data:
15
16
  if cargo_company.erp_code == cargo_company_code:
16
17
  return cargo_company
17
- raise Exception("CargoCompany does not exists: {}".format(
18
+ raise CargoCompanyException("CargoCompany does not exists: {}".format(
18
19
  cargo_company_code))
19
20
 
20
21
  def get_data(self) -> List[CargoCompany]:
@@ -56,7 +56,7 @@ class GetOrCreateCustomer(OmnitronCommandInterface):
56
56
  new_customer.last_name = data.last_name
57
57
  if must_update:
58
58
  customer = self.endpoint(channel_id=self.integration.channel_id).update(
59
- id=customer.pk, item=customer)
59
+ id=customer.pk, item=new_customer)
60
60
  else:
61
61
  new_customer = Customer()
62
62
  new_customer.channel = self.integration.channel_id
@@ -1,5 +1,7 @@
1
1
  from dataclasses import asdict
2
- from typing import List
2
+ from typing import Any, List
3
+
4
+ from requests import exceptions as requests_exceptions
3
5
 
4
6
  from omnisdk.omnitron.endpoints import (ChannelCreateOrderEndpoint,
5
7
  ChannelIntegrationActionEndpoint,
@@ -15,12 +17,13 @@ from omnisdk.omnitron.models import Order, OrderShippingInfo, \
15
17
  from channel_app.core.commands import OmnitronCommandInterface
16
18
  from channel_app.core.data import (OrderBatchRequestResponseDto,
17
19
  OmnitronCreateOrderDto, OmnitronOrderDto,
18
- OrderItemDto, CancelOrderDto, ErrorReportDto)
20
+ OrderItemDto, CancelOrderDto,
21
+ CancellationRequestDto)
19
22
  from channel_app.core.utilities import split_list
20
23
  from channel_app.omnitron.batch_request import ClientBatchRequest
21
24
  from channel_app.omnitron.commands.batch_requests import ProcessBatchRequests
22
25
  from channel_app.omnitron.constants import (ContentType, BatchRequestStatus)
23
- from channel_app.omnitron.exceptions import OrderException
26
+ from channel_app.omnitron.exceptions import AppException, OrderException
24
27
 
25
28
 
26
29
  class GetOrders(OmnitronCommandInterface):
@@ -227,10 +230,12 @@ class CreateOrders(OmnitronCommandInterface):
227
230
 
228
231
  except OrderException:
229
232
  return is_order_exists
230
-
231
- order = self.endpoint(
232
- channel_id=self.integration.channel_id
233
- ).create(item=order_obj)
233
+ try:
234
+ order = self.endpoint(
235
+ channel_id=self.integration.channel_id
236
+ ).create(item=order_obj)
237
+ except requests_exceptions.HTTPError as exc:
238
+ raise OrderException(params=exc.response.text)
234
239
 
235
240
  self._update_batch_request(order)
236
241
  return order
@@ -274,6 +279,9 @@ class CreateOrders(OmnitronCommandInterface):
274
279
  for item in order_items:
275
280
  price_list = self.integration.catalog.price_list
276
281
  stock_list = self.integration.catalog.stock_list
282
+ if item.product not in product_dict:
283
+ raise AppException(
284
+ "Product not found: remote_id={}".format(item.product))
277
285
  order_item_data = {
278
286
  "product": product_dict[item.product],
279
287
  "status": item.status or "400",
@@ -488,7 +496,7 @@ class GetCancellationRequest(OmnitronCommandInterface):
488
496
 
489
497
  def get_data(self):
490
498
  """
491
- {"status": "approved", "cancellation_type": "refund or cancel", "order_item": 3212}
499
+ {"status": "approved", "cancellation_type": "refund or cancel"}
492
500
  """
493
501
  assert isinstance(self.objects, dict)
494
502
  query_params = self.objects
@@ -504,8 +512,125 @@ class GetCancellationRequest(OmnitronCommandInterface):
504
512
  if not batch:
505
513
  break
506
514
  cancellation_requests.extend(batch)
515
+
516
+ objects_data = self.create_batch_objects(
517
+ data=cancellation_requests, content_type=self.content_type)
518
+ self.update_batch_request(objects_data=objects_data)
519
+
507
520
  return cancellation_requests
521
+
522
+ def check_run(self, is_ok, formatted_data):
523
+ if not is_ok:
524
+ return False
525
+ return True
526
+
527
+
528
+ class GetCancellationRequestUpdates(GetCancellationRequest):
529
+ endpoint = ChannelCancellationRequestEndpoint
530
+ path = "updates"
531
+
532
+ def get_cancellation_requests(self, query_params={}) -> List[CancellationRequest]:
533
+ endpoint = self.endpoint(channel_id=self.integration.channel_id,
534
+ path=self.path)
535
+ cancellation_requests = endpoint.list(params=query_params)
536
+ for batch in endpoint.iterator:
537
+ if not batch:
538
+ break
539
+ cancellation_requests.extend(batch)
540
+
541
+ for cr in cancellation_requests:
542
+ cr.pk = cr.id
543
+
544
+ objects_data = self.create_batch_objects(
545
+ data=cancellation_requests, content_type=self.content_type)
546
+ self.update_batch_request(objects_data=objects_data)
547
+ return cancellation_requests
548
+
549
+ def check_run(self, is_ok, formatted_data):
550
+ if not is_ok:
551
+ return False
552
+ return True
553
+
508
554
 
555
+ class CreateCancellationRequest(OmnitronCommandInterface):
556
+ endpoint = ChannelCancellationRequestEndpoint
557
+
558
+ def get_data(self):
559
+ assert isinstance(self.objects, CancellationRequestDto)
560
+ cancellation_request = self.objects
561
+ # omnitron donusumleri yapilir.
562
+ omnitron_reason = self.get_omnitron_reason(cancellation_request.reason)
563
+ # omnitron reason
564
+ cancellation_request.reason = omnitron_reason
565
+ # remote_id
566
+ cancellation_request.remote_id = cancellation_request.remote_id
567
+ # omnitron order_item
568
+ omnitron_order_item = self.get_omnitron_order_item(cancellation_request.order_item)
569
+ cancellation_request.order_item = omnitron_order_item
570
+
571
+ data = asdict(cancellation_request)
572
+ return CancellationRequest(**data)
573
+
574
+ def send(self, validated_data) -> CancellationRequest:
575
+ """
576
+ :param validated_data: data for order
577
+ :return: cancellationrequest objects
578
+ """
579
+ endpoint = self.endpoint(channel_id=self.integration.channel_id)
580
+
581
+ response_cancellation_request = endpoint.create(item=validated_data)
582
+ response_cancellation_request.remote_id = validated_data.remote_id
583
+ response_cancellation_request.pk = response_cancellation_request.id
584
+ objects_data = self.create_batch_objects(
585
+ data=[response_cancellation_request],
586
+ content_type=ContentType.cancellation_request.value)
587
+
588
+ self.update_batch_request(objects_data=objects_data)
589
+ return response_cancellation_request
590
+
591
+ def normalize_response(self, data, response) -> List[object]:
592
+ return [response]
593
+
594
+ def check_run(self, is_ok, formatted_data):
595
+ if not is_ok:
596
+ return False
597
+ return True
598
+
599
+ def get_omnitron_order_item(self, channel_order_item):
600
+ """
601
+ order_item_remote_id -> omnitron orderitem remote_id str
602
+ :return: int
603
+ """
604
+ end_point = ChannelIntegrationActionEndpoint(
605
+ channel_id=self.integration.channel_id)
606
+
607
+ params = {"channel": self.integration.channel_id,
608
+ "content_type_name": ContentType.order_item.value,
609
+ "remote_id__exact": channel_order_item,
610
+ "sort": "id"}
611
+ integration_actions = end_point.list(params=params)
612
+ for item in end_point.iterator:
613
+ if not item:
614
+ break
615
+ integration_actions.extend(item)
616
+
617
+ if not integration_actions:
618
+ raise AppException(
619
+ "OrderItem not found, number={}".format(
620
+ channel_order_item))
621
+ if len(integration_actions) != 1:
622
+ raise AppException("Multiple records returned from Omnitron "
623
+ "for a single order item: remote_id: {}".format(
624
+ channel_order_item))
625
+ return integration_actions[0].object_id
626
+
627
+ def get_omnitron_reason(self, channel_reason):
628
+ configuration = self.integration.channel.conf
629
+ omnitron_reason = configuration.get("reason_mapping", {}).get(channel_reason)
630
+ if omnitron_reason:
631
+ return omnitron_reason
632
+ return 10
633
+
509
634
 
510
635
  class UpdateOrderItems(OmnitronCommandInterface):
511
636
  endpoint = ChannelOrderItemEndpoint
@@ -6,13 +6,25 @@ from omnisdk.omnitron.endpoints import (
6
6
  ChannelCustomerEndpoint,
7
7
  ChannelOrderEndpoint,
8
8
  ChannelOrderItemEndpoint,
9
- )
10
- from channel_app.core.data import CustomerDto, OrderBatchRequestResponseDto
9
+ ChannelCancellationRequestEndpoint,
10
+ ChannelBatchRequestEndpoint)
11
+ from omnisdk.omnitron.models import CancellationRequest
12
+
13
+ from channel_app.core.data import CancellationRequestDto, CustomerDto, OrderBatchRequestResponseDto
11
14
  from channel_app.core.tests import BaseTestCaseMixin
12
15
  from channel_app.omnitron.commands.orders.cargo_companies import GetCargoCompany
13
16
  from channel_app.omnitron.commands.orders.customers import GetOrCreateCustomer
14
- from channel_app.omnitron.commands.orders.orders import GetOrderItems, GetOrderItemsWithOrder, ProcessOrderBatchRequests
15
- from channel_app.omnitron.constants import BatchRequestStatus, CustomerIdentifierField
17
+ from channel_app.omnitron.commands.orders.orders import (
18
+ CreateCancellationRequest,
19
+ GetCancellationRequestUpdates,
20
+ GetOrderItems,
21
+ GetOrderItemsWithOrder,
22
+ ProcessOrderBatchRequests,
23
+ ChannelIntegrationActionEndpoint)
24
+ from channel_app.omnitron.constants import (
25
+ BatchRequestStatus,
26
+ CancellationType,
27
+ CustomerIdentifierField)
16
28
 
17
29
 
18
30
  class TestProcessOrderBatchRequests(BaseTestCaseMixin):
@@ -482,3 +494,99 @@ class TestGetOrderItemsWithOrder(BaseTestCaseMixin):
482
494
 
483
495
  self.assertEqual(len(orders), 1)
484
496
  self.assertEqual(len(orders[0].orderitem_set), 2)
497
+
498
+ class TestGetCancellationRequestUpdates(BaseTestCaseMixin):
499
+ """
500
+ Test case for GetCancellationRequestUpdates
501
+ run: python -m unittest channel_app.omnitron.commands.tests.test_orders.GetCancellationRequestUpdates
502
+ """
503
+
504
+ def setUp(self) -> None:
505
+ self.instance = GetCancellationRequestUpdates(
506
+ integration=self.mock_integration,
507
+ )
508
+
509
+ self.instance.objects = {
510
+ 'status': 'completed',
511
+ 'cancellation_type': 'refund'
512
+ }
513
+ self.endpoint = ChannelCancellationRequestEndpoint
514
+ self.cancellation_request = MagicMock(
515
+ pk=1,
516
+ status='completed',
517
+ cancellation_type='refund',
518
+ easy_return=None,
519
+ order_item=1,
520
+ )
521
+ return super().setUp()
522
+
523
+ @patch.object(BaseClient, 'get_instance')
524
+ @patch.object(ChannelCancellationRequestEndpoint, '_list')
525
+ @patch.object(ChannelBatchRequestEndpoint, 'update')
526
+ def test_get_data(self, mock_endpoint, mock_get_instance, mock_batch_request):
527
+ response_data = [
528
+ MagicMock(
529
+ pk=1,
530
+ status='completed',
531
+ cancellation_type=CancellationType.refund.value,
532
+ easy_return=None,
533
+ order_item=1,
534
+ ),
535
+ MagicMock(
536
+ pk=2,
537
+ status='completed',
538
+ cancellation_type=CancellationType.refund.value,
539
+ easy_return=None,
540
+ order_item=2,
541
+ )
542
+ ]
543
+ response = MagicMock()
544
+ response.list.return_value = response_data
545
+ with patch.object(self.endpoint, '__new__', return_value=response):
546
+ data = self.instance.get_data()
547
+ self.assertEqual(len(data), 2)
548
+ self.assertEqual(data[0].status, self.instance.objects['status'])
549
+
550
+ @patch.object(GetCancellationRequestUpdates, 'get_cancellation_requests')
551
+ def test_update_cancellation_request(self, mock_get_cancellation_requests):
552
+ mock_get_cancellation_requests.return_value = self.cancellation_request
553
+ self.instance.get_cancellation_requests(self.cancellation_request)
554
+ self.assertEqual(self.cancellation_request.status, self.instance.objects['status'])
555
+ self.assertEqual(self.cancellation_request.cancellation_type, self.instance.objects['cancellation_type'])
556
+
557
+
558
+ class TestCreateCancellationRequest(BaseTestCaseMixin):
559
+ """
560
+ Test case for CreateCancellationRequest
561
+ run: python -m unittest channel_app.omnitron.commands.tests.test_orders.TestCreateCancellationRequest
562
+ """
563
+
564
+ def setUp(self) -> None:
565
+ self.instance = CreateCancellationRequest(
566
+ integration=self.mock_integration)
567
+
568
+ self.endpoint = ChannelCancellationRequestEndpoint
569
+ self.instance.objects = CancellationRequestDto(
570
+ order_item='1',
571
+ reason='reason_code',
572
+ remote_id='2',
573
+ cancellation_type=CancellationType.refund.value)
574
+ return super().setUp()
575
+
576
+ @patch.object(BaseClient, 'get_instance')
577
+ @patch.object(CreateCancellationRequest, 'get_omnitron_order_item')
578
+ def test_get_data(self, mock_get_instance, mock_get_omnitron_order_item):
579
+ mock_get_omnitron_order_item.return_value = 1
580
+ response_data = CancellationRequest(
581
+ pk=1,
582
+ status='waiting',
583
+ cancellation_type='refund',
584
+ easy_return=None,
585
+ order_item=1,
586
+ )
587
+ response = MagicMock()
588
+ response.create.return_value = response_data
589
+
590
+ with patch.object(self.endpoint, '__new__', return_value=response):
591
+ data = self.instance.get_data()
592
+ self.assertIsInstance(data, CancellationRequest)
@@ -96,3 +96,8 @@ class ChannelConfSchemaDataTypes:
96
96
  json = 'json'
97
97
  list = 'list'
98
98
  integer = 'integer'
99
+
100
+
101
+ class CancellationType(Enum):
102
+ cancel = "cancel"
103
+ refund = "refund"
@@ -1,8 +1,11 @@
1
- class IntegrationMappingException(Exception):
1
+ class AppException(Exception):
2
2
  def __init__(self, params=None):
3
- super(IntegrationMappingException, self).__init__()
3
+ super(BaseException, self).__init__()
4
4
  self.params = params
5
5
 
6
+ class IntegrationMappingException(AppException):
7
+ pass
8
+
6
9
 
7
10
  class CountryException(IntegrationMappingException):
8
11
  pass
@@ -24,19 +27,13 @@ class AddressException(IntegrationMappingException):
24
27
  pass
25
28
 
26
29
 
27
- class OrderException(Exception):
28
- def __init__(self, params=None):
29
- super(OrderException, self).__init__()
30
- self.params = params
30
+ class OrderException(AppException):
31
+ pass
31
32
 
32
33
 
33
- class CargoCompanyException(Exception):
34
- def __init__(self, params=None):
35
- super().__init__()
36
- self.params = params
34
+ class CargoCompanyException(AppException):
35
+ pass
37
36
 
38
37
 
39
- class CustomerException(Exception):
40
- def __init__(self, params=None):
41
- super(CustomerException, self).__init__()
42
- self.params = params
38
+ class CustomerException(AppException):
39
+ pass
@@ -18,6 +18,8 @@ from channel_app.omnitron.commands.orders.customers import GetOrCreateCustomer
18
18
  from channel_app.omnitron.commands.orders.orders import (
19
19
  CreateOrders,
20
20
  CreateOrderShippingInfo,
21
+ GetCancellationRequestUpdates,
22
+ CreateCancellationRequest,
21
23
  GetOrders,
22
24
  ProcessOrderBatchRequests,
23
25
  CreateOrderCancel,
@@ -135,6 +137,8 @@ class OmnitronIntegration(BaseIntegration):
135
137
  "get_product_objects": GetProductObjects,
136
138
  "get_product_from_batch_request": GetProductsFromBatchrequest,
137
139
  "get_cancellation_requests": GetCancellationRequest,
140
+ "get_cancellation_requests_update": GetCancellationRequestUpdates,
141
+ "create_cancellation_requests": CreateCancellationRequest,
138
142
  "update_order_items": UpdateOrderItems
139
143
  # "fetch_cancellation_plan": FetchCancellationPlan
140
144
  }
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: channel_app
3
- Version: 0.0.148
3
+ Version: 0.0.150
4
4
  Summary: Channel app for Sales Channels
5
5
  Home-page: https://github.com/akinon/channel_app
6
6
  Author: akinonteam
@@ -1,7 +1,7 @@
1
1
  channel_app/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
2
  channel_app/app/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
3
  channel_app/app/order/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
- channel_app/app/order/service.py,sha256=YFP4QAWx0aaWhrG5lgnpyDIJXtJYLAnyDDW1a8w2DOs,11585
4
+ channel_app/app/order/service.py,sha256=ZYQ7TRyVRk3VyNPfXyhdfVpLljtpHP8Gdijiq_47Wtk,20462
5
5
  channel_app/app/product/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
6
6
  channel_app/app/product/service.py,sha256=7DZF-Vtoaf5eKT1m_ccEOAqUxWSO7Csop4HEtJmcrvw,10646
7
7
  channel_app/app/product_image/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -13,30 +13,30 @@ channel_app/app/product_stock/service.py,sha256=6oS4tkWkkVAwEMFWqn0uc0zZgByoxP69
13
13
  channel_app/app/setup/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
14
14
  channel_app/app/setup/service.py,sha256=d53IKrQjahNZvxCaZAmXo2VUKBMM6-wm-P9I9tBTYOY,4553
15
15
  channel_app/channel/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
16
- channel_app/channel/integration.py,sha256=q7wwPvYukEEoLCMZZ6d4GDiRHV8u_dPHT3cGU6DUuik,3587
16
+ channel_app/channel/integration.py,sha256=fDx5nxa6w-4gMucU7xo_OTOkqPHdBUHeDtuzeaDJlXE,3769
17
17
  channel_app/channel/commands/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
18
18
  channel_app/channel/commands/product_categories.py,sha256=ktN8NnWNcHcVREVOU-SSZbH5ZEwihAUOgHsZm1KcEpY,52
19
19
  channel_app/channel/commands/product_images.py,sha256=8lCSt-_YkD1IytAXOtAJAwWd9d53QZPKir-iopK1fC0,4855
20
20
  channel_app/channel/commands/product_prices.py,sha256=pOY_1qb_0soGyK1wkTy2epL4xUeFflFfWLGCKoVRiCo,4855
21
21
  channel_app/channel/commands/product_stocks.py,sha256=3mUz9K1zA3ljvtcOBgD5uQsMHBmzTxrSfj5vHXBV5qs,8157
22
22
  channel_app/channel/commands/products.py,sha256=ZzmJbcOJISOcsZ9F3FL012rqU-eNhwW_LGYYlb2WmzA,5257
23
- channel_app/channel/commands/setup.py,sha256=NNUq7jzBHXt61Jhm9XExm2kXp6u7YEjO45fjpIRiNKk,36040
23
+ channel_app/channel/commands/setup.py,sha256=GX2yp0yGsoKDjl_w3ooY_ftaVZ6-hk_F9B55KqBr3ho,36263
24
24
  channel_app/channel/commands/orders/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
25
- channel_app/channel/commands/orders/orders.py,sha256=PcoDuJDR-1RuZBPqKgkPXJWkbr7OwQasyqzKrXigmFg,12487
25
+ channel_app/channel/commands/orders/orders.py,sha256=edBCmp0BBg5qNhduWnB7p2yAf0pVFEZ5uef2EvVDUl0,15837
26
26
  channel_app/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
27
27
  channel_app/core/clients.py,sha256=o8OBkXwof8BobEyiiHPwmGsUcOlPb60u3oUeAUxo_hc,1591
28
- channel_app/core/commands.py,sha256=dQ-aJxZkc0j25hmp1Ui_s1ykY5LQ5_wxZCo6OrcxmnI,14120
29
- channel_app/core/data.py,sha256=-9jDxdYZrvUhusbOfvtAfHwlweky_p-XD2zzOW5liLA,6302
28
+ channel_app/core/commands.py,sha256=gGSsjHJmMTkj6OuzhUsbVMQCGGiumwnSzM1T9mqHiss,14316
29
+ channel_app/core/data.py,sha256=xiNQh_r_F3RXSO6jncHNEVLPO9sDVm_3A-MMOwdh6n8,6910
30
30
  channel_app/core/integration.py,sha256=OqpN8B3KBLsjjrbZXZaNVF6NtObejh7P_7kGFj1xU3o,2817
31
31
  channel_app/core/products.py,sha256=uInjFw-vze1XP8vWEeq4VWDZVQQIiatoe1YsQ6n_H5E,2092
32
- channel_app/core/settings.py,sha256=66y5YJksINO0WQ6UwXeYQXiCVfjrve0r4QgRENQaGyQ,1212
32
+ channel_app/core/settings.py,sha256=1KF8PhbjEqyZOWese9EFA_DnaSA1eVcscfShVIroTRo,1247
33
33
  channel_app/core/tests.py,sha256=ucgnLyb3D8H2JvjjH6icdRZzZQoMFbnlnFLylhoJ0Js,434
34
34
  channel_app/core/utilities.py,sha256=3iSU4RHFSsdTWBfUYBK23CRGtAIC-nYIBIJLm0Dlx3o,4168
35
35
  channel_app/omnitron/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
36
36
  channel_app/omnitron/batch_request.py,sha256=S8IHtbI1RtVLbnOwtfXSmkrREGp8wUYW2E-eu5omwyY,3550
37
- channel_app/omnitron/constants.py,sha256=2kvdez5VJPzhNcMyV0VaG_6JTYkUVYwuOifnMIwGOg8,2718
38
- channel_app/omnitron/exceptions.py,sha256=_NjIx5LKPbKiP5jrJJGIfKGsRbGK6Thas3j5MGlq8Js,928
39
- channel_app/omnitron/integration.py,sha256=Jw9SZeDMLKRxzrZB02FTVhwDbercawfCi_GwYSPqFdc,9253
37
+ channel_app/omnitron/constants.py,sha256=WZR6k_k2zZfN7lfi1ZLv1PphsHIq_LiZgw6Nd6LduvE,2793
38
+ channel_app/omnitron/exceptions.py,sha256=iVChxLBl6JJy42lgfnmZIA3Sa8ykL1_P0jErpRmOovY,672
39
+ channel_app/omnitron/integration.py,sha256=A3hIM2jVYR-CRzVIztq2iHQrlasmgCeY_9OZhUiAO6Y,9461
40
40
  channel_app/omnitron/commands/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
41
41
  channel_app/omnitron/commands/batch_requests.py,sha256=WXd1iCJKC-nCcMHZ2XDP9UVcC2Xq3MFd1uCqz8h5_pU,11638
42
42
  channel_app/omnitron/commands/error_reports.py,sha256=PFeWryOjAyN6huKn5W8gq-ii0aa2yTGPfBoWieNL5RQ,2942
@@ -48,17 +48,17 @@ channel_app/omnitron/commands/product_stocks.py,sha256=va2LbTtFMLe99kJr5aFceYLi2
48
48
  channel_app/omnitron/commands/products.py,sha256=As8Hnw3h6dOfPdxPBPUs-Hdip_9IaQXQyLAMsAylMTs,32098
49
49
  channel_app/omnitron/commands/setup.py,sha256=dcbvvIFDKKeDVziwR2qWJhVd92IlVLEoYIbMrxKjWDE,35220
50
50
  channel_app/omnitron/commands/orders/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
51
- channel_app/omnitron/commands/orders/addresses.py,sha256=FS63zncxP1hHjObq0Yjr9mq1voixzL52YdKt17Q0uV0,12358
52
- channel_app/omnitron/commands/orders/cargo_companies.py,sha256=pTyOgsoIBLHUIj7F2eB_y3NXS8p8Qi0rsqjIZ7AZiWs,1308
53
- channel_app/omnitron/commands/orders/customers.py,sha256=bBE5o3KFyReaMQm4dTrcZm7u0FEq3u-_YpVt5ru3_B8,3446
54
- channel_app/omnitron/commands/orders/orders.py,sha256=MJP3nAhBqOYfe028tjn7TOzxrjojcFNAIUScTxm2zXw,22755
51
+ channel_app/omnitron/commands/orders/addresses.py,sha256=2wjYOyAv5TSZ6c7TUl2SWSFCYg5Vmihimj1Iz4Ybm_U,12566
52
+ channel_app/omnitron/commands/orders/cargo_companies.py,sha256=Q5RKIbP8cNLRa82GA7TyjrKZ2gIDWXscMTQTSJOvwGE,1386
53
+ channel_app/omnitron/commands/orders/customers.py,sha256=1IbzZsQSIcroJagsinKy__q3vEU8kZj3LxNhxb-mWQ0,3450
54
+ channel_app/omnitron/commands/orders/orders.py,sha256=U_DwYsPzWo_MfFc1QUZhcLfKhg_bjoSGzpYutOFKFhs,27697
55
55
  channel_app/omnitron/commands/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
56
- channel_app/omnitron/commands/tests/test_orders.py,sha256=mG2o4hftXFoYvTfWmgP9QrGtgMUPudoFRYKRZLku0l0,16345
56
+ channel_app/omnitron/commands/tests/test_orders.py,sha256=acndyE5vpWUYdIaAsa2TlJxxmtUNRKE0IDP7DJRMgTo,20451
57
57
  channel_app/omnitron/commands/tests/test_product_images.py,sha256=y6tmiJ00kd2GTqSv4MOCjUnXFFSAKhhAwsqQ0l0ccNk,3492
58
58
  channel_app/omnitron/commands/tests/test_product_prices.py,sha256=5HPX9PmjGw6gk3oNrwtWLqdrOkfeNx1mYP-pYwOesZU,3496
59
59
  channel_app/omnitron/commands/tests/test_product_stocks.py,sha256=q4RGlrCNUUJyN5CBL1fzrvdd4Q3xt816mbMRQT0XEd0,3496
60
60
  channel_app/omnitron/commands/tests/test_products.py,sha256=DUUdB7pKe-wj8H1N-otKhR-97z37Q3Mh0QgROlnrKTQ,102028
61
- channel_app-0.0.148.dist-info/METADATA,sha256=4z7ZPV0_H7HL_j3rZjKgc6ROo4azRlDW26c_m339WWw,309
62
- channel_app-0.0.148.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92
63
- channel_app-0.0.148.dist-info/top_level.txt,sha256=JT-gM6L5Cwxr1xEoN7NHrREDs-d6iGFGfRnK-NrJ3tU,12
64
- channel_app-0.0.148.dist-info/RECORD,,
61
+ channel_app-0.0.150.dist-info/METADATA,sha256=hBDfLNla_Z7s_B6rgAPeAFHb6V3kN0lM1TkvzleiOz0,309
62
+ channel_app-0.0.150.dist-info/WHEEL,sha256=Mdi9PDNwEZptOjTlUcAth7XJDFtKrHYaQMPulZeBCiQ,91
63
+ channel_app-0.0.150.dist-info/top_level.txt,sha256=JT-gM6L5Cwxr1xEoN7NHrREDs-d6iGFGfRnK-NrJ3tU,12
64
+ channel_app-0.0.150.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: bdist_wheel (0.42.0)
2
+ Generator: setuptools (73.0.1)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5