diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..706fd07 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +.idea +.vscode diff --git a/AgreementProcess.puml b/AgreementProcess.puml index 2e7abaa..3bb1b35 100644 --- a/AgreementProcess.puml +++ b/AgreementProcess.puml @@ -45,4 +45,4 @@ endif end group :Передаем задачу в груминг и далее по процессу движения задачи; stop -@enduml \ No newline at end of file +@enduml diff --git a/oms-ddc/oms-ddc.puml b/oms-ddc/oms-ddc.puml index ac2c2d3..42826b1 100644 --- a/oms-ddc/oms-ddc.puml +++ b/oms-ddc/oms-ddc.puml @@ -1,11 +1,76 @@ @startuml -'https://plantuml.com/sequence-diagram autonumber +boundary LT_trigger +queue logistic_tracker.logistic_order_changes as kafka_lt +participant DDC +participant OMS_Order +queue touch.events as Touch +database db -Alice -> Bob: Authentication Request -Bob --> Alice: Authentication Response +loop +LT_trigger -> kafka_lt: Событие изменения лог заказа +DDC -> kafka_lt: Читает сообщение +end +alt customer_shipment.now > customer_shipment.before is False +DDC -> DDC: пропускает сообщение +else customer_shipment.now > customer_shipment.before is True +DDC -> OMS_Order: Ожидает подтверждение\nпереноса ДД от OMS через wf +alt Сигнал с подтверждением переноса ДД не пришло +DDC -> DDC: Прекращает ожидание события +else Сигнал с подтверждением переноса ДД пришло +OMS_Order -> DDC: Сигнал с подтверждением переноса ДД +DDC -> DDC: Проверяет что не было уведомлений\nпо заказу в течении этих суток +alt Было уведомление в последние сутки +DDC -> DDC: Пропускает данное изменение +else Не было уведомлений в последние сутки +DDC -> DDC: Проверяет заказ робота или клиента? +alt Заказ робота +DDC -> CRM: Отправка сообщения в топик CRM +DDC -> db: Записывает данные о поставленной задаче в БД +else Заказ клиента +DDC -> OMS_Order: Получить данные по заказу +OMS_Order -> DDC: Вернуть данные по заказу +DDC -> DDC: Подготовить данные для\nотправки в топик Touch +DDC -> Touch: Отправить нотификацию в топик Touch (b2c смс, b2b email) +DDC -> db: Записывает данные о нотификации клиента в БД +end +end +end +end -Alice -> Bob: Another authentication Request -Alice <-- Bob: another authentication Response -@enduml \ No newline at end of file + +@enduml + + + +@startuml +start +:DDC читает топик LT; +if (customer_shipment.now > customer_shipment.before is False) then +:Пропускает сообщение; +kill +else +:DDC Ожидает подтверждение\nпереноса ДД от OMS через wf; +endif + +if (Сигнал с подтверждением переноса ДД пришел?) then (нет) +:Прекращает ожидание события\nничего не делает; +kill +else (да) +if (Событие уведомления по заказу было в течении суток?) then (да) +:Пропускает событие; +kill +else (нет) +endif + +if (Заказ назначен на менеджера?) then (да) +:Отправка сообщения в топик CRM; +:Записывает данные о поставленной задаче в БД; +else (нет (заказ робота)) +:Отправить нотификацию в топик Touch (b2c смс, b2b email); +:Записывает данные о нотификации клиента в БД; +endif +stop + +@enduml diff --git a/oms/autobot.puml b/oms/autobot.puml new file mode 100644 index 0000000..a3e05e1 --- /dev/null +++ b/oms/autobot.puml @@ -0,0 +1,63 @@ +@startuml +participant "Топик сообщений" as Topic +participant "Сервис обработки" as Service +participant "База данных" as DB +participant "МСКБ API" as MSKB +participant "Bifrost API" as Bifrost +participant "CRM API" as CRM +participant "TOUCH API" as TOUCH + +Topic -> Service: Сообщение с letter_guid,\ncontractor_guid,\ncontact_person_guid,\ncommodity_guid +activate Service + +Service -> DB: Проверить заказ по autoBotLetterGuid=letter_guid +alt Заказ уже существует + Service --> Topic: Пропустить сообщение + deactivate Service +else Заказа нет + Service -> Service: Валидация contractor_guid + alt contractor_guid пустой + Service -> DB: Найти контрагента по contact_person_guid\nв последних заказах + alt Контрагент не найден + Service --> Topic: Завершить обработку + deactivate Service + else Найден contractor_guid + end + else несколько contractor_guid + Service -> DB: Найти последний завершенный заказ\nдля каждого contractor_guid + end + + Service -> Service: Валидация contact_person_guid + alt contact_person_guid пустой + Service -> MSKB: /api/business/v2/physic/\nпоиск по letter_from + alt Не найдено + Service -> DB: Найти в последнем заказе\nпо contractor_guid + end + end + + Service -> Service: Валидация commodity_guid + alt commodity_guid пустые + Service --> Topic: Завершить обработку + deactivate Service + end + + Service -> DB: Найти последний завершенный заказ\nдля получения shipment данных + Service -> MSKB: /api/business/v2/juristic/search\nполучить GUID менеджера + Service -> Bifrost: bifrost.v1.ActiveDirectoryService/GetUserByID\nпроверить email менеджера + alt email != letter_to + Service --> Topic: Завершить обработку + deactivate Service + end + + Service -> Service: Создать заказ + Service -> DB: createOrder + Service -> Service: Автооформление заказа (flowId=6) + Service -> DB: Обновить заказ\n(IsAutoBotOrder=true,\nautoBotLetterGuid=letter_guid) + + Service -> CRM: Создать задачу менеджеру\n"Заказ не прошел АО..." + Service -> TOUCH: /api/v1/jsonapi/send-email-message\nОповестить менеджера + + Service --> Topic: Обработка завершена + deactivate Service +end +@enduml \ No newline at end of file diff --git a/oms/autoorder/change-ao.puml b/oms/autoorder/change-ao.puml index 3a39f61..9de15da 100644 --- a/oms/autoorder/change-ao.puml +++ b/oms/autoorder/change-ao.puml @@ -41,4 +41,180 @@ workflow -> workflow: Проверяет наличие\nкрупногабар end end end +@enduml + + + +@startuml Редактирование заказа процесс +skinparam backgroundColor #FFFFFF +skinparam componentStyle rectangle + +title Бизнес-процесс редактирования заказа + +actor User as U +participant "Frontend ARM" as F +participant "Gateway" as G +participant "Workflow" as W +participant "Order" as OS +participant "History" as H +participant "WTIS" as WTIS +participant "MongoDB" as DB + +== Инициация редактирования == + +U -> F: Клик на кнопку "Редактирование заказа" +activate F + +F -> G: GET /orders/v1/{orderID}/start-correction +activate G + +G -> W: ExecuteWorkflow(B2CGetEditableFieldsWorkflow) +activate W + +== Workflow: Получение редактируемых полей == + +W -> OS: gRPC: GetOrder(orderID) +activate OS +OS -> DB: Поиск заказа +DB --> OS: Данные заказа +OS --> W: Order entity +deactivate OS + +W -> H: gRPC: IsTransactionExist(orderID) +activate H +H -> H: Transaction Service\nIsTransactionExist() +H -> DB: Поиск открытой транзакции +DB --> H: TransactionID или null +H --> W: TransactionID или uuid.Nil +deactivate H + +alt Транзакция не существует + W -> H: gRPC: StartTransaction(orderID, userID) + activate H + H -> H: Transaction Service\nStartTransaction() + H -> H: Создание новой транзакции\n(статус: Opened) + H -> DB: Сохранение транзакции + DB --> H: Подтверждение + H --> W: TransactionID + deactivate H +end + +W -> W: Определение редактируемых полей\n(editorder.FieldsDispatcher) +W -> W: Activity: GetEditableFieldsFromWTIS(orderID) +W -> WTIS: API GET GetEditableFieldsFromWTIS(orderID) +activate WTIS +WTIS --> W: Права на редактирование атрибутов +deactivate WTIS + +W -> W: Проверка прав пользователя\n(permissions) +W -> W: Формирование ответа\n(CorrectionAnswer) +W --> G: Результат workflow +deactivate W + +G --> F: CorrectionAnswer\n(редактируемые поля) +deactivate G + +F -> F: Показать уведомление\n"У вас есть 5 минут на редактирование" +F --> U: Интерфейс редактирования активирован +deactivate F + +== Мониторинг транзакции == + +loop Каждые 30 секунд + F -> F: checkOrderHasTransaction() + F -> G: GET /orders/v1/{orderID} + G --> F: hasTransaction: boolean + alt hasTransaction = false + F -> F: Показать ошибку\n"Время на редактирование вышло" + F -> F: Перезагрузить страницу + end +end + +== Завершение редактирования == + +U -> F: Клик "Сохранить" или "Отменить" +activate F + +F -> G: GET /orders/v1/{orderID}/end-correction\n?typeCorrection=...&typeEndCorrection=... +activate G + +G -> W: ExecuteWorkflow(B2CEndCorrectionsWorkflow) +activate W + +== Workflow: Завершение редактирования == + +W -> W: Lock ресурса (mutex)\n(10 минут блокировка) + +W -> OS: gRPC: GetOrder(orderID) +activate OS +OS -> DB: Поиск заказа +DB --> OS: Данные заказа +OS --> W: Order entity +deactivate OS + +W -> W: Activity: IsTransactionExist(orderID) +W -> H: gRPC: IsTransactionExist(orderID) +activate H +H -> H: Transaction Service\nIsTransactionExist() +H -> DB: Поиск транзакции +DB --> H: TransactionID +H --> W: TransactionID +deactivate H + +alt typeEndCorrection = "reject" + W -> W: Activity: EndTransaction(orderID, userID, true) + W -> H: gRPC: EndTransaction(orderID, userID, true) + activate H + H -> H: Transaction Service\nEndTransaction() + H -> H: Закрытие транзакции\n(статус: Rejected) + H -> DB: Обновление транзакции + DB --> H: Подтверждение + H --> W: Результат + deactivate H + W -> W: Unlock ресурса + W --> G: Успешная отмена +else typeEndCorrection = "success" + W -> W: ManualActionWorkflow.ExecuteAsChild()\n(синхронизация с WTIS) + W -> W: Activity: GetOrderByID(orderID)\n(обновленные данные) + W -> OS: gRPC: GetOrder(orderID) + activate OS + OS -> DB: Поиск заказа + DB --> OS: Обновленные данные заказа + OS --> W: Order entity + deactivate OS + W -> W: Activity: EndTransaction(orderID, userID, false) + W -> H: gRPC: EndTransaction(orderID, userID, false) + activate H + H -> H: Transaction Service\nEndTransaction() + H -> H: Закрытие транзакции\n(статус: Finished) + H -> DB: Обновление транзакции + H -> H: publishEvents()\n(публикация событий) + H --> W: Результат + deactivate H + W -> W: SaveOrderWithShipment()\n(сохранение изменений) + W -> OS: gRPC: UpsertOrderWithShipment(orderID) + activate OS + OS -> H: Transaction Service\nIsTransactionExist() + activate H + H -> DB: Поиск транзакции + DB --> H: TransactionID + H --> OS: TransactionID + deactivate H + OS -> DB: Сохранение заказа + DB --> OS: Подтверждение + OS --> W: Order entity + deactivate OS + W -> W: Unlock ресурса + W --> G: Успешное сохранение +end + +deactivate W +G --> F: Результат завершения транзакции +deactivate G + +F -> F: Обновление интерфейса +F --> U: Редактирование завершено +deactivate F + + @enduml \ No newline at end of file diff --git a/oms/interface-arm/order/history.puml b/oms/interface-arm/order/history.puml index fbae6b2..9258810 100644 --- a/oms/interface-arm/order/history.puml +++ b/oms/interface-arm/order/history.puml @@ -35,4 +35,109 @@ History --> OMS: answer OMS --> ARM: answer ARM --> user: Отображает корректировки по заданным условиям +@enduml + + + + +@startuml +scale 1000*1000 +mainframe Взаимодействие с историей изменения заказа +actor Пользователь as user +participant ARM as ARM +participant Gateway as Gateway +participant History as History +participant Bifrost as Bifrost +autonumber + +user -> ARM: Нажимает кнопку "История изменений" +ARM -> Gateway: REST GET /history/v1/order/{orderID} +Gateway -> History: gRPC GetChangesByOrderIDAndParameters() +History --> Gateway: EventsByOrderIDResponse +Gateway -> Bifrost: gRPC GetUsersByIDs() [для получения имен менеджеров] +Bifrost --> Gateway: UserInfo[] +Gateway --> ARM: Таблица истории изменений с именами менеджеров +ARM --> user: Рендерит модальное окно "История изменений" + +user -> ARM: Нажимает кнопку "Подробнее" в корректировке +ARM -> Gateway: REST GET /history/v1/events?eventIDs=[eventID] +Gateway -> History: gRPC GetEventChangesByIDs() +History --> Gateway: EventChangesByIDResponse[] +Gateway -> Bifrost: gRPC GetUserByIDV2() [для получения имени менеджера] +Bifrost --> Gateway: UserInfo +Gateway --> ARM: Таблица истории изменений с именами менеджеров +ARM --> user: Отображает полную информацию о корректировке + +user -> ARM: Выбирает фильтр по дате или по типу корректировки +ARM -> Gateway: REST GET /history/v1/order/{orderID}?eventCorrectionType=...&createdAts=... +Gateway -> History: gRPC GetChangesByOrderIDAndParameters() [с фильтрами] +History --> Gateway: EventsByOrderIDResponse +Gateway -> Bifrost: gRPC GetUsersByIDs() [для получения имен менеджеров] +Bifrost --> Gateway: UserInfo[] +Gateway --> ARM: Таблица истории изменений с именами менеджеров +ARM --> user: Отображает корректировки по заданным условиям + +user -> ARM: Вводит идентификатор корректировки и нажимает Enter +ARM -> Gateway: REST GET /history/v1/events?eventIDs=[eventID] +Gateway -> History: gRPC GetEventChangesByIDs() +History --> Gateway: EventChangesByIDResponse[] +Gateway -> Bifrost: gRPC GetUserByIDV2() [для получения имени менеджера] +Bifrost --> Gateway: UserInfo +Gateway --> ARM: История изменений с именами менеджеров +ARM --> user: Отображает корректировки по заданным условиям + +@enduml + +@startuml +scale 1200*1200 +mainframe Взаимодействие с историей изменения заказа +actor Пользователь as user +participant ARM as ARM +participant Gateway as Gateway +participant History as History +participant Bifrost as Bifrost +autonumber + +user -> ARM: Нажимает кнопку "История изменений" +ARM -> Gateway: REST GET /history/v1/filters +Gateway -> History: gRPC GetTypesOfEvents() +History --> Gateway: AvailableActions (список типов событий) +Gateway --> ARM: HistoryFiltersList (eventCorrectionType[]) +ARM -> Gateway: REST GET /history/v1/order/{orderID} +Gateway -> History: gRPC GetChangesByOrderIDAndParameters() +History --> Gateway: EventsByOrderIDResponse +Gateway -> Bifrost: gRPC GetUsersByIDs() [для получения имен менеджеров] +Bifrost --> Gateway: UserInfo[] +Gateway --> ARM: HistoryList (события с именами менеджеров) +ARM --> user: Рендерит модальное окно "История изменений" с фильтрами + +user -> ARM: Нажимает кнопку "Подробнее" в корректировке +ARM -> Gateway: REST GET /history/v1/events?eventIDs=[eventID] +Gateway -> History: gRPC GetEventChangesByIDs() +History --> Gateway: EventChangesByIDResponse[] +Gateway -> Bifrost: gRPC GetUserByIDV2() [для получения имени менеджера] +Bifrost --> Gateway: UserInfo +Gateway --> ARM: HistoryEvent (с полными изменениями) +ARM --> user: Отображает полную информацию о корректировке + +alt Первый тип поиска по дате и/или типу корректировки +user -> ARM: Выбирает фильтр по дате или по типу корректировки +ARM -> Gateway: REST GET /history/v1/order/{orderID}?eventCorrectionType=...&createdAts=... +Gateway -> History: gRPC GetChangesByOrderIDAndParameters() [с фильтрами] +History --> Gateway: EventsByOrderIDResponse +Gateway -> Bifrost: gRPC GetUsersByIDs() [для получения имен менеджеров] +Bifrost --> Gateway: UserInfo[] +Gateway --> ARM: HistoryList (отфильтрованные события) +ARM --> user: Отображает корректировки по заданным условиям +else Второй тип поиска по идентификатору корректировки +user -> ARM: Вводит идентификатор корректировки и нажимает Enter +ARM -> Gateway: REST GET /history/v1/events?eventIDs=[eventID] +Gateway -> History: gRPC GetEventChangesByIDs() +History --> Gateway: EventChangesByIDResponse[] +Gateway -> Bifrost: gRPC GetUserByIDV2() [для получения имени менеджера] +Bifrost --> Gateway: UserInfo +Gateway --> ARM: HistoryEvent (с полными изменениями) +ARM --> user: Отображает корректировки по заданным условиям +end + @enduml \ No newline at end of file diff --git a/oms/order mongoDB.puml b/oms/order mongoDB.puml index 3f1529d..e5a6d85 100644 --- a/oms/order mongoDB.puml +++ b/oms/order mongoDB.puml @@ -8,34 +8,64 @@ FontName Helvetica FontColor black FontSize 18 - FontStyle bold + 'FontStyle bold } arrow { LineColor #000 - LineThickness 3 - LineStyle 2 + LineThickness 1 + LineStyle 5 } highlight { BackGroundColor #e5e5e5 FontColor black } } - ' Здесь находятся расцветки изменений. Необходимо создать новый объект по образу .firstChange + ' Здесь находятся расцветки изменений. Необходимо создать новый объект по образу .headerBlock + .headerBlock { + FontColor red + FontStyle bold + BackGroundColor grey + } .firstChange { - FontColor blue + FontColor black + FontStyle bold + BackGroundColor Blue } ' Здесь указываем какие атрибуты нужно подсвечивать в схеме -#highlight "order" / "Recipient" / "ID" <> -#highlight "order" / "Recipient" / "RecipientAddress" <> -#highlight "order" / "Recipient" / "RecipientPhone" <> -#highlight "order" / "Recipient" / "RecipientName" <> +'Пример другого цвета +#highlight "order" / "Shipment" / "shipmentFastDelivery" <> + +' Заголовки (выделены красным и темно-серым для улучшения читаемости) +#highlight "order" / "Artifacts" / "Artifacts" <> +#highlight "order" / "Artifacts" / "Artifacts" <> +#highlight "order" / "B2CContractor" / "B2CContractor" <> +#highlight "order" / "B2BContractor" / "B2BContractor" <> +#highlight "order" / "Properties" / "Properties" <> +#highlight "order" / "Supplies (array)" / "Supplies (array)" <> +#highlight "order" / "Shipment" / "Shipment" <> +#highlight "order" / "Shipment" / "ShipmentPickup" / "ShipmentPickup" <> +#highlight "order" / "Shipment" / "ShipmentPickupFranchise" / "ShipmentPickupFranchise" <> +#highlight "order" / "Shipment" / "ShipmentCourier" / "ShipmentCourier" <> +#highlight "order" / "Shipment" / "shipmentTKCourier" / "shipmentTKCourier" <> +#highlight "order" / "Shipment" / "ShipmentTKPickup" / "ShipmentTKPickup" <> +#highlight "order" / "Shipment" / "shipmentFastDelivery" / "shipmentFastDelivery" <> +#highlight "order" / "Shipment" / "Meta" / "Meta" <> +#highlight "order" / "Contractor" / "Contractor" <> +#highlight "order" / "Recipient" / "Recipient" <> +#highlight "order" / "managerInfo" / "managerInfo" <> { "order": { - "orderID": "uuid || Номер заказа", + "ID": "uuid || Номер заказа", + "ContractorID": "uuid || Идентификатор контрагента", + "RootOrder": "uuid || UUID корневого заказа", + "Number": "string || Номер заказа в формате ****-******-*****", + "ContractorType": "int || Тип КА", + "OrderStatus": "int || Идентификатор статуса заказа (от 0 до 7)", "managerInfo": { + "managerInfo": "Блок информации о менеджере в заказе (ManagerInfo)", "CreatedBy": "uuid || Идентификатор автора заказа из AD", "CreatedFullName": "string || ФИО автора заказа", "UpdatedBy": "uuid || Идентификатор последнего обновлявшего заказ", @@ -44,94 +74,72 @@ "ManagerPhoneNumber": "string || Номер телефона менеджера", "ManagerExtensionNumber": "string || Добавочный номер телефона менеджера" }, - "RootOrder": "uuid || UUID корневого заказа", - "Number": "string || Номер заказа в формате ****-******-*****", - "OrderStatus": "int || Идентификатор статуса заказа (от 0 до 7)", - "Contractor": { - "Type": "int || Тип контрагента.", - "B2CContractor": { + "B2CContractor": { + "B2CContractor": "Контрагент b2c (вложенный объект с атрибутами дальше по ветке)", + "Person": { + "ID": "uuid || Идентификатор (UUID) контрагента", + "FullName": "string || Полное ФИО КА", + "Phone": "string || Номер телефона КА", + "Email": "string || Email адрес КА" + } + }, + "B2BContractor": { + "B2BContractor": "Блок контрагента B2b", + "ID": "uuid || Идентификатор (UUID) контрагента", + "Name": "string || Полное наименование КА", + "TIN": "string || Номер ИНН", + "edo": "boolean || Признак что КА работает по ЭДО", + "isPDZ": "boolean || false", + "paymentType": "integer || Признак оплаты, 1 - предоплата, 2 - постоплата", + "Agent": { + "ID": "uuid || Индентификатор агента заказа", + "OrderNumber": "string || Номер заказа в системе агента", + "ContractType": "integer || Тип договора к заказу, 1 - агентский, 2 - клиентский, 3 - торговый дом" + }, + "ContactPersons (array)": { "Person": { "ID": "uuid || Идентификатор (UUID) контрагента", "FullName": "string || Полное ФИО КА", "Phone": "string || Номер телефона КА", "Email": "string || Email адрес КА" - } + }, + "SmsPhoneNumber": "string || Номер телефона для СМС" }, - "B2BContractor": { - "ID": "uuid || Идентификатор (UUID) контрагента", - "Name": "string || Полное наименование КА", - "TIN": "string || Номер ИНН", - "ContactPersons (array)": { - "Person": { - "ID": "uuid || Идентификатор (UUID) контрагента", - "FullName": "string || Полное ФИО КА", - "Phone": "string || Номер телефона КА", - "Email": "string || Email адрес КА" - }, - "SmsPhoneNumber": "string || Номер телефона для СМС" - }, - "CurrentContactPersonID": "uuid || ID выбранного КЛ для заказа", - "Curator": { - "ID": "uuid || Идентификатор куратора", - "FullName": "string || ФИО куратора" - }, - "Contract": { - "ID": "uuid || Идентификатор договора", - "Number": "string || Номер договора", - "Kind": "int || Тип договора" - }, - "BaseDocumentSettings": { - "GovernmentContractID": "string || Идентификатор государственного контракта", - "InvoiceTransferBasis": "string || Основание передачи в счете на оплату", - "ShippingDocuments": { - "TransferBasisDocument": "string || документ-основание передачи(сдачи)/получения(приемки)", - "TransferBasisAdditionalDetails": "string || Дополнительные сведения основания передачи", - "OtherInformation": "string || Иные сведения" - } + "CurrentContactPersonID": "uuid || ID выбранного КЛ для заказа", + "Curator": { + "ID": "uuid || Идентификатор куратора", + "FullName": "string || ФИО куратора" + }, + "KAM": { + "ID": "uuid || Идентификатор КАМа", + "FullName": "string || ФИО КАМа" + }, + "Contract": { + "ID": "uuid || Идентификатор договора", + "Number": "string || Номер договора", + "Kind": "int || Тип договора" + }, + "BaseDocumentSettings": { + "GovernmentContractID": "string || Идентификатор государственного контракта", + "InvoiceTransferBasis": "string || Основание передачи в счете на оплату", + "ShippingDocuments": { + "TransferBasisDocument": "string || документ-основание передачи(сдачи)/получения(приемки)", + "TransferBasisAdditionalDetails": "string || Дополнительные сведения основания передачи", + "OtherInformation": "string || Иные сведения" } } }, "Recipient": { + "Recipient": "Блок грузополучателя (Deprecated) для поддержки старых заказов. Актуальный в shipment", "ID": "uuid || Идентификатор (UUID) грузополучателя", "RecipientName": "string || Имя грузополучателя заказа", "RecipientPhone": "string || Номер телефона грузополучателя", - "RecipientAddress": "string || Адрес грузополучателя" - }, - "Properties": { - "BasicTimestamps": { - "CreatedAt": "date-time || Дата и время создания заказа", - "UpdatedAt": "date-time || Дата и время последнего обновления заказа" - }, - "OriginID": "int || Идентификатор источника заказа", - "SiteOrderDate": "date-time || Дата и время заказа выбранное на сайте", - "OrderComment": "string || Комментарий к заказу. Во wtis: primSklad", - "TtnNumber": "string || Номер ТТН", - "TtnDate": "string || Дата ТТН", - "IsPartialShipmentFromSite": "bool || Признак ЧО с сайта", - "PaymentAmount": "float || Сумма внесенной оплаты", - "BookingEndDates": "array || Массив с датами истечения бронирования заказа", - "IsPrepaymentRequired": "bool || Признак Необходима предоплата", - "RegionGUID": "uuid || Идентификатор (UUID) региона", - "RegionName": "string || Наименование региона", - "TypeOrderFromSite": "string || Тип заказа с сайта. normal / fast", - "Firma": "GUID фирмы отгружающей товар." - }, - "Artifacts": { - "PartialShipment": "bool || Признак Частичная отгрузка", - "OrderMasterSystem": "string || Признак мастер-система по заказу", - "KkmDate": "string || Дата ККМ", - "KkmAmount": "float || Сумма оплаты через ККМ", - "PaymentKkm": "bool || Признак оплата через ККМ", - "PaymentCb": "bool || Признак оплата по счету", - "PaymentCard": "bool || Признак картой", - "IsEwalletPayment": "bool || Признак оплата с сайта", - "OrderStateWtis": "int || Состояние заказа из WTIS", - "AttbOplata": "int || Статус оплаты (0 - Не оплачено, 1 - Частичная оплата, 2 - Оплачено). || deprecated", - "OrderStatusWtis": "int || Статус заказа из WTIS", - "IsPromoEnabled": "bool || Признак, что сайт взаимодействует с МС Promo и берет распродажную инфу оттуда.", - "IsYandexEnabled": "bool || Признак, что адрес передается в новом формате для курьерки." + "RecipientAddress": "string || Адрес грузополучателя", + "isConsingeeApprove": "boolean || Признак подтверждения смены ГП" }, + "Items": "map[uuid.UUID]Item || Товары в заказе", "Supplies (array)": { + "Supplies (array)": "Блок товарной части (supply)", "ID": "uuid || Идентификатор поставки", "ShipmentID": "uuid || Идентификатор шипмента", "ProductID": "uuid || Идентификатор номенклатуры", @@ -142,110 +150,287 @@ "Quantity": "int || Количество товара в доставке. Суммарное количество должно быть равно quantity в items", "StatusItem": "int || Идентификатор статуса товара", "Artifacts": { - "StatusItemWtis": "int || Клиентский статус товара из WTIS", - "Attb": "Состоние товара из WTIS", - "FlagReturn": "bool || Признак Возврат товара. 1 - товар с вкладки Возвраты, 0 - для товаров с вкладки Товары.", + "UUIDWtis": "uuid || UID товара из wtis", + "StatusItemWtis": "int || Статус товара из wtis", + "Attb": "int || Состояние товара во WTIS", + "AttbSklad": "int || Статус местонахождения товара (0 - Свободный, 1 - проверен)", + "AttbShipped": "int || Признак 'Товар доставлен' (0 - не доставлен, 1 - доставлен)", + "AttbReserve": "int || Атрибут резерва", + "FlagReturn": "bool || Признак Возврат товара. 1 - товар с вкладки Возвраты, 0 - для товаров с вкладки Товары.", "FlagReturnedToSklad": "bool || Принят на склад", + "ReturnReason": "int || Причина возврата (1-sklad,2-kurier,3-manager,4-client)", "AppendUser": "uuid || ID пользователя кто добавил поставку", - "ChangeUser": "uuid || ID пользователя кто последний изменил поставку" + "ChangeUser": "uuid || ID пользователя кто последний изменил поставку", + "OnHold": "bool || Флаг товар в процессе переноса", + "IsLargeSized": "bool || Флаг кгт (крупногабаритный товар)" }, "DateCanDeliver": "date-time || Дата 'Сможем доставить'.", "CreatedAt": "date-time || Дата создания поставки", "UpdatedAt": "date-time || Дата последнего обновления поставки", "Prices": { + "SupplyID": "uuid || Идентификатор поставки", "DiscountPrice": "float || Сумма скидки", + "DiscountManualPrice": "float || Сумма скидки (ручная корректировка)", "DiscountCategory": "string || Категория скидки", - "DiscountReason": "string || Причина скидки", + "DiscountType": "string || Тип скидки (manager, contractor)", + "DiscountManualType": "string || Тип ручной корректировки цены", + "DiscountManualTypeID": "uuid || Идентификатор типа ручной корректировки", + "Reason": "int || Причина скидки", "InitialPrice": "float || Начальная цена", "PurchasePrice": "float || Цена закупки", "Price": "float || Цена товара", + "SalePrice": "float || Продажная цена", "Discount": "float || Процент скидки", "ClearanceSaleID": "uuid || Идентификатор распродажи", "IsPromoCodeUsed": "bool || Флаг использования промокода", "PromotionID": "int || Идентификатор акции из МС Promo", + "PromoCode": "string || Промокод в заказе", + "DiscountClearanceSale": "float || Сумма скидки от акции Промо", + "DiscountPromoCode": "float || Сумма скидки от промокода", + "DiscountClearance": "float || Процент скидки от акции/скидки", "ExtraCost": "float || Цена доставки на единицу товара" }, "IsRestored": "bool || Признак восстановления поставки.", + "IsAutoRestored": "bool || Признак автовосстановления поставки через sync", "DeliveryDate": "date-time || Дата доставки" }, + "Supplies": "Supplies || поставки", + "Properties": { + "Properties": "Блок свойства заказа", + "BasicTimestamps": { + "CreatedAt": "date-time || Дата и время создания заказа", + "UpdatedAt": "date-time || Дата и время последнего обновления заказа" + }, + "NumberSchemeBalance": "string || Номер схемы баланса", + "AccountingLine": "AccountingLine || Линия учета", + "OriginID": "int || Идентификатор источника заказа", + "SiteOrderDate": "date-time || Дата и время заказа выбранное на сайте", + "OrderComment": "string || Комментарий к заказу. Во wtis: primSklad", + "PrimSklad": "string || Примечание для менеджера", + "TtnNumber": "string || Номер ТТН", + "TtnDate": "string || Дата ТТН", + "Ttn": "string || Товарно-транспортная накладная (ТТН)", + "BillIsAutoOrdered": "bool || Признак 'Счет автоотправлен'", + "IsAutoReserved": "bool || Признак Заказ автооформлен", + "IsAutoBotOrder": "bool || Признак Заказ создан автоботом", + "IsPartialShipmentFromSite": "bool || Признак ЧО с сайта", + "IsLeasing": "bool || Признак оформления заказа в лизинг", + "PaymentAmount": "float || Сумма внесенной оплаты", + "PaymentPercentage": "int || процент оплаченности заказа", + "Prepayment": "float || Сумма внесенной предоплаты", + "ManagerGroup": "int || Группа менеджера", + "ManagerID": "uuid || Идентификатор (UUID) менеджера заказа", + "ManagerFullName": "string || ФИО менеджера заказа", + "ManagerPhoneNumber": "string || Телефон менеджера заказа", + "ManagerExtensionNumber": "string || Добавочный номер телефона менеджера", + "ConfirmationStatus": "ConfirmationStatus || Статус подтвержения заказа клиентом", + "BookingEndDates": "array || Массив с датами истечения бронирования заказа", + "PaymentDoc": "string || Наименование платежного документа", + "IsPrepaymentRequired": "bool || Признак 'Необходима предоплата'", + "RegionGUID": "uuid || Идентификатор (UUID) региона", + "RegionName": "string || Наименование региона", + "IsTest": "bool || Признак тестового заказа", + "ReasonForCancelingOrder": "int || Причина отмены заказа", + "TypeOrderFromSite": "string || Тип заказа с сайта. normal / fast", + "Firma": "GUID фирмы отгружающей товар.", + "FlowID": "int || Флоу заказа (аналог OriginID с доп логикой)", + "PriceFixing": { + "Number": "int || Порядковый номер фиксации", + "EndDate": "date-time || Дата окончания фиксации" + }, + "b2gLaw": "string || Федеральный закон по которому отгружается заказ", + "b2gLawSite": "string || Федеральный закон выбранный пользователем на сайте", + "SalesChannelID": "int || Идентификатор канала продаж", + "SalesChannelName": "string || Наименование канала продаж", + "GroupManagerName": "string || Наименование группы менеджеров", + "IsAoSuccess": "bool || Флаг успешного автооформления", + "ReturnOrder": "bool || Признак возвратного заказа", + "VerificationCode": "bool || Признак подтверждения получения заказа по коду" + }, + "Artifacts": { + "Artifacts": "Блок артефактов", + "UUIDWtis": "uuid || UUID заказа из wtis", + "PartialShipment": "bool || Признак Частичная отгрузка", + "Firma": "uuid || GUID фирмы отгружающей товар", + "RegionID": "int || Идентификатор региона из wtis", + "MainRegionID": "int || Идентификатор главного региона из wtis", + "BasketNumber": "string || Номер корзины клиента", + "OrderMasterSystem": "string || Признак мастер-система по заказу", + "StockMasterSystem": "StockMasterSystem || Мастер система по товародвижению", + "KkmDate": "string || Дата ККМ", + "KkmAmount": "float || Сумма оплаты через ККМ", + "PaymentKkm": "bool || Признак оплата через ККМ", + "PaymentCb": "bool || Признак оплата по счету", + "PaymentCard": "bool || Признак картой", + "IsEwalletPayment": "bool || Признак оплата с сайта", + "IsCredit": "bool || Признак кредитного заказа", + "OrderStateWtis": "int || Состояние заказа из WTIS", + "AttbOplata": "int || Статус оплаты (0 - Не оплачено, 1 - Частичная оплата, 2 - Оплачено). || deprecated", + "OrderStatusWtis": "int || Статус заказа из WTIS", + "IsPromoEnabled": "bool || Признак, что сайт взаимодействует с МС Promo и берет распродажную инфу оттуда.", + "IsYandexEnabled": "bool || Признак, что адрес передается в новом формате для курьерки." + }, + "UpdateReason": "int || Причина обновления", + "Parts": "map[uuid.UUID]Part || Части заказа", + "HasTransaction": "bool || Признак наличия транзакции", + "IsNewVersion": "bool || Признак новой версии сущности", + "BaseShipmentID": "uuid || UUID доставки", + "DeliveryDate": "date-time || Дата доставки", "Shipment": { - "Meta": { - "ID": "uuid || Идентификатор shipment", - "OrderID": "uuid || Идентификатор заказа", - "MethodID": "int || Идентификатор шипмента", - "Status": "int || Статус доставки", - "DeliveryDate": "date-time || Дата доставки", - "Services": { - "Settings": { - "SpreadExtraCost": "bool || Размазать стоимость доставки по товарам связанным с доставкой" - } - }, - "CreatedAt": "date-time || Дата создания доставки", - "UpdatedAt": "date-time || Дата последнего обновления доставки" + "Shipment": "Блок Доставка (Shipment)", + "Meta": { + "Meta": "Блок мета информации о доставке (Meta)", + "ID": "uuid || Идентификатор shipment", + "OrderID": "uuid || Идентификатор заказа", + "MethodID": "int || Идентификатор шипмента", + "Status": "int || Статус доставки", + "FSMStatus": "object || fsm для статуса", + "Artifacts": { + "DeliveryWith": "string || Начальный временной промежуток курьерской доставки", + "TrackingNumberID": "int || Deprecated", + "PartnerDeliverTo": "string || Deprecated", + "DestinationOfficeID": "int || Deprecated", + "Category": "int || Deprecated", + "DeliveryOn": "string || Верхняя граница часов доставки", + "DeliveryWay": "string || Тип доставки, через транспортную компанию", + "DeliveryType": "bool || 0 - обычная доставка 1 - доставка строительных материалов", + "DeliveryZone": "int || id зоны доставки строительных материалов", + "VeerouteExportDate": "date-time || Дата выгрузки в Veeroute", + "AddressID": "int || Идентификатор адреса доставки (внутренний от WTIS)", + "DeliveryDestinationType": "int || Тип отгрузки (1 - склад, 2 - курьер, 4 - ТК)" + }, + "DeliveryDate": "date-time || Дата доставки", + "IsCustomDeliveryDate": "bool || Ручное изменение дата доставки", + "Services": { + "Settings": { + "SpreadExtraCost": "bool || Размазать стоимость доставки по товарам связанным с доставкой", + "IsShipmentPossible": "bool || Отгружать с ПДЗ", + "isPacking": "bool || Признак 'Упаковать заказ как на ТК'" }, - "ShipmentPickup": { - "OfficeGUID": "uuid || Идентификатор офиса" - }, - "ShipmentCourier": { - "FactDeliveryBoy": "uuid || Идентификатор курьера который отдал заказ", - "FreeReason": "int || Причина бесплатной доставки", - "FiasID": "uuid || FIAS идентификатор адреса доставки", - "IntervalGUID": "uuid || Идентификатор интервала курьерской доставки", - "DeliveryAregGUID": "uuid || Идентификатор AREG адреса доставки", - "AddressTail": { - "AddressTailID": "uuid || Идентификатор хвоста адреса", - "Flat": "int || Номер квартиры", - "Entrance": "int || Подъезд", - "Floor": "int || Этаж", - "AddressComment": "string || Комментарий к адресу", - "ContactNumber": "string || Контактный номер в адресе доставки" - }, - "IntervalValue": "string || Значение интервала доставки", - "Latitude": "string || Широта адреса доставки", - "Longitude": "string || Долгота адреса доставки", - "CourierGUID": "uuid || Идентификатор курьера в заказе", - "DeliveryBoyName": "string || ФИО курьера в заказе", - "AddrDostav": "string || Адрес доставки", - "CourierDeliveryCost": "int || Стоимость доставки", - "CourierComment": "string || Комментарий для курьера" - }, - "ShipmentTKPickup": { - "TransportCompanyID": "uuid || Идентификатор транспортной компании", - "TransportCompanyCityID": "uuid || Идентификатор города ТК", - "TransportCompanyCityName": "string || Название города ТК", - "TransportCompanyExternalCode": "string || Внешний код офиса ТК в системе CDEK", - "TransportCompanyTariffID": "uuid || Идентификатор тарифа ТК", - "TransportCompanyTariffName": "string || Наименование тарифа", - "CourierDeliveryCost": "int || Стоимость доставки", - "CourierComment": "string || Комментарий для курьера" - }, - "shipmentTKCourier": { - "TransportCompanyID": "uuid || Идентификатор транспортной компании", - "TransportCompanyCityID": "uuid || Идентификатор города ТК", - "TransportCompanyCityName": "string || Название города ТК", - "TransportCompanyExternalCode": "string || Внешний код офиса ТК в системе CDEK", - "TransportCompanyTariffID": "uuid || Идентификатор тарифа ТК", - "TransportCompanyTariffName": "string || Наименование тарифа", - "IntervalValue": "string || Значение интервала доставки", - "Latitude": "string || Широта адреса доставки", - "Longitude": "string || Долгота адреса доставки", - "AddrDostav": "string || Адрес доставки", - "FiasID": "uuid || FIAS идентификатор адреса доставки", - "IntervalGUID": "uuid || Идентификатор интервала курьерской доставки", - "DeliveryAregGUID": "uuid || Идентификатор AREG адреса доставки", - "AddressTail": { - "AddressTailID": "uuid || Идентификатор хвоста адреса", - "Flat": "int || Номер квартиры", - "Entrance": "int || Подъезд", - "Floor": "int || Этаж", - "AddressComment": "string || Комментарий к адресу", - "ContactNumber": "string || Контактный номер в адресе доставки" - }, - "CourierDeliveryCost": "int || Стоимость доставки", - "DeliveryWay": "int || Тип доставки, через транспортную компанию", - "CourierComment": "string || Комментарий для курьера" + "LiftToFloor": { + "Price": "int || Цена услуги подъема на этаж", + "ElevatorStatus": "int || Статус лифта" } + }, + "CreatedAt": "date-time || Дата создания доставки", + "UpdatedAt": "date-time || Дата последнего обновления доставки", + "Recipient": { + "ID": "uuid || Идентификатор грузополучателя", + "RecipientName": "string || Имя грузополучателя", + "RecipientPhone": "string || Телефон грузополучателя", + "IsConsigneeApprove": "bool || Наличие подтверждения о смене ГП", + "InvoiceConsigneeAddress": "string || Доп адрес грузополучателя" } + }, + "ShipmentPickup": { + "ShipmentPickup": "Блок Самовывоз (ShipmentPickup)", + "OfficeGUID": "uuid || Идентификатор офиса" + }, + "ShipmentPickupFranchise": { + "ShipmentPickupFranchise": "Блок Самовывоз франшиза (ShipmentPickupFranchise)", + "OfficeGUID": "uuid || UUID ТТ франшизы", + "FranchisePartnerID": "uuid || UUID партнера из МСКБ", + "FranchisePartnerName": "string || Наименование партнера из МСКБ" + }, + "ShipmentCourier": { + "ShipmentCourier": "Блок Курьером (ShipmentCourier)", + "FactDeliveryBoy": "uuid || Идентификатор курьера который отдал заказ", + "FreeReason": "int || Причина бесплатной доставки", + "FiasID": "uuid || FIAS идентификатор адреса доставки", + "IntervalGUID": "uuid || Идентификатор интервала курьерской доставки", + "DeliveryAregGUID": "uuid || Идентификатор AREG адреса доставки", + "AddressTail": { + "AddressTailID": "uuid || Идентификатор хвоста адреса", + "Postcode": "string || Почтовый индекс", + "Flat": "string || Кв./Офис", + "Entrance": "string || Подъезд", + "Floor": "string || Этаж", + "AddressComment": "string || Комментарий к адресу", + "ContactNumber": "string || Контактный номер в адресе доставки" + }, + "IntervalValue": "string || Значение интервала доставки", + "Latitude": "string || Широта адреса доставки", + "Longitude": "string || Долгота адреса доставки", + "CourierGUID": "uuid || Идентификатор курьера в заказе", + "DeliveryBoyName": "string || ФИО курьера в заказе", + "AddrDostav": "string || Адрес доставки", + "CourierDeliveryCost": "int || Стоимость доставки", + "InitialCourierDeliveryCost": "int || Начальная цена доставки курьером", + "CourierComment": "string || Комментарий для курьера", + "DeliveryCategoryType": "int || Тип категории доставки", + "DeliveryCategoryName": "string || Название категории доставки", + "OfficeGUID": "uuid || Офис отгрузки курьеру" + }, + "ShipmentTKPickup": { + "ShipmentTKPickup": "Блок ТК Самовывоз (ShipmentTKPickup)", + "TransportCompanyID": "uuid || Идентификатор транспортной компании", + "TransportCompanyCityID": "uuid || Идентификатор города ТК", + "TransportCompanyCityName": "string || Название города ТК", + "TransportCompanyExternalCode": "string || Внешний код офиса ТК в системе CDEK", + "TransportCompanyTariffID": "uuid || Идентификатор тарифа ТК", + "TransportCompanyTariffName": "string || Наименование тарифа", + "CourierDeliveryCost": "int || Стоимость доставки", + "InitialCourierDeliveryCost": "int || Начальная цена доставки курьером", + "CourierComment": "string || Комментарий для курьера" + }, + "shipmentTKCourier": { + "shipmentTKCourier": "Блок ТК Курьером (ShipmentTKCourier)", + "TransportCompanyID": "uuid || Идентификатор транспортной компании", + "TransportCompanyCityID": "uuid || Идентификатор города ТК", + "TransportCompanyCityName": "string || Название города ТК", + "TransportCompanyExternalCode": "string || Внешний код офиса ТК в системе CDEK", + "TransportCompanyTariffID": "uuid || Идентификатор тарифа ТК", + "TransportCompanyTariffName": "string || Наименование тарифа", + "IntervalValue": "string || Значение интервала доставки", + "Latitude": "string || Широта адреса доставки", + "Longitude": "string || Долгота адреса доставки", + "AddrDostav": "string || Адрес доставки", + "FiasID": "uuid || FIAS идентификатор адреса доставки", + "IntervalGUID": "uuid || Идентификатор интервала курьерской доставки", + "DeliveryAregGUID": "uuid || Идентификатор AREG адреса доставки", + "AddressTail": { + "AddressTailID": "uuid || Идентификатор хвоста адреса", + "PostCode": "string || Индекс адреса доставки", + "Flat": "string || Кв./Офис", + "Entrance": "string || Подъезд", + "Floor": "string || Этаж", + "AddressComment": "string || Комментарий к адресу", + "ContactNumber": "string || Контактный номер в адресе доставки" + }, + "CourierDeliveryCost": "int || Стоимость доставки", + "InitialCourierDeliveryCost": "int || Начальная цена доставки курьером", + "DeliveryWay": "int || Тип доставки, через транспортную компанию", + "CourierComment": "string || Комментарий для курьера", + "DeliveryCategoryType": "int || Тип категории доставки", + "DeliveryCategoryName": "string || Название категории доставки" + }, + "shipmentFastDelivery": { + "shipmentFastDelivery": "Блок Быстрая доставка (ShipmentFastDelivery)", + "OfficeGUID": "uuid || Идентификатор офиса", + "FactDeliveryBoy": "uuid || Идентификатор курьера который отдал заказ", + "FreeReason": "int || Причина бесплатной доставки", + "FiasID": "uuid || FIAS идентификатор адреса доставки", + "IntervalGUID": "uuid || Идентификатор интервала курьерской доставки", + "DeliveryAregGUID": "uuid || Идентификатор AREG адреса доставки", + "AddressTail": { + "AddressTailID": "uuid || Идентификатор хвоста адреса", + "Flat": "string || Кв./Офис", + "Entrance": "string || Подъезд", + "Floor": "string || Этаж", + "AddressComment": "string || Комментарий к адресу", + "ContactNumber": "string || Контактный номер в адресе доставки" + }, + "IntervalValue": "string || Значение интервала доставки", + "Latitude": "string || Широта адреса доставки", + "Longitude": "string || Долгота адреса доставки", + "CourierGUID": "uuid || Идентификатор курьера в заказе", + "DeliveryBoyName": "string || ФИО курьера в заказе", + "AddrDostav": "string || Адрес доставки", + "CourierDeliveryCost": "int || Стоимость доставки", + "CourierComment": "string || Комментарий для курьера", + "DeliveryDate": "date-time || Дата доставки" } } -@endjson \ No newline at end of file + } +} +@endjson diff --git a/oms/process/commodity-process-logic.puml b/oms/process/commodity-process-logic.puml new file mode 100644 index 0000000..745b1d7 --- /dev/null +++ b/oms/process/commodity-process-logic.puml @@ -0,0 +1,83 @@ +@startuml +!theme plain +title Обработка товарных позиций при корректировке + +start + +:Получена корректировка заказа; + +:Сравнить товары OMS и WTIS; + +partition "Определить операции с товарами" { + :Товары для добавления; + note right: Есть в OMS, нет в WTIS + + :Товары для удаления; + note right: Есть в WTIS, нет в OMS + + :Товары для изменения; + note right: Есть в обоих, но с отличиями +} + +partition "Обработать изменения товаров" { + if (Есть товары для изменения?) then (да) + :Для каждого товара проверить изменения; + + if (Изменилось количество?) then (да) + if (Товар в резерве?) then (да) + :Создать копию с новым количеством; + :Удалить избыточную часть; + note right: Сложная логика split + else (нет) + :Изменить количество напрямую; + endif + endif + + if (Изменилась цена?) then (да) + :Обновить цену и скидку; + endif + + if (Изменился резерв?) then (да) + :Обновить дату резерва; + endif + endif +} + +partition "Применить операции" { + if (Есть товары для добавления?) then (да) + :Создать новые товарные позиции; + endif + + if (Есть товары для изменения?) then (да) + :Обновить существующие позиции; + endif + + if (Есть товары для удаления?) then (да) + :Снять резерв с товаров; + :Установить статус "Удален"; + :Удалить из заказа; + endif +} + +partition "Обработать резервирование" { + if (Смена региона или ПВЗ?) then (да) + :Снять резерв со всех товаров; + note right: При смене региона/ПВЗ + endif + + if (Есть товары для резервирования?) then (да) + :Зарезервировать товары; + note right: Из массива reserve + endif + + if (Есть товары для снятия резерва?) then (да) + :Снять резерв с товаров; + note right: Из массива unreserve + endif +} + +:Завершить обработку; + +stop + +@enduml \ No newline at end of file diff --git a/oms/process/correction-wtis.puml b/oms/process/correction-wtis.puml new file mode 100644 index 0000000..29862c5 --- /dev/null +++ b/oms/process/correction-wtis.puml @@ -0,0 +1,158 @@ +@startuml +!theme plain +title Обработка корректировки заказа на WTIS + +participant "Kafka" as Kafka +participant "Обработчик" as Handler +participant "Сервис синхронизации" as Service +participant "Сравнитель заказов" as Differ +participant "Создатель заказов" as Creator +participant "Резервирование" as Reserve +participant "База данных" as DB + +== Получение корректировки == +Kafka -> Handler: Сообщение корректировки +Handler -> Service: Обработать корректировку + +== Поиск заказа == +Service -> DB: Найти заказ по GUID +alt Заказ не найден + Service -> Creator: Создать новый заказ +else Заказ существует + Service -> Differ: Сравнить заказы OMS и WTIS + + == Анализ изменений == + Differ -> Differ: Сравнить поля заказа + note right: регион, ПВЗ, способ доставки,\nконтрагент, адрес, дата доставки + Differ -> Differ: Сравнить товарные позиции + note right: количество, цены, резерв + Differ --> Service: Список изменений + + == Специальная обработка смены региона/ПВЗ == + alt Смена региона или ПВЗ + Service -> Reserve: Снять резерв со всех товаров + note right: При смене региона/ПВЗ\nснимается весь резерв + end + + == Применение изменений == + Service -> Differ: Применить изменения к заказу + Service -> Creator: Сохранить заказ + + == Обработка товаров == + note over Service: **ДЕТАЛЬНАЯ СХЕМА:**\n"Обработка товарных позиций" + Service -> Service: Определить операции с товарами + note right: Товары для добавления,\nизменения, удаления + + alt Есть товары для добавления + Service -> Creator: Добавить новые товары + end + + alt Есть товары для изменения + Service -> Service: Обновить существующие товары + note right: **См. детальную схему:**\n- Изменение количества (split)\n- Изменение цен\n- Изменение резерва + end + + alt Есть товары для удаления + Service -> Reserve: Снять резерв + Service -> Service: Удалить товары + note right: **См. детальную схему:**\nУстановка статуса "Удален" + end +end + +== Резервирование товаров == +note over Service: **ДЕТАЛЬНАЯ СХЕМА:**\n"Обработка товарных позиций"\n(блок "Резервирование") +alt Есть товары для резервирования + Service -> Reserve: Зарезервировать товары + note right: Из массива reserve +end + +alt Есть товары для снятия резерва + Service -> Reserve: Снять резерв + note right: Из массива unreserve +end + +== Завершение == +Service -> Service: Обновить сайтовый заказ +Service -> Service: Отправить SMS клиенту +Service -> Service: Экспортировать в OMS +Service --> Handler: Результат обработки +Handler --> Kafka: Подтверждение + +@enduml + + + + + +@startuml +!theme plain +title Обработка корректировки заказа на WTIS + +start +:Получение сообщения корректировки из Kafka oms.order.sync; + +if (Заказ найден в БД?) then (нет) + :Создать новый заказ; +else (да) + :Сравнить заказы OMS и WTIS по атрибутам; + + if (Смена региона или ПВЗ И есть товары для резерва?) then (да) + :Снять резерв с товаров из массива reserve; + else (нет) + endif + + :Применить изменения к заказу; + :Сохранить заказ в БД; + + :Определить операции с товарами; + + if (Есть товары для добавления?) then (да) + :Добавить новые товары в заказ; + else (нет) + endif + + if (Есть товары для изменения?) then (да) + :Обновить существующие товары; + if (Есть товары с уменьшением количества в резерве?) then (да) + :Создать копию товара с новым количеством; + :Удалить избыточную часть; + else (нет) + endif + else (нет) + endif + + if (Есть товары для удаления?) then (да) + :Снять резерв с товаров; + :Установить статус "Удален"; + :Удалить товары из заказа; + else (нет) + endif + + :Установить скидки, контакты, адреса; + :Обновить дополнительные свойства заказа; + + if (Есть товары для резервирования И не сайтовый заказ?) then (да) + :Зарезервировать товары из массива reserve; + else (нет) + endif + + if (Есть товары для снятия резерва И не отмена заказа?) then (да) + :Снять резерв с товаров из массива unreserve; + else (нет) + endif + + :Обновить заказ во wtis_doc_zayavki; + :Обновить заказ во wtis_doc_zayavki_site; + + if (Не сайтовый заказ И активный И подтвержденный?) then (да) + :Отправить SMS клиенту с задержкой 10 минут; + else (нет) + endif + + :Экспортировать данные обратно в OMS; +endif + +:Подтверждение обработки в Kafka; +stop + +@enduml \ No newline at end of file diff --git a/oms/process/create-order.puml b/oms/process/create-order.puml new file mode 100644 index 0000000..e5b8b45 --- /dev/null +++ b/oms/process/create-order.puml @@ -0,0 +1,48 @@ +@startuml Процесс создания и жизненный цикл заказа + +state "Заказ не создан" as start + +state "НОВЫЙ" as new_order + +state "ЗАБРОНИРОВАН" as booked { + state "Таймер брони (3 дня)" as reserve_timer +} + +state "Оформление..." as processing_payment +state "В РАБОТЕ" as in_progress +state "ОТМЕНЕН" as cancelled + +state "Товар в закупке" as purchasing + +start --> new_order : Создать заказ + +new_order --> cancelled : Кнопка "Отменить заказ"\n(Ручная отмена) + +new_order --> booked : Кнопка "Забронировать"\n(Синхронный запрос во Втис) + +booked --> booked : **Успех:** Товары зарезервированы + +booked --> new_order : Кнопка "Отменить бронирование"\n(Таймер брони продолжает идти)" + +reserve_timer --> cancelled : Истек 3 дня\n(Автоотмена брони) + +booked --> cancelled : Кнопка "Отменить заказ"\n(Ручная отмена) + +new_order --> processing_payment : Кнопка "Оформить" +booked --> processing_payment : Кнопка "Оформить" + +processing_payment --> in_progress : **Успех:** Товары доступны\nЗаказ передан в системы товародвижения + +processing_payment --> purchasing : **Неудача:** Товара нет в наличии\n(Запуск процесса закупки) +purchasing --> in_progress : Товар закуплен + +state in_progress { + state "Заказ выполняется" as active + state "Резерв продлен" as extended + active --> extended : Кнопка "Продлить резерв"\n(Правила: 1 раз если не оплачен,\n∞ раз (Ст. менеджер) если оплачен) + extended --> active +} + +in_progress --> cancelled : Кнопка "Отменить заказ" + +@enduml \ No newline at end of file diff --git a/plantuml.jar b/plantuml.jar new file mode 100644 index 0000000..6fa5ed3 Binary files /dev/null and b/plantuml.jar differ diff --git a/pricing/1500 CompetitorProductMultipleSave.puml b/pricing/1500 CompetitorProductMultipleSave.puml index ac2c2d3..c631fe2 100644 --- a/pricing/1500 CompetitorProductMultipleSave.puml +++ b/pricing/1500 CompetitorProductMultipleSave.puml @@ -1,11 +1,115 @@ -@startuml -'https://plantuml.com/sequence-diagram +@startuml CompetitorProductMultipleSave +scale 0.8 +actor Client +participant "API Endpoint" as API +participant "Validation" as Validation +participant "Database" as DB +participant "Kafka" as Kafka +participant "Logging" as Log autonumber +Client -> API: POST /v1/ui/competitor-product/multiple-save\n{JSON request} +API -> Validation: Deserialize JSON to Protobuf -Alice -> Bob: Authentication Request -Bob --> Alice: Authentication Response +alt Deserialization error + Validation -> Log: ERROR "PRC-MATCH-1501 | " + API -> Client: 400 Bad Request\n{error details} + return +end -Alice -> Bob: Another authentication Request -Alice <-- Bob: another authentication Response +group Type = CREATE (0) + Validation -> Validation: Check for IDs in CREATE mode + loop For each invalid object + Validation -> Log: WARN "PRC-MATCH-1502 | " + end + + Validation -> Validation: Check for duplicates in request + loop For each duplicate + Validation -> Log: WARN "PRC-MATCH-1503 | " + end + + Validation -> DB: Bulk SELECT by (competitor_id + sku) + alt DB error + DB -> Log: ERROR "PRC-MATCH-1504 | " + API -> Client: 500 Server Error\n{error response} + + end + + loop For each existing record + Validation -> Log: WARN "PRC-MATCH-1505 | " + end + + DB -> API: Return existing records + Validation -> Validation: Filter valid records + + alt No valid records + API -> Client: 200 OK\n{empty response} + + end + + API -> DB: Bulk INSERT with RETURNING id + alt DB error + DB -> Log: ERROR "PRC-MATCH-1504 | " + API -> Client: 500 Server Error\n{error response} + + end + DB -> API: Return new IDs +end + +group Type = UPDATE (1) + Validation -> Validation: Check for missing IDs + loop For each invalid object + Validation -> Log: WARN "PRC-MATCH-1502 | " + end + + Validation -> Validation: Check for duplicate IDs + loop For each duplicate + Validation -> Log: WARN "PRC-MATCH-1503 | " + end + + Validation -> DB: Bulk SELECT by IDs + alt DB error + DB -> Log: ERROR "PRC-MATCH-1504 | " + API -> Client: 500 Server Error\n{error response} + return + end + + loop For each not found ID + Validation -> Log: WARN "PRC-MATCH-1505 | " + end + + Validation -> Validation: Validate status transitions + loop For each invalid transition + Validation -> Log: WARN "PRC-MATCH-1506 | " + end + + alt No valid records + API -> Client: 200 OK\n{empty response} + return + end + + API -> DB: Bulk UPDATE + alt DB error + DB -> Log: ERROR "PRC-MATCH-1504 | " + API -> Client: 500 Server Error\n{error response} + return + end +end + +API -> Kafka: Send to parsing.collector.out +alt Kafka error + Kafka -> Log: ERROR "PRC-MATCH-1507 | " + API -> Client: 500 Server Error\n{error response} + return +end + +API -> Kafka: Send to parsing.competitor_product_status.update +alt Kafka error + Kafka -> Log: ERROR "PRC-MATCH-1508 | " + API -> Client: 500 Server Error\n{error response} + return +end + +API -> Client: 200 OK\n{success response} +API -> Log: INFO "PRC-MATCH-1509 | " @enduml \ No newline at end of file diff --git a/Машина схема.puml b/Машина схема.puml new file mode 100644 index 0000000..de75733 --- /dev/null +++ b/Машина схема.puml @@ -0,0 +1,78 @@ +@startuml +actor Пользователь +participant "АРМ" as UI +participant "Gateway" as GW +participant "Scrooge\n(список причин)" as SCR +participant "Backend" as BE +participant "WorkFlow\nimportPriceSupplyToOrderWorkflow" as WF +participant "MongoDB" as ORD +participant "Product‑info\n(SKU в GUID)" as PI +participant "Scrooge\n(лимиты и скидки)" as LIM +participant "MS Product\n(названия товаров)" as PRD +autonumber + +== Получение списка причин == +Пользователь -> UI : нажимает «Импорт цен» +UI -> GW : GET /info/v1/discount-manual-types +GW -> SCR : вызов ручки получения типов +SCR --> GW : ответ 200 (список причин) +GW --> UI : ответ 200 (список причин) +UI -> UI : отображает список причин для выбора +Пользователь -> UI : выбирает причину + +== Загрузка Excel‑файла == +Пользователь -> UI : прикрепляет Excel и нажимает «Загрузить» +UI -> GW : POST /orders/v1/{orderId}/products/import-price\n(file + manualType) +GW -> BE : перенаправляет запрос + +== Парсинг Excel == +BE -> BE : • парсинг\n• нормализация\n• базовая валидация +alt обнаружены бизнес‑ошибки при парсинге + BE -> BE : формирует ошибки\n(price_null, duplicate) + BE -> GW : ответ 200 + ошибки + GW -> UI : ответ 200 + ошибки + UI -> Пользователь : показывает список ошибок\nбизнес-ошибка "Товар не найден..." +end + BE -> WF : запускает WorkFlow (orderId, manualType, [{GUID/SKU, price}]) + +== WF — проверка товара == +WF -> ORD : товар по GUID есть? +alt товар не найден +ORD --> WF : Ответ, что товар найден +WF -> PI : вызывает ConvertSkusToUids(SKU)\nhigh+low → GUID +PI --> WF : отдает GUID +WF -> ORD : повторная проверка по GUID +ORD --> WF : найден / нет +alt всё ещё не найден +WF -> WF : пропускает товар +end +end + +== WF — проверка статусов == +WF -> ORD : запрос статуса товара / заказа +ORD -> WF: ответ со статусом товара / заказа +alt статус недопустим + WF -> BE : бизнес‑ошибка «Корректировка недоступна…» +end + +== WF — проверка цен == +WF -> LIM : получает скидки по товарам +LIM --> WF : возможные скидки +WF -> WF : сравнивает цену из файла с минимальной доступной +alt цена ниже доступной + WF -> WF : устанавливает минимальную цену по правам + WF -> BE : бизнес‑ошибка «Цена ниже допустимой…» +end + +== WF — обновление заказа == +WF -> ORD : обновляет кучу полей с ценами и скидками\nлогирует корректировку цен +ORD --> WF : отдает результат выполнения скрипта + +== Завершение == +WF -> PRD : Отдает GUID товара +PRD --> WF : Получает SKU + Name товара +WF --> BE : отдает результат и ошибки +BE --> GW : ответ 200 + ошибки (если есть) +GW --> UI : ответ 200 + ошибки (если есть) +UI --> Пользователь : показывает ошибки (если есть)\nи обновленные цены +@enduml \ No newline at end of file