feat: build dossier service timelines

This commit is contained in:
2026-10-31 10:02:55 +03:00
parent 78f4a052e9
commit 56997cb64e
3 changed files with 458 additions and 0 deletions
+42
View File
@@ -30,6 +30,14 @@ def get_service_item(service_item_id):
return rows[0] if rows else None
def list_service_items(dossier_id):
"""Получить все идентичности услуг досье в стабильном порядке."""
return query(
"SELECT * FROM service_items WHERE dossier_id = %s ORDER BY created_at, id",
(dossier_id,),
)
def insert_interval(data):
"""Создать интервал, сохраняя точные цены/количества строками.
@@ -65,6 +73,40 @@ def close_interval(interval_id, valid_to, closed_by_document_id=None):
)
def update_interval(interval_id, values):
"""Обновить разрешённый набор полей интервала без динамических имён от клиента."""
allowed = {
"valid_from", "valid_to", "date_status", "date_basis", "raw_name",
"config_params_json", "price", "qty", "sum", "vat_mode", "table_ref",
"quote", "status", "closed_by_document_id", "source_document_id",
}
selected = {field: value for field, value in values.items() if field in allowed}
if not selected:
return 0
assignments = ", ".join(f"{field} = %s" for field in selected)
return execute(
f"UPDATE timeline_intervals SET {assignments} WHERE id = %s",
[*selected.values(), interval_id],
)
def list_open_intervals(dossier_id, service_item_id=None):
"""Вернуть открытые интервалы, опционально отфильтрованные по услуге."""
if service_item_id is None:
return query(
"""SELECT * FROM timeline_intervals
WHERE dossier_id = %s AND valid_to IS NULL
ORDER BY valid_from, service_item_id, id""",
(dossier_id,),
)
return query(
"""SELECT * FROM timeline_intervals
WHERE dossier_id = %s AND service_item_id = %s AND valid_to IS NULL
ORDER BY valid_from, id""",
(dossier_id, service_item_id),
)
def list_timeline(dossier_id, as_of_date=None):
"""Получить историю либо активный на дату срез по досье.