Merge pull request 'projects-summary-handler: ручка для таблицы снизу страницы навигации' (#93) from projects-summary-handler into test
Reviewed-on: #93
This commit is contained in:
commit
e518579a38
82
api/alembic/versions/0017_project_summary.py
Normal file
82
api/alembic/versions/0017_project_summary.py
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
import os
|
||||||
|
import re
|
||||||
|
|
||||||
|
from alembic import op
|
||||||
|
|
||||||
|
|
||||||
|
revision = "0017"
|
||||||
|
down_revision = "0016"
|
||||||
|
branch_labels = None
|
||||||
|
depends_on = None
|
||||||
|
|
||||||
|
|
||||||
|
_DOLLAR_TAG_RE = re.compile(r"\$\w+\$")
|
||||||
|
|
||||||
|
|
||||||
|
def _find_dollar_tag(line: str) -> str | None:
|
||||||
|
m = _DOLLAR_TAG_RE.search(line.strip())
|
||||||
|
return m.group(0) if m else None
|
||||||
|
|
||||||
|
|
||||||
|
def _split_statements(sql: str) -> list[str]:
|
||||||
|
statements: list[str] = []
|
||||||
|
current: list[str] = []
|
||||||
|
in_dollar = False
|
||||||
|
dollar_tag: str | None = None
|
||||||
|
|
||||||
|
for line in sql.split("\n"):
|
||||||
|
stripped = line.strip()
|
||||||
|
if stripped.startswith("--"):
|
||||||
|
continue
|
||||||
|
|
||||||
|
if not in_dollar:
|
||||||
|
tag = _find_dollar_tag(stripped)
|
||||||
|
if tag and tag.endswith("$") and tag.startswith("$"):
|
||||||
|
dollar_tag = tag
|
||||||
|
in_dollar = True
|
||||||
|
current.append(line)
|
||||||
|
continue
|
||||||
|
|
||||||
|
if in_dollar and dollar_tag and stripped.startswith(dollar_tag):
|
||||||
|
after = stripped[len(dollar_tag):].strip()
|
||||||
|
if after == ";" or after == "":
|
||||||
|
in_dollar = False
|
||||||
|
dollar_tag = None
|
||||||
|
if after == ";":
|
||||||
|
current.append(line)
|
||||||
|
statements.append("\n".join(current))
|
||||||
|
current = []
|
||||||
|
continue
|
||||||
|
|
||||||
|
if not in_dollar and stripped.rstrip().endswith(";"):
|
||||||
|
current.append(line)
|
||||||
|
statements.append("\n".join(current))
|
||||||
|
current = []
|
||||||
|
continue
|
||||||
|
|
||||||
|
current.append(line)
|
||||||
|
|
||||||
|
remaining = "\n".join(current).strip()
|
||||||
|
if remaining:
|
||||||
|
statements.append(remaining)
|
||||||
|
|
||||||
|
return statements
|
||||||
|
|
||||||
|
|
||||||
|
def upgrade() -> None:
|
||||||
|
ddl_path = os.path.join(os.path.dirname(__file__), "sql", "0017_project_summary.sql")
|
||||||
|
with open(ddl_path) as f:
|
||||||
|
content = f.read()
|
||||||
|
|
||||||
|
statements = _split_statements(content)
|
||||||
|
for stmt in statements:
|
||||||
|
stripped = stmt.strip().rstrip(";").strip()
|
||||||
|
if not stripped:
|
||||||
|
continue
|
||||||
|
if all(l.strip().startswith("--") or not l.strip() for l in stripped.split("\n")):
|
||||||
|
continue
|
||||||
|
op.execute(stripped)
|
||||||
|
|
||||||
|
|
||||||
|
def downgrade() -> None:
|
||||||
|
pass
|
||||||
149
api/alembic/versions/sql/0017_project_summary.sql
Normal file
149
api/alembic/versions/sql/0017_project_summary.sql
Normal file
@ -0,0 +1,149 @@
|
|||||||
|
-- DROP FUNCTION v3.v_project_summary_jsonb(int4);
|
||||||
|
|
||||||
|
CREATE OR REPLACE FUNCTION v3.v_project_summary_jsonb(p_project_id integer)
|
||||||
|
RETURNS TABLE(row_type character varying, depth integer, sort_order bigint, data jsonb)
|
||||||
|
LANGUAGE sql
|
||||||
|
STABLE
|
||||||
|
AS $function$
|
||||||
|
WITH
|
||||||
|
project AS (
|
||||||
|
SELECT p.id, p.name
|
||||||
|
FROM v3.project p
|
||||||
|
WHERE p.id = p_project_id
|
||||||
|
),
|
||||||
|
base AS (
|
||||||
|
SELECT
|
||||||
|
rpy.year,
|
||||||
|
r.report_type,
|
||||||
|
ei.sheet,
|
||||||
|
q.quarter,
|
||||||
|
q.adj_by_items,
|
||||||
|
q.adj_increase,
|
||||||
|
q.actual_m1, q.actual_m2, q.actual_m3
|
||||||
|
FROM v3.rf_project_year rpy
|
||||||
|
LEFT JOIN v3.rf_project_report r ON r.rf_project_year_id = rpy.id
|
||||||
|
LEFT JOIN v3.rf_project_report_line l ON l.rf_project_report_id = r.id
|
||||||
|
LEFT JOIN v3.rf_project_report_quarter q ON q.rf_project_report_line_id = l.id
|
||||||
|
LEFT JOIN v3.expense_item ei ON ei.id = l.expense_item_id
|
||||||
|
WHERE rpy.project_id = p_project_id
|
||||||
|
),
|
||||||
|
py AS (
|
||||||
|
SELECT
|
||||||
|
year,
|
||||||
|
-- Объем финансирования по контрольному листу (годовой базовый план = adj_by_items)
|
||||||
|
COALESCE(SUM(adj_by_items) FILTER (WHERE sheet = 'AHR'), 0) AS fin_ahr,
|
||||||
|
COALESCE(SUM(adj_by_items) FILTER (WHERE sheet = 'AHR' AND report_type = 'LIMIT'), 0) AS fin_ahr_limit,
|
||||||
|
COALESCE(SUM(adj_by_items) FILTER (WHERE sheet = 'AHR' AND report_type = 'CURRENT_EXPENSES'), 0) AS fin_ahr_current,
|
||||||
|
COALESCE(SUM(adj_by_items) FILTER (WHERE sheet = 'CAP' AND report_type = 'LIMIT'), 0) AS fin_kv,
|
||||||
|
-- Базовый период 01.01-31.03 (базовый план, квартал 1)
|
||||||
|
COALESCE(SUM(adj_by_items) FILTER (WHERE sheet = 'AHR' AND quarter = 1), 0) AS bq1_ahr,
|
||||||
|
COALESCE(SUM(adj_by_items) FILTER (WHERE sheet = 'AHR' AND quarter = 1 AND report_type = 'LIMIT'), 0) AS bq1_ahr_limit,
|
||||||
|
COALESCE(SUM(adj_by_items) FILTER (WHERE sheet = 'AHR' AND quarter = 1 AND report_type = 'CURRENT_EXPENSES'), 0) AS bq1_ahr_current,
|
||||||
|
COALESCE(SUM(adj_by_items) FILTER (WHERE sheet = 'CAP' AND quarter = 1 AND report_type = 'LIMIT'), 0) AS bq1_kv,
|
||||||
|
-- Скорректированный период 01.04-30.06 (квартал 2, corrected_plan = adj_by_items + adj_increase)
|
||||||
|
COALESCE(SUM(COALESCE(adj_by_items,0)+COALESCE(adj_increase,0)) FILTER (WHERE sheet = 'AHR' AND quarter = 2), 0) AS cq2_ahr,
|
||||||
|
COALESCE(SUM(COALESCE(adj_by_items,0)+COALESCE(adj_increase,0)) FILTER (WHERE sheet = 'AHR' AND quarter = 2 AND report_type = 'LIMIT'), 0) AS cq2_ahr_limit,
|
||||||
|
COALESCE(SUM(COALESCE(adj_by_items,0)+COALESCE(adj_increase,0)) FILTER (WHERE sheet = 'AHR' AND quarter = 2 AND report_type = 'CURRENT_EXPENSES'), 0) AS cq2_ahr_current,
|
||||||
|
COALESCE(SUM(COALESCE(adj_by_items,0)+COALESCE(adj_increase,0)) FILTER (WHERE sheet = 'CAP' AND quarter = 2 AND report_type = 'LIMIT'), 0) AS cq2_kv,
|
||||||
|
-- Скорректированный период 01.07-30.09 (квартал 3)
|
||||||
|
COALESCE(SUM(COALESCE(adj_by_items,0)+COALESCE(adj_increase,0)) FILTER (WHERE sheet = 'AHR' AND quarter = 3), 0) AS cq3_ahr,
|
||||||
|
COALESCE(SUM(COALESCE(adj_by_items,0)+COALESCE(adj_increase,0)) FILTER (WHERE sheet = 'AHR' AND quarter = 3 AND report_type = 'LIMIT'), 0) AS cq3_ahr_limit,
|
||||||
|
COALESCE(SUM(COALESCE(adj_by_items,0)+COALESCE(adj_increase,0)) FILTER (WHERE sheet = 'AHR' AND quarter = 3 AND report_type = 'CURRENT_EXPENSES'), 0) AS cq3_ahr_current,
|
||||||
|
COALESCE(SUM(COALESCE(adj_by_items,0)+COALESCE(adj_increase,0)) FILTER (WHERE sheet = 'CAP' AND quarter = 3 AND report_type = 'LIMIT'), 0) AS cq3_kv,
|
||||||
|
-- Скорректированный период 01.10-31.12 (квартал 4)
|
||||||
|
COALESCE(SUM(COALESCE(adj_by_items,0)+COALESCE(adj_increase,0)) FILTER (WHERE sheet = 'AHR' AND quarter = 4), 0) AS cq4_ahr,
|
||||||
|
COALESCE(SUM(COALESCE(adj_by_items,0)+COALESCE(adj_increase,0)) FILTER (WHERE sheet = 'AHR' AND quarter = 4 AND report_type = 'LIMIT'), 0) AS cq4_ahr_limit,
|
||||||
|
COALESCE(SUM(COALESCE(adj_by_items,0)+COALESCE(adj_increase,0)) FILTER (WHERE sheet = 'AHR' AND quarter = 4 AND report_type = 'CURRENT_EXPENSES'), 0) AS cq4_ahr_current,
|
||||||
|
COALESCE(SUM(COALESCE(adj_by_items,0)+COALESCE(adj_increase,0)) FILTER (WHERE sheet = 'CAP' AND quarter = 4 AND report_type = 'LIMIT'), 0) AS cq4_kv,
|
||||||
|
-- Фактические расходы АХР по кварталам (actual = m1+m2+m3)
|
||||||
|
COALESCE(SUM(COALESCE(actual_m1,0)+COALESCE(actual_m2,0)+COALESCE(actual_m3,0)) FILTER (WHERE sheet = 'AHR' AND quarter = 1), 0) AS aq1_ahr,
|
||||||
|
COALESCE(SUM(COALESCE(actual_m1,0)+COALESCE(actual_m2,0)+COALESCE(actual_m3,0)) FILTER (WHERE sheet = 'AHR' AND quarter = 1 AND report_type = 'LIMIT'), 0) AS aq1_ahr_limit,
|
||||||
|
COALESCE(SUM(COALESCE(actual_m1,0)+COALESCE(actual_m2,0)+COALESCE(actual_m3,0)) FILTER (WHERE sheet = 'AHR' AND quarter = 1 AND report_type = 'CURRENT_EXPENSES'), 0) AS aq1_ahr_current,
|
||||||
|
COALESCE(SUM(COALESCE(actual_m1,0)+COALESCE(actual_m2,0)+COALESCE(actual_m3,0)) FILTER (WHERE sheet = 'AHR' AND quarter = 2), 0) AS aq2_ahr,
|
||||||
|
COALESCE(SUM(COALESCE(actual_m1,0)+COALESCE(actual_m2,0)+COALESCE(actual_m3,0)) FILTER (WHERE sheet = 'AHR' AND quarter = 2 AND report_type = 'LIMIT'), 0) AS aq2_ahr_limit,
|
||||||
|
COALESCE(SUM(COALESCE(actual_m1,0)+COALESCE(actual_m2,0)+COALESCE(actual_m3,0)) FILTER (WHERE sheet = 'AHR' AND quarter = 2 AND report_type = 'CURRENT_EXPENSES'), 0) AS aq2_ahr_current,
|
||||||
|
COALESCE(SUM(COALESCE(actual_m1,0)+COALESCE(actual_m2,0)+COALESCE(actual_m3,0)) FILTER (WHERE sheet = 'AHR' AND quarter = 3), 0) AS aq3_ahr,
|
||||||
|
COALESCE(SUM(COALESCE(actual_m1,0)+COALESCE(actual_m2,0)+COALESCE(actual_m3,0)) FILTER (WHERE sheet = 'AHR' AND quarter = 3 AND report_type = 'LIMIT'), 0) AS aq3_ahr_limit,
|
||||||
|
COALESCE(SUM(COALESCE(actual_m1,0)+COALESCE(actual_m2,0)+COALESCE(actual_m3,0)) FILTER (WHERE sheet = 'AHR' AND quarter = 3 AND report_type = 'CURRENT_EXPENSES'), 0) AS aq3_ahr_current,
|
||||||
|
COALESCE(SUM(COALESCE(actual_m1,0)+COALESCE(actual_m2,0)+COALESCE(actual_m3,0)) FILTER (WHERE sheet = 'AHR' AND quarter = 4), 0) AS aq4_ahr,
|
||||||
|
COALESCE(SUM(COALESCE(actual_m1,0)+COALESCE(actual_m2,0)+COALESCE(actual_m3,0)) FILTER (WHERE sheet = 'AHR' AND quarter = 4 AND report_type = 'LIMIT'), 0) AS aq4_ahr_limit,
|
||||||
|
COALESCE(SUM(COALESCE(actual_m1,0)+COALESCE(actual_m2,0)+COALESCE(actual_m3,0)) FILTER (WHERE sheet = 'AHR' AND quarter = 4 AND report_type = 'CURRENT_EXPENSES'), 0) AS aq4_ahr_current,
|
||||||
|
-- Фактические расходы КВ по кварталам
|
||||||
|
COALESCE(SUM(COALESCE(actual_m1,0)+COALESCE(actual_m2,0)+COALESCE(actual_m3,0)) FILTER (WHERE sheet = 'CAP' AND quarter = 1), 0) AS aq1_kv,
|
||||||
|
COALESCE(SUM(COALESCE(actual_m1,0)+COALESCE(actual_m2,0)+COALESCE(actual_m3,0)) FILTER (WHERE sheet = 'CAP' AND quarter = 1 AND report_type = 'LIMIT'), 0) AS aq1_kv_limit,
|
||||||
|
COALESCE(SUM(COALESCE(actual_m1,0)+COALESCE(actual_m2,0)+COALESCE(actual_m3,0)) FILTER (WHERE sheet = 'CAP' AND quarter = 1 AND report_type = 'CURRENT_EXPENSES'), 0) AS aq1_kv_current,
|
||||||
|
COALESCE(SUM(COALESCE(actual_m1,0)+COALESCE(actual_m2,0)+COALESCE(actual_m3,0)) FILTER (WHERE sheet = 'CAP' AND quarter = 2), 0) AS aq2_kv,
|
||||||
|
COALESCE(SUM(COALESCE(actual_m1,0)+COALESCE(actual_m2,0)+COALESCE(actual_m3,0)) FILTER (WHERE sheet = 'CAP' AND quarter = 2 AND report_type = 'LIMIT'), 0) AS aq2_kv_limit,
|
||||||
|
COALESCE(SUM(COALESCE(actual_m1,0)+COALESCE(actual_m2,0)+COALESCE(actual_m3,0)) FILTER (WHERE sheet = 'CAP' AND quarter = 2 AND report_type = 'CURRENT_EXPENSES'), 0) AS aq2_kv_current,
|
||||||
|
COALESCE(SUM(COALESCE(actual_m1,0)+COALESCE(actual_m2,0)+COALESCE(actual_m3,0)) FILTER (WHERE sheet = 'CAP' AND quarter = 3), 0) AS aq3_kv,
|
||||||
|
COALESCE(SUM(COALESCE(actual_m1,0)+COALESCE(actual_m2,0)+COALESCE(actual_m3,0)) FILTER (WHERE sheet = 'CAP' AND quarter = 3 AND report_type = 'LIMIT'), 0) AS aq3_kv_limit,
|
||||||
|
COALESCE(SUM(COALESCE(actual_m1,0)+COALESCE(actual_m2,0)+COALESCE(actual_m3,0)) FILTER (WHERE sheet = 'CAP' AND quarter = 3 AND report_type = 'CURRENT_EXPENSES'), 0) AS aq3_kv_current,
|
||||||
|
COALESCE(SUM(COALESCE(actual_m1,0)+COALESCE(actual_m2,0)+COALESCE(actual_m3,0)) FILTER (WHERE sheet = 'CAP' AND quarter = 4), 0) AS aq4_kv,
|
||||||
|
COALESCE(SUM(COALESCE(actual_m1,0)+COALESCE(actual_m2,0)+COALESCE(actual_m3,0)) FILTER (WHERE sheet = 'CAP' AND quarter = 4 AND report_type = 'LIMIT'), 0) AS aq4_kv_limit,
|
||||||
|
COALESCE(SUM(COALESCE(actual_m1,0)+COALESCE(actual_m2,0)+COALESCE(actual_m3,0)) FILTER (WHERE sheet = 'CAP' AND quarter = 4 AND report_type = 'CURRENT_EXPENSES'), 0) AS aq4_kv_current
|
||||||
|
FROM base
|
||||||
|
GROUP BY year
|
||||||
|
),
|
||||||
|
rows AS (
|
||||||
|
SELECT 'PROJECT'::varchar AS row_type, NULL::int AS year,
|
||||||
|
NULL::numeric AS fin_ahr, NULL::numeric AS fin_ahr_limit, NULL::numeric AS fin_ahr_current, NULL::numeric AS fin_kv,
|
||||||
|
NULL::numeric AS bq1_ahr, NULL::numeric AS bq1_ahr_limit, NULL::numeric AS bq1_ahr_current, NULL::numeric AS bq1_kv,
|
||||||
|
NULL::numeric AS cq2_ahr, NULL::numeric AS cq2_ahr_limit, NULL::numeric AS cq2_ahr_current, NULL::numeric AS cq2_kv,
|
||||||
|
NULL::numeric AS cq3_ahr, NULL::numeric AS cq3_ahr_limit, NULL::numeric AS cq3_ahr_current, NULL::numeric AS cq3_kv,
|
||||||
|
NULL::numeric AS cq4_ahr, NULL::numeric AS cq4_ahr_limit, NULL::numeric AS cq4_ahr_current, NULL::numeric AS cq4_kv,
|
||||||
|
NULL::numeric AS aq1_ahr, NULL::numeric AS aq1_ahr_limit, NULL::numeric AS aq1_ahr_current,
|
||||||
|
NULL::numeric AS aq2_ahr, NULL::numeric AS aq2_ahr_limit, NULL::numeric AS aq2_ahr_current,
|
||||||
|
NULL::numeric AS aq3_ahr, NULL::numeric AS aq3_ahr_limit, NULL::numeric AS aq3_ahr_current,
|
||||||
|
NULL::numeric AS aq4_ahr, NULL::numeric AS aq4_ahr_limit, NULL::numeric AS aq4_ahr_current,
|
||||||
|
NULL::numeric AS aq1_kv, NULL::numeric AS aq1_kv_limit, NULL::numeric AS aq1_kv_current,
|
||||||
|
NULL::numeric AS aq2_kv, NULL::numeric AS aq2_kv_limit, NULL::numeric AS aq2_kv_current,
|
||||||
|
NULL::numeric AS aq3_kv, NULL::numeric AS aq3_kv_limit, NULL::numeric AS aq3_kv_current,
|
||||||
|
NULL::numeric AS aq4_kv, NULL::numeric AS aq4_kv_limit, NULL::numeric AS aq4_kv_current
|
||||||
|
UNION ALL
|
||||||
|
SELECT 'YEAR'::varchar, year,
|
||||||
|
fin_ahr, fin_ahr_limit, fin_ahr_current, fin_kv,
|
||||||
|
bq1_ahr, bq1_ahr_limit, bq1_ahr_current, bq1_kv,
|
||||||
|
cq2_ahr, cq2_ahr_limit, cq2_ahr_current, cq2_kv,
|
||||||
|
cq3_ahr, cq3_ahr_limit, cq3_ahr_current, cq3_kv,
|
||||||
|
cq4_ahr, cq4_ahr_limit, cq4_ahr_current, cq4_kv,
|
||||||
|
aq1_ahr, aq1_ahr_limit, aq1_ahr_current,
|
||||||
|
aq2_ahr, aq2_ahr_limit, aq2_ahr_current,
|
||||||
|
aq3_ahr, aq3_ahr_limit, aq3_ahr_current,
|
||||||
|
aq4_ahr, aq4_ahr_limit, aq4_ahr_current,
|
||||||
|
aq1_kv, aq1_kv_limit, aq1_kv_current,
|
||||||
|
aq2_kv, aq2_kv_limit, aq2_kv_current,
|
||||||
|
aq3_kv, aq3_kv_limit, aq3_kv_current,
|
||||||
|
aq4_kv, aq4_kv_limit, aq4_kv_current
|
||||||
|
FROM py
|
||||||
|
)
|
||||||
|
SELECT
|
||||||
|
r.row_type,
|
||||||
|
CASE r.row_type WHEN 'PROJECT' THEN 0 ELSE 1 END AS depth,
|
||||||
|
ROW_NUMBER() OVER (
|
||||||
|
ORDER BY CASE r.row_type WHEN 'PROJECT' THEN 0 WHEN 'YEAR' THEN 1 ELSE 2 END,
|
||||||
|
COALESCE(r.year, 0)
|
||||||
|
) AS sort_order,
|
||||||
|
jsonb_build_object(
|
||||||
|
'header', jsonb_build_object('project_id', p_project_id, 'name', p.name, 'year', r.year),
|
||||||
|
'financing', jsonb_build_object('ahr', r.fin_ahr, 'ahr_limit', r.fin_ahr_limit, 'ahr_current', r.fin_ahr_current, 'kv', r.fin_kv),
|
||||||
|
'base_q1', jsonb_build_object('ahr', r.bq1_ahr, 'ahr_limit', r.bq1_ahr_limit, 'ahr_current', r.bq1_ahr_current, 'kv', r.bq1_kv),
|
||||||
|
'corrected_q2', jsonb_build_object('ahr', r.cq2_ahr, 'ahr_limit', r.cq2_ahr_limit, 'ahr_current', r.cq2_ahr_current, 'kv', r.cq2_kv),
|
||||||
|
'corrected_q3', jsonb_build_object('ahr', r.cq3_ahr, 'ahr_limit', r.cq3_ahr_limit, 'ahr_current', r.cq3_ahr_current, 'kv', r.cq3_kv),
|
||||||
|
'corrected_q4', jsonb_build_object('ahr', r.cq4_ahr, 'ahr_limit', r.cq4_ahr_limit, 'ahr_current', r.cq4_ahr_current, 'kv', r.cq4_kv),
|
||||||
|
'actual_ahr', jsonb_build_object(
|
||||||
|
'q1', jsonb_build_object('ahr', r.aq1_ahr, 'ahr_limit', r.aq1_ahr_limit, 'ahr_current', r.aq1_ahr_current),
|
||||||
|
'q2', jsonb_build_object('ahr', r.aq2_ahr, 'ahr_limit', r.aq2_ahr_limit, 'ahr_current', r.aq2_ahr_current),
|
||||||
|
'q3', jsonb_build_object('ahr', r.aq3_ahr, 'ahr_limit', r.aq3_ahr_limit, 'ahr_current', r.aq3_ahr_current),
|
||||||
|
'q4', jsonb_build_object('ahr', r.aq4_ahr, 'ahr_limit', r.aq4_ahr_limit, 'ahr_current', r.aq4_ahr_current)
|
||||||
|
),
|
||||||
|
'actual_kv', jsonb_build_object(
|
||||||
|
'q1', jsonb_build_object('kv', r.aq1_kv, 'kv_limit', r.aq1_kv_limit, 'kv_current', r.aq1_kv_current),
|
||||||
|
'q2', jsonb_build_object('kv', r.aq2_kv, 'kv_limit', r.aq2_kv_limit, 'kv_current', r.aq2_kv_current),
|
||||||
|
'q3', jsonb_build_object('kv', r.aq3_kv, 'kv_limit', r.aq3_kv_limit, 'kv_current', r.aq3_kv_current),
|
||||||
|
'q4', jsonb_build_object('kv', r.aq4_kv, 'kv_limit', r.aq4_kv_limit, 'kv_current', r.aq4_kv_current)
|
||||||
|
)
|
||||||
|
) AS data
|
||||||
|
FROM rows r
|
||||||
|
CROSS JOIN project p;
|
||||||
|
$function$
|
||||||
|
;
|
||||||
@ -175,6 +175,32 @@ async def get_rf_rollup(
|
|||||||
return BaseListResponse(count=len(rows), result=_rows_to_payload(rows))
|
return BaseListResponse(count=len(rows), result=_rows_to_payload(rows))
|
||||||
|
|
||||||
|
|
||||||
|
@router.get("/projects/{project_id}/summary")
|
||||||
|
async def get_project_summary(
|
||||||
|
project_id: int,
|
||||||
|
response: Response,
|
||||||
|
db: AsyncSession = Depends(get_db),
|
||||||
|
current_user: AppUser = Depends(get_current_active_user_with_set_db),
|
||||||
|
) -> BaseListResponse[SheetResponse]:
|
||||||
|
project_service = ProjectService(db)
|
||||||
|
t0 = time.perf_counter()
|
||||||
|
rows = await project_service.get_project_summary_rows(
|
||||||
|
project_id=project_id,
|
||||||
|
user=current_user,
|
||||||
|
)
|
||||||
|
db_ms = (time.perf_counter() - t0) * 1000
|
||||||
|
response.headers["X-DB-Time-Ms"] = f"{db_ms:.2f}"
|
||||||
|
extra = {
|
||||||
|
"type": "db_time",
|
||||||
|
"time_ms": f"{db_ms:.2f}",
|
||||||
|
"handler": "get_project_summary",
|
||||||
|
"project_id": project_id,
|
||||||
|
"user": current_user.id,
|
||||||
|
}
|
||||||
|
logger.info(f"db_time: {extra}", extra=extra)
|
||||||
|
return BaseListResponse(count=len(rows), result=_rows_to_payload(rows))
|
||||||
|
|
||||||
|
|
||||||
@router.patch("/projects/{project_id}/report/{year}/{report_type}/cell")
|
@router.patch("/projects/{project_id}/report/{year}/{report_type}/cell")
|
||||||
async def upd_form3_cell(
|
async def upd_form3_cell(
|
||||||
project_id: int,
|
project_id: int,
|
||||||
|
|||||||
@ -334,6 +334,17 @@ class ProjectRepository:
|
|||||||
)
|
)
|
||||||
).all()
|
).all()
|
||||||
|
|
||||||
|
async def get_project_summary_rows(self, project_id: int) -> list[tuple]:
|
||||||
|
query = text(
|
||||||
|
"""
|
||||||
|
SELECT row_type, depth, sort_order, data
|
||||||
|
FROM v3.v_project_summary_jsonb(CAST(:project_id AS INT))
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
return (
|
||||||
|
await self.db.execute(query, {"project_id": project_id})
|
||||||
|
).all()
|
||||||
|
|
||||||
async def upd_form3_cell(
|
async def upd_form3_cell(
|
||||||
self,
|
self,
|
||||||
report_id: int,
|
report_id: int,
|
||||||
|
|||||||
@ -113,6 +113,16 @@ class ProjectService:
|
|||||||
sections=sections,
|
sections=sections,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
async def get_project_summary_rows(
|
||||||
|
self,
|
||||||
|
project_id: int,
|
||||||
|
user: AppUser,
|
||||||
|
) -> list[tuple]:
|
||||||
|
project = await self.get_instance(project_id, user)
|
||||||
|
if not project:
|
||||||
|
raise ValidationException("Проект не найден")
|
||||||
|
return await self.project_repo.get_project_summary_rows(project_id=project_id)
|
||||||
|
|
||||||
async def upd_form3_cell(
|
async def upd_form3_cell(
|
||||||
self,
|
self,
|
||||||
project_id: int,
|
project_id: int,
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user