From 8d6e7ba51b6d248686d81f1c788b027d3f1b2aa7 Mon Sep 17 00:00:00 2001 From: tsygankoviva Date: Wed, 21 Oct 2026 17:31:34 +0300 Subject: [PATCH] =?UTF-8?q?svod2-filter-fix2:=20=D0=B5=D1=81=D0=BB=D0=B8?= =?UTF-8?q?=20=D0=B7=D0=B0=D0=BF=D0=BE=D0=BB=D0=BD=D0=B5=D0=BD=20=D1=82?= =?UTF-8?q?=D0=BE=D0=BB=D1=8C=D0=BA=D0=BE=20=D0=B2=D1=81=D0=BF=20=D0=BD?= =?UTF-8?q?=D0=B5=20=D0=B1=D0=B5=D1=80=D0=B5=D0=BC=20=D0=B2=20=D1=81=D0=B2?= =?UTF-8?q?=D0=BE=D0=B4=202?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../sql/0049_summary2_related_records.sql | 68 +++++++++++++++++-- .../unit/test_summary2_related_records_sql.py | 19 +++--- 2 files changed, 75 insertions(+), 12 deletions(-) diff --git a/api/alembic/versions/sql/0049_summary2_related_records.sql b/api/alembic/versions/sql/0049_summary2_related_records.sql index 80820ba..845d0fb 100644 --- a/api/alembic/versions/sql/0049_summary2_related_records.sql +++ b/api/alembic/versions/sql/0049_summary2_related_records.sql @@ -1,4 +1,4 @@ --- Keep source lines with a related data record. For plan and quarter data, +-- Keep source lines with a related data record. For plan, quarter and rent data, -- require a nonzero number, a date, or text containing a non-whitespace character. -- Other data sections qualify by record presence, even if their fields are empty. -- DISTINCT prevents one-to-many joins from duplicating lines before pagination. @@ -123,7 +123,27 @@ WITH empty_sections AS MATERIALIZED ( OR presence_budget_line_quarter.plan_revision_sequester <> 0 OR presence_budget_line_quarter.plan_revision_comment ~ '[^[:space:]]' ) - OR presence_rent_detail.line_id IS NOT NULL + OR ( + presence_rent_detail.contract_number ~ '[^[:space:]]' + OR presence_rent_detail.contract_end_date IS NOT NULL + OR presence_rent_detail.plan_q1 <> 0 + OR presence_rent_detail.plan_q2 <> 0 + OR presence_rent_detail.plan_q3 <> 0 + OR presence_rent_detail.plan_q4 <> 0 + OR presence_rent_detail.actual_jan <> 0 + OR presence_rent_detail.actual_feb <> 0 + OR presence_rent_detail.actual_mar <> 0 + OR presence_rent_detail.actual_apr <> 0 + OR presence_rent_detail.actual_may <> 0 + OR presence_rent_detail.actual_jun <> 0 + OR presence_rent_detail.actual_jul <> 0 + OR presence_rent_detail.actual_aug <> 0 + OR presence_rent_detail.actual_sep <> 0 + OR presence_rent_detail.actual_oct <> 0 + OR presence_rent_detail.actual_nov <> 0 + OR presence_rent_detail.actual_dec <> 0 + OR presence_rent_detail.comment ~ '[^[:space:]]' + ) OR presence_security_detail.line_id IS NOT NULL OR presence_utility_detail.line_id IS NOT NULL ) @@ -401,7 +421,27 @@ WITH empty_sections AS MATERIALIZED ( OR presence_budget_line_quarter.plan_revision_sequester <> 0 OR presence_budget_line_quarter.plan_revision_comment ~ '[^[:space:]]' ) - OR presence_rent_detail.line_id IS NOT NULL + OR ( + presence_rent_detail.contract_number ~ '[^[:space:]]' + OR presence_rent_detail.contract_end_date IS NOT NULL + OR presence_rent_detail.plan_q1 <> 0 + OR presence_rent_detail.plan_q2 <> 0 + OR presence_rent_detail.plan_q3 <> 0 + OR presence_rent_detail.plan_q4 <> 0 + OR presence_rent_detail.actual_jan <> 0 + OR presence_rent_detail.actual_feb <> 0 + OR presence_rent_detail.actual_mar <> 0 + OR presence_rent_detail.actual_apr <> 0 + OR presence_rent_detail.actual_may <> 0 + OR presence_rent_detail.actual_jun <> 0 + OR presence_rent_detail.actual_jul <> 0 + OR presence_rent_detail.actual_aug <> 0 + OR presence_rent_detail.actual_sep <> 0 + OR presence_rent_detail.actual_oct <> 0 + OR presence_rent_detail.actual_nov <> 0 + OR presence_rent_detail.actual_dec <> 0 + OR presence_rent_detail.comment ~ '[^[:space:]]' + ) OR presence_security_detail.line_id IS NOT NULL OR presence_utility_detail.line_id IS NOT NULL ) @@ -674,7 +714,27 @@ WITH eligible_lines AS ( OR presence_budget_line_quarter.plan_revision_sequester <> 0 OR presence_budget_line_quarter.plan_revision_comment ~ '[^[:space:]]' ) - OR presence_rent_detail.line_id IS NOT NULL + OR ( + presence_rent_detail.contract_number ~ '[^[:space:]]' + OR presence_rent_detail.contract_end_date IS NOT NULL + OR presence_rent_detail.plan_q1 <> 0 + OR presence_rent_detail.plan_q2 <> 0 + OR presence_rent_detail.plan_q3 <> 0 + OR presence_rent_detail.plan_q4 <> 0 + OR presence_rent_detail.actual_jan <> 0 + OR presence_rent_detail.actual_feb <> 0 + OR presence_rent_detail.actual_mar <> 0 + OR presence_rent_detail.actual_apr <> 0 + OR presence_rent_detail.actual_may <> 0 + OR presence_rent_detail.actual_jun <> 0 + OR presence_rent_detail.actual_jul <> 0 + OR presence_rent_detail.actual_aug <> 0 + OR presence_rent_detail.actual_sep <> 0 + OR presence_rent_detail.actual_oct <> 0 + OR presence_rent_detail.actual_nov <> 0 + OR presence_rent_detail.actual_dec <> 0 + OR presence_rent_detail.comment ~ '[^[:space:]]' + ) OR presence_security_detail.line_id IS NOT NULL OR presence_utility_detail.line_id IS NOT NULL ) diff --git a/api/tests/unit/test_summary2_related_records_sql.py b/api/tests/unit/test_summary2_related_records_sql.py index fa1a628..04bfd39 100644 --- a/api/tests/unit/test_summary2_related_records_sql.py +++ b/api/tests/unit/test_summary2_related_records_sql.py @@ -22,7 +22,7 @@ def data_columns(table): for node in ast.walk(ast.parse(path.read_text())) if isinstance(node, ast.AnnAssign) and isinstance(node.target, ast.Name) - and node.target.id not in ("line_id", "quarter") + and node.target.id not in ("id", "line_id", "vsp_id", "quarter") } @@ -46,9 +46,11 @@ class Summary2RelatedRecordsSQLTest(unittest.TestCase): """) for table in TABLES: columns = "line_id" - if table in ("plan", "budget_line_quarter"): + if table in ("plan", "budget_line_quarter", "rent_detail"): columns += "".join(f", {field} {'NUMERIC' if kind == 'Numeric' else 'TEXT'}" for field, kind in data_columns(table).items()) + if table == "rent_detail": + columns += ", id, vsp_id" if table == "budget_line_quarter": columns += ", quarter" if table == "contract_detail": @@ -81,7 +83,7 @@ class Summary2RelatedRecordsSQLTest(unittest.TestCase): self.db.execute(f"INSERT INTO v3.{table}(line_id) VALUES (999)") self.assertEqual(self.rows(index), []) self.db.execute(f"INSERT INTO v3.{table}(line_id) VALUES (1)") - self.assertEqual(len(self.rows(index)), 0 if table in ("plan", "budget_line_quarter") else 1) + self.assertEqual(len(self.rows(index)), 0 if table in ("plan", "budget_line_quarter", "rent_detail") else 1) self.db.execute(f"DELETE FROM v3.{table}") def test_multiple_related_records_do_not_duplicate_lines(self): @@ -92,15 +94,16 @@ class Summary2RelatedRecordsSQLTest(unittest.TestCase): ("FORM_2" if index == 1 else "FORM_4",)) self.assertEqual(len(self.rows(index)), 1) - def test_default_plan_and_quarters_do_not_qualify(self): - for table in ("plan", "budget_line_quarter"): + def test_default_plan_quarter_and_rent_data_do_not_qualify(self): + for table in ("plan", "budget_line_quarter", "rent_detail"): fields = data_columns(table) names = ", ".join(fields) values = [0 if kind == "Numeric" else " \t\n\r" if kind == "String" else None for kind in fields.values()] placeholders = ", ".join("?" for _ in fields) self.db.execute(f"INSERT INTO v3.{table}(line_id, {names}) VALUES (1, {placeholders})", values) - # Service quarter numbers must not qualify as meaningful data. + # Service IDs and quarter numbers must not qualify as meaningful data. + self.db.execute("UPDATE v3.rent_detail SET id = 42, vsp_id = 123") self.db.execute("UPDATE v3.budget_line_quarter SET quarter = 1") for quarter in (2, 3, 4): self.db.execute("INSERT INTO v3.budget_line_quarter(line_id, quarter, actual_m1) VALUES (1, ?, 0)", @@ -114,11 +117,11 @@ class Summary2RelatedRecordsSQLTest(unittest.TestCase): self.assertEqual(len(self.rows(index)), 1) self.db.execute("DELETE FROM v3.reserve") - def test_each_meaningful_plan_or_quarter_field_qualifies(self): + def test_each_meaningful_plan_quarter_or_rent_field_qualifies(self): for index in range(3): self.db.execute("UPDATE v3.budget_form SET form_type_code = ?", ("FORM_2" if index == 1 else "FORM_1",)) - for table in ("plan", "budget_line_quarter"): + for table in ("plan", "budget_line_quarter", "rent_detail"): for field, kind in data_columns(table).items(): values = (12, -12) if kind == "Numeric" else ("2026-10-21",) if kind == "Date" else (" text ",) for value in values: -- 2.47.2