Загрузка данных


CREATE OR REPLACE FUNCTION integration.get_unv_available_contracts_api(p_request text)
 RETURNS text
 LANGUAGE plpgsql
AS $function$

DECLARE

    v_params     jsonb;

    v_client_id  integer;

    v_result     jsonb;

BEGIN

    /* Проверка входного JSON */

    IF NOT utils.check_json(p_request) THEN

        RETURN jsonb_build_object(

            'status', 'Ошибка',

            'message', 'Неверный формат JSON'

        )::text;

    END IF;



    v_params := p_request::jsonb;



    /* Проверка идентификатора клиента */

    IF COALESCE(v_params ->> 'id', '') !~ '^[0-9]+$' THEN

        RETURN jsonb_build_object(

            'status', 'Ошибка',

            'message', 'Не указан корректный идентификатор клиента'

        )::text;

    END IF;



    v_client_id := (v_params ->> 'id')::integer;



    IF NOT EXISTS (

        SELECT 1

        FROM ourpension.individual ind

        WHERE ind.id = v_client_id

    ) THEN

        RETURN jsonb_build_object(

            'status', 'Ошибка',

            'message', 'Клиент не найден'

        )::text;

    END IF;



    WITH params AS (

        SELECT

            EXTRACT(YEAR FROM CURRENT_DATE)::integer AS current_year

    ),

    contributions AS (

        SELECT

            c.id AS contract_id,

            c.number AS contract_number,

            c.service_type AS contract_type,

            c."date" AS contract_date,

            EXTRACT(YEAR FROM o.operation_date)::integer

                AS tax_period_year,

            SUM(t.value) AS contributions_amount

        FROM back_office.incoming_order io

        JOIN back_office.incoming_order_operation ioo

            ON ioo.incoming_order_id = io.id

        JOIN back_office.operation o

            ON o.id = ioo.operation_id

        JOIN back_office.operation_type ot

            ON ot.id = o.operation_type_id

        JOIN back_office."transaction" t

            ON t.operation_id = o.id

        JOIN back_office.account a

            ON a.id = t.credit_account_id

        JOIN back_office.account_type at

            ON at.id = a.account_type_id

        JOIN ourpension.contract c

            ON c.id = io.contract_id

        JOIN ourpension.individual ind

            ON ind.id = io.individual_id

        CROSS JOIN params p

        WHERE io.individual_id = v_client_id



          /* Три предыдущих налоговых периода */

          AND o.operation_date >=

              make_date(p.current_year - 3, 1, 1)

          AND o.operation_date <

              make_date(p.current_year, 1, 1)



          /* Только авторизованные и неудалённые операции */

          AND o.approved IS NOT NULL

          AND o.deleted IS NULL

          AND io.payment_return IS NOT TRUE



          /* Проверка кода операции и мнемоники счёта */

          AND (

                (

                    c.service_type = 'NPO'

                    AND ot.code = 'DEPOSIT_ENROLLMENT'

                    AND at.mnemonics = 'ИПС_ФЛ'

                )

                OR

                (

                    c.service_type = 'PDS'

                    AND ot.code = 'PDS_DEPOSIT_ENROLLMENT'

                    AND at.mnemonics = 'ПДС СВ'

                )

              )



          /* Клиент должен относиться к договору */

          AND (

                c.individual_id = v_client_id

                OR (

                    c.service_type = 'PDS'

                    AND c.family_member IS TRUE

                )

              )



          /* СНИЛС должен быть заполнен */

          AND NULLIF(TRIM(ind.insurance_number), '') IS NOT NULL



          /* Исключаем умерших клиентов */

          AND NOT EXISTS (

              SELECT 1

              FROM ourpension.application_death_info adi

              WHERE adi.individual_id = ind.id

                AND adi.accepted IS NOT NULL

                AND adi.canceled IS NULL

          )

        GROUP BY

            c.id,

            c.number,

            c.service_type,

            c."date",

            EXTRACT(YEAR FROM o.operation_date)

        HAVING SUM(t.value) > 0

    ),

    calculated AS (

        SELECT

            c.contract_id,

            c.contract_number,

            c.contract_type,

            c.tax_period_year,

            c.contributions_amount,



            /* Предварительный вычет — 13% с учётом лимита */

            ROUND(

                LEAST(

                    c.contributions_amount,

                    CASE

                        WHEN c.contract_type = 'NPO'

                         AND c.contract_date < DATE '2025-01-01'

                            THEN 19500::numeric

                        ELSE 52000::numeric

                    END

                ) * 0.13,

                2

            ) AS preliminary_deduction_amount

        FROM contributions c

    ),

    contracts AS (

        SELECT

            c.contract_id,

            c.contract_number,

            c.contract_type,

            COALESCE(s.annual_deduction_flag, 0)

                AS annual_deduction_flag,

            jsonb_agg(

                jsonb_build_object(

                    'tax_period_year',

                        c.tax_period_year,

                    'contributions_amount',

                        c.contributions_amount,

                    'preliminary_deduction_amount',

                        c.preliminary_deduction_amount

                )

                ORDER BY c.tax_period_year DESC

            ) AS periods

        FROM calculated c

        LEFT JOIN report.unv_annual_setting s

            ON s.client_id = v_client_id

           AND s.contract_id = c.contract_id

        GROUP BY

            c.contract_id,

            c.contract_number,

            c.contract_type,

            s.annual_deduction_flag

    )

    SELECT jsonb_build_object(

        'client_id',

            v_client_id,

        'contracts',

            COALESCE(

                jsonb_agg(

                    jsonb_build_object(

                        'contract_id',

                            c.contract_id,

                        'contract_number',

                            c.contract_number,

                        'contract_type',

                            c.contract_type,

                        'annual_deduction_flag',

                            c.annual_deduction_flag,

                        'periods',

                            c.periods

                    )

                    ORDER BY

                        c.contract_type,

                        c.contract_number

                ),

                '[]'::jsonb

            )

    )

    INTO v_result

    FROM contracts c;



    RETURN v_result::text;

END;

$function$