Добавлен архитектурный скетч
This commit is contained in:
635
C4-Architecture.md
Normal file
635
C4-Architecture.md
Normal file
@ -0,0 +1,635 @@
|
|||||||
|
[Назад](/README.md)
|
||||||
|
|
||||||
|
# C4 Architecture Diagrams - TaskManager
|
||||||
|
|
||||||
|
## Содержание
|
||||||
|
1. [Level 1: System Context](#level-1-system-context)
|
||||||
|
2. [Level 2: Container Diagram](#level-2-container-diagram)
|
||||||
|
3. [Level 3: Component Diagram - Tasks Service](#level-3-component-diagram---tasks-service)
|
||||||
|
4. [Level 3: Component Diagram - Adapter Layer](#level-3-component-diagram---adapter-layer)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Level 1: System Context
|
||||||
|
|
||||||
|
Показывает TaskManager в контексте пользователей и внешних систем.
|
||||||
|
|
||||||
|
```mermaid
|
||||||
|
C4Context
|
||||||
|
title System Context diagram for TaskManager
|
||||||
|
|
||||||
|
Person(hotel_staff, "Hotel Staff", "Сотрудники отеля (горничные, техники, менеджеры)")
|
||||||
|
Person(admin, "System Admin", "Администратор системы")
|
||||||
|
Person(guest, "Hotel Guest", "Гость отеля")
|
||||||
|
|
||||||
|
System(taskmanager, "TaskManager", "Платформа для управления задачами между подразделениями отеля и интеграции с внешними системами")
|
||||||
|
|
||||||
|
System_Ext(pms, "PMS System", "Система управления отелем (Opera, Fidelio)")
|
||||||
|
System_Ext(erp, "ERP System", "Система управления ресурсами")
|
||||||
|
System_Ext(housekeeping, "Housekeeping App", "Приложение для управления уборкой")
|
||||||
|
System_Ext(email, "Email System", "SMTP сервер для отправки email")
|
||||||
|
System_Ext(sms, "SMS Gateway", "Сервис отправки SMS (Twilio)")
|
||||||
|
System_Ext(telegram, "Telegram", "Telegram Bot API")
|
||||||
|
System_Ext(s3, "AWS S3", "Хранилище файлов")
|
||||||
|
|
||||||
|
Rel(hotel_staff, taskmanager, "Создает и управляет задачами", "Web/Mobile")
|
||||||
|
Rel(admin, taskmanager, "Настраивает систему, связи, роли", "Web Admin")
|
||||||
|
Rel(guest, taskmanager, "Создает запросы на обслуживание", "Telegram Bot")
|
||||||
|
|
||||||
|
Rel(taskmanager, pms, "Получает/отправляет данные о бронированиях, номерах", "REST API/Webhook")
|
||||||
|
Rel(taskmanager, erp, "Интегрируется с учетом ресурсов", "REST API")
|
||||||
|
Rel(taskmanager, housekeeping, "Отправляет задачи на уборку", "REST API/Push")
|
||||||
|
Rel(taskmanager, email, "Отправляет уведомления", "SMTP")
|
||||||
|
Rel(taskmanager, sms, "Отправляет SMS уведомления", "REST API")
|
||||||
|
Rel(taskmanager, telegram, "Получает запросы гостей, отправляет уведомления", "Webhook/Bot API")
|
||||||
|
Rel(taskmanager, s3, "Хранит файлы и фото", "S3 API")
|
||||||
|
|
||||||
|
UpdateLayoutConfig($c4ShapeInRow="3", $c4BoundaryInRow="2")
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Level 2: Container Diagram
|
||||||
|
|
||||||
|
Показывает основные контейнеры (приложения и хранилища данных) внутри TaskManager.
|
||||||
|
|
||||||
|
```mermaid
|
||||||
|
C4Container
|
||||||
|
title Container diagram for TaskManager
|
||||||
|
|
||||||
|
Person(hotel_staff, "Hotel Staff", "Сотрудники отеля")
|
||||||
|
Person(admin, "System Admin", "Администратор системы")
|
||||||
|
Person(guest, "Hotel Guest", "Гость отеля")
|
||||||
|
|
||||||
|
System_Ext(pms, "PMS System", "Opera/Fidelio")
|
||||||
|
System_Ext(erp, "ERP System", "ERP")
|
||||||
|
System_Ext(housekeeping_ext, "Housekeeping App", "External App")
|
||||||
|
System_Ext(email_ext, "Email System", "SMTP")
|
||||||
|
System_Ext(sms_ext, "SMS Gateway", "Twilio")
|
||||||
|
System_Ext(telegram_ext, "Telegram", "Bot API")
|
||||||
|
System_Ext(s3_ext, "AWS S3", "File Storage")
|
||||||
|
|
||||||
|
Container_Boundary(taskmanager, "TaskManager System") {
|
||||||
|
|
||||||
|
Container(web_admin, "Web Admin", "React, TypeScript", "Веб-приложение для настройки системы и управления")
|
||||||
|
Container(mobile_app, "Mobile App", "React Native/Flutter", "Мобильное приложение для сотрудников")
|
||||||
|
|
||||||
|
Container(api_gateway, "API Gateway", "Kong/Envoy", "Единая точка входа, маршрутизация, аутентификация")
|
||||||
|
|
||||||
|
Container(tasks_service, "Tasks Service", "Python, FastAPI, gRPC", "Управление задачами")
|
||||||
|
Container(connections_service, "Connections Service", "Python, FastAPI, gRPC", "Управление связями между адаптерами")
|
||||||
|
Container(users_service, "Users Service", "Python, FastAPI, gRPC", "Управление пользователями")
|
||||||
|
Container(permissions_service, "Permissions Service", "Python, FastAPI, gRPC", "Управление ролями и правами (RBAC)")
|
||||||
|
Container(notification_service, "Notification Service", "Python, FastAPI", "Отправка уведомлений через разные каналы")
|
||||||
|
Container(file_storage_service, "File Storage Service", "Python, FastAPI", "Управление файлами")
|
||||||
|
Container(audit_service, "Audit Service", "Python, FastAPI", "Логирование всех действий")
|
||||||
|
Container(scheduler_service, "Scheduler Service", "Python, FastAPI", "Управление периодическими задачами")
|
||||||
|
Container(events_service, "Events Service", "Python, FastAPI, gRPC", "Управление мероприятиями")
|
||||||
|
|
||||||
|
Container(pms_adapter, "PMS Adapter", "Python", "Адаптер для PMS системы")
|
||||||
|
Container(erp_adapter, "ERP Adapter", "Python", "Адаптер для ERP системы")
|
||||||
|
Container(housekeeping_adapter, "Housekeeping Adapter", "Python", "Адаптер для приложения уборки")
|
||||||
|
Container(telegram_adapter, "Telegram Bot Adapter", "Python", "Адаптер для Telegram бота")
|
||||||
|
|
||||||
|
ContainerQueue(kafka, "Message Broker", "Apache Kafka", "Асинхронная коммуникация между сервисами")
|
||||||
|
|
||||||
|
ContainerDb(postgres, "Database", "PostgreSQL", "Хранение данных системы")
|
||||||
|
ContainerDb(redis, "Cache", "Redis", "Кэширование данных, сессии")
|
||||||
|
}
|
||||||
|
|
||||||
|
Rel(hotel_staff, web_admin, "Использует", "HTTPS")
|
||||||
|
Rel(hotel_staff, mobile_app, "Использует", "HTTPS")
|
||||||
|
Rel(admin, web_admin, "Настраивает систему", "HTTPS")
|
||||||
|
Rel(guest, telegram_adapter, "Отправляет запросы", "Telegram")
|
||||||
|
|
||||||
|
Rel(web_admin, api_gateway, "Делает API запросы", "REST/gRPC-Web")
|
||||||
|
Rel(mobile_app, api_gateway, "Делает API запросы", "REST/gRPC")
|
||||||
|
|
||||||
|
Rel(api_gateway, tasks_service, "Маршрутизирует запросы", "gRPC")
|
||||||
|
Rel(api_gateway, users_service, "Маршрутизирует запросы", "gRPC")
|
||||||
|
Rel(api_gateway, connections_service, "Маршрутизирует запросы", "gRPC")
|
||||||
|
Rel(api_gateway, events_service, "Маршрутизирует запросы", "gRPC")
|
||||||
|
Rel(api_gateway, file_storage_service, "Маршрутизирует запросы", "REST")
|
||||||
|
|
||||||
|
Rel(tasks_service, kafka, "Публикует события", "Kafka Protocol")
|
||||||
|
Rel(connections_service, kafka, "Публикует/читает события", "Kafka Protocol")
|
||||||
|
Rel(scheduler_service, kafka, "Публикует триггеры", "Kafka Protocol")
|
||||||
|
Rel(events_service, kafka, "Публикует события", "Kafka Protocol")
|
||||||
|
Rel(notification_service, kafka, "Читает события", "Kafka Protocol")
|
||||||
|
Rel(audit_service, kafka, "Читает все события", "Kafka Protocol")
|
||||||
|
|
||||||
|
Rel(tasks_service, permissions_service, "Проверяет права", "gRPC")
|
||||||
|
Rel(users_service, permissions_service, "Проверяет права", "gRPC")
|
||||||
|
|
||||||
|
Rel(pms_adapter, kafka, "Публикует сообщения", "Kafka Protocol")
|
||||||
|
Rel(erp_adapter, kafka, "Публикует сообщения", "Kafka Protocol")
|
||||||
|
Rel(housekeeping_adapter, kafka, "Публикует сообщения", "Kafka Protocol")
|
||||||
|
Rel(telegram_adapter, kafka, "Публикует сообщения", "Kafka Protocol")
|
||||||
|
|
||||||
|
Rel(pms_adapter, pms, "Получает/отправляет данные", "REST API/Webhook")
|
||||||
|
Rel(erp_adapter, erp, "Получает/отправляет данные", "REST API")
|
||||||
|
Rel(housekeeping_adapter, housekeeping_ext, "Отправляет задачи", "REST API/Push")
|
||||||
|
Rel(telegram_adapter, telegram_ext, "Взаимодействует с ботом", "Webhook/Bot API")
|
||||||
|
|
||||||
|
Rel(notification_service, email_ext, "Отправляет email", "SMTP")
|
||||||
|
Rel(notification_service, sms_ext, "Отправляет SMS", "REST API")
|
||||||
|
Rel(notification_service, telegram_ext, "Отправляет сообщения", "Bot API")
|
||||||
|
|
||||||
|
Rel(file_storage_service, s3_ext, "Хранит файлы", "S3 API")
|
||||||
|
|
||||||
|
Rel(tasks_service, postgres, "Читает/пишет данные", "SQL")
|
||||||
|
Rel(users_service, postgres, "Читает/пишет данные", "SQL")
|
||||||
|
Rel(connections_service, postgres, "Читает/пишет данные", "SQL")
|
||||||
|
Rel(permissions_service, postgres, "Читает/пишет данные", "SQL")
|
||||||
|
Rel(scheduler_service, postgres, "Читает/пишет данные", "SQL")
|
||||||
|
Rel(events_service, postgres, "Читает/пишет данные", "SQL")
|
||||||
|
Rel(audit_service, postgres, "Пишет логи", "SQL")
|
||||||
|
Rel(file_storage_service, postgres, "Пишет метаданные", "SQL")
|
||||||
|
|
||||||
|
Rel(tasks_service, redis, "Кэширует данные", "Redis Protocol")
|
||||||
|
Rel(users_service, redis, "Кэширует данные", "Redis Protocol")
|
||||||
|
Rel(permissions_service, redis, "Кэширует права", "Redis Protocol")
|
||||||
|
|
||||||
|
UpdateLayoutConfig($c4ShapeInRow="4", $c4BoundaryInRow="2")
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Level 3: Component Diagram - Tasks Service
|
||||||
|
|
||||||
|
Показывает внутреннюю структуру Tasks Service.
|
||||||
|
|
||||||
|
```mermaid
|
||||||
|
C4Component
|
||||||
|
title Component diagram for Tasks Service
|
||||||
|
|
||||||
|
Container_Ext(api_gateway, "API Gateway", "Kong/Envoy", "Точка входа")
|
||||||
|
Container_Ext(kafka, "Kafka", "Apache Kafka", "Message Broker")
|
||||||
|
ContainerDb_Ext(postgres, "PostgreSQL", "Database", "Основная БД")
|
||||||
|
ContainerDb_Ext(redis, "Redis", "Cache", "Кэш")
|
||||||
|
Container_Ext(permissions_service, "Permissions Service", "Python, gRPC", "Проверка прав")
|
||||||
|
Container_Ext(file_storage_service, "File Storage Service", "Python", "Управление файлами")
|
||||||
|
|
||||||
|
Container_Boundary(tasks_service, "Tasks Service") {
|
||||||
|
|
||||||
|
Component(grpc_api, "gRPC API", "Python, gRPC", "Обработка gRPC запросов")
|
||||||
|
Component(rest_api, "REST API", "FastAPI", "Обработка REST запросов (fallback)")
|
||||||
|
|
||||||
|
Component(task_controller, "Task Controller", "Python", "Обработка бизнес-логики задач")
|
||||||
|
Component(status_controller, "Status Controller", "Python", "Управление статусами задач")
|
||||||
|
Component(dependency_controller, "Dependency Controller", "Python", "Управление зависимостями")
|
||||||
|
Component(history_controller, "History Controller", "Python", "Управление историей изменений")
|
||||||
|
|
||||||
|
Component(task_repository, "Task Repository", "SQLAlchemy", "Работа с БД задач")
|
||||||
|
Component(status_repository, "Status Repository", "SQLAlchemy", "Работа с БД статусов")
|
||||||
|
Component(dependency_repository, "Dependency Repository", "SQLAlchemy", "Работа с БД зависимостей")
|
||||||
|
Component(history_repository, "History Repository", "SQLAlchemy", "Работа с БД истории")
|
||||||
|
|
||||||
|
Component(kafka_producer, "Kafka Producer", "aiokafka", "Публикация событий в Kafka")
|
||||||
|
Component(kafka_consumer, "Kafka Consumer", "aiokafka", "Чтение событий из Kafka")
|
||||||
|
|
||||||
|
Component(cache_manager, "Cache Manager", "Redis Client", "Управление кэшем")
|
||||||
|
Component(permission_client, "Permission Client", "gRPC Client", "Проверка прав доступа")
|
||||||
|
|
||||||
|
Component(task_validator, "Task Validator", "Pydantic", "Валидация данных задач")
|
||||||
|
Component(event_mapper, "Event Mapper", "Python", "Маппинг событий")
|
||||||
|
}
|
||||||
|
|
||||||
|
Rel(api_gateway, grpc_api, "Отправляет gRPC запросы", "gRPC")
|
||||||
|
Rel(api_gateway, rest_api, "Отправляет REST запросы", "HTTP/JSON")
|
||||||
|
|
||||||
|
Rel(grpc_api, task_controller, "Вызывает методы")
|
||||||
|
Rel(rest_api, task_controller, "Вызывает методы")
|
||||||
|
|
||||||
|
Rel(task_controller, task_validator, "Валидирует данные")
|
||||||
|
Rel(task_controller, permission_client, "Проверяет права")
|
||||||
|
Rel(task_controller, task_repository, "Работает с задачами")
|
||||||
|
Rel(task_controller, status_controller, "Изменяет статусы")
|
||||||
|
Rel(task_controller, dependency_controller, "Управляет зависимостями")
|
||||||
|
Rel(task_controller, history_controller, "Записывает историю")
|
||||||
|
Rel(task_controller, cache_manager, "Кэширует данные")
|
||||||
|
Rel(task_controller, kafka_producer, "Публикует события")
|
||||||
|
|
||||||
|
Rel(status_controller, status_repository, "Работает со статусами")
|
||||||
|
Rel(dependency_controller, dependency_repository, "Работает с зависимостями")
|
||||||
|
Rel(history_controller, history_repository, "Работает с историей")
|
||||||
|
|
||||||
|
Rel(kafka_consumer, event_mapper, "Маппит события")
|
||||||
|
Rel(event_mapper, task_controller, "Обрабатывает события")
|
||||||
|
|
||||||
|
Rel(task_repository, postgres, "Выполняет SQL запросы", "SQL")
|
||||||
|
Rel(status_repository, postgres, "Выполняет SQL запросы", "SQL")
|
||||||
|
Rel(dependency_repository, postgres, "Выполняет SQL запросы", "SQL")
|
||||||
|
Rel(history_repository, postgres, "Выполняет SQL запросы", "SQL")
|
||||||
|
|
||||||
|
Rel(cache_manager, redis, "Кэширует/читает данные", "Redis Protocol")
|
||||||
|
Rel(permission_client, permissions_service, "Проверяет права", "gRPC")
|
||||||
|
|
||||||
|
Rel(kafka_producer, kafka, "Публикует события", "Kafka Protocol")
|
||||||
|
Rel(kafka_consumer, kafka, "Читает события", "Kafka Protocol")
|
||||||
|
|
||||||
|
UpdateLayoutConfig($c4ShapeInRow="3", $c4BoundaryInRow="1")
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Level 3: Component Diagram - Adapter Layer
|
||||||
|
|
||||||
|
Показывает внутреннюю структуру адаптера (на примере PMS Adapter).
|
||||||
|
|
||||||
|
```mermaid
|
||||||
|
C4Component
|
||||||
|
title Component diagram for PMS Adapter (Example)
|
||||||
|
|
||||||
|
System_Ext(pms_system, "PMS System", "Opera/Fidelio", "Внешняя PMS система")
|
||||||
|
Container_Ext(kafka, "Kafka", "Apache Kafka", "Message Broker")
|
||||||
|
Container_Ext(postgres, "PostgreSQL", "Database", "Хранение состояния адаптера")
|
||||||
|
|
||||||
|
Container_Boundary(pms_adapter, "PMS Adapter") {
|
||||||
|
|
||||||
|
Component(webhook_handler, "Webhook Handler", "FastAPI", "Принимает webhook от PMS")
|
||||||
|
Component(api_poller, "API Poller", "Python, APScheduler", "Опрашивает PMS API по расписанию")
|
||||||
|
Component(rest_client, "REST Client", "httpx", "HTTP клиент для PMS API")
|
||||||
|
|
||||||
|
Component(inbound_transformer, "Inbound Transformer", "Python", "PMS формат → Стандартный формат")
|
||||||
|
Component(outbound_transformer, "Outbound Transformer", "Python", "Стандартный формат → PMS формат")
|
||||||
|
|
||||||
|
Component(message_validator, "Message Validator", "Pydantic", "Валидация сообщений")
|
||||||
|
Component(event_publisher, "Event Publisher", "aiokafka", "Публикация событий в Kafka")
|
||||||
|
Component(event_consumer, "Event Consumer", "aiokafka", "Чтение событий из Kafka")
|
||||||
|
|
||||||
|
Component(state_manager, "State Manager", "SQLAlchemy", "Управление состоянием синхронизации")
|
||||||
|
Component(error_handler, "Error Handler", "Python", "Обработка ошибок и retry")
|
||||||
|
Component(config_manager, "Config Manager", "Python", "Управление конфигурацией")
|
||||||
|
}
|
||||||
|
|
||||||
|
Rel(pms_system, webhook_handler, "Отправляет webhook", "HTTP/JSON")
|
||||||
|
Rel(api_poller, rest_client, "Запрашивает данные")
|
||||||
|
Rel(rest_client, pms_system, "Делает API запросы", "REST/SOAP")
|
||||||
|
|
||||||
|
Rel(webhook_handler, inbound_transformer, "Передает данные")
|
||||||
|
Rel(api_poller, inbound_transformer, "Передает данные")
|
||||||
|
|
||||||
|
Rel(inbound_transformer, message_validator, "Валидирует сообщение")
|
||||||
|
Rel(message_validator, event_publisher, "Публикует валидное событие")
|
||||||
|
|
||||||
|
Rel(event_consumer, kafka, "Читает исходящие события", "Kafka Protocol")
|
||||||
|
Rel(event_consumer, outbound_transformer, "Передает событие")
|
||||||
|
Rel(outbound_transformer, rest_client, "Отправляет в PMS")
|
||||||
|
|
||||||
|
Rel(event_publisher, kafka, "Публикует входящие события", "Kafka Protocol")
|
||||||
|
|
||||||
|
Rel(state_manager, postgres, "Сохраняет состояние", "SQL")
|
||||||
|
Rel(error_handler, state_manager, "Логирует ошибки")
|
||||||
|
|
||||||
|
Rel(webhook_handler, error_handler, "Обрабатывает ошибки")
|
||||||
|
Rel(api_poller, error_handler, "Обрабатывает ошибки")
|
||||||
|
Rel(rest_client, error_handler, "Обрабатывает ошибки")
|
||||||
|
|
||||||
|
Rel(config_manager, api_poller, "Предоставляет конфигурацию")
|
||||||
|
Rel(config_manager, rest_client, "Предоставляет конфигурацию")
|
||||||
|
|
||||||
|
UpdateLayoutConfig($c4ShapeInRow="3", $c4BoundaryInRow="1")
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Deployment Diagram (Kubernetes)
|
||||||
|
|
||||||
|
Показывает развертывание в Kubernetes кластере.
|
||||||
|
|
||||||
|
```mermaid
|
||||||
|
C4Deployment
|
||||||
|
title Deployment Diagram for TaskManager (Kubernetes)
|
||||||
|
|
||||||
|
Deployment_Node(k8s_cluster, "Kubernetes Cluster", "GKE/EKS/AKS") {
|
||||||
|
|
||||||
|
Deployment_Node(ingress_ns, "Namespace: ingress") {
|
||||||
|
Container(ingress, "Ingress Controller", "NGINX/Traefik", "Входная точка для внешнего трафика")
|
||||||
|
}
|
||||||
|
|
||||||
|
Deployment_Node(gateway_ns, "Namespace: gateway") {
|
||||||
|
Container(api_gateway, "API Gateway", "Kong/Envoy", "3 replicas", "Маршрутизация и аутентификация")
|
||||||
|
}
|
||||||
|
|
||||||
|
Deployment_Node(services_ns, "Namespace: services") {
|
||||||
|
Container(tasks_svc, "Tasks Service", "Python, FastAPI", "5 replicas", "Управление задачами")
|
||||||
|
Container(users_svc, "Users Service", "Python, FastAPI", "3 replicas", "Управление пользователями")
|
||||||
|
Container(connections_svc, "Connections Service", "Python, FastAPI", "2 replicas", "Управление связями")
|
||||||
|
Container(permissions_svc, "Permissions Service", "Python, FastAPI", "3 replicas", "RBAC")
|
||||||
|
Container(notification_svc, "Notification Service", "Python, FastAPI", "3 replicas", "Уведомления")
|
||||||
|
Container(file_storage_svc, "File Storage Service", "Python, FastAPI", "2 replicas", "Файлы")
|
||||||
|
Container(audit_svc, "Audit Service", "Python, FastAPI", "2 replicas", "Аудит")
|
||||||
|
Container(scheduler_svc, "Scheduler Service", "Python, FastAPI", "1 replica", "Планировщик")
|
||||||
|
Container(events_svc, "Events Service", "Python, FastAPI", "2 replicas", "Мероприятия")
|
||||||
|
}
|
||||||
|
|
||||||
|
Deployment_Node(adapters_ns, "Namespace: adapters") {
|
||||||
|
Container(pms_adapter, "PMS Adapter", "Python", "2 replicas", "PMS интеграция")
|
||||||
|
Container(erp_adapter, "ERP Adapter", "Python", "1 replica", "ERP интеграция")
|
||||||
|
Container(housekeeping_adapter, "Housekeeping Adapter", "Python", "2 replicas", "Уборка")
|
||||||
|
Container(telegram_adapter, "Telegram Adapter", "Python", "2 replicas", "Telegram бот")
|
||||||
|
}
|
||||||
|
|
||||||
|
Deployment_Node(data_ns, "Namespace: data") {
|
||||||
|
ContainerDb(postgres_primary, "PostgreSQL Primary", "PostgreSQL 15", "1 pod", "Основная БД (master)")
|
||||||
|
ContainerDb(postgres_replica, "PostgreSQL Replica", "PostgreSQL 15", "2 pods", "Реплики для чтения")
|
||||||
|
ContainerDb(redis_cluster, "Redis Cluster", "Redis 7", "3 pods", "Кэш и сессии")
|
||||||
|
ContainerQueue(kafka_cluster, "Kafka Cluster", "Apache Kafka", "3 brokers", "Message broker")
|
||||||
|
}
|
||||||
|
|
||||||
|
Deployment_Node(monitoring_ns, "Namespace: monitoring") {
|
||||||
|
Container(prometheus, "Prometheus", "Prometheus", "Сбор метрик")
|
||||||
|
Container(grafana, "Grafana", "Grafana", "Визуализация метрик")
|
||||||
|
Container(jaeger, "Jaeger", "Jaeger", "Distributed tracing")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Deployment_Node(external_services, "External Services") {
|
||||||
|
Container(s3, "AWS S3", "Object Storage", "Хранилище файлов")
|
||||||
|
Container(smtp, "SMTP Server", "Email", "Отправка email")
|
||||||
|
Container(sms_gateway, "SMS Gateway", "Twilio", "Отправка SMS")
|
||||||
|
}
|
||||||
|
|
||||||
|
Rel(ingress, api_gateway, "Routes traffic", "HTTPS")
|
||||||
|
|
||||||
|
Rel(api_gateway, tasks_svc, "Calls", "gRPC")
|
||||||
|
Rel(api_gateway, users_svc, "Calls", "gRPC")
|
||||||
|
Rel(api_gateway, connections_svc, "Calls", "gRPC")
|
||||||
|
Rel(api_gateway, events_svc, "Calls", "gRPC")
|
||||||
|
Rel(api_gateway, file_storage_svc, "Calls", "REST")
|
||||||
|
|
||||||
|
Rel(tasks_svc, kafka_cluster, "Publishes/Consumes", "Kafka Protocol")
|
||||||
|
Rel(connections_svc, kafka_cluster, "Publishes/Consumes", "Kafka Protocol")
|
||||||
|
Rel(scheduler_svc, kafka_cluster, "Publishes", "Kafka Protocol")
|
||||||
|
Rel(notification_svc, kafka_cluster, "Consumes", "Kafka Protocol")
|
||||||
|
Rel(audit_svc, kafka_cluster, "Consumes", "Kafka Protocol")
|
||||||
|
|
||||||
|
Rel(pms_adapter, kafka_cluster, "Publishes/Consumes", "Kafka Protocol")
|
||||||
|
Rel(erp_adapter, kafka_cluster, "Publishes/Consumes", "Kafka Protocol")
|
||||||
|
Rel(housekeeping_adapter, kafka_cluster, "Publishes/Consumes", "Kafka Protocol")
|
||||||
|
Rel(telegram_adapter, kafka_cluster, "Publishes/Consumes", "Kafka Protocol")
|
||||||
|
|
||||||
|
Rel(tasks_svc, postgres_primary, "Writes", "SQL")
|
||||||
|
Rel(tasks_svc, postgres_replica, "Reads", "SQL")
|
||||||
|
Rel(users_svc, postgres_primary, "Writes", "SQL")
|
||||||
|
Rel(users_svc, postgres_replica, "Reads", "SQL")
|
||||||
|
Rel(audit_svc, postgres_primary, "Writes logs", "SQL")
|
||||||
|
|
||||||
|
Rel(tasks_svc, redis_cluster, "Cache", "Redis Protocol")
|
||||||
|
Rel(users_svc, redis_cluster, "Cache", "Redis Protocol")
|
||||||
|
Rel(permissions_svc, redis_cluster, "Cache permissions", "Redis Protocol")
|
||||||
|
|
||||||
|
Rel(file_storage_svc, s3, "Stores files", "S3 API")
|
||||||
|
Rel(notification_svc, smtp, "Sends emails", "SMTP")
|
||||||
|
Rel(notification_svc, sms_gateway, "Sends SMS", "REST API")
|
||||||
|
|
||||||
|
Rel(prometheus, tasks_svc, "Scrapes metrics", "HTTP")
|
||||||
|
Rel(prometheus, users_svc, "Scrapes metrics", "HTTP")
|
||||||
|
Rel(grafana, prometheus, "Queries metrics", "HTTP")
|
||||||
|
|
||||||
|
UpdateLayoutConfig($c4ShapeInRow="3", $c4BoundaryInRow="1")
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Sequence Diagram: Creating Task from External System
|
||||||
|
|
||||||
|
Показывает последовательность действий при создании задачи из внешней системы.
|
||||||
|
|
||||||
|
```mermaid
|
||||||
|
sequenceDiagram
|
||||||
|
participant PMS as PMS System (Opera)
|
||||||
|
participant Adapter as PMS Adapter
|
||||||
|
participant Kafka as Apache Kafka
|
||||||
|
participant Connections as Connections Service
|
||||||
|
participant Tasks as Tasks Service
|
||||||
|
participant Permissions as Permissions Service
|
||||||
|
participant Audit as Audit Service
|
||||||
|
participant Notification as Notification Service
|
||||||
|
participant DB as PostgreSQL
|
||||||
|
participant Housekeeping as Housekeeping Adapter
|
||||||
|
participant HK_App as Housekeeping App
|
||||||
|
|
||||||
|
Note over PMS,HK_App: Сценарий: Гость выехал из номера, нужна уборка
|
||||||
|
|
||||||
|
PMS->>Adapter: Webhook: Guest Checkout (Room 305)
|
||||||
|
Adapter->>Adapter: Validate webhook signature
|
||||||
|
Adapter->>Adapter: Transform to standard format
|
||||||
|
Adapter->>Kafka: Publish: adapters.pms.checkout
|
||||||
|
|
||||||
|
Note over Kafka: Topic: adapters.pms.checkout
|
||||||
|
|
||||||
|
Kafka->>Connections: Consume: adapters.pms.checkout
|
||||||
|
Connections->>DB: Get routing rules for PMS → TaskManager
|
||||||
|
DB-->>Connections: Routing rules
|
||||||
|
Connections->>Connections: Apply rules: checkout → create cleaning task
|
||||||
|
Connections->>Kafka: Publish: connections.route_task
|
||||||
|
|
||||||
|
Note over Kafka: Topic: connections.route_task
|
||||||
|
|
||||||
|
Kafka->>Tasks: Consume: connections.route_task
|
||||||
|
Tasks->>Permissions: CheckPermission(source_adapter, create_task)
|
||||||
|
Permissions->>DB: Query permissions
|
||||||
|
DB-->>Permissions: Permission granted
|
||||||
|
Permissions-->>Tasks: Allowed
|
||||||
|
|
||||||
|
Tasks->>Tasks: Create task object
|
||||||
|
Tasks->>DB: INSERT INTO tasks (...)
|
||||||
|
DB-->>Tasks: Task created (id: uuid)
|
||||||
|
|
||||||
|
Tasks->>Kafka: Publish: tasks.created
|
||||||
|
|
||||||
|
Note over Kafka: Topic: tasks.created
|
||||||
|
|
||||||
|
par Parallel Processing
|
||||||
|
Kafka->>Audit: Consume: tasks.created
|
||||||
|
Audit->>DB: INSERT INTO audit_log
|
||||||
|
|
||||||
|
Kafka->>Notification: Consume: tasks.created
|
||||||
|
Notification->>DB: Get user notification preferences
|
||||||
|
DB-->>Notification: User prefers Telegram
|
||||||
|
Notification->>Notification: Send Telegram notification
|
||||||
|
|
||||||
|
Kafka->>Connections: Consume: tasks.created
|
||||||
|
Connections->>DB: Get routing rules for TaskManager → Housekeeping
|
||||||
|
DB-->>Connections: Route to Housekeeping Adapter
|
||||||
|
Connections->>Kafka: Publish: connections.route_task
|
||||||
|
end
|
||||||
|
|
||||||
|
Note over Kafka: Topic: connections.route_task
|
||||||
|
|
||||||
|
Kafka->>Housekeeping: Consume: connections.route_task
|
||||||
|
Housekeeping->>Housekeeping: Transform to Housekeeping App format
|
||||||
|
Housekeeping->>HK_App: POST /api/tasks (Room 305 cleaning)
|
||||||
|
HK_App-->>Housekeeping: Task assigned (assignee: Maria)
|
||||||
|
|
||||||
|
Housekeeping->>Kafka: Publish: adapters.housekeeping.task_assigned
|
||||||
|
|
||||||
|
Kafka->>Tasks: Consume: adapters.housekeeping.task_assigned
|
||||||
|
Tasks->>DB: UPDATE tasks SET assignee_id = ...
|
||||||
|
Tasks->>Kafka: Publish: tasks.assigned
|
||||||
|
|
||||||
|
Note over PMS,HK_App: Task created and assigned to housekeeping staff
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Sequence Diagram: Creating Event with Auto-Generated Tasks
|
||||||
|
|
||||||
|
Показывает создание мероприятия и автоматическую генерацию задач.
|
||||||
|
|
||||||
|
```mermaid
|
||||||
|
sequenceDiagram
|
||||||
|
participant User as Sales Manager
|
||||||
|
participant Web as Web Admin
|
||||||
|
participant Gateway as API Gateway
|
||||||
|
participant Events as Events Service
|
||||||
|
participant Tasks as Tasks Service
|
||||||
|
participant Kafka as Apache Kafka
|
||||||
|
participant DB as PostgreSQL
|
||||||
|
participant Notification as Notification Service
|
||||||
|
|
||||||
|
Note over User,Notification: Сценарий: Создание конференции на 50 человек
|
||||||
|
|
||||||
|
User->>Web: Create Event: "Marketing Conference"
|
||||||
|
Web->>Gateway: POST /api/v1/events (event details)
|
||||||
|
Gateway->>Gateway: Authenticate & Authorize
|
||||||
|
|
||||||
|
Gateway->>Events: CreateEvent(gRPC)
|
||||||
|
Events->>DB: INSERT INTO events
|
||||||
|
DB-->>Events: Event created (id: uuid)
|
||||||
|
|
||||||
|
Events->>Events: Generate tasks from event template
|
||||||
|
Note over Events: Tasks: Setup chairs, Prepare projector,<br/>Organize coffee break, etc.
|
||||||
|
|
||||||
|
loop For each generated task
|
||||||
|
Events->>Tasks: CreateTask(gRPC)
|
||||||
|
Tasks->>DB: INSERT INTO tasks
|
||||||
|
DB-->>Tasks: Task created
|
||||||
|
Tasks->>Kafka: Publish: tasks.created
|
||||||
|
Tasks-->>Events: Task ID
|
||||||
|
end
|
||||||
|
|
||||||
|
Events->>DB: INSERT INTO event_tasks (event_id, task_id)
|
||||||
|
Events->>Kafka: Publish: events.created
|
||||||
|
Events->>Kafka: Publish: events.tasks_generated
|
||||||
|
|
||||||
|
Events-->>Gateway: Event + generated tasks
|
||||||
|
Gateway-->>Web: 201 Created (event + tasks)
|
||||||
|
Web-->>User: Show created event with tasks
|
||||||
|
|
||||||
|
par Notify departments
|
||||||
|
Kafka->>Notification: Consume: tasks.created
|
||||||
|
loop For each task
|
||||||
|
Notification->>Notification: Get assignee notification prefs
|
||||||
|
Notification->>Notification: Send notification (Telegram/Email)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
Note over User,Notification: All tasks created and departments notified
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Data Flow Diagram
|
||||||
|
|
||||||
|
Показывает потоки данных в системе.
|
||||||
|
|
||||||
|
```mermaid
|
||||||
|
flowchart TB
|
||||||
|
subgraph External["External Systems"]
|
||||||
|
PMS["PMS System"]
|
||||||
|
ERP["ERP System"]
|
||||||
|
Guest["Guest (Telegram)"]
|
||||||
|
end
|
||||||
|
|
||||||
|
subgraph Adapters["Adapter Layer"]
|
||||||
|
PMS_A["PMS Adapter"]
|
||||||
|
ERP_A["ERP Adapter"]
|
||||||
|
TG_A["Telegram Adapter"]
|
||||||
|
end
|
||||||
|
|
||||||
|
subgraph Kafka["Apache Kafka"]
|
||||||
|
T1["adapters.*"]
|
||||||
|
T2["tasks.*"]
|
||||||
|
T3["connections.*"]
|
||||||
|
T4["notifications.*"]
|
||||||
|
T5["audit.*"]
|
||||||
|
end
|
||||||
|
|
||||||
|
subgraph Core["Core Services"]
|
||||||
|
Connections["Connections Service<br/>(Routing Rules)"]
|
||||||
|
Tasks["Tasks Service<br/>(Task Management)"]
|
||||||
|
Users["Users Service"]
|
||||||
|
Permissions["Permissions Service"]
|
||||||
|
end
|
||||||
|
|
||||||
|
subgraph Support["Support Services"]
|
||||||
|
Notification["Notification Service"]
|
||||||
|
Audit["Audit Service"]
|
||||||
|
Scheduler["Scheduler Service"]
|
||||||
|
end
|
||||||
|
|
||||||
|
subgraph Data["Data Layer"]
|
||||||
|
DB["PostgreSQL"]
|
||||||
|
Cache["Redis"]
|
||||||
|
end
|
||||||
|
|
||||||
|
%% External to Adapters
|
||||||
|
PMS -->|"Webhook/API"| PMS_A
|
||||||
|
ERP -->|"API"| ERP_A
|
||||||
|
Guest -->|"Telegram Bot"| TG_A
|
||||||
|
|
||||||
|
%% Adapters to Kafka
|
||||||
|
PMS_A -->|"Publish events"| T1
|
||||||
|
ERP_A -->|"Publish events"| T1
|
||||||
|
TG_A -->|"Publish events"| T1
|
||||||
|
|
||||||
|
%% Kafka to Connections
|
||||||
|
T1 -->|"Consume"| Connections
|
||||||
|
|
||||||
|
%% Connections routing
|
||||||
|
Connections -->|"Route messages"| T3
|
||||||
|
T3 -->|"Consume"| Tasks
|
||||||
|
|
||||||
|
%% Tasks operations
|
||||||
|
Tasks -->|"Publish events"| T2
|
||||||
|
Tasks -->|"Query permissions"| Permissions
|
||||||
|
Tasks -->|"Write/Read"| DB
|
||||||
|
Tasks -->|"Cache"| Cache
|
||||||
|
|
||||||
|
%% Support services
|
||||||
|
T2 -->|"Consume"| Notification
|
||||||
|
T2 -->|"Consume"| Audit
|
||||||
|
Scheduler -->|"Trigger tasks"| T2
|
||||||
|
|
||||||
|
Notification -->|"Send notifications"| External
|
||||||
|
Audit -->|"Write logs"| DB
|
||||||
|
|
||||||
|
%% Users and Permissions
|
||||||
|
Users -->|"Write/Read"| DB
|
||||||
|
Permissions -->|"Write/Read"| DB
|
||||||
|
Permissions -->|"Cache permissions"| Cache
|
||||||
|
|
||||||
|
style Kafka fill:#ff9900
|
||||||
|
style Core fill:#00cc66
|
||||||
|
style Support fill:#3399ff
|
||||||
|
style Data fill:#cc66ff
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Notes
|
||||||
|
|
||||||
|
### Как использовать эти диаграммы:
|
||||||
|
|
||||||
|
1. **System Context (Level 1)**: Показывает TaskManager как черный ящик в контексте пользователей и внешних систем. Используйте для презентации бизнес-заказчикам.
|
||||||
|
|
||||||
|
2. **Container Diagram (Level 2)**: Показывает основные приложения и хранилища данных. Используйте для обсуждения с архитекторами и DevOps командой.
|
||||||
|
|
||||||
|
3. **Component Diagrams (Level 3)**: Показывают внутреннюю структуру отдельных сервисов. Используйте для разработчиков при проектировании конкретного сервиса.
|
||||||
|
|
||||||
|
4. **Deployment Diagram**: Показывает как система развернута в Kubernetes. Используйте для DevOps и планирования инфраструктуры.
|
||||||
|
|
||||||
|
5. **Sequence Diagrams**: Показывают взаимодействие компонентов во времени для конкретных сценариев. Используйте для понимания бизнес-процессов.
|
||||||
@ -129,7 +129,7 @@
|
|||||||
#### **Проблема 6: Неэффективное управление задачами для мероприятий**
|
#### **Проблема 6: Неэффективное управление задачами для мероприятий**
|
||||||
|
|
||||||
**AS-IS:**
|
**AS-IS:**
|
||||||
- Менеджер по продажам вручную составляет "фанкшн" или "меморандум" (Word документ)
|
- Менеджер по продажам вручную составляет "функшн" или "меморандум" (Word документ)
|
||||||
- В документе описываются все задачи для разных служб:
|
- В документе описываются все задачи для разных служб:
|
||||||
- Застройка зала (расстановка столов, стульев)
|
- Застройка зала (расстановка столов, стульев)
|
||||||
- Предоставление оборудования (проектор, экран)
|
- Предоставление оборудования (проектор, экран)
|
||||||
@ -142,15 +142,15 @@
|
|||||||
**TO-BE:**
|
**TO-BE:**
|
||||||
- Менеджер описывает мероприятие в системе один раз
|
- Менеджер описывает мероприятие в системе один раз
|
||||||
- Система автоматически создает задачи для каждой службы
|
- Система автоматически создает задачи для каждой службы
|
||||||
- Автоматическая генерация "фанкшн"
|
- Автоматическая генерация "функшн"
|
||||||
- Все задачи отслеживаются в единой системе
|
- Все задачи отслеживаются в единой системе
|
||||||
- Массовое создание связанных задач для разных подразделений
|
- Массовое создание связанных задач для разных подразделений
|
||||||
|
|
||||||
**Требование:**
|
**Требование:**
|
||||||
- Возможность массового создания задач (bulk task creation)
|
- Возможность массового создания задач (bulk task creation)
|
||||||
- Описание мероприятия с автоматической декомпозицией на задачи
|
- Описание мероприятия с автоматической декомпозицией на задачи
|
||||||
- Привязка задач к конференц-залам и времени
|
- Привязка задач к конференц-залам и времени
|
||||||
- Формирование документа "фанкшн" на основе введенных данных
|
- Формирование документа "функшн" на основе введенных данных
|
||||||
|
|
||||||
**Примечание:** Функционал, который можно продавать отдельным модулем. Пока не решен полноценно ни одной существующей системой.
|
**Примечание:** Функционал, который можно продавать отдельным модулем. Пока не решен полноценно ни одной существующей системой.
|
||||||
|
|
||||||
|
|||||||
1053
Архитектура системы TaskManager.md
Normal file
1053
Архитектура системы TaskManager.md
Normal file
File diff suppressed because it is too large
Load Diff
240
Архитектурный скетч.drawio
Normal file
240
Архитектурный скетч.drawio
Normal file
@ -0,0 +1,240 @@
|
|||||||
|
<mxfile host="65bd71144e">
|
||||||
|
<diagram id="7gCwj9mQwRpnqfD4ykJp" name="Page-1">
|
||||||
|
<mxGraphModel dx="4779" dy="3497" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="827" pageHeight="1169" math="0" shadow="0">
|
||||||
|
<root>
|
||||||
|
<mxCell id="0"/>
|
||||||
|
<mxCell id="1" parent="0"/>
|
||||||
|
<object placeholders="1" c4Name="Message Broker" c4Type="Container" c4Technology="Apache Kafka" c4Description="Очередь сообщений" label="<font style="font-size: 16px"><b>%c4Name%</b></font><div>[%c4Type%:&nbsp;%c4Technology%]</div><br><div><font style="font-size: 11px"><font color="#E6E6E6">%c4Description%</font></div>" id="2">
|
||||||
|
<mxCell style="shape=cylinder3;size=15;direction=south;whiteSpace=wrap;html=1;boundedLbl=1;rounded=0;labelBackgroundColor=none;fillColor=#23A2D9;fontSize=12;fontColor=#ffffff;align=center;strokeColor=#0E7DAD;metaEdit=1;points=[[0.5,0,0],[1,0.25,0],[1,0.5,0],[1,0.75,0],[0.5,1,0],[0,0.75,0],[0,0.5,0],[0,0.25,0]];resizable=0;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="-780" y="-40" width="240" height="120" as="geometry"/>
|
||||||
|
</mxCell>
|
||||||
|
</object>
|
||||||
|
<object placeholders="1" c4Name="connections-service" c4Type="Service" c4Technology="Python" c4Description="Управляет связями между адаптерами системы" label="<font style="font-size: 16px"><b>%c4Name%</b></font><div>[%c4Type%: %c4Technology%]</div><br><div><font style="font-size: 11px"><font color="#E6E6E6">%c4Description%</font></div>" id="3">
|
||||||
|
<mxCell style="rounded=1;whiteSpace=wrap;html=1;fontSize=11;labelBackgroundColor=none;fillColor=#23A2D9;fontColor=#ffffff;align=center;arcSize=10;strokeColor=#0E7DAD;metaEdit=1;resizable=0;points=[[0.25,0,0],[0.5,0,0],[0.75,0,0],[1,0.25,0],[1,0.5,0],[1,0.75,0],[0.75,1,0],[0.5,1,0],[0.25,1,0],[0,0.75,0],[0,0.5,0],[0,0.25,0]];" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="-80" y="-200" width="240" height="120" as="geometry"/>
|
||||||
|
</mxCell>
|
||||||
|
</object>
|
||||||
|
<object placeholders="1" c4Name="PMS Adapter" c4Type="Service" c4Technology="Python" c4Description="Адаптер передачи сообщений в систему" label="<font style="font-size: 16px"><b>%c4Name%</b></font><div>[%c4Type%: %c4Technology%]</div><br><div><font style="font-size: 11px"><font color="#E6E6E6">%c4Description%</font></div>" id="4">
|
||||||
|
<mxCell style="rounded=1;whiteSpace=wrap;html=1;fontSize=11;labelBackgroundColor=none;fillColor=#23A2D9;fontColor=#ffffff;align=center;arcSize=10;strokeColor=#0E7DAD;metaEdit=1;resizable=0;points=[[0.25,0,0],[0.5,0,0],[0.75,0,0],[1,0.25,0],[1,0.5,0],[1,0.75,0],[0.75,1,0],[0.5,1,0],[0.25,1,0],[0,0.75,0],[0,0.5,0],[0,0.25,0]];" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="-1690" y="-120" width="240" height="120" as="geometry"/>
|
||||||
|
</mxCell>
|
||||||
|
</object>
|
||||||
|
<object placeholders="1" c4Name="Custom Adapter #N" c4Type="Service" c4Technology="Python" c4Description="Адаптер передачи сообщений в систему" label="<font style="font-size: 16px"><b>%c4Name%</b></font><div>[%c4Type%: %c4Technology%]</div><br><div><font style="font-size: 11px"><font color="#E6E6E6">%c4Description%</font></div>" id="6">
|
||||||
|
<mxCell style="rounded=1;whiteSpace=wrap;html=1;fontSize=11;labelBackgroundColor=none;fillColor=#23A2D9;fontColor=#ffffff;align=center;arcSize=10;strokeColor=#0E7DAD;metaEdit=1;resizable=0;points=[[0.25,0,0],[0.5,0,0],[0.75,0,0],[1,0.25,0],[1,0.5,0],[1,0.75,0],[0.75,1,0],[0.5,1,0],[0.25,1,0],[0,0.75,0],[0,0.5,0],[0,0.25,0]];" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="-1410" y="40" width="240" height="120" as="geometry"/>
|
||||||
|
</mxCell>
|
||||||
|
</object>
|
||||||
|
<object placeholders="1" c4Name="PMS" c4Type="Software System" c4Description="" label="<font style="font-size: 16px"><b>%c4Name%</b></font><div>[%c4Type%]</div><br><div><font style="font-size: 11px"><font color="#cccccc">%c4Description%</font></div>" id="7">
|
||||||
|
<mxCell style="rounded=1;whiteSpace=wrap;html=1;labelBackgroundColor=none;fillColor=#8C8496;fontColor=#ffffff;align=center;arcSize=10;strokeColor=#736782;metaEdit=1;resizable=0;points=[[0.25,0,0],[0.5,0,0],[0.75,0,0],[1,0.25,0],[1,0.5,0],[1,0.75,0],[0.75,1,0],[0.5,1,0],[0.25,1,0],[0,0.75,0],[0,0.5,0],[0,0.25,0]];" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="-1690" y="-480" width="240" height="120" as="geometry"/>
|
||||||
|
</mxCell>
|
||||||
|
</object>
|
||||||
|
<object placeholders="1" c4Name="ERP" c4Type="Software System" c4Description="" label="<font style="font-size: 16px"><b>%c4Name%</b></font><div>[%c4Type%]</div><br><div><font style="font-size: 11px"><font color="#cccccc">%c4Description%</font></div>" id="8">
|
||||||
|
<mxCell style="rounded=1;whiteSpace=wrap;html=1;labelBackgroundColor=none;fillColor=#8C8496;fontColor=#ffffff;align=center;arcSize=10;strokeColor=#736782;metaEdit=1;resizable=0;points=[[0.25,0,0],[0.5,0,0],[0.75,0,0],[1,0.25,0],[1,0.5,0],[1,0.75,0],[0.75,1,0],[0.5,1,0],[0.25,1,0],[0,0.75,0],[0,0.5,0],[0,0.25,0]];" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="-1410" y="-480" width="240" height="120" as="geometry"/>
|
||||||
|
</mxCell>
|
||||||
|
</object>
|
||||||
|
<object placeholders="1" c4Name="Housekeeper" c4Type="Software System" c4Description="" label="<font style="font-size: 16px"><b>%c4Name%</b></font><div>[%c4Type%]</div><br><div><font style="font-size: 11px"><font color="#cccccc">%c4Description%</font></div>" id="9">
|
||||||
|
<mxCell style="rounded=1;whiteSpace=wrap;html=1;labelBackgroundColor=none;fillColor=#8C8496;fontColor=#ffffff;align=center;arcSize=10;strokeColor=#736782;metaEdit=1;resizable=0;points=[[0.25,0,0],[0.5,0,0],[0.75,0,0],[1,0.25,0],[1,0.5,0],[1,0.75,0],[0.75,1,0],[0.5,1,0],[0.25,1,0],[0,0.75,0],[0,0.5,0],[0,0.25,0]];" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="-1130" y="-480" width="240" height="120" as="geometry"/>
|
||||||
|
</mxCell>
|
||||||
|
</object>
|
||||||
|
<object placeholders="1" c4Name="tasks-service" c4Type="Service" c4Technology="Python" c4Description="Управляет всеми тасками системы" label="<font style="font-size: 16px"><b>%c4Name%</b></font><div>[%c4Type%: %c4Technology%]</div><br><div><font style="font-size: 11px"><font color="#E6E6E6">%c4Description%</font></div>" id="21">
|
||||||
|
<mxCell style="rounded=1;whiteSpace=wrap;html=1;fontSize=11;labelBackgroundColor=none;fillColor=#23A2D9;fontColor=#ffffff;align=center;arcSize=10;strokeColor=#0E7DAD;metaEdit=1;resizable=0;points=[[0.25,0,0],[0.5,0,0],[0.75,0,0],[1,0.25,0],[1,0.5,0],[1,0.75,0],[0.75,1,0],[0.5,1,0],[0.25,1,0],[0,0.75,0],[0,0.5,0],[0,0.25,0]];" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="-360" y="-200" width="240" height="120" as="geometry"/>
|
||||||
|
</mxCell>
|
||||||
|
</object>
|
||||||
|
<object placeholders="1" c4Name="БД" c4Type="Container" c4Technology="Postgress" c4Description="Сохранение данных системы" label="<font style="font-size: 16px"><b>%c4Name%</b></font><div>[%c4Type%:&nbsp;%c4Technology%]</div><br><div><font style="font-size: 11px"><font color="#E6E6E6">%c4Description%</font></div>" id="22">
|
||||||
|
<mxCell style="shape=cylinder3;size=15;whiteSpace=wrap;html=1;boundedLbl=1;rounded=0;labelBackgroundColor=none;fillColor=#23A2D9;fontSize=12;fontColor=#ffffff;align=center;strokeColor=#0E7DAD;metaEdit=1;points=[[0.5,0,0],[1,0.25,0],[1,0.5,0],[1,0.75,0],[0.5,1,0],[0,0.75,0],[0,0.5,0],[0,0.25,0]];resizable=0;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="-360" y="480" width="240" height="120" as="geometry"/>
|
||||||
|
</mxCell>
|
||||||
|
</object>
|
||||||
|
<object placeholders="1" c4Name="Web admin" c4Type="Container" c4Technology="Typescript, React" c4Description="Админка для управления системой" label="<font style="font-size: 16px"><b>%c4Name%</b></font><div>[%c4Type%:&nbsp;%c4Technology%]</div><br><div><font style="font-size: 11px"><font color="#E6E6E6">%c4Description%</font></div>" id="23">
|
||||||
|
<mxCell style="shape=mxgraph.c4.webBrowserContainer2;whiteSpace=wrap;html=1;boundedLbl=1;rounded=0;labelBackgroundColor=none;strokeColor=#118ACD;fillColor=#23A2D9;strokeColor=#118ACD;strokeColor2=#0E7DAD;fontSize=12;fontColor=#ffffff;align=center;metaEdit=1;points=[[0.5,0,0],[1,0.25,0],[1,0.5,0],[1,0.75,0],[0.5,1,0],[0,0.75,0],[0,0.5,0],[0,0.25,0]];resizable=0;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="-360" y="-960" width="240" height="160" as="geometry"/>
|
||||||
|
</mxCell>
|
||||||
|
</object>
|
||||||
|
<object placeholders="1" c4Name="Service Layer" c4Type="SystemScopeBoundary" c4Application="Layer" label="<font style="font-size: 16px"><b><div style="text-align: left">%c4Name%</div></b></font><div style="text-align: left">[%c4Application%]</div>" id="24">
|
||||||
|
<mxCell style="rounded=1;fontSize=11;whiteSpace=wrap;html=1;dashed=1;arcSize=20;fillColor=none;strokeColor=#666666;fontColor=#333333;labelBackgroundColor=none;align=left;verticalAlign=bottom;labelBorderColor=none;spacingTop=0;spacing=10;dashPattern=8 4;metaEdit=1;rotatable=0;perimeter=rectanglePerimeter;noLabel=0;labelPadding=0;allowArrows=0;connectable=0;expand=0;recursiveResize=0;editable=1;pointerEvents=0;absoluteArcSize=1;points=[[0.25,0,0],[0.5,0,0],[0.75,0,0],[1,0.25,0],[1,0.5,0],[1,0.75,0],[0.75,1,0],[0.5,1,0],[0.25,1,0],[0,0.75,0],[0,0.5,0],[0,0.25,0]];" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="-400" y="-280" width="880" height="600" as="geometry"/>
|
||||||
|
</mxCell>
|
||||||
|
</object>
|
||||||
|
<object placeholders="1" c4Name="Mobile Apps" c4Type="Container" c4Technology="?" c4Description="Отдельные приложения для работников" label="<font style="font-size: 16px"><b>%c4Name%</b></font><div>[%c4Type%:&nbsp;%c4Technology%]</div><br><div><font style="font-size: 11px"><font color="#E6E6E6">%c4Description%</font></div>" id="25">
|
||||||
|
<mxCell style="shape=mxgraph.c4.webBrowserContainer2;whiteSpace=wrap;html=1;boundedLbl=1;rounded=0;labelBackgroundColor=none;strokeColor=#118ACD;fillColor=#23A2D9;strokeColor=#118ACD;strokeColor2=#0E7DAD;fontSize=12;fontColor=#ffffff;align=center;metaEdit=1;points=[[0.5,0,0],[1,0.25,0],[1,0.5,0],[1,0.75,0],[0.5,1,0],[0,0.75,0],[0,0.5,0],[0,0.25,0]];resizable=0;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="-80" y="-960" width="240" height="160" as="geometry"/>
|
||||||
|
</mxCell>
|
||||||
|
</object>
|
||||||
|
<object placeholders="1" c4Name="Telegram Bot" c4Type="Container" c4Technology="?" c4Description="Бот для управления системой" label="<font style="font-size: 16px"><b>%c4Name%</b></font><div>[%c4Type%:&nbsp;%c4Technology%]</div><br><div><font style="font-size: 11px"><font color="#E6E6E6">%c4Description%</font></div>" id="26">
|
||||||
|
<mxCell style="shape=mxgraph.c4.webBrowserContainer2;whiteSpace=wrap;html=1;boundedLbl=1;rounded=0;labelBackgroundColor=none;strokeColor=#118ACD;fillColor=#23A2D9;strokeColor=#118ACD;strokeColor2=#0E7DAD;fontSize=12;fontColor=#ffffff;align=center;metaEdit=1;points=[[0.5,0,0],[1,0.25,0],[1,0.5,0],[1,0.75,0],[0.5,1,0],[0,0.75,0],[0,0.5,0],[0,0.25,0]];resizable=0;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="200" y="-960" width="240" height="160" as="geometry"/>
|
||||||
|
</mxCell>
|
||||||
|
</object>
|
||||||
|
<object placeholders="1" c4Name="Client Layer" c4Type="SystemScopeBoundary" c4Application="Layer" label="<font style="font-size: 16px"><b><div style="text-align: left">%c4Name%</div></b></font><div style="text-align: left">[%c4Application%]</div>" id="27">
|
||||||
|
<mxCell style="rounded=1;fontSize=11;whiteSpace=wrap;html=1;dashed=1;arcSize=20;fillColor=none;strokeColor=#666666;fontColor=#333333;labelBackgroundColor=none;align=left;verticalAlign=bottom;labelBorderColor=none;spacingTop=0;spacing=10;dashPattern=8 4;metaEdit=1;rotatable=0;perimeter=rectanglePerimeter;noLabel=0;labelPadding=0;allowArrows=0;connectable=0;expand=0;recursiveResize=0;editable=1;pointerEvents=0;absoluteArcSize=1;points=[[0.25,0,0],[0.5,0,0],[0.75,0,0],[1,0.25,0],[1,0.5,0],[1,0.75,0],[0.75,1,0],[0.5,1,0],[0.25,1,0],[0,0.75,0],[0,0.5,0],[0,0.25,0]];" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="-400" y="-1040" width="880" height="320" as="geometry"/>
|
||||||
|
</mxCell>
|
||||||
|
</object>
|
||||||
|
<object placeholders="1" c4Name="API Gateway Layer" c4Type="SystemScopeBoundary" c4Application="Layer" label="<font style="font-size: 16px"><b><div style="text-align: left">%c4Name%</div></b></font><div style="text-align: left">[%c4Application%]</div>" id="31">
|
||||||
|
<mxCell style="rounded=1;fontSize=11;whiteSpace=wrap;html=1;dashed=1;arcSize=20;fillColor=none;strokeColor=#666666;fontColor=#333333;labelBackgroundColor=none;align=left;verticalAlign=bottom;labelBorderColor=none;spacingTop=0;spacing=10;dashPattern=8 4;metaEdit=1;rotatable=0;perimeter=rectanglePerimeter;noLabel=0;labelPadding=0;allowArrows=0;connectable=0;expand=0;recursiveResize=0;editable=1;pointerEvents=0;absoluteArcSize=1;points=[[0.25,0,0],[0.5,0,0],[0.75,0,0],[1,0.25,0],[1,0.5,0],[1,0.75,0],[0.75,1,0],[0.5,1,0],[0.25,1,0],[0,0.75,0],[0,0.5,0],[0,0.25,0]];" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="-400" y="-640" width="880" height="280" as="geometry"/>
|
||||||
|
</mxCell>
|
||||||
|
</object>
|
||||||
|
<object placeholders="1" c4Name="REST API" c4Type="Service" c4Technology="?" c4Description="" label="<font style="font-size: 16px"><b>%c4Name%</b></font><div>[%c4Type%: %c4Technology%]</div><br><div><font style="font-size: 11px"><font color="#E6E6E6">%c4Description%</font></div>" id="32">
|
||||||
|
<mxCell style="rounded=1;whiteSpace=wrap;html=1;fontSize=11;labelBackgroundColor=none;fillColor=#23A2D9;fontColor=#ffffff;align=center;arcSize=10;strokeColor=#0E7DAD;metaEdit=1;resizable=0;points=[[0.25,0,0],[0.5,0,0],[0.75,0,0],[1,0.25,0],[1,0.5,0],[1,0.75,0],[0.75,1,0],[0.5,1,0],[0.25,1,0],[0,0.75,0],[0,0.5,0],[0,0.25,0]];" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="-360" y="-560" width="240" height="120" as="geometry"/>
|
||||||
|
</mxCell>
|
||||||
|
</object>
|
||||||
|
<object placeholders="1" c4Name="gRPC" c4Type="Service" c4Technology="?" c4Description="" label="<font style="font-size: 16px"><b>%c4Name%</b></font><div>[%c4Type%: %c4Technology%]</div><br><div><font style="font-size: 11px"><font color="#E6E6E6">%c4Description%</font></div>" id="33">
|
||||||
|
<mxCell style="rounded=1;whiteSpace=wrap;html=1;fontSize=11;labelBackgroundColor=none;fillColor=#23A2D9;fontColor=#ffffff;align=center;arcSize=10;strokeColor=#0E7DAD;metaEdit=1;resizable=0;points=[[0.25,0,0],[0.5,0,0],[0.75,0,0],[1,0.25,0],[1,0.5,0],[1,0.75,0],[0.75,1,0],[0.5,1,0],[0.25,1,0],[0,0.75,0],[0,0.5,0],[0,0.25,0]];" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="-80" y="-560" width="240" height="120" as="geometry"/>
|
||||||
|
</mxCell>
|
||||||
|
</object>
|
||||||
|
<object placeholders="1" c4Name="WebSocket" c4Type="Service" c4Technology="?" c4Description="" label="<font style="font-size: 16px"><b>%c4Name%</b></font><div>[%c4Type%: %c4Technology%]</div><br><div><font style="font-size: 11px"><font color="#E6E6E6">%c4Description%</font></div>" id="34">
|
||||||
|
<mxCell style="rounded=1;whiteSpace=wrap;html=1;fontSize=11;labelBackgroundColor=none;fillColor=#23A2D9;fontColor=#ffffff;align=center;arcSize=10;strokeColor=#0E7DAD;metaEdit=1;resizable=0;points=[[0.25,0,0],[0.5,0,0],[0.75,0,0],[1,0.25,0],[1,0.5,0],[1,0.75,0],[0.75,1,0],[0.5,1,0],[0.25,1,0],[0,0.75,0],[0,0.5,0],[0,0.25,0]];" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="200" y="-560" width="240" height="120" as="geometry"/>
|
||||||
|
</mxCell>
|
||||||
|
</object>
|
||||||
|
<object placeholders="1" c4Name="users-service" c4Type="Service" c4Technology="Python" c4Description="Управление пользователями системы" label="<font style="font-size: 16px"><b>%c4Name%</b></font><div>[%c4Type%: %c4Technology%]</div><br><div><font style="font-size: 11px"><font color="#E6E6E6">%c4Description%</font></div>" id="35">
|
||||||
|
<mxCell style="rounded=1;whiteSpace=wrap;html=1;fontSize=11;labelBackgroundColor=none;fillColor=#23A2D9;fontColor=#ffffff;align=center;arcSize=10;strokeColor=#0E7DAD;metaEdit=1;resizable=0;points=[[0.25,0,0],[0.5,0,0],[0.75,0,0],[1,0.25,0],[1,0.5,0],[1,0.75,0],[0.75,1,0],[0.5,1,0],[0.25,1,0],[0,0.75,0],[0,0.5,0],[0,0.25,0]];" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="200" y="-200" width="240" height="120" as="geometry"/>
|
||||||
|
</mxCell>
|
||||||
|
</object>
|
||||||
|
<object placeholders="1" c4Name="notification-service" c4Type="Service" c4Technology="Python" c4Description="Управление уведомлениями системы" label="<font style="font-size: 16px"><b>%c4Name%</b></font><div>[%c4Type%: %c4Technology%]</div><br><div><font style="font-size: 11px"><font color="#E6E6E6">%c4Description%</font></div>" id="36">
|
||||||
|
<mxCell style="rounded=1;whiteSpace=wrap;html=1;fontSize=11;labelBackgroundColor=none;fillColor=#23A2D9;fontColor=#ffffff;align=center;arcSize=10;strokeColor=#0E7DAD;metaEdit=1;resizable=0;points=[[0.25,0,0],[0.5,0,0],[0.75,0,0],[1,0.25,0],[1,0.5,0],[1,0.75,0],[0.75,1,0],[0.5,1,0],[0.25,1,0],[0,0.75,0],[0,0.5,0],[0,0.25,0]];" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="-360" y="-40" width="240" height="120" as="geometry"/>
|
||||||
|
</mxCell>
|
||||||
|
</object>
|
||||||
|
<object placeholders="1" c4Name="file-storage-service" c4Type="Service" c4Technology="Python" c4Description="Управление файлами системы" label="<font style="font-size: 16px"><b>%c4Name%</b></font><div>[%c4Type%: %c4Technology%]</div><br><div><font style="font-size: 11px"><font color="#E6E6E6">%c4Description%</font></div>" id="37">
|
||||||
|
<mxCell style="rounded=1;whiteSpace=wrap;html=1;fontSize=11;labelBackgroundColor=none;fillColor=#23A2D9;fontColor=#ffffff;align=center;arcSize=10;strokeColor=#0E7DAD;metaEdit=1;resizable=0;points=[[0.25,0,0],[0.5,0,0],[0.75,0,0],[1,0.25,0],[1,0.5,0],[1,0.75,0],[0.75,1,0],[0.5,1,0],[0.25,1,0],[0,0.75,0],[0,0.5,0],[0,0.25,0]];" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="-80" y="-40" width="240" height="120" as="geometry"/>
|
||||||
|
</mxCell>
|
||||||
|
</object>
|
||||||
|
<object placeholders="1" c4Name="audit-service" c4Type="Service" c4Technology="Python" c4Description="Аудит действий пользователя" label="<font style="font-size: 16px"><b>%c4Name%</b></font><div>[%c4Type%: %c4Technology%]</div><br><div><font style="font-size: 11px"><font color="#E6E6E6">%c4Description%</font></div>" id="38">
|
||||||
|
<mxCell style="rounded=1;whiteSpace=wrap;html=1;fontSize=11;labelBackgroundColor=none;fillColor=#23A2D9;fontColor=#ffffff;align=center;arcSize=10;strokeColor=#0E7DAD;metaEdit=1;resizable=0;points=[[0.25,0,0],[0.5,0,0],[0.75,0,0],[1,0.25,0],[1,0.5,0],[1,0.75,0],[0.75,1,0],[0.5,1,0],[0.25,1,0],[0,0.75,0],[0,0.5,0],[0,0.25,0]];" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="200" y="-40" width="240" height="120" as="geometry"/>
|
||||||
|
</mxCell>
|
||||||
|
</object>
|
||||||
|
<object placeholders="1" c4Name="scheduler-service" c4Type="Service" c4Technology="Python" c4Description="Создание задач по расписанию" label="<font style="font-size: 16px"><b>%c4Name%</b></font><div>[%c4Type%: %c4Technology%]</div><br><div><font style="font-size: 11px"><font color="#E6E6E6">%c4Description%</font></div>" id="39">
|
||||||
|
<mxCell style="rounded=1;whiteSpace=wrap;html=1;fontSize=11;labelBackgroundColor=none;fillColor=#23A2D9;fontColor=#ffffff;align=center;arcSize=10;strokeColor=#0E7DAD;metaEdit=1;resizable=0;points=[[0.25,0,0],[0.5,0,0],[0.75,0,0],[1,0.25,0],[1,0.5,0],[1,0.75,0],[0.75,1,0],[0.5,1,0],[0.25,1,0],[0,0.75,0],[0,0.5,0],[0,0.25,0]];" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="-360" y="120" width="240" height="120" as="geometry"/>
|
||||||
|
</mxCell>
|
||||||
|
</object>
|
||||||
|
<object placeholders="1" c4Name="permissions-service" c4Type="Service" c4Technology="Python" c4Description="Управление правами доступа пользователей" label="<font style="font-size: 16px"><b>%c4Name%</b></font><div>[%c4Type%: %c4Technology%]</div><br><div><font style="font-size: 11px"><font color="#E6E6E6">%c4Description%</font></div>" id="40">
|
||||||
|
<mxCell style="rounded=1;whiteSpace=wrap;html=1;fontSize=11;labelBackgroundColor=none;fillColor=#23A2D9;fontColor=#ffffff;align=center;arcSize=10;strokeColor=#0E7DAD;metaEdit=1;resizable=0;points=[[0.25,0,0],[0.5,0,0],[0.75,0,0],[1,0.25,0],[1,0.5,0],[1,0.75,0],[0.75,1,0],[0.5,1,0],[0.25,1,0],[0,0.75,0],[0,0.5,0],[0,0.25,0]];" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="-80" y="120" width="240" height="120" as="geometry"/>
|
||||||
|
</mxCell>
|
||||||
|
</object>
|
||||||
|
<object placeholders="1" c4Name="events-service" c4Type="Service" c4Technology="Python" c4Description="Управление мероприятиями" label="<font style="font-size: 16px"><b>%c4Name%</b></font><div>[%c4Type%: %c4Technology%]</div><br><div><font style="font-size: 11px"><font color="#E6E6E6">%c4Description%</font></div>" id="41">
|
||||||
|
<mxCell style="rounded=1;whiteSpace=wrap;html=1;fontSize=11;labelBackgroundColor=none;fillColor=#23A2D9;fontColor=#ffffff;align=center;arcSize=10;strokeColor=#0E7DAD;metaEdit=1;resizable=0;points=[[0.25,0,0],[0.5,0,0],[0.75,0,0],[1,0.25,0],[1,0.5,0],[1,0.75,0],[0.75,1,0],[0.5,1,0],[0.25,1,0],[0,0.75,0],[0,0.5,0],[0,0.25,0]];" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="200" y="120" width="240" height="120" as="geometry"/>
|
||||||
|
</mxCell>
|
||||||
|
</object>
|
||||||
|
<object placeholders="1" c4Name="Adapter Layer" c4Type="SystemScopeBoundary" c4Application="Layer" label="<font style="font-size: 16px"><b><div style="text-align: left">%c4Name%</div></b></font><div style="text-align: left">[%c4Application%]</div>" id="42">
|
||||||
|
<mxCell style="rounded=1;fontSize=11;whiteSpace=wrap;html=1;dashed=1;arcSize=20;fillColor=none;strokeColor=#666666;fontColor=#333333;labelBackgroundColor=none;align=left;verticalAlign=bottom;labelBorderColor=none;spacingTop=0;spacing=10;dashPattern=8 4;metaEdit=1;rotatable=0;perimeter=rectanglePerimeter;noLabel=0;labelPadding=0;allowArrows=0;connectable=0;expand=0;recursiveResize=0;editable=1;pointerEvents=0;absoluteArcSize=1;points=[[0.25,0,0],[0.5,0,0],[0.75,0,0],[1,0.25,0],[1,0.5,0],[1,0.75,0],[0.75,1,0],[0.5,1,0],[0.25,1,0],[0,0.75,0],[0,0.5,0],[0,0.25,0]];" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="-1730" y="-200" width="880" height="440" as="geometry"/>
|
||||||
|
</mxCell>
|
||||||
|
</object>
|
||||||
|
<object placeholders="1" c4Name="ERP Adapter" c4Type="Service" c4Technology="Python" c4Description="Адаптер передачи сообщений в систему" label="<font style="font-size: 16px"><b>%c4Name%</b></font><div>[%c4Type%: %c4Technology%]</div><br><div><font style="font-size: 11px"><font color="#E6E6E6">%c4Description%</font></div>" id="43">
|
||||||
|
<mxCell style="rounded=1;whiteSpace=wrap;html=1;fontSize=11;labelBackgroundColor=none;fillColor=#23A2D9;fontColor=#ffffff;align=center;arcSize=10;strokeColor=#0E7DAD;metaEdit=1;resizable=0;points=[[0.25,0,0],[0.5,0,0],[0.75,0,0],[1,0.25,0],[1,0.5,0],[1,0.75,0],[0.75,1,0],[0.5,1,0],[0.25,1,0],[0,0.75,0],[0,0.5,0],[0,0.25,0]];" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="-1410" y="-120" width="240" height="120" as="geometry"/>
|
||||||
|
</mxCell>
|
||||||
|
</object>
|
||||||
|
<object placeholders="1" c4Name="Housekeeping Adapter" c4Type="Service" c4Technology="Python" c4Description="Адаптер передачи сообщений в систему" label="<font style="font-size: 16px"><b>%c4Name%</b></font><div>[%c4Type%: %c4Technology%]</div><br><div><font style="font-size: 11px"><font color="#E6E6E6">%c4Description%</font></div>" id="44">
|
||||||
|
<mxCell style="rounded=1;whiteSpace=wrap;html=1;fontSize=11;labelBackgroundColor=none;fillColor=#23A2D9;fontColor=#ffffff;align=center;arcSize=10;strokeColor=#0E7DAD;metaEdit=1;resizable=0;points=[[0.25,0,0],[0.5,0,0],[0.75,0,0],[1,0.25,0],[1,0.5,0],[1,0.75,0],[0.75,1,0],[0.5,1,0],[0.25,1,0],[0,0.75,0],[0,0.5,0],[0,0.25,0]];" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="-1130" y="-120" width="240" height="120" as="geometry"/>
|
||||||
|
</mxCell>
|
||||||
|
</object>
|
||||||
|
<object placeholders="1" c4Name="Telegram Bot Adapter" c4Type="Service" c4Technology="Python" c4Description="Адаптер передачи сообщений в систему" label="<font style="font-size: 16px"><b>%c4Name%</b></font><div>[%c4Type%: %c4Technology%]</div><br><div><font style="font-size: 11px"><font color="#E6E6E6">%c4Description%</font></div>" id="45">
|
||||||
|
<mxCell style="rounded=1;whiteSpace=wrap;html=1;fontSize=11;labelBackgroundColor=none;fillColor=#23A2D9;fontColor=#ffffff;align=center;arcSize=10;strokeColor=#0E7DAD;metaEdit=1;resizable=0;points=[[0.25,0,0],[0.5,0,0],[0.75,0,0],[1,0.25,0],[1,0.5,0],[1,0.75,0],[0.75,1,0],[0.5,1,0],[0.25,1,0],[0,0.75,0],[0,0.5,0],[0,0.25,0]];" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="-1690" y="40" width="240" height="120" as="geometry"/>
|
||||||
|
</mxCell>
|
||||||
|
</object>
|
||||||
|
<object placeholders="1" c4Name="Data Layer" c4Type="SystemScopeBoundary" c4Application="Layer" label="<font style="font-size: 16px"><b><div style="text-align: left">%c4Name%</div></b></font><div style="text-align: left">[%c4Application%]</div>" id="46">
|
||||||
|
<mxCell style="rounded=1;fontSize=11;whiteSpace=wrap;html=1;dashed=1;arcSize=20;fillColor=none;strokeColor=#666666;fontColor=#333333;labelBackgroundColor=none;align=left;verticalAlign=bottom;labelBorderColor=none;spacingTop=0;spacing=10;dashPattern=8 4;metaEdit=1;rotatable=0;perimeter=rectanglePerimeter;noLabel=0;labelPadding=0;allowArrows=0;connectable=0;expand=0;recursiveResize=0;editable=1;pointerEvents=0;absoluteArcSize=1;points=[[0.25,0,0],[0.5,0,0],[0.75,0,0],[1,0.25,0],[1,0.5,0],[1,0.75,0],[0.75,1,0],[0.5,1,0],[0.25,1,0],[0,0.75,0],[0,0.5,0],[0,0.25,0]];" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="-400" y="400" width="880" height="280" as="geometry"/>
|
||||||
|
</mxCell>
|
||||||
|
</object>
|
||||||
|
<object placeholders="1" c4Name="Cache" c4Type="Container" c4Technology="Redis" c4Description="Сохранение данных системы" label="<font style="font-size: 16px"><b>%c4Name%</b></font><div>[%c4Type%:&nbsp;%c4Technology%]</div><br><div><font style="font-size: 11px"><font color="#E6E6E6">%c4Description%</font></div>" id="50">
|
||||||
|
<mxCell style="shape=cylinder3;size=15;whiteSpace=wrap;html=1;boundedLbl=1;rounded=0;labelBackgroundColor=none;fillColor=#23A2D9;fontSize=12;fontColor=#ffffff;align=center;strokeColor=#0E7DAD;metaEdit=1;points=[[0.5,0,0],[1,0.25,0],[1,0.5,0],[1,0.75,0],[0.5,1,0],[0,0.75,0],[0,0.5,0],[0,0.25,0]];resizable=0;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="-80" y="480" width="240" height="120" as="geometry"/>
|
||||||
|
</mxCell>
|
||||||
|
</object>
|
||||||
|
<object placeholders="1" c4Name="File Storage" c4Type="Container" c4Technology="S3" c4Description="Сохранение данных системы" label="<font style="font-size: 16px"><b>%c4Name%</b></font><div>[%c4Type%:&nbsp;%c4Technology%]</div><br><div><font style="font-size: 11px"><font color="#E6E6E6">%c4Description%</font></div>" id="51">
|
||||||
|
<mxCell style="shape=cylinder3;size=15;whiteSpace=wrap;html=1;boundedLbl=1;rounded=0;labelBackgroundColor=none;fillColor=#23A2D9;fontSize=12;fontColor=#ffffff;align=center;strokeColor=#0E7DAD;metaEdit=1;points=[[0.5,0,0],[1,0.25,0],[1,0.5,0],[1,0.75,0],[0.5,1,0],[0,0.75,0],[0,0.5,0],[0,0.25,0]];resizable=0;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="200" y="480" width="240" height="120" as="geometry"/>
|
||||||
|
</mxCell>
|
||||||
|
</object>
|
||||||
|
<object placeholders="1" c4Name="External System" c4Type="SystemScopeBoundary" c4Application="Layer" label="<font style="font-size: 16px"><b><div style="text-align: left">%c4Name%</div></b></font><div style="text-align: left">[%c4Application%]</div>" id="52">
|
||||||
|
<mxCell style="rounded=1;fontSize=11;whiteSpace=wrap;html=1;dashed=1;arcSize=20;fillColor=none;strokeColor=#666666;fontColor=#333333;labelBackgroundColor=none;align=left;verticalAlign=bottom;labelBorderColor=none;spacingTop=0;spacing=10;dashPattern=8 4;metaEdit=1;rotatable=0;perimeter=rectanglePerimeter;noLabel=0;labelPadding=0;allowArrows=0;connectable=0;expand=0;recursiveResize=0;editable=1;pointerEvents=0;absoluteArcSize=1;points=[[0.25,0,0],[0.5,0,0],[0.75,0,0],[1,0.25,0],[1,0.5,0],[1,0.75,0],[0.75,1,0],[0.5,1,0],[0.25,1,0],[0,0.75,0],[0,0.5,0],[0,0.25,0]];" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="-1730" y="-520" width="880" height="240" as="geometry"/>
|
||||||
|
</mxCell>
|
||||||
|
</object>
|
||||||
|
<mxCell id="55" style="edgeStyle=none;html=1;exitX=0.5;exitY=0;exitDx=0;exitDy=0;exitPerimeter=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;entryPerimeter=0;" edge="1" parent="1" source="43" target="8">
|
||||||
|
<mxGeometry relative="1" as="geometry"/>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="56" style="edgeStyle=none;html=1;exitX=0.5;exitY=0;exitDx=0;exitDy=0;exitPerimeter=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;entryPerimeter=0;" edge="1" parent="1" source="4" target="7">
|
||||||
|
<mxGeometry relative="1" as="geometry"/>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="57" style="edgeStyle=none;html=1;exitX=0.5;exitY=0;exitDx=0;exitDy=0;exitPerimeter=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;entryPerimeter=0;" edge="1" parent="1" source="44" target="9">
|
||||||
|
<mxGeometry relative="1" as="geometry"/>
|
||||||
|
</mxCell>
|
||||||
|
<object placeholders="1" c4Type="Relationship" c4Technology="e.g. JSON/HTTP" c4Description="e.g. Makes API calls" label="<div style="text-align: left"><div style="text-align: center"><b>%c4Description%</b></div><div style="text-align: center">[%c4Technology%]</div></div>" id="64">
|
||||||
|
<mxCell style="endArrow=blockThin;html=1;fontSize=10;fontColor=#404040;strokeWidth=1;endFill=1;strokeColor=#828282;elbow=vertical;metaEdit=1;endSize=14;startSize=14;jumpStyle=arc;jumpSize=16;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1">
|
||||||
|
<mxGeometry width="240" relative="1" as="geometry">
|
||||||
|
<mxPoint x="39.93" y="-774.5" as="sourcePoint"/>
|
||||||
|
<mxPoint x="39.56" y="-584.5" as="targetPoint"/>
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
</object>
|
||||||
|
<object placeholders="1" c4Type="Relationship" id="65">
|
||||||
|
<mxCell style="endArrow=blockThin;html=1;fontSize=10;fontColor=#404040;strokeWidth=1;endFill=1;strokeColor=#828282;elbow=vertical;metaEdit=1;endSize=14;startSize=14;jumpStyle=arc;jumpSize=16;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1">
|
||||||
|
<mxGeometry width="240" relative="1" as="geometry">
|
||||||
|
<mxPoint x="39.62" y="-420" as="sourcePoint"/>
|
||||||
|
<mxPoint x="40" y="-220" as="targetPoint"/>
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
</object>
|
||||||
|
<object placeholders="1" c4Type="Relationship" id="66">
|
||||||
|
<mxCell style="endArrow=blockThin;html=1;fontSize=10;fontColor=#404040;strokeWidth=1;endFill=1;strokeColor=#828282;elbow=vertical;metaEdit=1;endSize=14;startSize=14;jumpStyle=arc;jumpSize=16;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1">
|
||||||
|
<mxGeometry width="240" relative="1" as="geometry">
|
||||||
|
<mxPoint x="39.089999999999996" y="260" as="sourcePoint"/>
|
||||||
|
<mxPoint x="39.47" y="460" as="targetPoint"/>
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
</object>
|
||||||
|
<object placeholders="1" c4Type="Relationship" id="67">
|
||||||
|
<mxCell style="endArrow=blockThin;html=1;fontSize=10;fontColor=#404040;strokeWidth=1;endFill=1;strokeColor=#828282;elbow=vertical;metaEdit=1;endSize=14;startSize=14;jumpStyle=arc;jumpSize=16;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1">
|
||||||
|
<mxGeometry width="240" relative="1" as="geometry">
|
||||||
|
<mxPoint x="-930" y="20" as="sourcePoint"/>
|
||||||
|
<mxPoint x="-790" y="20" as="targetPoint"/>
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
</object>
|
||||||
|
<object placeholders="1" c4Type="Relationship" id="68">
|
||||||
|
<mxCell style="endArrow=blockThin;html=1;fontSize=10;fontColor=#404040;strokeWidth=1;endFill=1;strokeColor=#828282;elbow=vertical;metaEdit=1;endSize=14;startSize=14;jumpStyle=arc;jumpSize=16;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1">
|
||||||
|
<mxGeometry width="240" relative="1" as="geometry">
|
||||||
|
<mxPoint x="-790" y="40" as="sourcePoint"/>
|
||||||
|
<mxPoint x="-930" y="40" as="targetPoint"/>
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
</object>
|
||||||
|
<object placeholders="1" c4Type="Relationship" id="69">
|
||||||
|
<mxCell style="endArrow=blockThin;html=1;fontSize=10;fontColor=#404040;strokeWidth=1;endFill=1;strokeColor=#828282;elbow=vertical;metaEdit=1;endSize=14;startSize=14;jumpStyle=arc;jumpSize=16;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1">
|
||||||
|
<mxGeometry width="240" relative="1" as="geometry">
|
||||||
|
<mxPoint x="-520" y="9.23" as="sourcePoint"/>
|
||||||
|
<mxPoint x="-380" y="9.23" as="targetPoint"/>
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
</object>
|
||||||
|
<object placeholders="1" c4Type="Relationship" id="70">
|
||||||
|
<mxCell style="endArrow=blockThin;html=1;fontSize=10;fontColor=#404040;strokeWidth=1;endFill=1;strokeColor=#828282;elbow=vertical;metaEdit=1;endSize=14;startSize=14;jumpStyle=arc;jumpSize=16;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1">
|
||||||
|
<mxGeometry width="240" relative="1" as="geometry">
|
||||||
|
<mxPoint x="-380" y="29.23" as="sourcePoint"/>
|
||||||
|
<mxPoint x="-520" y="29.23" as="targetPoint"/>
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
</object>
|
||||||
|
</root>
|
||||||
|
</mxGraphModel>
|
||||||
|
</diagram>
|
||||||
|
</mxfile>
|
||||||
117
Вопросы по архитектуре.md
Normal file
117
Вопросы по архитектуре.md
Normal file
@ -0,0 +1,117 @@
|
|||||||
|
[Назад](/README.md)
|
||||||
|
|
||||||
|
# Вопросы по архитектуре TaskManager
|
||||||
|
|
||||||
|
## 1. Стандартизация сообщений
|
||||||
|
- Какие ключевые поля должны быть в стандартизированном сообщении?
|
||||||
|
- Например: task_id, source_system, target_system, task_type, priority, description, attachments, due_date
|
||||||
|
- Нужна ли поддержка разных типов задач (одноразовые, периодические, срочные)?
|
||||||
|
|
||||||
|
**Ответ:**
|
||||||
|
1. Пока не думал над контрактом, тк это уже детали. Наверно общие поля стоит указать, как минимум для примера. Но контракт точно поменяется, многое будет зависить от выбора решений.
|
||||||
|
2. Задачи точно будут одноразовые и периодические
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. Connections-service
|
||||||
|
- Связи между системами должны быть двусторонними или направленными?
|
||||||
|
- Нужна ли поддержка правил маршрутизации (например, "все задачи типа 'уборка' из System_1 идут в System_2")?
|
||||||
|
- Должны ли связи настраиваться динамически через админку без перезапуска сервисов?
|
||||||
|
|
||||||
|
**Ответ:**
|
||||||
|
1. Сложно сказать, наверное правильнее строить односторонние связи. В случае если нам нужна двусторонняя связь, то мы сперва деляем связь от системы 1 к системе 2, а потом отдельную связь от системы 2 к системе 1. Думаю так будет гибче?
|
||||||
|
2. Какие то правила наверняка потребуются в будующем, стоит заложится под это, но пока не понятно как это будет
|
||||||
|
3. Да связи настраиваются динамически через админку и без перезапуска.
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. Адаптеры
|
||||||
|
- Какие типы внешних систем предполагаются для первых адаптеров? (PMS системы, ERP, существующие task-менеджеры?)
|
||||||
|
- Адаптеры должны работать по push-модели (отправляют сами) или pull-модели (периодически опрашивают внешние системы)?
|
||||||
|
- Нужна ли поддержка WebHooks для интеграций?
|
||||||
|
|
||||||
|
**Ответ:**
|
||||||
|
1. PMS, ERP, управление уборщицами
|
||||||
|
2. Суть адаптера в том, что он адаптер. Системы бывают очень разные, гдето есть api, гдето надо будет самому пойти в базу, гдето нужно опрашивать систему, гдето система сама будет отправлять данные. Вообщем каждый адаптер будет уникален, но его задача адаптировать сообщения от\из системы в нашу
|
||||||
|
3. Пока сложно сказать, не понятно применение, какие у тебя идеи?
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. Tasks-service
|
||||||
|
- Какие основные статусы задачи? (created, assigned, in_progress, completed, cancelled, rejected?)
|
||||||
|
- Нужна ли поддержка подзадач и зависимостей между задачами?
|
||||||
|
- Нужно ли версионирование задач (история изменений)?
|
||||||
|
|
||||||
|
**Ответ:**
|
||||||
|
1. Пока да, но вероятно пользователь захочет созхдавать "свои" статусы. Поэтому вероятно стоит заложится что в MVP делаем стандартынй набор, а потом чтобы смогли поддержать гибкость
|
||||||
|
2. Между задачами точно появятся зависимости. На счет подзадач не уверен, пока откажемся от них
|
||||||
|
3. История изменений нужна
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 5. Безопасность и разграничение доступа
|
||||||
|
- Будет ли мультитенантность (несколько отелей в одной инсталляции)?
|
||||||
|
- Какие основные роли предполагаются? (admin, manager, department_head, worker?)
|
||||||
|
- Нужна ли изоляция данных между отелями?
|
||||||
|
|
||||||
|
**Ответ:**
|
||||||
|
1. Да отелей у компании может быть несколько
|
||||||
|
2. админ, техподдержка, и по ролям дальше, все виды сотрудников. скорее всего тоже надо делать настраиваемым, чтобы можно было для отелей настроить свои роли, вдруг там уникальные какието названия
|
||||||
|
3. Скорее всего нет, так как тот же маркетинг один на всю сетку отелей. Мы все же говорим что отелей несколько, но владелец один. Тоесть между отелями разных владельцев связей не будет!
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 6. Масштабирование
|
||||||
|
- Сколько отелей планируется поддерживать в одной инсталляции?
|
||||||
|
- Какой объем сообщений в день ожидается (примерно)?
|
||||||
|
- Kafka будет в одном экземпляре или нужен кластер?
|
||||||
|
|
||||||
|
**Ответ:**
|
||||||
|
1. Может быть разное, от 1 до 50 (а может и больше)
|
||||||
|
2. Пока не известно, будем проводить НТ после разработки MVP
|
||||||
|
3. Пока предполагаем одну, кажется должно хватить. Разграничивать сообщения топиками.
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 7. Дополнительные сервисы
|
||||||
|
- **File Storage Service** - где хранить фото/файлы? (S3-compatible, локально, CDN?)
|
||||||
|
- **Notification Service** - нужны ли уведомления? (email, push, SMS?)
|
||||||
|
- **Audit Service** - нужен ли отдельный сервис для аудита действий?
|
||||||
|
- **Scheduler Service** - для периодических задач нужен отдельный сервис?
|
||||||
|
|
||||||
|
**Ответ:**
|
||||||
|
1. s3
|
||||||
|
2. уведомления нужны: email, push, sms, telegram, max и любые другие месенджеры
|
||||||
|
3. да аудит нужен
|
||||||
|
4. scheduler тоже нужен
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 8. Технологический стек
|
||||||
|
- Python сервисы - какой фреймворк? (FastAPI, Django, Flask?)
|
||||||
|
- Нужна ли REST API Gateway перед всеми сервисами?
|
||||||
|
- GraphQL рассматривается или только REST?
|
||||||
|
- Контейнеризация (Docker) + оркестрация (Kubernetes, Docker Compose)?
|
||||||
|
|
||||||
|
**Ответ:**
|
||||||
|
1. Пока не понятно. Это уже детали
|
||||||
|
2. Rest api нужно для веба. Но еще для веба нужно получать информацию и от сервера. Поэтому вероятно лучше сразу смотреть в grpc + может rest оставить для каких то отдельных запросов
|
||||||
|
3. Да, скорее всего кластер кубер. Сервисы по контейнерам с возможностью масштабирования подов
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 9. Дополнительные вопросы от вас
|
||||||
|
Есть ли у вас дополнительные требования или ограничения, которые нужно учесть при проектировании?
|
||||||
|
|
||||||
|
**Ответ:**
|
||||||
|
1. Пока наверно все рассказал
|
||||||
|
|
||||||
|
|
||||||
Reference in New Issue
Block a user