Esempio n. 1
0
    def handle_object(self, n_direction, handler):
        """Выполнение обработчика по объекту
        На вход направление интеграции и обработчик объекта, который должен принимать ObjectInfo.
        После того, как станет известно, что за объект интегрируется, обработчик должен заполнить о нем информацию о ObjectInfo"""
        obj_info = ObjectInfo()
        session_id = self._get_session_by_direction(n_direction)

        try:
            handler(obj_info)

            object_id = obj_info.id_external

            if not object_id:
                raise AppException("Не указан ИД объекта")

            # проверим, если в лог не написали нечего, то добавим инфу, что объект загрузился
            object_log_dict = self._object_log_by_session_dict[session_id]

            if object_id not in object_log_dict:
                self.write_info_log(object_id, "OK", n_direction)
        except AppException as err:
            object_id = obj_info.id_external

            if not object_id:
                object_id = "Неизвестный объект"

            self.write_error_log(object_id, str(err), n_direction)
Esempio n. 2
0
    def __sync_with_act(self):
        # создание накладных
        act_out = self.id_act_out

        if act_out is None:
            act_out = StkAct.inset_out_act()
            act_out.s_desc = "Сформирована от \"" + self.get_head_line() + "\""
            act_out.save()
            self.id_act_out = act_out

        if act_out.s_state != StkAct.STATE_REGISTERING:
            raise AppException(
                "Ошибка синхронизации с расходной накладной. Накладная в неверном состоянии"
            )

        # Формирование списка ТМЦ для накладной
        self_gds_out_dict = {}

        def add_qty(id_good, n_qty):
            if id_good in self_gds_out_dict:
                self_gds_out_dict[id_good] = self_gds_out_dict[id_good] + n_qty
            else:
                self_gds_out_dict[id_good] = n_qty

        for order_det in TrdOrderDet.objects.filter(id_order=self):
            add_qty(order_det.id_good_id, order_det.n_qty)

        act_out.apply_det_data(self_gds_out_dict)
Esempio n. 3
0
def run_order_integration(request):
    """Запуск интеграции по всем контурам"""
    has_errors = False
    error_text_lines = []

    for circuit in IntgCircuit.objects.all():
        integrator = None
        if circuit.s_type == IntgCircuit.TYPE_EBAY:
            integrator = EbayIntegrator()
        elif circuit.s_type == IntgCircuit.TYPE_Wix:
            integrator = WixIntegrator()
        else:
            raise AppException('Неизвестный тип контура: ' + circuit.s_type)

        integrator.run(circuit)

        # Собиаем информацию о выполненнии
        if integrator.has_errors():
            if not has_errors:
                has_errors = True
            error_text_lines = error_text_lines + integrator.get_report()

    if has_errors:
        # Переводим текст в html, чтобы норм отобразить
        return render(
            request,
            'show_text.html',
            context={'lines': error_text_lines},
        )
    else:
        return HttpResponseRedirect(reverse('trd_orders'))
Esempio n. 4
0
    def on_start_run(self):
        # Получаем параметры подключения

        if not self.circuit.s_config:
            raise AppException('Не указана конфигурация подключения контура ' + str(self.circuit))

        json_data = json.loads(self.circuit.s_config)
        self.url = json_data.get('url')
        self.secret = json_data.get('secret')

        # Загружаем меппинги
        self.mapping_goods_dict = GoodMapping.get_by_circuit(self.circuit)
        self.mapping_delivery_service_dict = DeliverySystemMapping.get_by_circuit(self.circuit)
Esempio n. 5
0
    def roll_back_state(id):
        # откат состояния
        with transaction.atomic():
            act = StkAct.objects.select_for_update().get(pk=id)
            if act.s_state == StkAct.STATE_REGISTERING:
                raise AppException("Ошибка отката накладной. Накладная находится в состоянии Оформляется")

            act.set_s_state(StkAct.STATE_REGISTERING)
            act.save()

            # Обновляем остатки
            qty_dict: Dict = act.__get_det_qty()
            StkRemains.apply_changes(qty_dict, act.n_direction * -1)
