From 072ced2815f69f57f3db1e4b684ef15c60fb53a2 Mon Sep 17 00:00:00 2001 From: Andrey Date: Mon, 8 Apr 2024 19:15:50 +0300 Subject: [PATCH] Initial commit --- .idea/.gitignore | 8 + .idea/modules.xml | 8 + .idea/php.xml | 19 + .idea/plantUML.iml | 8 + .idea/vcs.xml | 6 + example.proto | 255 +++++++++++ oms/autoorder/FRQ-1.puml | 46 ++ oms/autoorder/FRQ-2.puml | 55 +++ oms/autoorder/change-ao.puml | 39 ++ .../free-rest.puml | 30 ++ .../reserve-rest.puml | 24 ++ oms/interface-arm/contragent/add-contact.puml | 15 + .../contragent/add-contragent-to-order.puml | 15 + .../contragent/change-contractor.puml | 30 ++ .../contragent/create-contractor.puml | 19 + .../contragent/get-contractor-info.puml | 19 + .../contragent/get-contragent-info.puml | 21 + .../contragent/search-contractor.puml | 38 ++ .../docs/get realizations MVP.puml | 20 + .../docs/payment-with-kafka.puml | 19 + oms/interface-arm/docs/payment.puml | 46 ++ .../docs/realizations-or-payment.puml | 36 ++ oms/interface-arm/docs/realizations.puml | 38 ++ oms/interface-arm/order/get-region.puml | 41 ++ oms/personal-cabinet/change note.puml | 23 + oms/personal-cabinet/favorites.puml | 23 + oms/personal-cabinet/get-info-order.puml | 17 + oms/personal-cabinet/get-note.puml | 16 + oms/process/action.puml | 58 +++ oms/process/basket-import.puml | 26 ++ oms/process/booking.puml | 77 ++++ oms/process/correction.puml | 79 ++++ oms/site-integration/AS IS.puml | 59 +++ oms/site-integration/TO BE.puml | 66 +++ ordering.puml | 119 ++++++ personal-cabinet.puml | 85 ++++ search/Architecture Scheme Search.drawio.xml | 2 + search/Mycroft.puml | 37 ++ search/Sherlock scheme.puml | 38 ++ search/Watson.drawio.svg | 4 + search/Watson.drawio.xml | 2 + search/Watson.puml | 82 ++++ search/WatsonScheme.puml | 404 ++++++++++++++++++ search/WatsonWithMicroservices.puml | 142 ++++++ search/WatsonWithPDM.puml | 266 ++++++++++++ search/WatsonWithSite.puml | 227 ++++++++++ search/Общий процесс autocomplete.puml | 68 +++ search/Общий процесс filters.puml | 55 +++ search/Общий процесс products.puml | 64 +++ search/Схема поиск.png | Bin 0 -> 28585 bytes shipment.puml | 32 ++ 51 files changed, 2926 insertions(+) create mode 100644 .idea/.gitignore create mode 100644 .idea/modules.xml create mode 100644 .idea/php.xml create mode 100644 .idea/plantUML.iml create mode 100644 .idea/vcs.xml create mode 100644 example.proto create mode 100644 oms/autoorder/FRQ-1.puml create mode 100644 oms/autoorder/FRQ-2.puml create mode 100644 oms/autoorder/change-ao.puml create mode 100644 oms/free-rest-and-reserve-journal/free-rest.puml create mode 100644 oms/free-rest-and-reserve-journal/reserve-rest.puml create mode 100644 oms/interface-arm/contragent/add-contact.puml create mode 100644 oms/interface-arm/contragent/add-contragent-to-order.puml create mode 100644 oms/interface-arm/contragent/change-contractor.puml create mode 100644 oms/interface-arm/contragent/create-contractor.puml create mode 100644 oms/interface-arm/contragent/get-contractor-info.puml create mode 100644 oms/interface-arm/contragent/get-contragent-info.puml create mode 100644 oms/interface-arm/contragent/search-contractor.puml create mode 100644 oms/interface-arm/docs/get realizations MVP.puml create mode 100644 oms/interface-arm/docs/payment-with-kafka.puml create mode 100644 oms/interface-arm/docs/payment.puml create mode 100644 oms/interface-arm/docs/realizations-or-payment.puml create mode 100644 oms/interface-arm/docs/realizations.puml create mode 100644 oms/interface-arm/order/get-region.puml create mode 100644 oms/personal-cabinet/change note.puml create mode 100644 oms/personal-cabinet/favorites.puml create mode 100644 oms/personal-cabinet/get-info-order.puml create mode 100644 oms/personal-cabinet/get-note.puml create mode 100644 oms/process/action.puml create mode 100644 oms/process/basket-import.puml create mode 100644 oms/process/booking.puml create mode 100644 oms/process/correction.puml create mode 100644 oms/site-integration/AS IS.puml create mode 100644 oms/site-integration/TO BE.puml create mode 100644 ordering.puml create mode 100644 personal-cabinet.puml create mode 100644 search/Architecture Scheme Search.drawio.xml create mode 100644 search/Mycroft.puml create mode 100644 search/Sherlock scheme.puml create mode 100644 search/Watson.drawio.svg create mode 100644 search/Watson.drawio.xml create mode 100644 search/Watson.puml create mode 100644 search/WatsonScheme.puml create mode 100644 search/WatsonWithMicroservices.puml create mode 100644 search/WatsonWithPDM.puml create mode 100644 search/WatsonWithSite.puml create mode 100644 search/Общий процесс autocomplete.puml create mode 100644 search/Общий процесс filters.puml create mode 100644 search/Общий процесс products.puml create mode 100644 search/Схема поиск.png create mode 100644 shipment.puml diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..13566b8 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,8 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Editor-based HTTP Client requests +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..4351daa --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/php.xml b/.idea/php.xml new file mode 100644 index 0000000..f324872 --- /dev/null +++ b/.idea/php.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/plantUML.iml b/.idea/plantUML.iml new file mode 100644 index 0000000..c956989 --- /dev/null +++ b/.idea/plantUML.iml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..94a25f7 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/example.proto b/example.proto new file mode 100644 index 0000000..274e408 --- /dev/null +++ b/example.proto @@ -0,0 +1,255 @@ +syntax = "proto3"; + +package promo; + +option go_package = "./;pb"; +option php_namespace = "GRPC"; +option php_metadata_namespace = "GRPC\\GPBMetadata"; + +import "google/api/annotations.proto"; + +service PromoService { + // ListProductsPromotion проверяет наличие акционных цен по товарам + rpc ListProductsPromotion(ListProductsPromotionRequest) returns (ListProductsPromotionResponse) { + option (google.api.http) = { + post: "/ListProductsPromotion" + body: "*" + }; + } + + // GetPromotionsDetails возвращает общую информацию по акциям + rpc GetPromotionsDetails(GetPromotionsDetailsRequest) returns (GetPromotionsDetailsResponse) { + option (google.api.http) = { + post: "/GetPromotionsDetails" + body: "*" + }; + } + + // ListPromotionsV0 список активных акций + // возвращает список активных акций в порядке приоритета + // для кажого типа акции может вернуться максимум 2 акции среди которых нужно выбрать первую, + // которая подходит для текущего типа пользователя. + // Метод сделан для переходного периода, пока сайт не может получать тип пользователя + rpc ListPromotionsV0(ListPromotionsV0Request) returns (ListPromotionsV0Response) { + option deprecated = true; + option (google.api.http) = { + post: "/ListPromotionsV0" + body: "*" + }; + } + + // ListPromotionsV1 список активных акций + // возвращает по одной самой приоритетной акции каждого типа в порядке приоритета + rpc ListPromotionsV1(ListPromotionsV1Request) returns (ListPromotionsV1Response) { + option (google.api.http) = { + post: "/ListPromotionsV1" + body: "*" + }; + } + + // GetPromotionDetails получает общую информацию об акции + rpc GetPromotionDetails(GetPromotionDetailsRequest) returns (GetPromotionDetailsResponse) { + option (google.api.http) = { + post: "/GetPromotionDetails" + body: "*" + }; + } + + // GetPromotionRubrics возвращает список рубрик, в которых есть акционные товары + rpc GetPromotionRubrics(GetPromotionRubricsRequest) returns (GetPromotionRubricsResponse) { + option (google.api.http) = { + post: "/GetPromotionRubrics" + body: "*" + }; + } + + // GetPromotionID возвращает ID акции по ее UUID + rpc GetPromotionID(GetPromotionIDRequest) returns (GetPromotionIDResponse) { + option (google.api.http) = { + post: "/GetPromotionID" + body: "*" + }; + } + + // ListPromotion листинг акции + rpc ListPromotion(ListPromotionRequest) returns (ListPromotionResponse) { + option (google.api.http) = { + post: "/ListPromotion" + body: "*" + }; + } +} + +message Product { + string id = 1; + Price promotion_price = 2; + // availability_quantity - минимальное из 2х значений: + // "лимит в заказе" или "максимальное количество товара которое может быть продано по акционной цене" + float availability_quantity = 3; + // order_limit - максимальное количество товара в заказе + int32 order_limit = 4; + // is_upload_to_feed - выгружать ли товар в фиды + bool is_upload_to_feed = 5; +} + +message Price { + int64 rubles = 1; +} + +enum OrderBy { + ORDER_BY_UNSPECIFIED = 0; + ORDER_BY_PROMO_PRICE = 1; + ORDER_BY_DISCOUNT = 2; + ORDER_BY_POPULARITY = 3; + ORDER_BY_RATING = 4; + ORDER_BY_REVIEWS = 5; +} + +enum OrderDirection { + ORDER_DIRECTION_UNSPECIFIED = 0; + ORDER_DIRECTION_ASC = 1; + ORDER_DIRECTION_DESC = 2; +} + +message ListProductsPromotionRequest { + repeated string product_ids = 1; + string locality_id = 2; + UserType user_type = 3; + bool disable_cache = 4; +} + +message ListProductsPromotionResponse { + repeated PromotionProducts promotion_products = 1; +} + +message PromotionProducts { + repeated Product products = 1; + PromotionDetails promotion_details = 2; +} + +message Nameplate { + string title = 1; + string hint_description = 2; + string color = 3; + string text_color = 4; +} + +message Meta { + string title = 1; + string description = 2; + string keywords = 3; +} + +enum PromotionType { + PROMOTION_TYPE_UNSPECIFIED = 0; + PROMOTION_TYPE_BLACK_FRIDAY = 1; + PROMOTION_TYPE_PRODUCT_OF_THE_MONTH = 2; + PROMOTION_TYPE_SALE_IN_THE_STORE = 3; + PROMOTION_TYPE_SUPER_PRICE = 4; +} + +message GetPromotionsDetailsRequest { + repeated int32 promotion_ids = 1; +} + +message GetPromotionsDetailsResponse { + repeated PromotionDetails promotion_details = 1; +} + +message PromotionDetails { + int32 id = 1; + string uuid = 2; + string slug = 3; + PromotionClientType client_type = 4; + string name = 5; + string title = 6; + Nameplate nameplate = 7; + Meta meta = 8; + PromotionType type = 100; + string description = 9; + string frameColor = 10; +} + +// PromotionClientType свойство акции определяющие контрагентов для которых действует акция +// PROMOTION_CLIENT_TYPE_ALL - акция подходит для любого клиента +// PROMOTION_CLIENT_TYPE_B2C - акция подходит только для b2c +// PROMOTION_CLIENT_TYPE_B2B - акция подходит только для b2b +enum PromotionClientType { + PROMOTION_CLIENT_TYPE_UNSPECIFIED = 0; + PROMOTION_CLIENT_TYPE_ALL = 1; + PROMOTION_CLIENT_TYPE_B2C = 2; + PROMOTION_CLIENT_TYPE_B2B = 3; +} + +message ListPromotionsV0Request { + string locality_id = 1; +} + +message ListPromotionsV0Response { + repeated PromotionDetails promotion_details = 1; +} + +message ListPromotionsV1Request { + string locality_id = 1; + UserType user_type = 2; +} + +message ListPromotionsV1Response { + repeated PromotionDetails promotion_details = 1; +} + +// UserType тип пользователя который делает запрос +enum UserType { + USER_TYPE_UNSPECIFIED = 0; + USER_TYPE_B2C = 1; + USER_TYPE_B2B = 2; +} + +message GetPromotionDetailsRequest { + string locality_id = 1; + UserType user_type = 2; + string promotion_slug = 3; +} + +message GetPromotionDetailsResponse { + PromotionDetails promotion_details = 1; +} + +message GetPromotionRubricsRequest { + string promotion_slug = 1; + string locality_id = 2; + UserType user_type = 3; +} + +message GetPromotionRubricsResponse { + repeated string rubric_ids = 1; +} + +message GetPromotionIDRequest { + string uuid = 1; +} + +message GetPromotionIDResponse { + int32 promotion_id = 1; +} + +message ListPromotionRequest { + string locality_id = 1; + UserType user_type = 2; + string promotion_slug = 3; + + string rubric_id = 4; + OrderBy order_by = 7; + OrderDirection order_direction = 8; + + int64 page_number = 9; + + bool disable_cache = 10; + + int32 limit = 11; +} + +message ListPromotionResponse { + repeated Product products = 1; + int64 total_products = 2; +} diff --git a/oms/autoorder/FRQ-1.puml b/oms/autoorder/FRQ-1.puml new file mode 100644 index 0000000..0ea58a3 --- /dev/null +++ b/oms/autoorder/FRQ-1.puml @@ -0,0 +1,46 @@ +@startuml +mainframe "FRQ-1 Заказ.ПолучениеДанных." +Actor USER +participant SITE +participant WTIS +queue Название_топика_1 +queue Название_топика_2 +participant OMS +participant Officer + + +autonumber 1 +USER -> USER: Создает заказ на сайте +USER -> SITE: Сущность "Заказ"\nс набором атрибутов +SITE -> WTIS: Сущность "Заказ"\nс набором атрибутов +WTIS -> WTIS: Проверка условий\nи отбор заказов +WTIS -> Название_топика_1: Записывает Сущность\n"Заказ" с набором\nатрибутов +OMS -> Название_топика_1: Читает Сущность\n"Заказ" с набором\nатрибутов +OMS -> OMS: Валидация КА +autonumber 7.1 +alt валидация пройдена +OMS -> OMS: Продолжение сценария +else валидация не пройдена +OMS -> Название_топика_2: Сущность "Заказ"\nс набором атрибутов +end +autonumber 8 +OMS <-> Officer: Получение лимитов офиса +OMS -> OMS: Валидация способа получения +alt валидация пройдена +autonumber 9.1 +OMS -> OMS: Продолжение сценария +else валидация не пройдена +OMS -> Название_топика_2: Сущность "Заказ"\nс набором атрибутов +end +autonumber 10 +OMS -> OMS: Валидация способа оплаты +alt валидация пройдена +autonumber 10.1 +OMS -> OMS: Продолжение сценария +else валидация не пройдена +OMS -> Название_топика_2: Сущность "Заказ"\nс набором атрибутов +end +autonumber 11 +OMS -> OMS: Данные о заказе\nполучены и провалидированы +OMS -> OMS: Переход к бизнес-проверкам +@enduml \ No newline at end of file diff --git a/oms/autoorder/FRQ-2.puml b/oms/autoorder/FRQ-2.puml new file mode 100644 index 0000000..5435ebc --- /dev/null +++ b/oms/autoorder/FRQ-2.puml @@ -0,0 +1,55 @@ +@startuml +mainframe "FRQ-2 Заказ.БизнесПроверки." + +queue Название_топика_2 +database ClickHouse +participant OMS +participant DRUZ +participant PDM + + +autonumber 1 +OMS -> PDM: Запрашивает\nGUID производителя товара +OMS -> OMS: Проверка на возможность\nпродажи товара + +alt валидация пройдена +autonumber 2.1 +OMS -> OMS: Продолжение сценария +else валидация не пройдена +OMS -> ClickHouse: Логирование не\nпройденных проверок +OMS -> Название_топика_2: Сущность "Заказ"\nс набором атрибутов +end +autonumber 3 + +OMS -> DRUZ: Запрашивает \nпризнак "Наличие" +OMS -> OMS: Проверка что товары\nиз заказа в наличии +alt валидация пройдена +autonumber 4.1 +OMS -> OMS: Продолжение сценария +else валидация не пройдена +OMS -> ClickHouse: Логирование не\nпройденных проверок +OMS -> Название_топика_2: Сущность "Заказ"\nс набором атрибутов +end +autonumber 5 +OMS -> PDM: Запрашивает ВГХ товара +OMS -> OMS: Расчитывает объем и\nобщий вес заказа +OMS -> OMS: Проверка на лимиты\nВГХ ТТ +alt валидация пройдена +autonumber 7.1 +OMS -> OMS: Продолжение сценария +else валидация не пройдена +OMS -> ClickHouse: Логирование не\nпройденных проверок +OMS -> Название_топика_2: Сущность "Заказ"\nс набором атрибутов +end +autonumber 8 +OMS -> OMS: Проверка способа\nоплаты на ТТ +alt валидация пройдена +autonumber 8.1 +OMS -> OMS: Продолжение сценария +else валидация не пройдена +OMS -> ClickHouse: Логирование не\nпройденных проверок +OMS -> Название_топика_2: Сущность "Заказ"\nс набором атрибутов +end + + +@enduml \ No newline at end of file diff --git a/oms/autoorder/change-ao.puml b/oms/autoorder/change-ao.puml new file mode 100644 index 0000000..cdd3abc --- /dev/null +++ b/oms/autoorder/change-ao.puml @@ -0,0 +1,39 @@ +@startuml +scale 1500x1500 +mainframe Автооформление заказов +actor user as user +participant SITE +queue kafka +participant Gateway +participant workflow +participant wtis + +user -> SITE: Оформляет заказ +SITE -> SITE: Сохраняет заказ в БД +SITE --> kafka: Пишет заказ в kafka +Gateway --> kafka: Забирает заказ + +Gateway -> workflow: CreateB2CAO +workflow -> workflow: Проверяет условия АО +workflow -> workflow: Проверяет тип доставки +alt Тип доставки "Курьером" +workflow -> workflow: Устанавливает таймер на N минут + alt Поступила оплата в заказ до истечения срока таймера + workflow -> workflow: Заканчивает автооформление\nУстанавливает дату доставки\nзаказа + else Не поступила оплата в заказ до истечения срока таймера + workflow -> wtis: Заказ передается во WTIS\nМеняется мастер система + end +else Тип доставки "Самовывоз" +workflow -> workflow: Проверяет наличие\nкрупногабаритных товаров\nв заказе + alt Крупногабаритных товаров в заказе нет + workflow -> workflow: Заканчивает автооформление\nУстанавливает дату доставки\nзаказа + else Крупногабаритные товары в заказе есть + workflow -> workflow: Устанавливает таймер на N минут + alt Поступила оплата в заказ до истечения срока таймера + workflow -> workflow: Заканчивает автооформление\nУстанавливает дату доставки\nзаказа + else Не поступила оплата в заказ до истечения срока таймера + workflow -> wtis: Заказ передается во WTIS\nМеняется мастер система + end + end +end +@enduml \ No newline at end of file diff --git a/oms/free-rest-and-reserve-journal/free-rest.puml b/oms/free-rest-and-reserve-journal/free-rest.puml new file mode 100644 index 0000000..144d38f --- /dev/null +++ b/oms/free-rest-and-reserve-journal/free-rest.puml @@ -0,0 +1,30 @@ +@startuml +scale 1200*1200 +mainframe Получение свободных остатков +actor Пользователь as user +participant ARM as ARM +participant OMS as OMS +participant Shcat as Shcat +participant Susanin as Susanin +autonumber + +user -> ARM: Нажимает на остатки товара\nв товарной строке заказа +ARM -> OMS: API GET /quantity-list-by-office +activate OMS +OMS -> OMS: валидирует запрос + + +OMS -> Shcat: POST method rests.get +activate Shcat +return answer API POST + +OMS -> Susanin: POST method get_logistic_chains_with_priority +activate Susanin +return answer API POST + +OMS -> OMS: Сращивает ответы\nмежду собой +OMS -> OMS: Формирует два массива:\n1. По лог.цепям\n2. Прочие склады + +return answer API GET +ARM --> user: Рендерит данные в модальном окне +@enduml \ No newline at end of file diff --git a/oms/free-rest-and-reserve-journal/reserve-rest.puml b/oms/free-rest-and-reserve-journal/reserve-rest.puml new file mode 100644 index 0000000..d104df6 --- /dev/null +++ b/oms/free-rest-and-reserve-journal/reserve-rest.puml @@ -0,0 +1,24 @@ +@startuml +scale 1200*1200 +mainframe Получение остатков под резервом +actor Пользователь as user +participant ARM as ARM +participant OMS as OMS +participant Susanin as Susanin +autonumber + +user -> ARM: Нажимает на остатки товара\nв товарной строке заказа +ARM -> OMS: API GET /quantity-list-by-office +activate OMS +OMS -> OMS: валидирует запрос + +OMS -> Susanin: POST method get_logistic_chains_with_priority +activate Susanin +return answer API POST + +OMS -> OMS: запрос в mongodb Order с фильтрами по товару +OMS -> OMS: Формирует два массива:\n1. По лог.цепям\n2. Прочие склады + +return answer API GET +ARM --> user: Рендерит данные в модальном окне +@enduml \ No newline at end of file diff --git a/oms/interface-arm/contragent/add-contact.puml b/oms/interface-arm/contragent/add-contact.puml new file mode 100644 index 0000000..116be94 --- /dev/null +++ b/oms/interface-arm/contragent/add-contact.puml @@ -0,0 +1,15 @@ +@startuml +scale 800*800 +mainframe Добавление контакта к КА в заказе +actor Пользователь as user +participant ARM as ARM +participant OMS as OMS +autonumber + +user -> ARM: Добавляет контакт КА в кратком блоке КА +activate ARM +ARM -> OMS: API POST /orders/{orderId}/contacts/add +activate OMS +return API POST answer +return ок +@enduml \ No newline at end of file diff --git a/oms/interface-arm/contragent/add-contragent-to-order.puml b/oms/interface-arm/contragent/add-contragent-to-order.puml new file mode 100644 index 0000000..e0d20bf --- /dev/null +++ b/oms/interface-arm/contragent/add-contragent-to-order.puml @@ -0,0 +1,15 @@ +@startuml +scale 800*800 +mainframe Добавление КА к заказу +actor Пользователь as user +participant ARM as ARM +participant OMS as OMS +autonumber + +user -> ARM: Добавляет КА в заказ +activate ARM +ARM -> OMS: API POST /orders/{orderId}/contractors/add +activate OMS +return API POST answer +return ок +@enduml \ No newline at end of file diff --git a/oms/interface-arm/contragent/change-contractor.puml b/oms/interface-arm/contragent/change-contractor.puml new file mode 100644 index 0000000..d3407b3 --- /dev/null +++ b/oms/interface-arm/contragent/change-contractor.puml @@ -0,0 +1,30 @@ +@startuml +scale 800*800 +mainframe Обновление данных в модели КА +actor Пользователь as user +participant ARM as ARM +participant OMS as OMS +participant MSKB as MSKB +autonumber + +user -> ARM: Нажимает кнопку "Сохранить" +ARM -> OMS: API PUT /contractors/{contractorID} +activate OMS +OMS -> OMS: Разделяет модель КА\nна основные поля\n+ контакты +alt Если изменена только основная модель +OMS -> MSKB: API POST api/business/v2/physic/update +activate MSKB +return answer API POST +else Если добавлены контакты +OMS -> MSKB: API POST api/business/v2/contact/create +activate MSKB +return answer API POST +else Если удалены контакты +OMS -> MSKB: Удаление контакта КА:\n API DELETE api/business/v2/contact/delete +activate MSKB +return answer API DELETE +end + +return answer API PUT +ARM --> user: Показывает сообщение и\nзакрывает модалку +@enduml \ No newline at end of file diff --git a/oms/interface-arm/contragent/create-contractor.puml b/oms/interface-arm/contragent/create-contractor.puml new file mode 100644 index 0000000..ffdf0fc --- /dev/null +++ b/oms/interface-arm/contragent/create-contractor.puml @@ -0,0 +1,19 @@ +@startuml +scale 800*800 +mainframe Логика "Создание КА" +actor Пользователь as user +participant ARM as ARM +participant OMS as OMS +participant MSKB as MSKB +autonumber + +user -> ARM: Нажимает кнопку "Создать контрагента" +ARM -> OMS: API POST /contractors/create +activate OMS +OMS -> MSKB: API POST api/business/v2/physic/create +activate MSKB +return answer API POST + +return answer API POST +ARM --> user: Показывает сообщение и\nзакрывает модалку +@enduml \ No newline at end of file diff --git a/oms/interface-arm/contragent/get-contractor-info.puml b/oms/interface-arm/contragent/get-contractor-info.puml new file mode 100644 index 0000000..f133d26 --- /dev/null +++ b/oms/interface-arm/contragent/get-contractor-info.puml @@ -0,0 +1,19 @@ +@startuml +scale 800*800 +mainframe Получение данных для полной карточки КА +actor Пользователь as user +participant ARM as ARM +participant OMS as OMS +participant MSKB as MSKB +autonumber + +user -> ARM: Открывает карточку контрагента +ARM -> OMS: API GET /contractors/{contractorID} +activate OMS +OMS -> MSKB: GraphQL contractorPhysic +activate MSKB +return answer API GET + +return answer get_short_info_contact +ARM --> user: Рендерит карточку контрагента +@enduml \ No newline at end of file diff --git a/oms/interface-arm/contragent/get-contragent-info.puml b/oms/interface-arm/contragent/get-contragent-info.puml new file mode 100644 index 0000000..af39360 --- /dev/null +++ b/oms/interface-arm/contragent/get-contragent-info.puml @@ -0,0 +1,21 @@ +@startuml +scale 800*800 +mainframe Логика подблока "Информация о контрагенте" +actor Пользователь as user +participant ARM as ARM +participant OMS as OMS +participant WTIS as WTIS +autonumber + +user -> ARM: Нажимает кнопку раскрытия блока +activate ARM +ARM -> OMS: API GET\n/contractors/{contractorID}/orderInfo +activate OMS +OMS -> WTIS: API GET\napi/order/oms_export/contragent_info_oms/{guid} +activate WTIS +WTIS -> WTIS: prepare data +return API GET answer +return API GET answer + +return Рендерит блок +@enduml \ No newline at end of file diff --git a/oms/interface-arm/contragent/search-contractor.puml b/oms/interface-arm/contragent/search-contractor.puml new file mode 100644 index 0000000..6c83118 --- /dev/null +++ b/oms/interface-arm/contragent/search-contractor.puml @@ -0,0 +1,38 @@ +@startuml +scale 800*800 +mainframe Логика блока "Поиск КА" +actor Пользователь as user +participant ARM as ARM +participant OMS as OMS +participant MSKB as MSKB +autonumber + +user -> ARM: Нажимает кнопку "Поиск КА" + +return рендерит шаблон модального окна + +alt Если ищем только по номеру телефона +user -> ARM: Заполняет номер телефона полностью +else Если ищем только по email +user -> ARM: Заполняет email полностью +else Если ищем по номеру телефона И email +user -> ARM: Заполняет номер телефона И email полностью +end +ARM -> ARM: валидирует поля +alt Валидация не успешна +ARM -> user: Информирует пользователя об ошибках + +else Валидация успешно пройдена +ARM -> OMS: /contractors/search +activate OMS +end + +OMS -> MSKB: API POST /api/business/v2/physic/search +activate MSKB +MSKB -> MSKB: prepare_data +return answer API POST + +return success + +ARM -> user: Отображает результаты поиска +@enduml \ No newline at end of file diff --git a/oms/interface-arm/docs/get realizations MVP.puml b/oms/interface-arm/docs/get realizations MVP.puml new file mode 100644 index 0000000..bc29f55 --- /dev/null +++ b/oms/interface-arm/docs/get realizations MVP.puml @@ -0,0 +1,20 @@ +@startuml +scale 1000*1000 +mainframe Получение данных (Реализации, оплаты) от WTIS MVP +participant WTIS as WTIS +queue kafka +participant workflow as workflow +collections Redis as redis +autonumber +hnote over WTIS: После MVP WTIS изменится\nна сервис баланса + +loop Всегда +WTIS -> kafka: Пишет все инфо\nо документах по заказу +workflow -> kafka: Получает документы\nк заказу из очереди +alt данных нет в кэше по ключу +workflow -> redis: Сохраняет в кэш\nКраткую форму на 7 дней\nПолную форму на 3 дня +else данные есть в кэше по ключу +workflow -> redis: Удаляет запись по ключу +workflow -> redis: Сохраняет в кэш\nКраткую форму на 7 дней\nПолную форму на 3 дня +end +@enduml \ No newline at end of file diff --git a/oms/interface-arm/docs/payment-with-kafka.puml b/oms/interface-arm/docs/payment-with-kafka.puml new file mode 100644 index 0000000..391bf70 --- /dev/null +++ b/oms/interface-arm/docs/payment-with-kafka.puml @@ -0,0 +1,19 @@ +@startuml +scale 1000*1000 +mainframe Получение данных безналичная оплата / оплата по счету из kafka +participant paykeeper +participant 1C +queue kafka +participant workflow as workflow +collections PaymentsDb as PaymentsDb +autonumber + +loop Всегда +paykeeper -> kafka: Пишет все инфо\nо документах по заказу +1C -> kafka: Пишет все инфо\nо документах по заказу +workflow -> kafka: Получает документы\nк заказу из очереди +workflow -> workflow: Преобразовывает данные +workflow -> PaymentsDb: Записывает в коллекцию +end + +@enduml \ No newline at end of file diff --git a/oms/interface-arm/docs/payment.puml b/oms/interface-arm/docs/payment.puml new file mode 100644 index 0000000..3d94983 --- /dev/null +++ b/oms/interface-arm/docs/payment.puml @@ -0,0 +1,46 @@ +@startuml +scale 1000*1000 +mainframe Получение данных для отрисовки таблицы оплат MVP +participant WTIS as WTIS +collections Redis as redis +participant payments as payments +participant workflow as workflow +participant gateway as gateway +participant ARM as ARM +actor user as user +autonumber +hnote over WTIS: После MVP WTIS изменится\nна сервис баланса + +autonumber 1 +user -> ARM: Открывает заказ +ARM -> gateway: Запрашивает\nдокументы к заказу +activate gateway +== Получение данных о наличной оплате == +gateway -> redis: Проверяет наличие\nданных в кэше +alt данные есть в кэше +redis --> gateway: Возвращает\nдокументы\n к заказу +else данных нет в кэше +redis --> gateway: Возвращает\nпустой ответ +gateway -> workflow: Триггерит на\nобновление данных +activate workflow +workflow -> WTIS: API GET order_doc_info() +activate WTIS +WTIS --> workflow: answer +deactivate WTIS +workflow -> redis: Сохраняет в кэш\nКраткую форму на 7 дней\nПолную форму на 3 дня (спорно) +redis --> workflow: Сообщение об успешном сохранении +workflow --> gateway: Возвращает\nдокументы\n к заказу +end +== Получение данных о других типах оплаты == +workflow -> payments: Запрашивает данные\nоб онлайн оплате И\nпо счету +activate payments +payments --> workflow: answer +deactivate payments +workflow -> workflow: Агрегирует данные\nс источников +workflow --> gateway: answer +deactivate workflow +gateway --> ARM: возвращает\nданные об оплатах +deactivate gateway +ARM --> user: Рендерит блок\nдокументов + +@enduml \ No newline at end of file diff --git a/oms/interface-arm/docs/realizations-or-payment.puml b/oms/interface-arm/docs/realizations-or-payment.puml new file mode 100644 index 0000000..d657b4a --- /dev/null +++ b/oms/interface-arm/docs/realizations-or-payment.puml @@ -0,0 +1,36 @@ +@startuml +scale 1000*1000 +mainframe Получение данных для отрисовки модалки Реализации или оплаты наличными +participant WTIS as WTIS +collections Redis as redis +participant workflow as workflow +participant gateway as gateway +participant ARM as ARM +actor user as user + +autonumber +hnote over WTIS: После MVP WTIS изменится\nна сервис баланса + +user -> ARM: Открывает заказ +ARM -> gateway: Запрашивает\nдокументы к заказу +activate gateway +gateway -> redis: Проверяет наличие\nданных в кэше +alt данные есть в кэше +redis --> gateway: Возвращает\nдокументы\n к заказу +else данных нет в кэше +redis --> gateway: Возвращает\nпустой ответ +gateway -> workflow: Триггерит на\nобновление данных +activate workflow +workflow -> WTIS: API GET order_doc_info() +activate WTIS +return answer +deactivate WTIS +workflow -> redis: Сохраняет в кэш\nКраткую форму на 7 дней\nПолную форму на 3 дня (спорно) +redis --> workflow: Сообщение об успешном сохранении +workflow --> gateway: Возвращает\nдокументы\n к заказу +deactivate workflow +end +gateway --> ARM: данные по документу +ARM -> user: рендерит модальное\nокно с инфо\nо документе + +@enduml \ No newline at end of file diff --git a/oms/interface-arm/docs/realizations.puml b/oms/interface-arm/docs/realizations.puml new file mode 100644 index 0000000..f95ea46 --- /dev/null +++ b/oms/interface-arm/docs/realizations.puml @@ -0,0 +1,38 @@ +@startuml +scale 1000*1000 +mainframe Получение данных для отрисовки таблицы реализаций MVP +participant WTIS as WTIS +collections Redis as redis +participant workflow as workflow +participant gateway as gateway +participant ARM as ARM +actor user as user +autonumber +hnote over WTIS: После MVP WTIS изменится\nна сервис баланса + +autonumber 1 +user -> ARM: Открывает заказ +ARM -> gateway: Запрашивает\nдокументы к заказу +activate gateway +gateway -> redis: Проверяет наличие\nданных в кэше +alt данные есть в кэше +redis --> gateway: Возвращает\nдокументы\n к заказу +else данных нет в кэше +redis --> gateway: Возвращает\nпустой ответ +gateway -> workflow: Триггерит на\nобновление данных +activate workflow +workflow -> WTIS: API GET order_doc_info() +activate WTIS +return answer +deactivate WTIS +workflow -> redis: Сохраняет в кэш\nКраткую форму на 7 дней\nПолную форму на 3 дня (спорно) +redis --> workflow: Сообщение об успешном сохранении +workflow --> gateway: Возвращает\nдокументы\n к заказу +deactivate workflow +end + +gateway --> ARM: возвращает\nданные о заказе +deactivate gateway +ARM --> user: Рендерит блок\nдокументов + +@enduml \ No newline at end of file diff --git a/oms/interface-arm/order/get-region.puml b/oms/interface-arm/order/get-region.puml new file mode 100644 index 0000000..577662f --- /dev/null +++ b/oms/interface-arm/order/get-region.puml @@ -0,0 +1,41 @@ + @startuml +scale 800*800 +mainframe Получение списка регионов от Officer +actor Пользователь as user +participant ARM as ARM +participant gateway as gateway +collections redis as redis +participant workflow as workflow +participant officer as officer +autonumber + +user -> ARM: Открывает форму\nзаказа +activate ARM +ARM -> gateway: REST API GET\n инфо о регионах +activate gateway +gateway -> redis: Запрашивает\nсписок\nрегионов + +opt Данные о регионах есть в кэше +redis --> gateway: answer +else Данные необходимо обновить в кэше +gateway -> workflow: триггерит обновление +activate workflow +workflow -> officer: GraphQL method\noffices +activate officer +officer --> workflow: GraphQL answer +workflow -> officer: GraphQL method\nlocalities +officer --> workflow: GraphQL answer +deactivate officer +workflow -> workflow: Обработка\nданных +workflow -> redis: Записывает регионы\nи параметры в экш +workflow --> gateway: answer +deactivate workflow +end + +gateway --> ARM: REST API GET\nanswer +deactivate gateway +ARM --> user: Рендерит данные +deactivate ARM +@enduml + + \ No newline at end of file diff --git a/oms/personal-cabinet/change note.puml b/oms/personal-cabinet/change note.puml new file mode 100644 index 0000000..23fb7d4 --- /dev/null +++ b/oms/personal-cabinet/change note.puml @@ -0,0 +1,23 @@ + @startuml +mainframe Добавление/удаление заметки пользователя в ЛК +scale 1500x1500 +actor user as user +participant ARM +participant Gateway +participant personalCabinet + +autonumber +user -> ARM: Нажимает кнопку "Главная" +alt Пользователь ввел текст и снял фокус с поля +ARM -> Gateway: Отправляет запрос на\nPUT personal-cabinet/v1/note +else Пользователь нажал кнопку "Очистить" +ARM -> Gateway: Отправляет запрос на\nDELETE personal-cabinet/v1/note +end + + +ARM -> Gateway: Отправляет запрос на GET personal-cabinet/v1/note +Gateway -> personalCabinet: Вызывает методы для\nизменения заметок по пользователю +personalCabinet --> Gateway: answer +Gateway --> ARM: answer +ARM --> user: answer +@enduml \ No newline at end of file diff --git a/oms/personal-cabinet/favorites.puml b/oms/personal-cabinet/favorites.puml new file mode 100644 index 0000000..c023c14 --- /dev/null +++ b/oms/personal-cabinet/favorites.puml @@ -0,0 +1,23 @@ +@startuml +mainframe Взаимодействие с избранным +scale 1500x1500 +actor user as user +participant ARM +participant Gateway +participant Order + +autonumber +user -> ARM: Нажимает иконку\nсердечка в любом заказе + +alt Поле было предварительно выделено (активное состояние) +ARM -> Gateway: Отправляет запрос на\nDELETE orders/v1/{orderID}/favorite +else Поле было предварительно не выделено (не активное состояние) +ARM -> Gateway: Отправляет запрос на\nPOST orders/v1/{orderID}/favorite +end + +Gateway -> Order: Вызывает метод\nвзаимодействия с заказом +Order -> Order: Обновляет модель order\n(Либо добавляет uuid юзера\nлибо удаляет) +Order --> Gateway: answer +Gateway --> ARM: answer +ARM --> user: answer +@enduml \ No newline at end of file diff --git a/oms/personal-cabinet/get-info-order.puml b/oms/personal-cabinet/get-info-order.puml new file mode 100644 index 0000000..912326f --- /dev/null +++ b/oms/personal-cabinet/get-info-order.puml @@ -0,0 +1,17 @@ +@startuml +mainframe Получение данных о заказах для ЛК пользователя +scale 1500x1500 +actor user as user +participant ARM +participant Gateway +participant Order + +autonumber +user -> ARM: Нажимает кнопку "Главная" +user -> ARM: Нажимает кнопку "Статистика по заказам" +ARM -> Gateway: Отправляет запрос на GET personal-cabinet/v1/stats +Gateway -> Order: Вызывает методы для получения всех необходимых срезов по заказам +Order --> Gateway: answer +Gateway --> ARM: answer +ARM --> user: Рендерит информационные блоки +@enduml \ No newline at end of file diff --git a/oms/personal-cabinet/get-note.puml b/oms/personal-cabinet/get-note.puml new file mode 100644 index 0000000..a2ac929 --- /dev/null +++ b/oms/personal-cabinet/get-note.puml @@ -0,0 +1,16 @@ + @startuml +mainframe Получение заметки пользователя для ЛК +scale 1500x1500 +actor user as user +participant ARM +participant Gateway +participant personalCabinet + +autonumber +user -> ARM: Нажимает кнопку "Главная" +ARM -> Gateway: Отправляет запрос на GET personal-cabinet/v1/note +Gateway -> personalCabinet: Вызывает методы для получения заметок по пользователю +personalCabinet --> Gateway: answer +Gateway --> ARM: answer +ARM --> user: Рендерит текст в блоке заметок +@enduml \ No newline at end of file diff --git a/oms/process/action.puml b/oms/process/action.puml new file mode 100644 index 0000000..34a5299 --- /dev/null +++ b/oms/process/action.puml @@ -0,0 +1,58 @@ +@startuml +mainframe TO BE применение акций и скидок в заказе B2C +scale 1500x1500 +actor user as user +participant ARM +participant Sherlock +participant Gateway +participant Order +participant PDM +participant Druz +participant SCROOGE +participant Promo + +autonumber +user -> ARM: Нажимает кнопку "Применить скидки" +ARM -> ARM: Рендерит модальное окно +ARM -> ARM: Акции сайта - чекбокс активен +ARM -> ARM: Скидки, выбрано: Без скидки +autonumber 5.1 +alt Выбирает только скидки уровня ОПТ + user -> ARM: Выбирает тип ОПТа для клиента + user -> ARM: Снимает чекбокс "Акции сайта" + user -> ARM: Нажимает кнопку "Применить" + ARM -> Gateway: Передает запрос + Gateway -> Gateway: Получает название региона из кэша + Gateway -> SCROOGE: Запрашивает цены из SCROOGE согласно уровню ОПТа + SCROOGE --> Gateway: answer +autonumber 6.1 +else Выбирает только акции сайта + user -> ARM: Оставляет чекбокс "Акции сайта" + user -> ARM: Оставляет скидку с типом "Без скидки" + user -> ARM: Нажимает кнопку "Применить" + ARM -> Gateway: Передает запрос + Gateway -> Gateway: Получает название региона из кэша + Gateway -> Gateway: Готовит запрос в promo + Gateway -> Promo: Запрашивает акции и цены по товарам из Promo + Promo --> Gateway: answer +autonumber 7.1 +else Выбирает акции и скидки ОПТ + user -> ARM: Выбирает тип ОПТа для клиента + user -> ARM: Оставляет чекбокс "Акции сайта" + user -> ARM: Нажимает кнопку "Применить" + ARM -> Gateway: Передает запрос + Gateway -> Gateway: Получает название региона из кэша + Gateway -> Gateway: Готовит запрос в promo + Gateway -> Promo: Запрашивает акции и цены по товарам из Promo + Promo --> Gateway: answer + Gateway -> SCROOGE: Запрашивает цены из SCROOGE согласно уровню ОПТа + SCROOGE --> Gateway: answer + Gateway -> Gateway: Применяет наименьшие цены\nк каждому из товаров +end +autonumber 8 +Gateway -> Order: Записывает изменения в модель +Order --> Gateway: Изменения успешно применены +Gateway -> Gateway: Собирает ответ для frontend +Gateway --> ARM: Answer +ARM -> user: Отображает примененные акции +@enduml \ No newline at end of file diff --git a/oms/process/basket-import.puml b/oms/process/basket-import.puml new file mode 100644 index 0000000..c6746e7 --- /dev/null +++ b/oms/process/basket-import.puml @@ -0,0 +1,26 @@ +@startuml +scale 800x800 +actor user as user +participant ARM +participant Gateway +participant SITE + +autonumber +user -> ARM: Вводит номер корзины +ARM -> Gateway: Запрос на info/cart +Gateway -> SITE: Запрос на api/v1/json/user-cart/ +SITE --> Gateway: answer +Gateway -> Gateway: Получает название региона из кэша +Gateway -> Gateway: Запрашивает цены из SCROOGE +Gateway -> Gateway: Запрашивает инфо о товаре из PDM +Gateway -> Gateway: Собирает ответ для frontend +Gateway --> ARM: answer +ARM -> ARM: Проверяет регионы\nв запросе и в заказе + +alt Регион корзины == регион заказа +ARM --> user: answer +else Регион корзины <> регион заказа +ARM -> user: Запрашивает\nподтверждение\nо смене региона +end + +@enduml \ No newline at end of file diff --git a/oms/process/booking.puml b/oms/process/booking.puml new file mode 100644 index 0000000..b27f44b --- /dev/null +++ b/oms/process/booking.puml @@ -0,0 +1,77 @@ +@startuml +scale 2000x2000 +mainframe Внесение изменения в заказ в статусе "В работе" +Actor USER +participant ARM +participant Gateway +participant Workflow +participant History +participant WTIS + +'-------------------------------------------action------------------- +autonumber + +USER -> ARM: Открывает заказ +USER -> ARM: Нажимает кнопку\n"Редактировать заказ" +ARM -> Gateway: Запрос с номером заказа +Gateway -> Workflow: Инициирует запуск workflow +Workflow -> History: Открывает транзакцию\nrpc StartTransaction(StartTransactionRequest) +History --> Workflow: Подтверждает открытие транзакции\nreturn StartTransactionResponse +Workflow --> Gateway: Возвращает поля доступные\nдля редактирования +Gateway --> ARM: Возвращает ответ что транзакция открыта +ARM --> USER: Разблокирует все элементы в\nинтерфейсе для редактирования + +loop Внесение корректировок пользователем и наполнение транзакции +USER -> ARM: Вносит корректировки +ARM -> Gateway: Использует стандартные\nendpoint заказа +Gateway -> Workflow: Передает запрос в workflow +Workflow -> Workflow: Проверяет что транзакция открыта:\nВ ТЗ: Проверка наличия открытой транзакции +autonumber 14.1.1 +alt Транзакция закрыта +Workflow -> Gateway: Возвращает ошибку +Gateway -> ARM: answer +ARM -> USER: Выводит сообщение:\n"Транзакция была закрыта,\nнеобходимо заново открыть\nзаказ на корректировку" + +autonumber 14.2.1 +else Транзакция открыта +Workflow -> History: Отправляет GRPC сигнал\nс корректировками в History\nrpc CreateEvent(CreateEventRequest) +History -> History: Сохраняет\nкорректировки +History --> Workflow: return CreateEventResponse +Workflow --> Gateway: answer +Gateway --> ARM: answer +end 'Это end alt +autonumber 15 + +end 'Это end loop + +USER -> ARM: Нажимает кнопку\n"Сохранить изменения"\nИЛИ "Отменить изменения" +ARM -> Gateway: Отправляет запрос на\n/orders/end-correction/orderID={orderGUID} +Gateway -> Workflow: Вызывает wf +Workflow -> History: Запрашивает актуальное\nсостояние заказа\nrpc GetLastState(GetLastStateRequest) +History --> Workflow: Возвращает Модель заказа\nс примененными корректировками\nreturn GetLastStateResponse +Workflow -> Workflow: Закрывает транзакцию,\nсохраняет актуальный\nзаказ в Order/shipment +Workflow -> WTIS: Отправляет модель заказа через топик kafka:\nВ ТЗ: Функциональные изменения - "На стороне Gateway" - п.2 +WTIS -> WTIS: Обновляет сущность заказа + +autonumber 22.1.1 +alt Изменения успешно проведены +WTIS --> Workflow: Возвращает ответ success +Workflow -> History: Отправляет GRPC сигнал о закрытии\nтранзакции\nrpc EndTransaction(EndTransactionRequest) +History --> Workflow: Подтверждает закрытие\nтранзакции\nreturn EndTransactionResponse +Workflow --> Gateway: answer +Gateway --> ARM: answer +ARM --> USER: Отображает модальное\nокно "Изменения\nуспешно сохранены" + +autonumber 22.2.1 +else Изменения не проведены +WTIS --> Workflow: Возвращает ответ failed +Workflow -> History: Отправляет GRPC сигнал\nоб удалении транзакции +History --> Workflow: Отправляет GRPC сигнал\nчто транзакция удалена +Workflow -> Workflow: Откатывает изменения,\nудаляет корректировки +Workflow --> Gateway: answer +Gateway --> ARM: answer +ARM --> USER: Отображает модальное\nокно "Не удалось\nприменить изменения" +end + + +@enduml \ No newline at end of file diff --git a/oms/process/correction.puml b/oms/process/correction.puml new file mode 100644 index 0000000..a6c83eb --- /dev/null +++ b/oms/process/correction.puml @@ -0,0 +1,79 @@ +@startuml +scale 2000x2000 +mainframe Внесение изменения в заказ в статусе "В работе" +Actor USER +participant ARM +participant Gateway +participant Workflow +participant History +participant WTIS + +'-------------------------------------------action------------------- +autonumber + +USER -> ARM: Открывает заказ +USER -> ARM: Нажимает кнопку\n"Редактировать заказ" +ARM -> Gateway: Запрос с номером заказа +Gateway -> Workflow: Инициирует запуск workflow +Workflow -> History: Открывает транзакцию\nrpc StartTransaction(StartTransactionRequest) +History --> Workflow: Подтверждает открытие транзакции\nreturn StartTransactionResponse +Workflow -> Workflow: Запускает workflow с бизнес-логикой:\nВ ТЗ: Функциональные изменения\n-На стороне Workflow\n-"Получение доступных типов корректировок" +Workflow -> WTIS: Запрашивает признак доступности корректировки для атрибутов +WTIS -> Workflow: Возвращает доступные для редактирования атрибуты +Workflow --> Gateway: Возвращает поля доступные\nдля редактирования +Gateway --> ARM: Возвращает атрибуты\nдоступные для редактирования +ARM --> USER: Дизейблит недоступные для\nредактирования элементы\nВ ТЗ: Функциональные изменения\n"На стороне ARM" + +loop Внесение корректировок пользоваелем и наполнение транзакции +USER -> ARM: Вносит корректировки +ARM -> Gateway: Использует стандартные\nendpoint заказа +Gateway -> Workflow: Передает запрос в workflow +Workflow -> Workflow: Проверяет что транзакция открыта:\nВ ТЗ: Проверка наличия открытой транзакции +autonumber 14.1.1 +alt Транзакция закрыта +Workflow -> Gateway: Возвращает ошибку +Gateway -> ARM: answer +ARM -> USER: Выводит сообщение:\n"Транзакция была закрыта,\nнеобходимо заново открыть\nзаказ на корректировку" + +autonumber 14.2.1 +else Транзакция открыта +Workflow -> History: Отправляет GRPC сигнал\nс корректировками в History\nrpc CreateEvent(CreateEventRequest) +History -> History: Сохраняет\nкорректировки +History --> Workflow: return CreateEventResponse +Workflow --> Gateway: answer +Gateway --> ARM: answer +end 'Это end alt +autonumber 15 + +end 'Это end loop + +USER -> ARM: Нажимает кнопку\n"Сохранить изменения"\nИЛИ "Отменить изменения" +ARM -> Gateway: Отправляет запрос на\n/orders/end-correction/orderID={orderGUID} +Gateway -> Workflow: Вызывает wf +Workflow -> History: Запрашивает актуальное\nсостояние заказа\nrpc GetLastState(GetLastStateRequest) +History --> Workflow: Возвращает Модель заказа\nс примененнеными корректировками\nreturn GetLastStateResponse +Workflow -> Workflow: Закрывает транзакцию,\nсохраняет актуальный\nзаказ в Order/shipment +Workflow -> WTIS: Отправляет модель заказа через топик kafka: oms.order.sync\nВ ТЗ: Функциональные изменения - "На стороне Gateway" - п.2 +WTIS -> WTIS: Пытается применить\nвсе изменения в заказе + +autonumber 22.1.1 +alt Изменения успешно проведены +WTIS --> Workflow: Возвращает сигнал в temporal success +Workflow -> History: Отправляет GRPC сигнал о закрытии\nтранзакции\nrpc EndTransaction(EndTransactionRequest) +History --> Workflow: Подтверждает закрытие\nтранзакции\nreturn EndTransactionResponse +Workflow --> Gateway: answer +Gateway --> ARM: answer +ARM --> USER: Отображает модальное\nокно "Изменения\nуспешно сохранены" + +autonumber 22.2.1 +else Изменения не проведены +WTIS --> Workflow: Возвращает сигнал в temporal failed +Workflow -> History: Отправляет GRPC сигнал\nоб удалении транзакции +History --> Workflow: Отправляет GRPC сигнал\nчто транзакция удалена +Workflow -> Workflow: Откатывает изменения,\nудаляет корректировки +Workflow --> Gateway: answer +Gateway --> ARM: answer +ARM --> USER: Отображает модальное\nокно "Не удалось\nприменить изменения" +end + +@enduml \ No newline at end of file diff --git a/oms/site-integration/AS IS.puml b/oms/site-integration/AS IS.puml new file mode 100644 index 0000000..7d7ae20 --- /dev/null +++ b/oms/site-integration/AS IS.puml @@ -0,0 +1,59 @@ +@startuml +scale 1300x1300 +mainframe AS IS обмен по созданию заказа на сайте +Actor USER +participant SITE +database SITE_database +queue kafka_1 +participant WTIS +database WTIS_database +queue kafka_2 +participant OMS +database OMS_database +'-------------------------------------------action------------------- +autonumber + +USER -> SITE: Нажимает кнопку оформить заказ +SITE -> SITE_database: Проводит внутренние проверки\nи сохраняет в БД +SITE_database -> SITE: Заказ успешно сохранен + +autonumber 4.1 +alt Тип доставки в заказе: Самовывоз +SITE -> kafka_1: Записывает заказ в топик kafka: site.order.pickup.created +else Тип доставки в заказе: Курьером +SITE -> kafka_1: Записывает заказ в топик kafka: site.order.courier.created +else Тип доставки в заказе: ТК +SITE -> kafka_1: Записывает заказ в топик kafka: site.order.transport_company.created +end + +autonumber 5 +WTIS -> kafka_1: Читает сообщения из топика +WTIS -> WTIS_database: Сохраняет заказ +WTIS_database -> WTIS: Заказ успешно сохранен +WTIS -> WTIS: Проверяет условия для MVP\nсогласно настроек в wtis_settings + +autonumber 9.1 +alt Заказ подходит под условия OMS +WTIS -> kafka_2: Записывает заказ в топик: wtis.order_oms.created +else Заказ не подходит под условия OMS +WTIS -> WTIS: Продолжает процедуру автооформления\nзаказа и обогащения данными +WTIS -> WTIS: Конец процесса +end + +autonumber 10 +OMS -> kafka_2: Читает событие из топика +OMS -> OMS_database: Сохраняет заказ в БД +OMS_database -> OMS: Заказ успешно сохранен + +OMS -> OMS: Проводит бизнес проверки +OMS -> WTIS: Резервирует товары + +autonumber 15.1 +alt Успешно зарезервировано +WTIS -> OMS: Товары в заказе успешно зарезервированы +else Не успешно зарезервировано +WTIS -> WTIS: Ставит задачу на менеджера, меняет мастер-систему +WTIS -> WTIS: Конец процесса +end + +@enduml \ No newline at end of file diff --git a/oms/site-integration/TO BE.puml b/oms/site-integration/TO BE.puml new file mode 100644 index 0000000..416e12a --- /dev/null +++ b/oms/site-integration/TO BE.puml @@ -0,0 +1,66 @@ +@startuml +scale 1300x1300 +mainframe TO BE обмен по созданию заказа на сайте +Actor USER +participant SITE +database SITE_database +participant WTIS +database WTIS_database +queue kafka_1 +queue kafka_2 +participant OMS +database OMS_database +'-------------------------------------------action------------------- +autonumber + +USER -> SITE: Нажимает кнопку оформить заказ +SITE -> SITE_database: Проводит внутренние проверки\nи сохраняет в БД +SITE_database -> SITE: Заказ успешно сохранен + +autonumber 4.1 +alt Тип доставки в заказе: Самовывоз +SITE -> kafka_1: Записывает заказ в топик kafka: site.order.pickup.created +else Тип доставки в заказе: Курьером +SITE -> kafka_1: Записывает заказ в топик kafka: site.order.courier.created +else Тип доставки в заказе: ТК +SITE -> kafka_1: Записывает заказ в топик kafka: site.order.transport_company.created +end + +autonumber 5 +OMS -> kafka_1: Читает сообщения из топиков +OMS -> OMS: Проверяет условия для MVP +WTIS -> kafka_1: Читает сообщения из топиков +WTIS -> WTIS: Проверяет условия для MVP + +autonumber 9.1 +alt Подходит под условия OMS +WTIS -> WTIS: Не обрабатывает такой заказ +OMS -> OMS_database: Сохраняет заказ +OMS -> kafka_2: Записывает заказ в топик: oms.orders.sync +OMS_database -> OMS: Заказ успешно сохранен +WTIS -> kafka_2: Читает топик +WTIS -> WTIS: Создает заказ +WTIS -> OMS: Возвращает модель заказа через workflow +OMS -> OMS: Проводит автооформление +OMS -> WTIS: Резервирует товары + +autonumber 9.9.1 +alt Успешно зарезервировано +WTIS -> OMS: Товары в заказе успешно зарезервированы +WTIS -> WTIS: Конец процесса + +else Не успешно зарезервировано +WTIS -> WTIS: Ставит задачу на менеджера, меняет мастер-систему +WTIS -> WTIS: Конец процесса +end + + +else Не подходит под условия OMS +autonumber 10.1 +OMS -> OMS: Не обрабатывает такой заказ +WTIS -> WTIS_database: Сохраняет заказ +WTIS_database -> WTIS: Заказ успешно сохранен +WTIS -> WTIS: Конец процесса +end + +@enduml \ No newline at end of file diff --git a/ordering.puml b/ordering.puml new file mode 100644 index 0000000..f1dfb28 --- /dev/null +++ b/ordering.puml @@ -0,0 +1,119 @@ +@startuml +title Проверка лимитов заказа +autonumber + actor User + participant ARM as ARM + participant Gateway as Gateway + participant Workflow as Workflow + participant Temporal as Temporal + + User -> ARM: Нажатие кнопки "Оформить заказ" + ARM -> Gateway: Отправляет запрос на /orders/{orderID}/validate + Gateway -> Temporal: Отправка данных на\nоформление заказа и его проверку + Temporal --> Workflow: Получение сообщения + Workflow -> Workflow: Проверка лимитов ПВЗ и размеров товаров + Workflow -> Workflow: Завершает выполнение workflow + Workflow -> Temporal: Отдает результат проверки в Temporal. + Gateway --> Temporal: Слушает temporal и получает результат проверки + Gateway --> ARM: Ответ в виде кодов ответа с /orders/{orderID}/validate + + alt Проверки пройдены + ARM -> ARM: Проверки пройдены успешно + ARM -> Gateway: Вызывает метод bf orders/{orderID}/ordering оформления заказа\nи отправляет идентификатор orderId для оформления заказа в Gateway + else Проверки не пройдены + ARM -> User: Показывает Пользователю модальное\nокно с лимитами ПВЗ и выбором\nдальнейших действий - продолжить\nоформление или отменить. + alt Отмена оформления + User -> ARM: Нажимает кнопку "Отменить оформление" + ARM -> ARM: Закрывает модальное окно и ждет следующего действия от менеджера (Конец процесса) + else Продолжение оформления + User -> ARM: Нажимает кнопку "Продолжить оформление" + ARM -> Gateway: Вызывает метод bf orders/{orderID}/ordering оформления заказа\nи отправляет идентификатор orderId для оформления заказа в Gateway + end + end + note across: Продолжение описания алгоритма начинается с Workflow оформления заказа +@enduml + + +@startuml +title Оформление заказа +autonumber +participant User +participant ARM +participant Gateway +participant Temporal +participant Workflow +queue Kafka +participant Wtis +participant Order + +ARM -> Gateway: Вызов метода bf orders/{orderID}/ordering +ARM -> User: Блокирует заказ на изменение\nи выводит оповещения: "Оформление заказа", +Gateway -> Temporal: Отправляет данные\nна оформление заказа +Workflow --> Temporal: Получает сообщения о заказе +Workflow -> Workflow: Создает WorkflowOrdering +Workflow -> Temporal: Отправляет workflowID и runID +Temporal -> Gateway: Получает workflowID и runID +Gateway -> ARM: Отправка workflowID и runID\nв ответ на метод bf orders/{orderID}/ordering +ARM -> ARM: Сохранение workflowID и runID в куки на 5 минут +loop Раз в 5 секунд +ARM -> Gateway: Периодическая проверка состояния workflow\nзапросом на orders/{orderID}/workflow/{workflowID} +Gateway -> Temporal: Отправляет запрос на\nпроверку состояния workflow +Workflow -> Temporal: Слушает и получает запрос\nна состояние workflow +Workflow -> Temporal: Уточнение состояния workflow\n(в работе или завершен успешно\nили завершен с ошибкой)\n WorkflowOrdering +Gateway -> Temporal: Слушает и получает состояния\nworkflow +Gateway -> ARM: Получает ответ +end +alt До тех пор пока workflow не завершен + ARM -> User: ARM блокирует интерфейс пользователю +else workflow завершен успешно + ARM -> User: АРМ снимает блокировку и показывает оповещение\n"Заказ оформлен". И обновляет все данные\nсодержащие статусы, подробнее описано ниже. +else workflow завершен с ошибкой "Втис не доступен" + ARM -> User: АРМ снимает блокировку и показывает оповещение\n"Заказ не оформлен" +else workflow завершен с ошибкой "Не удалось взять в резерв товары" + ARM -> User: АРМ снимает блокировку и показывает\nоповещение "Не удалось товары взять в резерв".\nИ обновляет все данных содержащие статусы,\nподробнее описано ниже. +end + +Workflow -> Order: Забирает структуру заказа +Workflow -> Workflow: Конвертирует структуру заказа\nв нужную для Wtis +Workflow -> Workflow: Создает таймер ответа\nна запрос и ждет ответ от Wtis\nTBD: Сколько таймер? +Workflow -> Kafka: Записывает данные в топик\nKafka oms.orders.sync +alt Успешный сценарий + Wtis -> Kafka: Читает данные по заказу + Wtis -> Wtis: Создает заказ или сопоставляет\nс тем что уже есть и апдейтит\nего в БД + Wtis -> Wtis: При необходимости резервирует\nтовары через "Умный резерв" + Wtis -> Temporal: Отправляет сигнал что закончил свои флоу + +else WTIS не доступен + Wtis -> Kafka: Не забрал данные по заказу + Temporal -> Temporal: по таймауту понимает что\nвтис не ответил\nTBD: Где таймер?\nНа воркфлоу или на темпорал? + Workflow -> Temporal: Слушает Temporal и\nполучает информацию об ошибке + Workflow -> Order: Ничего не обновляет в БД Order +else WTIS частично взял товары в резерв + Wtis -> Kafka: Читает данные по заказу + Wtis -> Wtis: Создает заказ или сопоставляет\nс тем что уже есть и апдейтит\nего в БД + Wtis -> Wtis: При необходимости резервирует\nтовары через "Умный резерв"\n(частичный резерв) + Wtis -> Temporal: Отправляет сигнал что закончил\nсвои флоу частично + Workflow -> Temporal: Слушает Temporal и получает\nинформацию о проведенном резерв + Workflow -> Order: Обновляет ту часть товаров что была зарезервирована + Workflow -> Workflow: Меняет мастер систему\nв заказе на WTIS + Workflow -> Gateway: Возвращает ответ + Gateway -> ARM: Возвращает ответ + ARM -> User: Пишет сообщение пользователю:\n"Заказ не оформлен товары не зарезервировались" +end +Wtis -> Kafka: Записывает обновленные\nданные заказа +Temporal -> Kafka: Слушает топик wtis.orders.sync и получает структуру даных +Workflow -> Order: Маппит структуру и сохранет ее в Order, обновляя статусы заказов и товаров +Workflow -> Workflow: Запускает дочерний\nworkflow SendSMSMessage +Workflow -> Workflow: Завершает wf WorkflowOrdering +Workflow -> Temporal: Сообщает о завершении workflow +Gateway -> Temporal: Слушает Temporal и\nполучает сигнал что wf завершен +Gateway --> ARM: Возвращает ответ на bf orders/{orderID}/ordering +ARM -> User: Разблокирует интерфейс, меняет управляющие кнопки заказа +ARM -> Gateway: Вызывает метод bf /orders/{orderID}/products\nтоварного блока обновляет статусы товаров. +Gateway -> ARM: answer +ARM -> Gateway: Вызывает метод bf /orders/{orderID}\nзаказа обновляет статус заказа. +Gateway -> ARM: answer +ARM -> Gateway: Вызывает метод bf /orders/{orderID}/deliveries\nобновляет статус доставки. +Gateway -> ARM: answer + +@enduml \ No newline at end of file diff --git a/personal-cabinet.puml b/personal-cabinet.puml new file mode 100644 index 0000000..502337a --- /dev/null +++ b/personal-cabinet.puml @@ -0,0 +1,85 @@ +@startuml +mainframe Получение данных о заказах для ЛК пользователя +scale 1500x1500 +actor user as user +participant ARM +participant Gateway +participant Order + +autonumber +user -> ARM: Нажимает кнопку "Главная" +user -> ARM: Нажимает кнопку "Статистика по заказам" +ARM -> Gateway: Отправляет запрос на GET personal-cabinet/v1/stats +Gateway -> Order: Вызывает методы для получения всех необходимых срезов по заказам +Order --> Gateway: answer +Gateway --> ARM: answer +ARM --> user: Рендерит информационные блоки +@enduml + + +@startuml +mainframe Получение заметки пользователя для ЛК +scale 1500x1500 +actor user as user +participant ARM +participant Gateway +participant personalCabinet + +autonumber +user -> ARM: Нажимает кнопку "Главная" +ARM -> Gateway: Отправляет запрос на GET personal-cabinet/v1/note +Gateway -> personalCabinet: Вызывает методы для получения заметок по пользователю +personalCabinet --> Gateway: answer +Gateway --> ARM: answer +ARM --> user: Рендерит текст в блоке заметок +@enduml + + +@startuml +mainframe Взаимодействие с избранным +scale 1500x1500 +actor user as user +participant ARM +participant Gateway +participant Order + +autonumber +user -> ARM: Нажимает иконку\nсердечка в любом заказе + +alt Поле было предварительно выделено (активное состояние) +ARM -> Gateway: Отправляет запрос на\nDELETE orders/v1/{orderID}/favorite +else Поле было предварительно не выделено (не активное состояние) +ARM -> Gateway: Отправляет запрос на\nPOST orders/v1/{orderID}/favorite +end + +Gateway -> Order: Вызывает метод\nвзаимодействия с заказом +Order -> Order: Обновляет модель order\n(Либо добавляет uuid юзера\nлибо удаляет) +Order --> Gateway: answer +Gateway --> ARM: answer +ARM --> user: answer +@enduml + + +@startuml +mainframe Добавление/удаление заметки пользователя в ЛК +scale 1500x1500 +actor user as user +participant ARM +participant Gateway +participant personalCabinet + +autonumber +user -> ARM: Нажимает кнопку "Главная" +alt Пользователь ввел текст и снял фокус с поля +ARM -> Gateway: Отправляет запрос на\nPUT personal-cabinet/v1/note +else Пользователь нажал кнопку "Очистить" +ARM -> Gateway: Отправляет запрос на\nDELETE personal-cabinet/v1/note +end + + +ARM -> Gateway: Отправляет запрос на GET personal-cabinet/v1/note +Gateway -> personalCabinet: Вызывает методы для\nизменения заметок по пользователю +personalCabinet --> Gateway: answer +Gateway --> ARM: answer +ARM --> user: answer +@enduml \ No newline at end of file diff --git a/search/Architecture Scheme Search.drawio.xml b/search/Architecture Scheme Search.drawio.xml new file mode 100644 index 0000000..8a36ea8 --- /dev/null +++ b/search/Architecture Scheme Search.drawio.xml @@ -0,0 +1,2 @@ + +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 \ No newline at end of file diff --git a/search/Mycroft.puml b/search/Mycroft.puml new file mode 100644 index 0000000..e97f81b --- /dev/null +++ b/search/Mycroft.puml @@ -0,0 +1,37 @@ +@startuml +'Параметры для интерфейсов +skinparam interface { + backgroundColor #1a2eff + borderColor black +} + +'Параметры для компонентов +skinparam component { + FontSize 13 + ArrowFontStyle Bold + FontName Times New Roman + BorderColor black + BackgroundColor #e6ffef + ArrowFontName Courier + ArrowColor #111111 + ArrowFontColor #111111 +} + +frame Mycroft_scheme #ededed { + +database MySql #turquoise { + [Sphinx] +} + +database ElasticSearch #turquoise { + [Sherlock] +} + +[request] --> [Sherlock] +[request] --> [Sphinx] +[Sherlock] --> [aggregate] +[Sphinx] --> [aggregate] +[aggregate] --> [csv_files]: save + +} +@enduml \ No newline at end of file diff --git a/search/Sherlock scheme.puml b/search/Sherlock scheme.puml new file mode 100644 index 0000000..c323fce --- /dev/null +++ b/search/Sherlock scheme.puml @@ -0,0 +1,38 @@ +@startuml +'Параметры для интерфейсов +skinparam interface { + backgroundColor #1a2eff + borderColor black +} + +'Параметры для компонентов +skinparam component { + FontSize 13 + ArrowFontStyle Bold + FontName Times New Roman + BorderColor black + BackgroundColor #e6ffef + ArrowFontName Courier + ArrowColor #111111 + ArrowFontColor #111111 +} + +frame Sherlock_scheme #ededed { + +database "Elasticsearch" #turquoise { + [database] +} + [user_request] -u-> http_request_autocomplete + [user_request] -u-> http_request_full_text + http_request_autocomplete -u-> [database] + http_request_full_text -u-> [database] + + note top of http_request_full_text: POST /api/v1/product + note top of http_request_autocomplete: POST /api/v1/autocomplete + + [database] -u-> [filtering, sorting] + [filtering, sorting] -u-> [response_for_user] + + [response_for_user] -u-> http_response +} +@enduml \ No newline at end of file diff --git a/search/Watson.drawio.svg b/search/Watson.drawio.svg new file mode 100644 index 0000000..253ec4b --- /dev/null +++ b/search/Watson.drawio.svg @@ -0,0 +1,4 @@ + + + +
ТХ товара, категории,
производители и товары
ТХ товара, категории,...
PDM
PDM
Теговые страницы, распродажи, rnames
заголовки страниц и категорий, акции и
скидки, отзывы, просмотры заказа, seo сортировка
Теговые страницы, распродажи, rnames...
SITE(через топики kafka)
SITE(через топики kafka)
ID магазинов и AregID
ID магазинов и AregID
Officer
Officer
Факт наличия остатков в регионе
Факт наличия остатков в регионе
Shcat
Shcat
Цены и типы цен
Цены и типы цен
PriceFormer
PriceFormer
Информация о наличии в магазинах
Информация о наличии в магазинах
HamletX10
HamletX10
Watson
Watson
Text is not SVG - cannot display
\ No newline at end of file diff --git a/search/Watson.drawio.xml b/search/Watson.drawio.xml new file mode 100644 index 0000000..8296fcd --- /dev/null +++ b/search/Watson.drawio.xml @@ -0,0 +1,2 @@ + +5ZpZb9s4EIB/jYHdhwYSdfrRZxug3Q3gBdo+MhZtqZFMg6Zju79+KZGUhqZiuLXjA82DQg7v4fCbIZOONyi2Hxlepl9oQvIOcpJtxxt2kPiJkfhVSnZS4iI/lJI5yxIlawST7CdRQkdJ11lCVkZFTmnOs6UpnNLFgky5IcOM0Y1ZbUZzc9QlnhNLMJni3JZ+zRKeSmmMokb+iWTzVI/shl1ZUmBdWa1kleKEboDIG3W8AaOUy1SxHZC81J7Wi2w3fqO0nhgjC35Mgx/0xf/nCTnjYjN6zdPnx0mSfHA9NTm+0ysmiVCAylLGUzqnC5yPGmmf0fUiIWW3jsg1dT5TuhRCVwh/EM53ajfxmlMhSnmRq1IxY7b7BjPfy84eAp0dblXnMrdTOXvJSgsrumZTcmidynQwmxN+oJ7a1lIHYACl0I+EFkTMR1RgJMc8ezWNBCtbm9f1mu0QCbUjv7I7vuz4FedrNVRHKKInv4Eo6QgVxlW2P6q+Mi3ljkqjQVVTpHugVNYMqq+ne6hbxeor26IwF1rrPzORmpepqnQM6o9AqwjMRMp9Xbo3bl+P4oDE4RWJb7/VZj/jZwEfw85wns0XIj0V9kKYELwSxjNxuHuqoMiSRJo0WWU/8XPVX2lpS5oteLWdQb8TDFtt7+CBUjxSXTYUKGdAtgdtS5V+cB6cMFK0VPjUdny0+anen8rlNF2bnXqO2Z7OZitxSPaNt57hCfZsmfPT8Iu1mSZeNmnGyWSJq+O9EV7G3OI3kXC8osPQMfSBIpXfNMB39f6lAPah87biTzv36BpU/n26ovuka3CArvtglCCq4CNLFalczSvA2/I7BMQLNbUGupUDmOa+wVIf9BZCGrMFLkRI1M7kCLSCk+9bRO2ZyD1uIQaof8OhdIEzqnuQKoJOpx7FXmOtsR5o4psrqocYgYlFYPuQuSO2/utRBmY/0Ac5lsJ7IK3l1RArQoGeoWbq6cWWASCjzxt2eeiMLi8Mwsh0ef5ZXJ5/KR+HLKhMHv8b/VXtbqRPSL3TgbKVlrhnDOy7OasvePaC/766z/SiW/OZ8Z9xkfHu09WG1ql4HGqCDiyXBQkaAy+kuQi8UI+R+ePwhukYnwuOzoMbd+PTYPj++POsjf53NsumQtnXRtZ+mB/F10aW61pKuSSzAKa+w7KzM8u/T2ZF7dcD3wz4Kq+NYKzsGE8bjd+X6bEZm7rA78MYoNcGPGTeH2CoHYP6Q31FuVkoass/BxVR4ARmxIjOEjHqbnSE410qgrQf/SbpFPOrA3Q/5rsBgLZfiy4G0EsFfcF9AjRuB2gI4DU0L9N7D8AxuJr3dZHZ/IYZ55yRcWHkGWfvxEvx+0PMflt7YiIMHFNW3EAs2L01knX/DJCF9wmybivIujFAmG89eA5ATBe2B4DHho3wUbQOBo+/Nss53HI82D0XKss/mvmeGQ+eGA6+Pyvtx5FPuMgJ/9YS31yZlNd/57NvZV8xX9HF1TW1Hx4H/vupSmSbfxyRZtj8/403+h8= \ No newline at end of file diff --git a/search/Watson.puml b/search/Watson.puml new file mode 100644 index 0000000..5fd95c2 --- /dev/null +++ b/search/Watson.puml @@ -0,0 +1,82 @@ +@startuml +scale 0.8 +'Параметры для интерфейсов +skinparam interface { + backgroundColor #1a2eff + borderColor black +} +'Прямые стрелки +skinparam linetype ortho +'Параметры для компонентов +skinparam component { + FontSize 13 + ArrowFontStyle Bold + FontName Times New Roman + BorderColor black + BackgroundColor #e6ffef + ArrowFontName Courier + ArrowColor #111111 + ArrowFontColor #111111 +} + + +frame Watson_scheme #ededed { + +package "Site" #lightblue { + [Акции и скидки] -l-> kafka + [rnames] --> kafka + [Распродажи] --> kafka + [Теговые страницы] --> kafka + [Скрытие категорий \nпроизводителей] -l-> kafka + [Заголовоки страниц\n категорий] -l-> kafka + [Отзывы, просмотры,\n заказы и seo сортировка] --> kafka +} + +package "PDM" #lightblue { + [Товары] --> http_pdm : Каждые 10 минут + [Производители] --> http_pdm: Каждые 10 минут + [Категории] --> http_pdm: Каждые 2 часа + [Технические характеристики] --> http_pdm: Каждую минуту +} + +package "PriceFormer" #lightblue { + [Цены] -up-> http_price_former + [Типы цен] -up-> http_price_former +} + +package "HamletX10" #lightblue { + [Информация о наличии в магазинах] -> http_hamlet +} + +package "Shcat" #lightblue { + [Факт наличия \nостатков в регионе] -up-> http_shcat +} + +package "Officer" #lightblue { + [ID магазинов] -up-> http_officer + [AregID] -up-> http_officer +} + +database "MySql" #turquoise { + [database] +} + +'Site +kafka --> [database]: Чтение топиков из kafka + +'PDM +http_pdm --> [database] + +'HamletX10 +http_hamlet -up--> [database]: Каждый день + +'Officer +http_officer -up--> [database]: Каждую неделю + +'Shcat +http_shcat -up--> [database]: Запускается вручную + +'PriceFormer +http_price_former -up--> [database]: Каждую минуту +} +@enduml \ No newline at end of file diff --git a/search/WatsonScheme.puml b/search/WatsonScheme.puml new file mode 100644 index 0000000..5506465 --- /dev/null +++ b/search/WatsonScheme.puml @@ -0,0 +1,404 @@ +@startuml +frame AS_IS_ALL_SCHEME { +skinparam linetype ortho +scale 2500*1700 + + entity "search_availability_flag_{guid_office}" as availability { + * id : int auto_increment "PK" + -- + *product : char(36) + *is_availability : tinyint(1) + *create_at : timestamp + *update_at : timestamp + -- + unique (product) + } + + entity "search_remaining_{guid_office}" as remaining { + * id: int auto_increment "PK" + -- + *product: char(36) + *remaining: int + *create_at: timestamp + *update_at: timestamp + -- + unique (product) + } + + entity "search_check" as search_check { + *id: int auto_increment "PK" + -- + *locality: char(36) + *product: char(36) + *update_at: timestamp + -- + unique(locality, product) + } + entity "search_localities_offices" as localities_offices { + *id: int auto_increment "PK" + -- + *locality_guid: char(36) + *office_guid: char(36) + *is_active: tinyint(1) + -- + unique (office_guid) + } + + + + + + entity "search_countries" as countries { + *id: int auto_increment "PK" + -- + *code varchar(3) + *name: varchar(256) + *full_name: varchar(256) + *alpha_2: varchar(2) + *alpha_3: varchar(3) + -- + unique (code) + } + entity "search_prices_types_localities" as prices_types_localities { + *id: int auto_increment "PK" + -- + *hash: char(40) + *locality_guid: char(36) + *price_type_guid: char(36) + *type: varchar(128) + -- + unique (hash) + } + + entity "search_prices_types_products" as prices_types_products { + *id: int auto_increment "PK" + -- + *hash: char(40) + *product_guid: char(36) + *price_type_guid: char(36) + *price: decimal(10, 2) + *updated_at: timestamp + -- + unique (hash) + } + + entity "search_products_relevancy_counts" as products_relevancy_counts { + *id: bigint: auto_increment "PK" + -- + *product_guid: char(36) + *orders: int(11) + *views: int(11) + *reviews: int(11) + *updated_at: timestamp + -- + unique (product_guid) + } + + entity "search_products_relevancy_data_items" as relevancy_data_items { + *id: bigint: auto_increment "PK" + -- + *hash: char(40) + *product_guid: char(36) + *manufacter_guid: char(36) + *seo_position: int + *koef_sort: float + *updated_at: timestamp + -- + unique (hash) + } + + entity "search_products_sort_rating" as products_sort_rating { + *id: bigint: auto_increment "PK" + -- + *product_guid: char(36) + *rating: float + *updated_at: timestamp + -- + unique (product_guid) + } + + entity "search_manufacturers_settings" as manufacturers_settings { + *id: int auto_increment "PK" + -- + *manufacturer_guid: char(36) + *locality_guid: char(36) + *is_hide: tinyint(1) + *updated_at: timestamp + *created_at: timestamp + -- + unique (manufacturer_guid, locality_guid) + } + + entity "search_manufacturers" as manufacturers { + *id: int auto_increment "PK" + -- + *guid: char(36) + *name: varchar(256) + *is_our: tinyint(1) + *description: varchar(256) + *updated_at: timestamp + -- + unique (guid) + } + + entity "search_products" as products { + *id: int auto_increment "PK" + -- + *is_consumable: tinyint(1) + *is_on_site: tinyint(1) + *is_visible: tinyint(1) + *status: smallint + *is_discountinued: tinyint(1) + *is_for_order: tinyint(1) + *sku: int + *height: float + *lenght: float + *width: float + *guid: char(36) + *manufacter_guid: char(36) + *name_site: varchar(256) + *category: char(36) + *name_pdm: varchar(256) + *name_wtis: varchar(256) + *name_contractor: varchar(256) + *keywords: varchar(256) + *lights: varchar(20) + *country_code: varchar(3) + *uri: text + *advantages: text + *description: text + *equipment: text + *features: text + *updated_at: timestamp + -- + unique (guid) + } + + entity "search_products_categories" as products_categories { + *id: int auto_increment "PK" + -- + *hash: char(40) + *product_guid: char(36) + *category_guid: char(36) + *is_enabled: tinyint(1) + *updated_at: timestamp + -- + unique (hash) + } + + entity "search_categories_settings" as categories_settings { + *id: int auto_increment "PK" + -- + *category_guid: char(36) + *locality_guid: char(36) + *is_hide: tinyint(1) + *updated_at: timestamp + *created_at: timestamp + -- + unique (category_guid, locality_guid) + } + + entity "search_categories_relationship" as categories_relationship { + *id: int auto_increment "PK" + -- + *parent: char(36) + *child: char(36) + *main: tinyint(1) + *level: int + *line: int + *created_at: timestamp + } + + entity "search_categories" as categories { + *id: int auto_increment "PK" + -- + *guid: char(36) + name: varchar(256) + type: varchar(256) + parent_guid: char(36) + is_active: tinyint(1) + is_enable: tinyint(1) + up_caption: varchar(256) + updated_at: timestamp + -- + unique (guid) + } + + entity "search_products_sale" as product_sale { + *id: bigint: auto_increment "PK" + -- + *hash: char(40) + *guid: char(36) + *product_guid: char(36) + *locality_guid: char(36) + remaining: int + price: float + updated_at: timestamp + -- + unique (hash) + } + + entity "search_promotions" as promotions { + *id: int: auto_increment "PK" + -- + *product_guid: char(36) + *locality_guid char(36) + *name: varchar(256) + *updated_at: timestamp + } + + entity "search_specifications_bool" as specifications_bool { + *id: int auto_increment "PK" + -- + *hash: char(40) + *product_guid: char(36) + *guid: char(36) + *name: varchar(256) + *unit: varchar(256) + *description: text + *value: tinyint(1) + *updated_at: timestamp + -- + unique (hash) + } + + entity "search_specifications_collection" as specifications_collection { + *id: int auto_increment "PK" + -- + *hash: char(40) + *product_guid: char(36) + *guid: char(36) + *name: varchar(256) + *unit: varchar(256) + *description: text + *value: varchar(256) + *value_guid: char(36) + *updated_at: timestamp + -- + unique (hash) + } + + entity "search_specifications_float" as specifications_float { + *id: int auto_increment "PK" + -- + *hash: char(40) + *product_guid: char(36) + *guid: char(36) + *name: varchar(256) + *unit: varchar(256) + *description: text + *value: float + *updated_at: timestamp + -- + unique (hash) + } + + entity "search_specifications_int" as specifications_int { + *id: int auto_increment "PK" + -- + *hash: char(40) + *product_guid: char(36) + *guid: char(36) + *name: varchar(256) + *unit: varchar(256) + *description: text + *value: int + *updated_at: timestamp + -- + unique (hash) + } + + entity "search_specifications_range" as specifications_range { + *id: int auto_increment "PK" + -- + *hash: char(40) + *product_guid: char(36) + *guid: char(36) + *name: varchar(256) + *unit: varchar(256) + *description: text + *value_gte: float + *value_lte: float + *updated_at: timestamp + -- + unique (hash) + } + + entity "search_specifications_text" as specifications_text { + *id: int auto_increment "PK" + -- + *hash: char(40) + *product_guid: char(36) + *guid: char(36) + *name: varchar(256) + *unit: varchar(256) + *description: text + *value: varchar(256) + *updated_at: timestamp + -- + unique (hash) + } + entity "search_locality" as locality { + *id: mediumint(9) auto_increment "PK" + -- + *name: char(50) + *english_name: varchar(255) + *areg_id: char(36) + *is_enabled: tinyint(1) + } + + entity "search_dates_sync" as dates_sync { + *id: int auto_increment "PK" + -- + *is_successful tinyint(1) + *'system': text + *message: text + *date: datetime + } + + 'Связи + products -d----> specifications_bool + specifications_bool -r-> specifications_range + specifications_bool -r-> specifications_text + specifications_bool -r-> specifications_collection + specifications_bool -r-> specifications_int + specifications_bool -r-> specifications_float + 'products -d---> specifications_range + 'products -d---> specifications_text + 'products -d---> specifications_collection + 'products -d---> specifications_int + 'products -d---> specifications_float + + note left of specifications_bool: Все таблицы с тх связаны с \nтаблицей товаров по product_guid + products -l--> manufacturers + manufacturers -l-> manufacturers_settings + + prices_types_localities -> localities_offices + prices_types_products -> prices_types_localities + + products -d--> promotions + products -d--> availability + products -d--> search_check + products --> remaining + + + products -r--> relevancy_data_items + product_sale -> localities_offices + promotions -> localities_offices + + products -l--> prices_types_products + + products -u-> categories + products -> products_relevancy_counts + products -> product_sale + products -> products_sort_rating + + + categories -> categories_relationship + categories -> categories_settings + + products_categories -> products + products_categories -> categories + +} +@enduml diff --git a/search/WatsonWithMicroservices.puml b/search/WatsonWithMicroservices.puml new file mode 100644 index 0000000..32909ab --- /dev/null +++ b/search/WatsonWithMicroservices.puml @@ -0,0 +1,142 @@ +@startuml +skinparam linetype ortho +'============================================================================================ +'===========================================Микросервисы===================================== +'============================================================================================ +package Microservices <> { + abstract "Shcat" as shcat { + +request: POST + +endpoint: http://shcat.vseinstrumenti.ru/rpc + -- + *Method: rests.get + *nomenclature - guid товара + *source - guid магазина + -- + +response + -- + *nomenclature - guid товара + *source - guid офиса + *quntity - количество остатков + *quality - качество, по умолчанию 1 + } + + abstract "HamletX10" as hamlet { + +request: POST + +enpoint: http://hamlet-v2.vseinstrumenti.ru/rpc + -- + *Method: availability.chain + *store - guid офиса + *nomenclature - guid товара + *filter_zero_chain - скрывать или нет ЛЦ по которым нет наличия + -- + +response + -- + *available - Признак наличия + *store - guid офиса + *free - количество остатков + } + + abstract "Officer" as officer { + +request: POST + +endpoint: https://officer2go.vseinstrumenti.ru/query + -- + *Method: availability.get_offices + *locality_areg_id - areg_id города + -- + +response + -- + *id - guid офиса + *created_at - Дата создания + } + + abstract "Scrooge_sync" as scrooge { + +request: GET + +endpoint: http://exporter.scrooge-v2.vseinstrumenti.ru/file/price?after-id= + -- + +response + -- + *price + *price_type + } + + abstract "Scrooge_graphQL" as Scrooge_graphQL { + +request: POST + +endpoint: http://exporter.scrooge-v2.vseinstrumenti.ru/query + -- + *method: priceTypeBinding + -- + +response + -- + *priceTypeId + *priceCategory + *localityID + } +} + + +package MySql <> { + entity "search_availability_flag_{guid_office}" as availability { + * id : int auto_increment "PK" + -- + *product : char(36) + *is_availability : tinyint(1) + *create_at : timestamp + *update_at : timestamp + -- + unique (product) + } + + + entity "search_remaining_{guid_office}" as remaining { + * id: int auto_increment "PK" + -- + *product: char(36) + *remaining: int + *create_at: timestamp + *update_at: timestamp + -- + unique (product) + } + + entity "search_localities_offices" as localities_offices { + *id: int auto_increment "PK" + -- + *locality_guid: char(36) + *office_guid: char(36) + *is_active: tinyint(1) + -- + unique (office_guid) + } + + entity "search_prices_types_localities_2" as prices_types_localities { + *id: int auto_increment "PK" + -- + *hash: char(40) + *locality_guid: char(36) + *price_type_guid: char(36) + *type: varchar(128) + -- + unique (hash) + } + + + entity "search_prices_types_products_2" as prices_types_products { + *id: int auto_increment "PK" + -- + *hash: char(40) + *product_guid: char(36) + *price_type_guid: char(36) + *price: decimal(10, 2) + *updated_at: timestamp + -- + unique (hash) + } +} + + shcat -d-----> remaining + hamlet -d-----> availability + officer -d-----> localities_offices + scrooge -d-----> prices_types_products + Scrooge_graphQL -d--> prices_types_localities + +@enduml \ No newline at end of file diff --git a/search/WatsonWithPDM.puml b/search/WatsonWithPDM.puml new file mode 100644 index 0000000..8df3b3e --- /dev/null +++ b/search/WatsonWithPDM.puml @@ -0,0 +1,266 @@ +@startuml +skinparam linetype ortho +'=============================================================================== +'===================================PDM========================================= +'=============================================================================== +package PDM <> { + abstract ProductModuleName { + +request: GET + +endpoint: http://api.pdm.vseinstrumenti.ru/api/v1/products/* + +headers: Accept:application/json + Authorization:Bearer m1iXCmdwRlbqTU7gBCIe4Xpk8fIjVBGD + -- + *response: guid товара + -- + * - 2019-08-16 17:00:00 + } + + abstract CategoryModuleName { + +request: GET + +endpoint: http://api.pdm.vseinstrumenti.ru/api/v1/rubrics/* + +headers: Accept:application/json + Authorization:Bearer m1iXCmdwRlbqTU7gBCIe4Xpk8fIjVBGD + -- + *response: guid категории + -- + * - 2019-08-16 17:00:00 + } + + abstract ManufacturerModuleName { + +request: GET + +endpoint: http://api.pdm.vseinstrumenti.ru/api/v1/manufacturers/* + +headers: Accept:application/json + Authorization:Bearer m1iXCmdwRlbqTU7gBCIe4Xpk8fIjVBGD + -- + *response: guid производителя + -- + * - 2019-08-16 17:00:00 + } + + abstract SpecificationModuleName { + +request: GET + +endpoint: http://api.pdm.vseinstrumenti.ru/api/v1/tech_param/* + +headers: Accept:application/json + Authorization:Bearer m1iXCmdwRlbqTU7gBCIe4Xpk8fIjVBGD + -- + *response: guid изменившихся ТХ + -- + * - 2019-08-16 17:00:00 + } +} + +Package MySql <> { + package "Manufacter_MySql" <> { + entity "search_manufacturers_settings" as manufacturers_settings { + *id: int auto_increment "PK" + -- + *manufacturer_guid: char(36) + *locality_guid: char(36) + *is_hide: tinyint(1) + *updated_at: timestamp + *created_at: timestamp + -- + unique (manufacturer_guid, locality_guid) + } + + entity "search_manufacturers" as manufacturers { + *id: int auto_increment "PK" + -- + *guid: char(36) + *name: varchar(256) + *is_our: tinyint(1) + *description: varchar(256) + *updated_at: timestamp + -- + unique (guid) + } + } + + package "Products_MySql" <> { + entity "search_products" as products { + *id: int auto_increment "PK" + -- + *is_consumable: tinyint(1) + *is_on_site: tinyint(1) + *is_visible: tinyint(1) + *status: smallint + *is_discountinued: tinyint(1) + *is_for_order: tinyint(1) + *sku: int + *height: float + *lenght: float + *width: float + *guid: char(36) + *manufacter_guid: char(36) + *name_site: varchar(256) + *category: char(36) + *name_pdm: varchar(256) + *name_wtis: varchar(256) + *name_contractor: varchar(256) + *keywords: varchar(256) + *lights: varchar(20) + *country_code: varchar(3) + *uri: text + *advantages: text + *description: text + *equipment: text + *features: text + *updated_at: timestamp + -- + unique (guid) + } + + entity "search_products_categories" as products_categories { + *id: int auto_increment "PK" + -- + *hash: char(40) + *product_guid: char(36) + *category_guid: char(36) + *is_enabled: tinyint(1) + *updated_at: timestamp + -- + unique (hash) + } + } + + package "Categories_MySql" <> { + entity "search_categories_settings" as categories_settings { + *id: int auto_increment "PK" + -- + *category_guid: char(36) + *locality_guid: char(36) + *is_hide: tinyint(1) + *updated_at: timestamp + *created_at: timestamp + -- + unique (category_guid, locality_guid) + } + + entity "search_categories_relationship" as categories_relationship { + *id: int auto_increment "PK" + -- + *parent: char(36) + *child: char(36) + *main: tinyint(1) + *level: int + *line: int + *created_at: timestamp + } + + entity "search_categories" as categories { + *id: int auto_increment "PK" + -- + *guid: char(36) + name: varchar(256) + type: varchar(256) + parent_guid: char(36) + is_active: tinyint(1) + is_enable: tinyint(1) + up_caption: varchar(256) + updated_at: timestamp + -- + unique (guid) + } + } + + package PDM_Specifications <> { + entity "search_specifications_bool" as specifications_bool { + *id: int auto_increment "PK" + -- + *hash: char(40) + *product_guid: char(36) + *guid: char(36) + *name: varchar(256) + *unit: varchar(256) + *description: text + *value: tinyint(1) + *updated_at: timestamp + -- + unique (hash) + } + + entity "search_specifications_collection" as specifications_collection { + *id: int auto_increment "PK" + -- + *hash: char(40) + *product_guid: char(36) + *guid: char(36) + *name: varchar(256) + *unit: varchar(256) + *description: text + *value: varchar(256) + *value_guid: char(36) + *updated_at: timestamp + -- + unique (hash) + } + + entity "search_specifications_float" as specifications_float { + *id: int auto_increment "PK" + -- + *hash: char(40) + *product_guid: char(36) + *guid: char(36) + *name: varchar(256) + *unit: varchar(256) + *description: text + *value: float + *updated_at: timestamp + -- + unique (hash) + } + + entity "search_specifications_int" as specifications_int { + *id: int auto_increment "PK" + -- + *hash: char(40) + *product_guid: char(36) + *guid: char(36) + *name: varchar(256) + *unit: varchar(256) + *description: text + *value: int + *updated_at: timestamp + -- + unique (hash) + } + + entity "search_specifications_range" as specifications_range { + *id: int auto_increment "PK" + -- + *hash: char(40) + *product_guid: char(36) + *guid: char(36) + *name: varchar(256) + *unit: varchar(256) + *description: text + *value_gte: float + *value_lte: float + *updated_at: timestamp + -- + unique (hash) + } + + entity "search_specifications_text" as specifications_text { + *id: int auto_increment "PK" + -- + *hash: char(40) + *product_guid: char(36) + *guid: char(36) + *name: varchar(256) + *unit: varchar(256) + *description: text + *value: varchar(256) + *updated_at: timestamp + -- + unique (hash) + } + } +} + + SpecificationModuleName -up----> PDM_Specifications + ProductModuleName -up---> "Products_MySql" + CategoryModuleName -up----> "Categories_MySql" + ManufacturerModuleName -up---> "Manufacter_MySql" + +@enduml \ No newline at end of file diff --git a/search/WatsonWithSite.puml b/search/WatsonWithSite.puml new file mode 100644 index 0000000..7fe1a68 --- /dev/null +++ b/search/WatsonWithSite.puml @@ -0,0 +1,227 @@ +@startuml +skinparam linetype ortho + +'=============================================================================== +'=====================================Kafka===================================== +'=============================================================================== +package Site_kafka <> { + abstract promotions_kafka { + +Topics site.products.promotions + -- + *product_guid + *locality_guid + *promotions array[string] + } + abstract rnames_kafka { + + topics site.products.rname + -- + *url + *guid + } + abstract sale_kafka { + + site.products.sale + -- + *nomenclature_guid + *main_region_guid + *price + *clearance_sale_guid + *quantity_left + *status + } + abstract tagpage_delete_kafka { + + topics site.tagpage.delete + -- + *id + } + abstract tagpage_status_kafka { + + topics site.tagpage.status + -- + *id + *name + *is_active + *is_enable + } + + abstract makes_visibility_kafka { + + topics site.make.visibility + -- + *visibility + *makeGuid + *localities + } + abstract categories_visibility_kafka { + + topics site.categories.visibility + -- + *visibility + *values map[string] + *items array[string] + } + abstract up_caption_kafka { + + topics site.categories.up_caption + -- + *guid + *up_caption + } + abstract relevancy_kafka { + + topics site.products.relevancy + -- + *guid + *orders + *views + *rating + *reviews + *data [array] - массив данных + *[array].category + *[array].manufacturer + *[array].seo_position + *[array].koef_sort + } +} + + package "MySql" <> { + entity "search_products" as products { + *id: int auto_increment "PK" + -- + *is_consumable: tinyint(1) + *is_on_site: tinyint(1) + *is_visible: tinyint(1) + *status: smallint + *is_discountinued: tinyint(1) + *is_for_order: tinyint(1) + *sku: int + *height: float + *lenght: float + *width: float + *guid: char(36) + *manufacter_guid: char(36) + *name_site: varchar(256) + *category: char(36) + *name_pdm: varchar(256) + *name_wtis: varchar(256) + *name_contractor: varchar(256) + *keywords: varchar(256) + *lights: varchar(20) + *country_code: varchar(3) + *uri: text + *advantages: text + *description: text + *equipment: text + *features: text + *updated_at: timestamp + -- + unique (guid) + } + + entity "search_manufacturers_settings" as manufacturers_settings { + *id: int auto_increment "PK" + -- + *manufacturer_guid: char(36) + *locality_guid: char(36) + *is_hide: tinyint(1) + *updated_at: timestamp + *created_at: timestamp + -- + unique (manufacturer_guid, locality_guid) + } + + entity "search_categories_settings" as categories_settings { + *id: int auto_increment "PK" + -- + *category_guid: char(36) + *locality_guid: char(36) + *is_hide: tinyint(1) + *updated_at: timestamp + *created_at: timestamp + -- + unique (category_guid, locality_guid) + } + + entity "search_categories" as categories { + *id: int auto_increment "PK" + -- + *guid: char(36) + name: varchar(256) + type: varchar(256) + parent_guid: char(36) + is_active: tinyint(1) + is_enable: tinyint(1) + up_caption: varchar(256) + updated_at: timestamp + -- + unique (guid) + } + + entity "search_products_relevancy_counts" as products_relevancy_counts { + *id: bigint: auto_increment "PK" + -- + *product_guid: char(36) + *orders: int(11) + *views: int(11) + *reviews: int(11) + *updated_at: timestamp + -- + unique (product_guid) + } + + entity "search_products_relevancy_data_items" as relevancy_data_items { + *id: bigint: auto_increment "PK" + -- + *hash: char(40) + *product_guid: char(36) + *manufacter_guid: char(36) + *seo_position: int + *koef_sort: float + *updated_at: timestamp + -- + unique (hash) + } + + entity "search_products_sort_rating" as products_sort_rating { + *id: bigint: auto_increment "PK" + -- + *product_guid: char(36) + *rating: float + *updated_at: timestamp + -- + unique (product_guid) + } + + + entity "search_products_sale" as product_sale { + *id: bigint: auto_increment "PK" + -- + *hash: char(40) + *guid: char(36) + *product_guid: char(36) + *locality_guid: char(36) + remaining: int + price: float + updated_at: timestamp + -- + unique (hash) + } + + entity "search_promotions" as promotions { + *id: int: auto_increment "PK" + -- + *product_guid: char(36) + *locality_guid char(36) + *name: varchar(256) + *updated_at: timestamp + } + + } + + relevancy_kafka -d--> products_relevancy_counts + relevancy_kafka -d--> relevancy_data_items: data [array] + relevancy_kafka -d--> products_sort_rating: rating + rnames_kafka -d----> products + sale_kafka -d--> product_sale + promotions_kafka -d--> promotions + tagpage_status_kafka -d--> categories + tagpage_delete_kafka -d--> categories + makes_visibility_kafka -d--> manufacturers_settings + categories_visibility_kafka -d--> categories_settings + up_caption_kafka -d--> categories + +@enduml \ No newline at end of file diff --git a/search/Общий процесс autocomplete.puml b/search/Общий процесс autocomplete.puml new file mode 100644 index 0000000..b8dd9b0 --- /dev/null +++ b/search/Общий процесс autocomplete.puml @@ -0,0 +1,68 @@ +@startuml +mainframe api/v1/autocomplete Общая схема +Actor user +participant BackendSite +participant Sherlock +Database ElasticSearch + +user -> BackendSite: Вводит запрос в поисковую строку +BackendSite -> BackendSite: Обработка запроса на бэкенде\n сайта и формирование запроса\nдля Sherlock +BackendSite -> Sherlock: REST POST api/v1/autocomplete +Sherlock -> Sherlock: Перевод запроса\nна второй язык +Sherlock -> Sherlock: Преобразование запроса\n в структуру и формирование\nзапроса для ElasticSearch + + note over Sherlock + Отправка запроса в + ElasticSearch с доп + сортировкой по категориям + из Спектра + endnote + + +alt ElasticSearch ничего не вернул +Sherlock -> ElasticSearch: 8 запросов в 4 индекса: manufacturers,\ntagpage, categories, products на двух языках (RU, EN) +ElasticSearch --> Sherlock: Получен пустой ответ со всех 8-и запросов + + note over Sherlock + Отправляются доп.запрос + в ElasticSearch с меньшим + процентом вхождения + endnote + +Sherlock -> ElasticSearch: 8 запросов в 4 индекса: manufacturers,\ntagpage, categories, products на двух языках (RU, EN) +ElasticSearch --> Sherlock: Получен пустой ответ со всех 8-и запросов + +Sherlock --> BackendSite: Получен пустой ответ +Sherlock --> user: Пользователь получает страницу:\nРезультаты не найдены + +else Найдены товары + + +alt Есть товары спектр + note over ElasticSearch + ЕСЛИ хоть один из четырех индексов + отдал ответ, ТО он отдается на бэкенд + endnote + +Sherlock -> ElasticSearch: 8 запросов в 4 индекса: manufacturers,\ntagpage, categories, products на двух языках (RU, EN) + + note over ElasticSearch + Категории спектр поднимаются + наверх И товары внутри них + сортируются по скорингу + endnote + +else Товаров спектр не найдено +Sherlock -> ElasticSearch: 8 запросов в 4 индекса: manufacturers,\ntagpage, categories, products на двух языках (RU, EN) + note over ElasticSearch + Товары сортируются + по скорингу + endnote +end + +ElasticSearch --> Sherlock: Передает отсортированный\nсписок товаров +Sherlock --> BackendSite: Список товаров +BackendSite --> user: Пользователь получает страницу:\nРезультаты поиска + +end +@enduml \ No newline at end of file diff --git a/search/Общий процесс filters.puml b/search/Общий процесс filters.puml new file mode 100644 index 0000000..aebdd95 --- /dev/null +++ b/search/Общий процесс filters.puml @@ -0,0 +1,55 @@ +@startuml +mainframe api/v1/filters Общая схема +Actor user +participant BackendSite +participant Sherlock +Database ElasticSearch + +user -> BackendSite: Вводит запрос в поисковую строку +BackendSite -> BackendSite: Обработка запроса на бэкенде\n сайта и формирование запроса\nдля Sherlock + +BackendSite -> Sherlock: REST POST api/v1/filters +Sherlock -> Sherlock: Преобразование запроса\nв структуру и формирование\nзапроса для ElasticSearch + + note over Sherlock + Отправка запроса в + ElasticSearch с доп + сортировкой по категориям + из Спектра + endnote + + +alt ElasticSearch ничего не вернул +Sherlock -> ElasticSearch: REST GET products/_search +ElasticSearch --> Sherlock: Получен пустой ответ + + note over Sherlock + Отправляется доп.запрос + в ElasticSearch с меньшим + процентом вхождения + endnote + +Sherlock -> ElasticSearch: REST GET products/_search +ElasticSearch --> Sherlock: Получен пустой ответ +Sherlock --> BackendSite: Получен пустой ответ +Sherlock --> user: Пользователь получает страницу:\nРезультаты не найдены + +else Найдены товары +alt Есть товары спектр +Sherlock -> ElasticSearch: REST GET products/_search + note over ElasticSearch + Категории спектр + поднимаются наверх + endnote +else Товаров спектр не найдено +Sherlock -> ElasticSearch: REST GET products/_search +end + +ElasticSearch --> Sherlock: Передает список\nкатегорий и фильтров + +Sherlock --> BackendSite: Список категорий и фильтров + +BackendSite --> user: Пользователь получает фильтры\nна странице: Результаты поиска + +end +@enduml \ No newline at end of file diff --git a/search/Общий процесс products.puml b/search/Общий процесс products.puml new file mode 100644 index 0000000..0e2f04b --- /dev/null +++ b/search/Общий процесс products.puml @@ -0,0 +1,64 @@ +@startuml +mainframe api/v1/products Общая схема +Actor user +participant BackendSite +participant Sherlock +Database ElasticSearch + +user -> BackendSite: Вводит запрос в поисковую строку +BackendSite -> BackendSite: Обработка запроса на бэкенде\n сайта и формирование запроса\nдля Sherlock +BackendSite -> Sherlock: REST POST api/v1/products +Sherlock -> Sherlock: Перевод запроса\nна второй язык +Sherlock -> Sherlock: Преобразование запроса\n в структуру и формирование\nзапроса для ElasticSearch + + note over Sherlock + Отправка запроса в + ElasticSearch с доп + сортировкой по категориям + из Спектра + endnote + +alt ElasticSearch ничего не вернул +Sherlock -> ElasticSearch: REST GET products/_search RU +Sherlock -> ElasticSearch: REST GET products/_search EN +ElasticSearch --> Sherlock: Получен пустой ответ + + note over Sherlock + Отправляется доп.запрос + в ElasticSearch с меньшим + процентом вхождения + endnote + +Sherlock -> ElasticSearch: REST GET products/_search RU +Sherlock -> ElasticSearch: REST GET products/_search EN +ElasticSearch --> Sherlock: Получен пустой ответ +Sherlock --> BackendSite: Получен пустой ответ +Sherlock --> user: Пользователь получает страницу:\nРезультаты не найдены + +else Найдены товары + +alt Есть товары спектр +Sherlock -> ElasticSearch: REST GET products/_search RU +Sherlock -> ElasticSearch: REST GET products/_search EN + note over ElasticSearch + Категории спектр поднимаются + наверх И товары внутри них + сортируются по скорингу + endnote + +else Товаров спектр не найдено + +Sherlock -> ElasticSearch: REST GET products/_search RU +Sherlock -> ElasticSearch: REST GET products/_search EN + note over ElasticSearch + Товары сортируются + по скорингу + endnote +end + +ElasticSearch --> Sherlock: Передает отсортированный\nсписок товаров +Sherlock --> BackendSite: Список товаров +BackendSite --> user: Пользователь получает страницу:\nРезультаты поиска + +end +@enduml \ No newline at end of file diff --git a/search/Схема поиск.png b/search/Схема поиск.png new file mode 100644 index 0000000000000000000000000000000000000000..3b90b78394fad85328377c433cf437567700f118 GIT binary patch literal 28585 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 aG6tWmB9TVIe(x{WtthW5SNYOB@P7acxC-(B literal 0 HcmV?d00001 diff --git a/shipment.puml b/shipment.puml new file mode 100644 index 0000000..b2edf9b --- /dev/null +++ b/shipment.puml @@ -0,0 +1,32 @@ +@startjson +{ + "ShipmentDoc":{ + "ShipmentMeta":{ + "id":"uuid || Идентификатор доставки", + "OrderID":"uuid || Идентификатор заказа", + "MethodId":"int(enum) || Способы доставки", + "DeliveryDate":"datetime || Дата доставки", + "Services":{ + "Settings":{ + "SpreadExtraCost":"bool || Размазать стоимость доставки по товарам связанным с доставкой" + } + }, + "CreatedAt":"datetime || Дата создания доставки", + "UpdatedAt":"datetime || Дата обновления доставки", + "Artifact": { + "DeliveryWith":"string || Начальный временной промежуток курьерской доставки", + "TrackingNumberId":"int || Удалить, бесполезное поле", + "PartnerDeliverTo":"string || ??? ", + "DestinationOfficeID":"int || Идентификатор офиса, откуда везем товар", + "DeliveryOn":"string || Верхняя граница часов доставки ", + "DeliveryType":"bool || - обычная доставка 1 - доставка строительных материалов", + "DeliveryZone":"int || id зоны доставки строительных материалов из таблицы wtis_ref_town_zone ", + "VeerouteExportDate":"datetime || Дата выгрузки в Veeroute ", + "AddressID":"int || Идентификатор адреса доставки (внутренний от WTIS) " + } + }, + "": { + } + } + } +@endjson \ No newline at end of file