feat: build dossier service timelines
This commit is contained in:
@@ -107,6 +107,20 @@ def get_dossier(dossier_id):
|
||||
return _decode_dossier(rows[0]) if rows else None
|
||||
|
||||
|
||||
def list_dossier_documents(dossier_id):
|
||||
"""Вернуть документы досье в установленном порядке вместе с ролью связи."""
|
||||
return query(
|
||||
"""SELECT dd.*, d.filename, d.status AS document_status, d.doc_type,
|
||||
d.own_number, d.parent_number, d.doc_date, d.counterparty,
|
||||
d.zip_source
|
||||
FROM dossier_documents dd
|
||||
JOIN documents d ON d.id = dd.document_id
|
||||
WHERE dd.dossier_id = %s
|
||||
ORDER BY dd.seq_order, d.created_at, d.id""",
|
||||
(dossier_id,),
|
||||
)
|
||||
|
||||
|
||||
def clear_batch_dossiers(batch_id):
|
||||
"""Удалить все досье batch; таблицы с ON DELETE CASCADE очистятся вместе с ними."""
|
||||
with transaction():
|
||||
|
||||
@@ -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):
|
||||
"""Получить историю либо активный на дату срез по досье.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user