@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