Esempio n. 6
0
    def insert(id_act, id_good):
        n_order_max = 0

        for det in StkActDet.objects.filter(id_act_id=id_act).filter(id_good_id=id_good):
            if det.id_good_id == id_good:
                raise AppException("Позиция с таким ТМЦ и Накладной уже существует")

            if det.n_order > n_order_max:
                n_order_max = det.n_order

        obj = StkActDet()
        obj.set_id_act(id_act)
        obj.set_id_good(id_good)
        obj.set_n_order(n_order_max + 1)
        return obj
Esempio n. 7
0
    def on_start_run(self):
        # Получаем параметры подключения

        if not self.circuit.s_config:
            raise AppException('Не указана конфигурация подключения контура ' +
                               str(self.circuit))

        json_data = json.loads(self.circuit.s_config)
        self.app_id = json_data.get('appid')
        self.dev_id = json_data.get('devid')
        self.cert_id = json_data.get('certid')
        self.token = json_data.get('token')

        # Загружаем меппинги
        self.mapping_goods_dict = GoodMapping.get_by_circuit(self.circuit)
        self.mapping_delivery_service_dict = DeliverySystemMapping.get_by_circuit(
            self.circuit)
Esempio n. 8
0
    def apply_form_data(self, changed_act_det_array, deleted_act_det_array):
        # применение данных из формы редактирования
        with transaction.atomic():
            # блокируем объект
            if self.id is not None:
                old_act = StkAct.objects.select_for_update().get(pk = self.id)
                if old_act.s_state == StkAct.STATE_DONE:
                    raise AppException("Ошибка сохранения накладной. Накладная находится в состоянии Выполнен")

            self.save()

            for det in changed_act_det_array:
                det.id_act = self
                det.save()

            for det in deleted_act_det_array:
                det.delete()

            StkAct.apply_done_state(self.id)
Esempio n. 9
0
    def roll_back_state(id):
        # откат состояния
        with transaction.atomic():
            shift_result = MnfShiftResult.objects.select_for_update().get(
                pk=id)
            if shift_result.s_state == MnfShiftResult.STATE_REGISTERING:
                raise AppException(
                    "Ошибка отката отчета. Отчет находится в состоянии Оформляется"
                )

            # Откат накладной
            act_out = shift_result.id_act
            act_in = shift_result.id_act_in
            if act_out is not None:
                StkAct.roll_back_state(act_out.id)
            if act_in is not None:
                StkAct.roll_back_state(act_in.id)

            shift_result.s_state = MnfShiftResult.STATE_REGISTERING
            shift_result.save()
Esempio n. 10
0
def run_order_integration_by_id(request, pk):
    """Запуск интеграции по одному заказу"""
    trd_order = TrdOrder.objects.get(pk=pk)

    for circuit in IntgCircuit.objects.filter(
            id_trade_system=trd_order.id_trade_system):
        integrator = None
        if circuit.s_type == IntgCircuit.TYPE_EBAY:
            integrator = EbayIntegrator()
            integrator.run_by_single_order(trd_order.s_reg_num)
        else:
            raise AppException('Неизвестный тип контура: ' + circuit.s_type)

        if integrator.has_errors():
            # Переводим текст в html, чтобы норм отобразить
            return render(
                request,
                'show_text.html',
                context={'lines': integrator.get_report()},
            )
        else:
            return HttpResponseRedirect(
                reverse('trd_order-detail', args=[str(trd_order.id)]))
