@startuml title MaaS — end-to-end (process-checklist). Пример с MSK 2024-12-04 autonumber actor "Владелец" as Owner actor "Оператор" as Operator participant "API.Organization" as OrgAPI participant "API.Facility" as FacAPI participant "API.Checklist" as ChkAPI participant "API.ReviewTask" as RTAPI participant "Validators/Schedule" as Val participant "Boilerplates/Images" as Img participant "Scheduler (task_generator)" as Sched participant "IntervalCalculator" as Calc database "MongoDB (maas.*)" as DB == Создание организации == Owner -> OrgAPI : create(name, owner_id="user_123") OrgAPI -> DB : insert into maas.organizations\n{_id=owner_id, name, created_at, deleted=false} DB --> OrgAPI : ok == Создание заведения == Owner -> FacAPI : create(name="Shop #1", tz="Europe/Moscow", camera_ids=["cam_a"]) FacAPI -> Val : cameras_have_rights(["cam_a"]) Val --> FacAPI : ok FacAPI -> DB : insert into maas.facilities\n{_id="fac_001", organization_id, tz, camera_ids} DB --> FacAPI : ok == Создание чек-листа (type=process) == Owner -> ChkAPI : create(name, type="process", enabled=true,\nschedule, sources=[{facility:"fac_001", cameras:["cam_a"]}], questions) ChkAPI -> Val : validate {schedule, sources, enums} Val --> ChkAPI : ok ChkAPI -> Img : normalize/upload description_image(s) Img --> ChkAPI : description_image_url(s) ChkAPI -> DB : insert into maas.checklists\n{_id="chk_001", schedule, sources, questions,\n_marks:{}, created_at, deleted=false} DB --> ChkAPI : ok == Генерация задачи планировщиком == note over Sched now = 2024-12-05 06:06:06 MSK mark = _marks["fac_001"] или created_at schedule: ср/пт 15:00–16:59:59 end note Sched -> DB : aggregate активные чек-листы + lookup facilities Sched -> Calc : calc_allowed_interval(mark, now, schedule, tz="Europe/Moscow") note right of Calc Возврат: окно, которое завершилось [2024-12-04 15:00:00, 16:59:59] MSK end note Calc --> Sched : interval=[start_ts, end_ts] alt найдён завершившийся интервал Sched -> DB : insert into maas.review_tasks\n{organization_id, owner_id, checklist_id="chk_001",\n sources:{facility:"fac_001", cameras:["cam_a"]},\n type="process", status="open", assignee_id="NOT_SET",\n interval:[start_ts, end_ts], questions(snapshot),\n checklist(snapshot), facility(snapshot), created_at} DB --> Sched : ok Sched -> DB : update maas.checklists\n{$set: {"_marks.fac_001": now_ts}, updated_at} DB --> Sched : ok else интервал не найден Sched -> Sched: пропуск генерации end == Назначение и выполнение == Operator -> RTAPI : take_next() RTAPI -> DB : findOneAndUpdate в maas.review_tasks\n{status:"open"} -> {status:"in_progress", assignee_id=Operator} DB --> RTAPI : возвращает задачу RTAPI --> Operator: детали задачи (interval, questions, sources, ...) == Отметка результата вопроса == Operator -> RTAPI : update_question_result(task_id, qidx=0,\n comment="OK", proof_image=...) RTAPI -> Img : upload proof_image\n→ proof_image_url Img --> RTAPI : url RTAPI -> DB : update maas.review_tasks\n{questions[0].comment, questions[0].proof_image_url,\n updated_at} DB --> RTAPI : ok @enduml