E3 (B21): операции мультипоиска — статусная машина, скоуп, дашборд
- Модель search_operations: title, case_id (unique — операция на карточку),
status (planned/active/paused/completed/archived, CheckConstraint),
unit_id, contour_operation_id (заготовка B20-E4), created_by, closed_at.
- Alembic 009_e3_operations.
- backend/routers/operations.py: POST (создание; unit по умолчанию =
подразделение создателя; скоуп-проверка), GET список (скоуп-фильтр),
GET /{id} (403 вне скоупа), GET /summary (active/total/completed_24h),
PATCH (title/unit/status со статусной машиной: planned→active⇄paused→
completed→archived; недопустимые переходы 400; completed ставит closed_at).
Всё с аудитом operation_create/operation_update.
- Скоуп: unit_id ∈ visible_unit_ids (своё+подчинённые); РЦУ РЧС — все.
- Тесты E3 (12): создание с юнитом/дефолт/дубль кейса/cross-unit 403,
скоуп списков, статусная машина, summary, аудит, cross-scope 403.
222 passed, 5 skipped.
This commit is contained in:
@@ -337,6 +337,31 @@ class SecuritySetting(Base):
|
||||
|
||||
# ==================== B21/E2: аудит действий ====================
|
||||
|
||||
class SearchOperation(Base):
|
||||
"""B21/E3: поисковая операция — надстройка над карточкой (cases)."""
|
||||
__tablename__ = "search_operations"
|
||||
|
||||
id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
|
||||
title = Column(String(255), nullable=False)
|
||||
case_id = Column(UUID(as_uuid=True), ForeignKey("cases.id", ondelete="CASCADE"), nullable=False, unique=True)
|
||||
status = Column(String(20), nullable=False, default="active")
|
||||
unit_id = Column(UUID(as_uuid=True), ForeignKey("mchs_units.id", ondelete="SET NULL"))
|
||||
contour_operation_id = Column(UUID(as_uuid=True))
|
||||
created_by = Column(UUID(as_uuid=True), ForeignKey("users.id", ondelete="SET NULL"))
|
||||
created_at = Column(DateTime(timezone=True), server_default=func.now())
|
||||
updated_at = Column(DateTime(timezone=True), server_default=func.now())
|
||||
closed_at = Column(DateTime(timezone=True))
|
||||
|
||||
__table_args__ = (
|
||||
sa.CheckConstraint(
|
||||
"status IN ('planned','active','paused','completed','archived')",
|
||||
name="ck_search_operations_status",
|
||||
),
|
||||
sa.Index("idx_search_operations_status", "status"),
|
||||
sa.Index("idx_search_operations_unit", "unit_id"),
|
||||
)
|
||||
|
||||
|
||||
class AuditEvent(Base):
|
||||
"""Аудит действий (immutable): кто, когда, что. CREATE+READ only."""
|
||||
__tablename__ = "audit_events"
|
||||
|
||||
Reference in New Issue
Block a user