Esempio n. 11
0
    def apply_form_data(self, changed_items_array, deleted_items_array,
                        changed_materials_array, deleted_materials_array):
        # применение данных из формы редактирования
        with transaction.atomic():
            # блокируем объект
            if self.id is not None:
                old_obj = MnfShiftResult.objects.select_for_update().get(
                    pk=self.id)
                if old_obj.s_state == MnfShiftResult.STATE_DONE:
                    raise AppException(
                        "Ошибка сохранения накладной. Накладная находится в состоянии Выполнен"
                    )

            self.s_state = MnfShiftResult.STATE_DONE
            self.save()

            for det in changed_items_array:
                det.id_shift_result = self
                det.save()

            for det in deleted_items_array:
                det.delete()

            for det in changed_materials_array:
                det.id_shift_result = self
                det.save()

            for det in deleted_materials_array:
                det.delete()

            # синхронизация с накладной
            self.__sync_with_act()
            StkAct.apply_done_state(self.id_act_id)
            StkAct.apply_done_state(self.id_act_in.id)

            self.save()
Esempio n. 12
0
File: tests.py Progetto: durules/ANT
    def test_connect(self):
        #api = Trading(domain='api.sandbox.ebay.com',
        #              appid="AlekseyK-svarogmn-SBX-a23495a34-656da854", devid="897bd038-a619-4206-b7eb-c2ca642b4b37",
        #              certid="SBX-23495a34b3cd-991c-4300-9fc2-8def", token=self.get_token(), config_file=None)

        api = Trading(domain='api.ebay.com',
                      appid="AlekseyK-svarogmn-PRD-2a292be01-16024d26",
                      devid="897bd038-a619-4206-b7eb-c2ca642b4b37",
                      certid="PRD-a292be012d9f-eb3b-418a-ba77-f0cc",
                      token=self.get_token(),
                      config_file=None)

        response = api.execute(
            'GetOrders',
            {
                #'CreateTimeFrom': '2021-10-01T00:05:08.100Z',
                #'CreateTimeTo': '2021-10-30T18:05:08.100Z',
                'OrderIDArray': {
                    'OrderID': ['26-07500-81214']
                },
                'OrderRole': 'Seller',
                'OrderStatus': 'Completed'
            })
        time = response.dict()['Timestamp']
        order_dict = response.dict()['OrderArray']
        order_array = order_dict['Order']

        #PaidTime: 2021-10-08T02:13:41.000Z - oplachen
        #ShippedTime: 2021-10-08T07:24:02.000Z - dostavlen

        for order in order_array:
            self.print_order(order)

            # ИД заказа
            order_id = order.get('OrderID')
            # Дата оплаты
            paid_time = order.get('PaidTime')
            # Дата отправки
            shipped_time = order.get('ShippedTime')
            # Дата доставки
            actual_delivery_time = None
            # Дата создания
            created_time = order.get('CreatedTime')
            # Получатель
            shipping_address_name = None
            # Адрес
            shipping_address_address = None
            # Набор трек номеров
            shipment_tracking_number_set = set()
            # ПРоданные позиции
            selled_sku_dict = {}

            # рассчет даты доставки
            shipping_service_selected = order.get('ShippingServiceSelected')
            if shipping_service_selected:
                shipping_package_info = shipping_service_selected.get(
                    'ShippingPackageInfo')
                if shipping_package_info:
                    actual_delivery_time = shipping_package_info.get(
                        'ActualDeliveryTime')

            # Расчет адреса
            shipping_address = order.get('ShippingAddress')
            if shipping_address:
                shipping_address_name = shipping_address.get('Name')

                address_dict = {
                    'Страна': 'CountryName',
                    'Почтовый индекс': 'PostalCode',
                    'Область': 'StateOrProvince',
                    'Город': 'CityName',
                    'Улица': 'Street1',
                    'Улица2': 'Street2',
                }

                for key in address_dict:
                    value = shipping_address.get(address_dict[key])
                    if value:
                        if shipping_address_address:
                            shipping_address_address = shipping_address_address + '\n'
                        else:
                            shipping_address_address = ''
                        shipping_address_address = shipping_address_address + key + ': ' + value

            # Обработка позиций заказа
            transaction_array = order.get('TransactionArray')

            if not transaction_array:
                raise AppException("Не найден список позиций заказа")

            transaction = transaction_array.get('Transaction')

            if not transaction:
                raise AppException("Не найден список позиций заказа")

            for trans in transaction:
                # Расчет трек номера
                shipping_details = trans.get('ShippingDetails')
                if shipping_details:
                    shipment_tracking_details = shipping_details.get(
                        'ShipmentTrackingDetails')
                    if shipment_tracking_details:
                        shipment_tracking_number = shipment_tracking_details.get(
                            'ShipmentTrackingNumber')
                        if shipment_tracking_number:
                            shipment_tracking_number_set.add(
                                shipment_tracking_number)

                # Расчет товаров
                item = trans.get('Item')
                if item:
                    item_id = item.get('ItemID')
                    sku = item.get('SKU')
                    title = item.get('Title')
                    qty = int(trans.get('QuantityPurchased'))

                    if not sku:
                        raise AppException('Для товара ' + title +
                                           'не указан SKU')

                    if sku in selled_sku_dict:
                        selled_sku_dict[sku] = selled_sku_dict[sku] + qty
                    else:
                        selled_sku_dict[sku] = qty

            print(order_id)
            print(created_time)
            print(paid_time)
            print(shipped_time)
            print(actual_delivery_time)
            print(shipping_address_name)
            print(shipping_address_address)
            print(shipment_tracking_number_set)
            print(selled_sku_dict)
