B17/E5: ингестия полевых данных КОНТУРа
- POST /operations/{id}/field-data/sync: тянет GET /api/v1/vector/areas-checked
→ идемпотентный upsert в areas_checked (dedupe по contour_area_id:
geom/checked_at/result/coverage_pct/team_label, source=contour)
- GET /operations/{id}/areas-checked: теперь из локальной БД после sync
(source=db), фолбэк на живой прокси КОНТУРа если пусто (source=contour/empty)
- миграция 011_b17_field_data: areas_checked +contour_area_id/team_label/source
(+check ck_areas_checked_source)
- аудит field_data_sync; лог vector.contour field_sync_*
- фронт: кнопка «⟳ Синхронизировать полевые данные» в КОНТУР-панели,
слой проверенных квадратов на карте (зелёный=clear ≥99.5%, жёлтый=partial)
- тесты: +9 (267 passed) — sync/идемпотентность/502/аудит/локальное чтение
This commit is contained in:
+6
-1
@@ -203,10 +203,15 @@ class AreaChecked(Base):
|
||||
checked_at = Column(DateTime(timezone=True))
|
||||
result = Column(String(20), default="partial")
|
||||
coverage_pct = Column(Float)
|
||||
created_at = Column(DateTime, server_default=func.now())
|
||||
created_at = Column(DateTime(timezone=True), server_default=func.now())
|
||||
# B17: идемпотентный ингест из КОНТУРа
|
||||
contour_area_id = Column(String(64), index=True) # area_id на стороне КОНТУРа
|
||||
team_label = Column(String(100)) # callsign цепи (КОНТУР)
|
||||
source = Column(String(20), default="manual") # manual|contour
|
||||
|
||||
__table_args__ = (
|
||||
sa.CheckConstraint("result IN ('clear','found','partial')", name="ck_areas_checked_result"),
|
||||
sa.CheckConstraint("source IN ('manual','contour')", name="ck_areas_checked_source"),
|
||||
)
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user