From 2d0d64f3ef82a73174ac3d21465c21ca15159327 Mon Sep 17 00:00:00 2001 From: PotapovaA Date: Wed, 23 Sep 2026 03:17:06 +0300 Subject: [PATCH] =?UTF-8?q?=D0=B4=D0=BE=D0=B1=D0=B0=D0=B2=D0=B8=D0=BB?= =?UTF-8?q?=D0=B0=20=D1=83=D1=87=D0=B5=D1=82=20=D0=B0=D0=BB=D0=B8=D0=B0?= =?UTF-8?q?=D1=81=D0=BE=D0=B2=20=D0=B2=20=D0=B7=D0=B0=D0=BF=D1=80=D0=BE?= =?UTF-8?q?=D1=81=D0=B5=20=D0=BF=D1=80=D0=B8=20=D0=BF=D0=BE=D0=B8=D1=81?= =?UTF-8?q?=D0=BA=D0=B5=20=D0=BA=D0=BE=D0=BD=D1=82=D1=80=D0=B0=D0=B3=D0=B5?= =?UTF-8?q?=D0=BD=D1=82=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...1503a26_add_osv_counterparty_alias_flag.py | 259 ++++++++++++++++++ api/src/schemas/osv.py | 1 + 2 files changed, 260 insertions(+) create mode 100644 api/alembic/versions/c94eb1503a26_add_osv_counterparty_alias_flag.py diff --git a/api/alembic/versions/c94eb1503a26_add_osv_counterparty_alias_flag.py b/api/alembic/versions/c94eb1503a26_add_osv_counterparty_alias_flag.py new file mode 100644 index 0000000..344be9e --- /dev/null +++ b/api/alembic/versions/c94eb1503a26_add_osv_counterparty_alias_flag.py @@ -0,0 +1,259 @@ +"""Expose whether an OSV counterparty was resolved by alias. + +Revision ID: c94eb1503a26 +Revises: d614b414a32f +""" +from alembic import op + +revision = "c94eb1503a26" +down_revision = "d614b414a32f" +branch_labels = None +depends_on = None + + +def upgrade() -> None: + # PostgreSQL requires recreation when RETURNS TABLE changes. + # No CASCADE: dependent database objects must not be silently removed. + op.execute("DROP FUNCTION dkb.get_osv_entries_for_group(uuid, integer, text)") + op.execute(""" + CREATE OR REPLACE FUNCTION dkb.get_osv_entries_for_group( + p_company_group_id uuid, + p_period_year integer, + p_period_quarter text + ) + RETURNS TABLE ( + osv_entry_id uuid, + recognition_job_id uuid, + legal_entity_id uuid, + stored_file_id uuid, + account_code varchar, + account_id uuid, + account_root varchar, + counterparty_name varchar, + counterparty_inn varchar, + counterparty_id uuid, + counterparty_resolved_by_alias boolean, + opening_debit numeric, + opening_credit numeric, + turnover_debit numeric, + turnover_credit numeric, + closing_debit numeric, + closing_credit numeric, + legal_entity_name varchar, + company_group_id uuid, + company_group_name varchar, + original_name varchar, + file_status varchar, + period_year smallint, + period_quarter varchar, + uploaded_at timestamptz, + uploaded_by varchar, + finished_at timestamptz, + is_gsk boolean, + is_gk boolean, + entity_group_flag text + ) + LANGUAGE sql + STABLE + STRICT + AS $function$ + WITH classified_entries AS ( + SELECT + oe.id AS osv_entry_id, + oe.recognition_job_id, + oe.legal_entity_id, + oe.stored_file_id, + CASE + WHEN oe.account_id IS NOT NULL THEN coa.code + ELSE oe.account_code + END AS account_code, + oe.account_id, + oe.account_root, + oe.counterparty_name, + oe.counterparty_inn, + COALESCE(oe.counterparty_id, counterparty_by_inn.id, counterparty_by_alias.legal_entity_id) AS counterparty_id, + (oe.counterparty_id IS NULL + AND counterparty_by_inn.id IS NULL + AND counterparty_by_alias.legal_entity_id IS NOT NULL) + AS counterparty_resolved_by_alias, + oe.opening_debit, + oe.opening_credit, + oe.turnover_debit, + oe.turnover_credit, + oe.closing_debit, + oe.closing_credit, + le.name AS legal_entity_name, + le.company_group_id, + cg.name AS company_group_name, + sf.original_name, + sf.status AS file_status, + sf.period_year, + sf.period_quarter, + sf.uploaded_at, + sf.uploaded_by, + rj.finished_at, + EXISTS ( + SELECT 1 + FROM dkb.related_group_member AS member + JOIN dkb.related_group AS rg + ON rg.id = member.related_group_id + WHERE member.legal_entity_id = oe.legal_entity_id + AND member.is_current IS TRUE + AND rg.company_group_id = p_company_group_id + AND rg.kind = 'GSK' + ) AS is_gsk, + le.company_group_id = p_company_group_id AS is_gk + FROM dkb.osv_entry AS oe + LEFT JOIN dkb.legal_entity AS counterparty_by_inn + ON oe.counterparty_id IS NULL + AND counterparty_by_inn.inn = NULLIF(BTRIM(oe.counterparty_inn), '') + LEFT JOIN dkb.legal_entity_alias AS counterparty_by_alias + ON oe.counterparty_id IS NULL + AND counterparty_by_inn.id IS NULL + AND counterparty_by_alias.normalized_alias = NULLIF(BTRIM(oe.counterparty_name), '') + LEFT JOIN dkb.chart_of_account AS coa ON coa.id = oe.account_id + JOIN dkb.stored_file AS sf ON sf.id = oe.stored_file_id + JOIN dkb.legal_entity AS le ON le.id = oe.legal_entity_id + JOIN dkb.company_group AS cg ON cg.id = le.company_group_id + LEFT JOIN dkb.recognition_job AS rj + ON rj.id = oe.recognition_job_id + AND rj.file_id = sf.id + WHERE sf.status = 'UPLOADED' + AND sf.period_year = p_period_year + AND sf.period_quarter = p_period_quarter + AND EXISTS ( + SELECT 1 FROM dkb.company_group AS selected_group + WHERE selected_group.id = p_company_group_id + ) + ) + SELECT + ce.*, + CASE + WHEN ce.is_gsk THEN 'ГСК' + WHEN ce.is_gk THEN 'ГК' + ELSE 'Внешний' + END AS entity_group_flag + FROM classified_entries AS ce; + $function$; + """) + + +def downgrade() -> None: + op.execute("DROP FUNCTION dkb.get_osv_entries_for_group(uuid, integer, text)") + op.execute(""" + CREATE OR REPLACE FUNCTION dkb.get_osv_entries_for_group( + p_company_group_id uuid, + p_period_year integer, + p_period_quarter text + ) + RETURNS TABLE ( + osv_entry_id uuid, + recognition_job_id uuid, + legal_entity_id uuid, + stored_file_id uuid, + account_code varchar, + account_id uuid, + account_root varchar, + counterparty_name varchar, + counterparty_inn varchar, + counterparty_id uuid, + opening_debit numeric, + opening_credit numeric, + turnover_debit numeric, + turnover_credit numeric, + closing_debit numeric, + closing_credit numeric, + legal_entity_name varchar, + company_group_id uuid, + company_group_name varchar, + original_name varchar, + file_status varchar, + period_year smallint, + period_quarter varchar, + uploaded_at timestamptz, + uploaded_by varchar, + finished_at timestamptz, + is_gsk boolean, + is_gk boolean, + entity_group_flag text + ) + LANGUAGE sql + STABLE + STRICT + AS $function$ + WITH classified_entries AS ( + SELECT + oe.id AS osv_entry_id, + oe.recognition_job_id, + oe.legal_entity_id, + oe.stored_file_id, + CASE + WHEN oe.account_id IS NOT NULL THEN coa.code + ELSE oe.account_code + END AS account_code, + oe.account_id, + oe.account_root, + oe.counterparty_name, + oe.counterparty_inn, + COALESCE(oe.counterparty_id, counterparty_by_inn.id, counterparty_by_alias.legal_entity_id) AS counterparty_id, + oe.opening_debit, + oe.opening_credit, + oe.turnover_debit, + oe.turnover_credit, + oe.closing_debit, + oe.closing_credit, + le.name AS legal_entity_name, + le.company_group_id, + cg.name AS company_group_name, + sf.original_name, + sf.status AS file_status, + sf.period_year, + sf.period_quarter, + sf.uploaded_at, + sf.uploaded_by, + rj.finished_at, + EXISTS ( + SELECT 1 + FROM dkb.related_group_member AS member + JOIN dkb.related_group AS rg + ON rg.id = member.related_group_id + WHERE member.legal_entity_id = oe.legal_entity_id + AND member.is_current IS TRUE + AND rg.company_group_id = p_company_group_id + AND rg.kind = 'GSK' + ) AS is_gsk, + le.company_group_id = p_company_group_id AS is_gk + FROM dkb.osv_entry AS oe + LEFT JOIN dkb.legal_entity AS counterparty_by_inn + ON oe.counterparty_id IS NULL + AND counterparty_by_inn.inn = NULLIF(BTRIM(oe.counterparty_inn), '') + LEFT JOIN dkb.legal_entity_alias AS counterparty_by_alias + ON oe.counterparty_id IS NULL + AND counterparty_by_inn.id IS NULL + AND counterparty_by_alias.normalized_alias = NULLIF(BTRIM(oe.counterparty_name), '') + LEFT JOIN dkb.chart_of_account AS coa ON coa.id = oe.account_id + JOIN dkb.stored_file AS sf ON sf.id = oe.stored_file_id + JOIN dkb.legal_entity AS le ON le.id = oe.legal_entity_id + JOIN dkb.company_group AS cg ON cg.id = le.company_group_id + LEFT JOIN dkb.recognition_job AS rj + ON rj.id = oe.recognition_job_id + AND rj.file_id = sf.id + WHERE sf.status = 'UPLOADED' + AND sf.period_year = p_period_year + AND sf.period_quarter = p_period_quarter + AND EXISTS ( + SELECT 1 FROM dkb.company_group AS selected_group + WHERE selected_group.id = p_company_group_id + ) + ) + SELECT + ce.*, + CASE + WHEN ce.is_gsk THEN 'ГСК' + WHEN ce.is_gk THEN 'ГК' + ELSE 'Внешний' + END AS entity_group_flag + FROM classified_entries AS ce; + $function$; + """) + diff --git a/api/src/schemas/osv.py b/api/src/schemas/osv.py index 05d636c..a55af28 100644 --- a/api/src/schemas/osv.py +++ b/api/src/schemas/osv.py @@ -21,6 +21,7 @@ class OsvGroupEntryResponse(BaseModel): counterparty_name: str counterparty_inn: str counterparty_id: UUID | None + counterparty_resolved_by_alias: bool opening_debit: Decimal opening_credit: Decimal turnover_debit: Decimal