Esempio n. 13
0
    def import_order(self, order, obj_info):
        """Импорт одного заказа"""

        # ИД заказа
        order_id = str(order.get('number'))
        obj_info.id_external = order_id

        # Требуется сразу же сохранить новый заказ, т.к. сесии выгрузки запоминают дату последней выгрузки
        # и получают заказы начиная с даты последней выгрузки. Если сохранять все заказы, то они будут обработаны
        # новыми сессиями как незавршенные

        trd_order = TrdOrder.objects.filter(s_reg_num=order_id, id_trade_system=self.circuit.id_trade_system).first()

        if not trd_order:
            trd_order = TrdOrder.inset_by_trade_system(self.circuit.id_trade_system, self.s_user)
            trd_order.set_s_reg_num(order_id)
            trd_order.save()

        # Оплачен
        is_payed = order.get('paymentStatus') == "PAID"
        # Завершен
        is_finished = order.get('fulfillmentStatus') == "FULFILLED"
        # Дата создания
        created_time = order.get('_dateCreated')
        # Получатель
        shipping_address_name = None
        # Адрес
        shipping_address_address = None
        # Набор трек номеров
        shipment_tracking_number = None
        # ПРоданные позиции
        selled_sku_list = []
        # Способ доставки
        delivery_option = None

        # Расчет адреса
        shipping_info = order.get('shippingInfo')
        if shipping_info:
            delivery_option = shipping_info.get('deliveryOption')
            shipment_details = shipping_info.get('shipmentDetails')
            if shipment_details:
                # Получатель
                shipping_address_name = str(shipment_details.get('lastName')) + ' ' + str(
                    shipment_details.get('firstName'))
                address = shipment_details.get('address')
                if address:
                    # Адрес
                    shipping_address_address = address.get('formatted')

        # Трек номер
        fulfillments = order.get('fulfillments')
        if fulfillments:
            for fulfillment in fulfillments:
                tracking_info = fulfillment.get('trackingInfo')
                if tracking_info:
                    shipment_tracking_number = tracking_info.get('trackingNumber')

        # Товары
        line_items = order.get('lineItems')
        if line_items:
            for line_item in line_items:
                gds_id = line_item.get('name')
                n_qty = line_item.get('quantity')

                gds_dict = {
                    "id": gds_id,
                    "qty": n_qty
                }

                options = line_item.get('options')
                if options:
                    gds_dict["options"] = []
                    for option in options:
                        if option.get('selection') == "да":
                            gds_dict["options"].append(option.get("option"))

                selled_sku_list.append(gds_dict)


        # установка данных
        # сначала откатим заказ, т.к. он мог уже внести данные в склад
        old_state = trd_order.id_state
        if trd_order.id_state.is_write_off_goods():
            trd_order.set_id_state(TrdOrderState.get_start_state().id, self.s_user)

        trd_order.set_d_reg_date(self.__str_to_date(created_time))
        trd_order.set_s_receiver(shipping_address_name)
        trd_order.set_s_address(shipping_address_address)
        trd_order.set_s_track_num(shipment_tracking_number)

        trd_order.save()

        # Служба доставки
        if delivery_option:
            delivery_service = self.mapping_delivery_service_dict.get(delivery_option)
            if not delivery_service:
                raise AppException('Для службы доставки '+ delivery_option + ' не настроено сопоставление')
            trd_order.set_id_delivery_service(delivery_service)
        else:
            trd_order.set_id_delivery_service(None)

        trd_order.save()

        # Обработка ТМЦ
        selled_goods_dict = {}

        for selled_sku in selled_sku_list:
            external_id = selled_sku["id"]
            external_qty = selled_sku["qty"]

            mapping_goods = self.mapping_goods_dict.get(external_id)

            if not mapping_goods:
                raise AppException('Для товара '+ external_id + ' не настроено сопоставление')

            # Сам товар
            for good, n_qty in mapping_goods[GoodMapping.good_mapping_key()]:

                if good not in selled_goods_dict:
                    selled_goods_dict[good] = 0

                selled_goods_dict[good] = selled_goods_dict[good] + n_qty * external_qty

            # Опции товара
            options = selled_sku.get('options')
            if options:
                for option in options:
                    mapping_option = mapping_goods[GoodMapping.option_mapping_key()].get(option)

                    if not mapping_option:
                        raise AppException('Для товара ' + external_id + ' не настроено сопоставление опции ' + option)

                    for good, n_qty in mapping_option:

                        if good not in selled_goods_dict:
                            selled_goods_dict[good] = 0

                        selled_goods_dict[good] = selled_goods_dict[good] + n_qty * external_qty

        order_det_by_good_dict = {}
        # индксируем позиции заказа
        for trd_order_det in TrdOrderDet.objects.filter(id_order=trd_order):
            order_det_by_good_dict[trd_order_det.id_good] = trd_order_det

        # удаляем позиции, которых нет
        for order_det_good in order_det_by_good_dict:
            if order_det_good not in selled_goods_dict:
                order_det_by_good_dict[order_det_good].delete()

        # применяем позиции
        for selled_goods in selled_goods_dict:
            trd_order_det = order_det_by_good_dict.get(selled_goods)

            if not trd_order_det:
                trd_order_det = TrdOrderDet.insert(trd_order.id, selled_goods.id)

            trd_order_det.set_n_qty(selled_goods_dict[selled_goods])
            trd_order_det.save()

        trd_order.save()

        # Обработка состояния
        state = None
        if is_finished:
            # Из Wix нельзя понять, что заказ доставлен. ПОтому если ему вручную
            # было установлено состояние большее, чем отправлен, то ставим его
            state = TrdOrderState.objects.filter(n_order=400).first()
            if old_state.n_order > state.n_order:
                state = old_state

        if state:
            trd_order.set_id_state(state.id, self.s_user)
