diff --git a/api/alembic/versions/sql/0051_upd_form_cells_subtree.sql b/api/alembic/versions/sql/0051_upd_form_cells_subtree.sql index f3fb76a..2d09e32 100644 --- a/api/alembic/versions/sql/0051_upd_form_cells_subtree.sql +++ b/api/alembic/versions/sql/0051_upd_form_cells_subtree.sql @@ -1,7 +1,5 @@ -- AURORA-1850 (change: openspec/changes/aurora-1850-upd-form-cells-subtree): правка ячейки пересчитывает только затронутое поддерево. --- Параметр фокуса p_focus_lines (D1) и колонка _sort_rank (D2) в построителях FORM_2 AHR/CAP/OPER. --- Тела — буквальные, сняты с БД после 0050 (D8, before-0051.sql); порядок операторов — D9. --- FORM_1 (Task 5): те же правки, v_form1_view, v_form_view. Остальные функции добавляются следующими задачами плана. +-- AURORA-1850: фокусные сборщики FORM_1/FORM_2, скелет с _sort_rank, _form_affected_rows и дельта AHR на фокусном пути, jit=off. DROP FUNCTION v3.v_form2_view(integer, character varying, text[]); DROP FUNCTION v3.v_form2_sheet_jsonb(integer, character varying, text[]); diff --git a/api/tests/integration/test_upd_form_cells_subtree.py b/api/tests/integration/test_upd_form_cells_subtree.py index dda8bde..0829053 100644 --- a/api/tests/integration/test_upd_form_cells_subtree.py +++ b/api/tests/integration/test_upd_form_cells_subtree.py @@ -45,6 +45,7 @@ CASES = { "F2-AHR_LIMIT": ("FORM_2", "AHR_LIMIT", None, None, 0), "F2-OTCH9F": ("FORM_2", "OTCH9F", None, None, 0), "F2-AHR-plan": ("FORM_2", "AHR", None, ["plan"], 2048), + "F1-AHR-plan": ("FORM_1", "AHR", "Support", ["plan"], 2049), } SAT_FORM = 4 @@ -201,7 +202,6 @@ def test_affected_rows_match_reference(client, headers, db_exec, path, case): form_type, sheet, direction, sections, _ = CASES[case] form_id, units, batches = _prepare(client, headers, db_exec, case) assert units, "в листе нет строк" - is_tree = sheet in ("AHR", "CAP", "OPER") for i in units: _check(db_exec, path, form_type, form_id, sheet, [i], direction, sections, f"{case} id={i}", must_have_input=sheet != "AHR_LIMIT" and sheet != "OTCH9F") @@ -209,7 +209,6 @@ def test_affected_rows_match_reference(client, headers, db_exec, path, case): dev = batches[0][-1] rows = affected_rows(db_exec, form_id, sheet, [dev], direction, sections) assert not any(_has_input(r, dev) for r in rows), "Development INPUT попал в результат Support" - del is_tree for n, batch in enumerate(batches): _check(db_exec, path, form_type, form_id, sheet, batch, direction, sections, f"{case} batch#{n}") @@ -373,17 +372,22 @@ def _sort_key_candidate(db_exec): ORDER BY b.id LIMIT 1 """ ) - return rows[0][0] if rows else None + return (rows[0][0], rows[0][1]) if rows else None def test_sort_key_tie_node_before_line(client, headers, db_exec): - child = _sort_key_candidate(db_exec) - if child is None: + cand = _sort_key_candidate(db_exec) + if cand is None: pytest.skip("нет статьи AHR глубины 3 с дочерней глубины 4 и свободным id в budget_line") + child, parent = cand + assert child != parent form_id = _new_form(client, headers, "FORM_2", 2058) + # строка висит на родительской статье, а её id равен id дочерней статьи: + # ключ сортировки INPUT совпадает с ключом узла дочерней статьи (ничья) db_exec( "INSERT INTO v3.budget_line (id, budget_form_id, expense_item_id, name) " - "VALUES (:i, :f, :i, 'tie')", i=child, f=form_id) + "VALUES (:i, :f, :p, 'tie')", i=child, f=form_id, p=parent) + assert db_exec("SELECT expense_item_id FROM v3.budget_line WHERE id = :i", i=child)[0][0] == parent g1 = _get_sheet(client, headers, form_id, "AHR") g2 = _get_sheet(client, headers, form_id, "AHR") assert [row_key(r) for r in g1] == [row_key(r) for r in g2] @@ -391,13 +395,16 @@ def test_sort_key_tie_node_before_line(client, headers, db_exec): assert idx > 0 prev = g1[idx - 1] assert prev["row_type"] in TREE_TYPES and prev["data"]["header"]["expense_item_id"] == child, prev + assert prev["sort_order"] == g1[idx]["sort_order"] - 1 patch = _patch_cell(client, headers, form_id, "AHR", child, "plan.q1", 8) - node = next((r for r in patch if r["row_type"] in TREE_TYPES - and r["data"]["header"]["expense_item_id"] == child), None) - assert node is not None, "узел дочерней статьи отсутствует в ответе" - line_row = next(r for r in patch if r["row_type"] == "INPUT" and r["data"]["line_id"] == child) - assert node["sort_order"] < line_row["sort_order"] - assert_patch_rows_match_sheet(patch, _get_sheet(client, headers, form_id, "AHR")) + get_rows = _get_sheet(client, headers, form_id, "AHR") + line_patch = next(r for r in patch if r["row_type"] == "INPUT" and r["data"]["line_id"] == child) + line_get = next(r for r in get_rows if r["row_type"] == "INPUT" and r["data"]["line_id"] == child) + assert line_patch["sort_order"] == line_get["sort_order"] + node_get = next(r for r in get_rows if r["row_type"] in TREE_TYPES + and r["data"]["header"]["expense_item_id"] == child) + assert node_get["sort_order"] == line_get["sort_order"] - 1 + assert_patch_rows_match_sheet(patch, get_rows) def _delta_equals_get(db_exec, sheet, row_id):