Esempio n. 14
0
    def set_n_qty(self, value: int):
        if value < 0:
            raise AppException('Количество не должно быть отрицательным')

        self.n_qty = value
Esempio n. 15
0
    def __sync_with_act(self):
        # создание накладных
        act_out = self.id_act
        act_in = self.id_act_in

        if act_out is None:
            act_out = StkAct.inset_out_act()
            act_out.s_desc = "Сформирована от \"" + self.get_head_line() + "\""
            act_out.save()
            self.id_act = act_out

        if act_out.s_state != StkAct.STATE_REGISTERING:
            raise AppException(
                "Ошибка синхронизации с расходной накладной. Накладная в неверном состоянии"
            )

        if act_in is None:
            act_in = StkAct.inset_in_act()
            act_in.s_desc = "Сформирована от \"" + self.get_head_line() + "\""
            act_in.save()
            self.id_act_in = act_in

        if act_in.s_state != StkAct.STATE_REGISTERING:
            raise AppException(
                "Ошибка синхронизации с приходной накладной. Накладная в неверном состоянии"
            )

        # Формирование списка ТМЦ для накладной
        self_gds_out_dict = {}
        self_gds_in_dict = {}

        def add_qty(dict, id_good, n_qty):
            if id_good in dict:
                dict[id_good] = dict[id_good] + n_qty
            else:
                dict[id_good] = n_qty

        def add_out_qty(id_good, n_qty):
            add_qty(self_gds_out_dict, id_good, n_qty)

        def add_in_qty(id_good, n_qty):
            add_qty(self_gds_in_dict, id_good, n_qty)

        for shift_result_item in MnfShiftResultItems.objects.filter(
                id_shift_result=self):
            # приход
            add_in_qty(shift_result_item.id_item.id_good_id,
                       shift_result_item.n_qty)

            # расход
            for item_det in MnfItemDet.objects.filter(
                    id_item=shift_result_item.id_item):
                add_out_qty(item_det.id_good_id,
                            item_det.n_qty * shift_result_item.n_qty)

        for shift_result_material in MnfShiftResultMaterials.objects.filter(
                id_shift_result=self):
            add_out_qty(shift_result_material.id_good_id,
                        shift_result_material.n_qty)

        # обновление позиций
        act_out.apply_det_data(self_gds_out_dict)
        act_in.apply_det_data(self_gds_in_dict)
Esempio n. 16
0
 def on_export(self):
     """Действия выполняемые при экспорте.
     Требуется переопределить этот метод в наследнике.
     Метод должен получать список объекто экспорта, и для каждого вызывать handle_object
     Если импорт не используется, то отключите флаг is_import_enabled"""
     raise AppException("Не реализован экспорт объектов")
Esempio n. 17
0
    def import_order(self, order, obj_info):
        """Импорт одного заказа"""

        # ИД заказа
        order_id = order.get('OrderID')
        obj_info.id_external = order_id

        # Требуется сразу же сохранить новый заказ, т.к. сесии выгрузки запоминают дату последней выгрузки
        # и получают заказы начиная с даты последней выгрузки. Если сохранять все заказы, то они будут обработаны
        # новыми сессиями как незавршенные

        trd_order = TrdOrder.objects.filter(
            s_reg_num=order_id,
            id_trade_system=self.circuit.id_trade_system).first()

        if not trd_order:
            trd_order = TrdOrder.inset_by_trade_system(
                self.circuit.id_trade_system, self.s_user)
            trd_order.set_s_reg_num(order_id)
            trd_order.save()

        # Дата оплаты
        paid_time = order.get('PaidTime')
        # Дата отправки
        shipped_time = order.get('ShippedTime')
        # Дата доставки
        actual_delivery_time = None
        # Дата создания
        created_time = order.get('CreatedTime')
        # Служба доставки
        shipping_service_name = None
        # Получатель
        shipping_address_name = None
        # Адрес
        shipping_address_address = None
        # Набор трек номеров
        shipment_tracking_number_set = set()
        # ПРоданные позиции
        selled_sku_dict = {}

        # Получение информации о доставке
        shipping_service_selected = order.get('ShippingServiceSelected')
        if shipping_service_selected:
            shipping_service_name = shipping_service_selected.get(
                'ShippingService')
            shipping_package_info = shipping_service_selected.get(
                'ShippingPackageInfo')
            if shipping_package_info:
                actual_delivery_time = shipping_package_info.get(
                    'ActualDeliveryTime')

        # Расчет адреса
        shipping_address = order.get('ShippingAddress')
        if shipping_address:
            shipping_address_name = shipping_address.get('Name')

            address_dict = {
                'Страна': 'CountryName',
                'Почтовый индекс': 'PostalCode',
                'Область': 'StateOrProvince',
                'Город': 'CityName',
                'Улица': 'Street1',
                'Улица2': 'Street2',
            }

            for key in address_dict:
                value = shipping_address.get(address_dict[key])
                if value:
                    if shipping_address_address:
                        shipping_address_address = shipping_address_address + '\n'
                    else:
                        shipping_address_address = ''
                    shipping_address_address = shipping_address_address + key + ': ' + value

        # Обработка позиций заказа
        transaction_array = order.get('TransactionArray')

        if not transaction_array:
            raise AppException("Не найден список позиций заказа")

        transaction = transaction_array.get('Transaction')

        if not transaction:
            raise AppException("Не найден список позиций заказа")

        for trans in transaction:
            # Расчет трек номера
            shipping_details = trans.get('ShippingDetails')
            if shipping_details:
                shipment_tracking_details = shipping_details.get(
                    'ShipmentTrackingDetails')
                if shipment_tracking_details:
                    shipment_tracking_number = shipment_tracking_details.get(
                        'ShipmentTrackingNumber')
                    if shipment_tracking_number:
                        shipment_tracking_number_set.add(
                            shipment_tracking_number)

            # Расчет товаров
            item = trans.get('Item')
            if item:
                sku = item.get('SKU')
                title = item.get('Title')
                qty = int(trans.get('QuantityPurchased'))

                if not sku:
                    raise AppException('Для товара ' + title +
                                       ' не указан SKU')

                if sku in selled_sku_dict:
                    selled_sku_dict[sku] = selled_sku_dict[sku] + qty
                else:
                    selled_sku_dict[sku] = qty

        # установка данных
        # сначала откатим заказ, т.к. он мог уже внести данные в склад
        if trd_order.id_state.is_write_off_goods():
            trd_order.set_id_state(TrdOrderState.get_start_state().id,
                                   self.s_user)

        trd_order.set_d_reg_date(self.__str_to_date(created_time))
        trd_order.set_s_receiver(shipping_address_name)
        trd_order.set_s_address(shipping_address_address)
        trd_order.set_s_track_num(', '.join(shipment_tracking_number_set))

        trd_order.save()

        # Служба доставки
        if shipping_service_name:
            delivery_service = self.mapping_delivery_service_dict.get(
                shipping_service_name)
            if not delivery_service:
                raise AppException('Для службы доставки ' +
                                   shipping_service_name +
                                   ' не настроено сопоставление')
            trd_order.set_id_delivery_service(delivery_service)
        else:
            trd_order.set_id_delivery_service(None)

        trd_order.save()

        # Обработка ТМЦ
        selled_goods_dict = {}

        for selled_sku in selled_sku_dict:
            mapping_goods = self.mapping_goods_dict.get(selled_sku)

            if not mapping_goods:
                raise AppException('Для SKU ' + selled_sku +
                                   ' не настроено сопоставление')

            for good, n_qty in mapping_goods[GoodMapping.good_mapping_key()]:

                if good not in selled_goods_dict:
                    selled_goods_dict[good] = 0

                selled_goods_dict[good] = selled_goods_dict[
                    good] + n_qty * selled_sku_dict[selled_sku]

        order_det_by_good_dict = {}
        # индксируем позиции заказа
        for trd_order_det in TrdOrderDet.objects.filter(id_order=trd_order):
            order_det_by_good_dict[trd_order_det.id_good] = trd_order_det

        # удаляем позиции, которых нет
        for order_det_good in order_det_by_good_dict:
            if order_det_good not in selled_goods_dict:
                order_det_by_good_dict[order_det_good].delete()

        # применяем позиции
        for selled_goods in selled_goods_dict:
            trd_order_det = order_det_by_good_dict.get(selled_goods)

            if not trd_order_det:
                trd_order_det = TrdOrderDet.insert(trd_order.id,
                                                   selled_goods.id)

            trd_order_det.set_n_qty(selled_goods_dict[selled_goods])
            trd_order_det.save()

        trd_order.save()

        # Обработка состояния
        state = None
        if actual_delivery_time:
            # Доставлен
            state = TrdOrderState.objects.filter(n_order=500).first()
        elif shipped_time:
            # Отправлен
            state = TrdOrderState.objects.filter(n_order=400).first()

        if state:
            trd_order.set_id_state(state.id, self.s_user)