Загрузка данных
CREATE OR REPLACE FUNCTION back_office.get_eps_moving(p_beg_period date DEFAULT NULL::date, p_end_period date DEFAULT CURRENT_DATE, p_service_types character[] DEFAULT NULL::character(3)[], p_eps_code character varying DEFAULT NULL::character varying, p_is_show_list boolean DEFAULT true, p_periodicityes integer[] DEFAULT NULL::integer[], p_account character varying DEFAULT NULL::character varying, p_is_main_transaction boolean DEFAULT false)
RETURNS TABLE(eps_id integer, eps_detail_id integer, eps_code character varying, service_type character varying, eps_name character varying, line_number integer, contract_model_label character varying, account_dt character varying, kind_sub_dt1 text, kind_sub_dt2 text, kind_sub_dt3 text, account_ct character varying, kind_sub_ct1 text, kind_sub_ct2 text, kind_sub_ct3 text, oper_content character varying, is_main_transaction boolean, trans_description character varying, operation_id integer, operation_date date, operation_sum numeric, operation_name character varying, strategy_id integer, classification_id smallint, individual_id integer, entity_id integer, citizenship_country_code text, contract_id integer, pension_schema_id integer, incoming_order_id integer, incoming_order_number character varying, contragent_name text, periodicity smallint, href_sub_dt1 text, href_sub_dt2 text, href_sub_dt3 text, href_sub_ct1 text, href_sub_ct2 text, href_sub_ct3 text, account_number character varying)
LANGUAGE plpgsql
AS $function$
-- ========================================================================
-- Получение списка Движение ЕПС
-- Получатель - данные для списка Движение ЕПС и для выгрузки ежедневных операций
-- Создание: 10.08.2026 dv.pakhomov
-- ========================================================================
BEGIN
IF p_service_types IS NULL
OR ARRAY_LENGTH( p_service_types, 1 ) = 0
THEN
-- по умолчанию берем все Виды деятельности
p_service_types =
( SELECT ARRAY_AGG( uat.activity_eng_type )
FROM ourpension.uv_activity_type uat
WHERE uat.client_type = 0
);
END IF;
IF p_periodicityes IS NULL
OR ARRAY_LENGTH( p_periodicityes, 1 ) = 0
THEN
-- по умолчанию берем все Периодичности
p_periodicityes = ARRAY[ 1, 2 ];
END IF;
RETURN QUERY
WITH cte_var AS MATERIALIZED
( -- простые входные переменные
SELECT
p_eps_code as eps_code,
-- параметры-даты приводим к timestamp: начальная дата это начало суток
COALESCE( p_beg_period, '1990-01-01' )::timestamp as beg_period,
-- параметры-даты приводим к timestamp: конечная дата это конец суток
( SELECT COALESCE( p_end_period, CURRENT_DATE )::timestamp
+ interval '1 day'
- interval '1 msec'
) as end_period,
p_is_show_list as is_show_list,
p_is_main_transaction as is_main_transaction,
p_account as "account"
),
cte_service_types AS MATERIALIZED
( -- входной массив видов деятельности как набор данных
SELECT t.service_type
FROM UNNEST(p_service_types) t(service_type)
)
,
cte_periodicityes AS MATERIALIZED
( -- входной массив периодичностей как набор данных
SELECT t.periodicity
FROM UNNEST(p_periodicityes ) t(periodicity)
)
,
cte_href_parts AS MATERIALIZED
( -- постоянные фрагменты ссылок по ссылочным типам субконто
SELECT *
FROM
( VALUES
( 'PARTNERS_AGR', '', '', '' ),
( 'PARTNERS_I', '<a target="_blank" href="view?viewCode=Client_list&id=', '">', '</a>' ),
( 'PARTNERS_E', '<a target="_blank" href="view?viewCode=NCIuIMAW&id=', '">', '</a>' ),
( 'CONTRACT', '<a target="_blank" href="view?viewCode=7HPZX8vF&id=', '" target="_blank">', '</a>' ),
( 'PAY_ORDER', '<a target="_blank" href="view?viewCode=NL0wI3vg&id=', '" target="_blank">', '</a>' )
) v ( type_sub, id_prefix, id_name_text, name_suffix )
)
,
cte_eps_transaction AS MATERIALIZED
( -- здесь данные ЕПС с витрины
SELECT
et.id as eps_transaction_id,
e.id as eps_id,
s.operation_id,
e.code,
s.incoming_order_id,
COALESCE( e.service_type, '' ) as service_type,
COALESCE( e.contractor_type, -1 ) as contractor_type,
et.contract_id_dt,
et.contract_id_ct,
et.individual_id_dt,
et.individual_id_ct,
et.entity_id_dt,
et.entity_id_ct,
et.pens_schema_dt,
et.pens_schema_ct,
et.citizenship_country_code_dt,
et.citizenship_country_code_ct,
COALESCE( et.operation_sum, 0 ) as operation_sum,
et.strategy_id,
et.oper_date
FROM back_office.eps_transaction et
CROSS JOIN cte_var cv
INNER JOIN ourpension.eps e
ON e.id = et.eps_id
INNER JOIN back_office.eps_transaction_source s
ON s.id = et.eps_transaction_source_id
INNER JOIN cte_service_types cst
ON cst.service_type = e.service_type
INNER JOIN cte_periodicityes cp
ON cp.periodicity = e.periodicity
WHERE cv.is_show_list
AND et.oper_date BETWEEN
cv.beg_period AND cv.end_period
AND
( cv.eps_code IS NULL
OR e.code = cv.eps_code
)
)
,
cte_individual AS MATERIALIZED
( -- все ФЛ запроса с атрибутами (ФИО и гражданство)
SELECT
si.individual_id,
RTRIM( i.last_name || ' ' || i.first_name || ' ' || COALESCE( i.middle_name, '' ) ) as individual_name,
i.citizenship_country_code
FROM
( SELECT sg.individual_id
FROM
( SELECT dt.individual_id_dt AS individual_id
FROM cte_eps_transaction dt
WHERE dt.individual_id_dt IS NOT NULL
UNION
SELECT ct.individual_id_ct AS individual_id
FROM cte_eps_transaction ct
WHERE ct.individual_id_ct IS NOT NULL
) sg
GROUP BY sg.individual_id
) si
INNER JOIN ourpension.individual i
ON i.id = si.individual_id
)
,
cte_entity AS MATERIALIZED
( -- все ЮЛ запроса с названиями
SELECT
se.entity_id,
e.short_name as entity_name
FROM
( SELECT sg.entity_id
FROM
( SELECT dt.entity_id_dt AS entity_id
FROM cte_eps_transaction dt
WHERE dt.entity_id_dt IS NOT NULL
UNION
SELECT ct.entity_id_ct AS entity_id
FROM cte_eps_transaction ct
WHERE ct.entity_id_ct IS NOT NULL
) sg
GROUP BY sg.entity_id
) se
INNER JOIN ourpension.entity e
ON e.id = se.entity_id
)
,
cte_transaction_text AS
( -- определение текста в ячейках субконто
SELECT DISTINCT
ct.eps_transaction_id,
ct.eps_id,
ed.id as eps_detail_id,
ct.operation_sum,
ct.code,
lks.kind_subconto,
lks.subconto_order,
lns.text_sub,
( SELECT CONCAT
( chp.id_prefix
|| CASE lts.type_subconto
WHEN 'PARTNERS_I' THEN lks.individual_id::text
WHEN 'PARTNERS_E' THEN lks.entity_id::text
WHEN 'CONTRACT' THEN lks.contract_id::text
WHEN 'PAY_ORDER' THEN ct.incoming_order_id::text
END
|| chp.id_name_text,
lns.text_sub,
chp.name_suffix
) as href_sub
FROM cte_href_parts chp
WHERE chp.type_sub = lts.type_subconto
) as href_sub,
lks.contract_id,
ct.operation_id,
ct.strategy_id,
ct.incoming_order_id,
lks.individual_id,
lks.entity_id,
lks.citizenship_country_code,
lks.pension_schema_id,
CASE WHEN ct.contractor_type = 1
THEN ia."name" -- Агрегированный
ELSE COALESCE( ci.individual_name, ce.entity_name ) -- Персонифицированный
END as contragent_name,
ct.oper_date
FROM cte_eps_transaction ct
CROSS JOIN cte_var cv
INNER JOIN ourpension.eps_detail ed
ON ed.eps_id = ct.eps_id
AND
( ( NOT cv.is_main_transaction )
OR ed.is_main_transaction
)
INNER JOIN LATERAL
( SELECT
s_d.kind_subconto,
s_d.subconto_order, -- дебетовые ячейки субконто с 1 по 3
ct.individual_id_dt as individual_id,
ct.entity_id_dt as entity_id,
ct.contract_id_dt as contract_id,
ct.pens_schema_dt as pension_schema_id,
ct.citizenship_country_code_dt as citizenship_country_code
FROM ourpension.buh_account_subconto s_d
WHERE s_d.code_account = ed.account_dt
UNION
SELECT
s_c.kind_subconto,
s_c.subconto_order + 3, -- сдвигаем ячейку в кредитную зону с 4 по 6
ct.individual_id_ct as individual_id,
ct.entity_id_ct as entity_id,
ct.contract_id_ct as contract_id,
ct.pens_schema_ct as pension_schema_id,
ct.citizenship_country_code_ct as citizenship_country_code
FROM ourpension.buh_account_subconto s_c
WHERE s_c.code_account = ed.account_ct
) lks
ON true
INNER JOIN LATERAL
( -- Типизация субконто для ссылок
SELECT
CASE WHEN lks.kind_subconto = 'PARTNERS' THEN -- Контрагент
CASE
WHEN ct.contractor_type = 1 THEN 'PARTNERS_AGR'
WHEN lks.individual_id IS NOT NULL THEN 'PARTNERS_I'
WHEN lks.entity_id IS NOT NULL THEN 'PARTNERS_E'
END
ELSE lks.kind_subconto
END as type_subconto
) lts
ON true
LEFT JOIN cte_individual ci
ON ci.individual_id = lks.individual_id
LEFT JOIN cte_entity ce
ON ce.entity_id = lks.entity_id
LEFT JOIN back_office.incoming_order io
ON io.id = ct.incoming_order_id
LEFT JOIN ourpension.contract c
ON c.id = lks.contract_id
LEFT JOIN ourpension.individual_aggregated ia
ON ia.citizenship_country_code = lks.citizenship_country_code
LEFT JOIN prod_line.pens_scheme ps
ON ps.id = lks.pension_schema_id
INNER JOIN LATERAL
( -- Текстовое название субконто
SELECT
COALESCE
( CASE lks.kind_subconto
WHEN 'PARTNERS' THEN -- Контрагент
CASE WHEN ct.contractor_type = 1
THEN ia."name" -- Агрегированный
ELSE COALESCE( ci.individual_name, ce.entity_name ) -- Персонифицированный
END
WHEN 'CONTRACT' THEN c."number" -- Договор
WHEN 'PAY_ORDER' THEN io."number" -- Платежное поручение
END,
''
) as text_sub
) lns
ON true
WHERE lks.kind_subconto IS NOT null
AND
( cv.account IS NULL
OR ed.account_dt = cv.account
OR ed.account_ct = cv.account
)
)
,
cte_transaction_subconto AS
( -- соединение субконто в строки по транзакции + номер строки (проводка ЕПС)
SELECT
ctt.eps_transaction_id,
ctt.operation_id,
MAX( ctt.operation_sum ) as operation_sum,
ctt.eps_detail_id,
-- по ячейкам раскладываем имена субконто
MAX
( CASE WHEN ctt.subconto_order = 1
THEN ctt.text_sub
ELSE ''
END
) as kind_sub_dt1,
MAX
( CASE WHEN ctt.subconto_order = 2
THEN ctt.text_sub
ELSE ''
END
) as kind_sub_dt2,
MAX
( CASE WHEN ctt.subconto_order = 3
THEN ctt.text_sub
ELSE ''
END
) as kind_sub_dt3,
MAX
( CASE WHEN ctt.subconto_order = 4
THEN ctt.text_sub
ELSE ''
END
) as kind_sub_ct1,
MAX
( CASE WHEN ctt.subconto_order = 5
THEN ctt.text_sub
ELSE ''
END
) as kind_sub_ct2,
MAX
( CASE WHEN ctt.subconto_order = 6
THEN ctt.text_sub
ELSE ''
END
) as kind_sub_ct3,
-- по ячейкам раскладываем ссылки субконто
MAX
( CASE WHEN ctt.subconto_order = 1
THEN ctt.href_sub
ELSE ''
END
) as href_sub_dt1,
MAX
( CASE WHEN ctt.subconto_order = 2
THEN ctt.href_sub
ELSE ''
END
) as href_sub_dt2,
MAX
( CASE WHEN ctt.subconto_order = 3
THEN ctt.href_sub
ELSE ''
END
) as href_sub_dt3,
MAX
( CASE WHEN ctt.subconto_order = 4
THEN ctt.href_sub
ELSE ''
END
) as href_sub_ct1,
MAX
( CASE WHEN ctt.subconto_order = 5
THEN ctt.href_sub
ELSE ''
END
) as href_sub_ct2,
MAX
( CASE WHEN ctt.subconto_order = 6
THEN ctt.href_sub
ELSE ''
END
) as href_sub_ct3,
MAX(ctt.strategy_id) as strategy_id,
ctt.incoming_order_id,
ctt.oper_date,
MAX( ctt.contragent_name ) as contragent_name,
MAX( ctt.individual_id ) as individual_id,
MAX( ctt.entity_id ) as entity_id,
MAX( ctt.citizenship_country_code ) as citizenship_country_code,
MAX( ctt.contract_id ) as contract_id,
MAX( ctt.pension_schema_id ) as pension_schema_id
FROM cte_transaction_text ctt
GROUP BY
ctt.eps_transaction_id,
ctt.eps_detail_id,
ctt.operation_id,
ctt.incoming_order_id,
ctt.oper_date
ORDER BY
ctt.eps_detail_id,
ctt.eps_transaction_id
)
,
cte_oper_sum AS
( -- соединение транзакций по операциям + номер строки (проводка ЕПС)
SELECT
cts.operation_id,
cts.eps_detail_id,
SUM( cts.operation_sum ) as operation_sum,
ed.account_dt,
cts.kind_sub_dt1,
cts.kind_sub_dt2,
cts.kind_sub_dt3,
ed.account_ct,
cts.kind_sub_ct1,
cts.kind_sub_ct2,
cts.kind_sub_ct3,
cts.strategy_id,
cts.incoming_order_id,
cts.oper_date,
MAX( cts.href_sub_dt1 ) as href_sub_dt1,
MAX( cts.href_sub_dt2 ) as href_sub_dt2,
MAX( cts.href_sub_dt3 ) as href_sub_dt3,
MAX( cts.href_sub_ct1 ) as href_sub_ct1,
MAX( cts.href_sub_ct2 ) as href_sub_ct2,
MAX( cts.href_sub_ct3 ) as href_sub_ct3,
MAX( cts.individual_id ) as individual_id,
MAX( cts.entity_id ) as entity_id,
MAX( cts.citizenship_country_code ) as citizenship_country_code,
MAX( cts.contract_id ) as contract_id,
MAX( cts.pension_schema_id ) as pension_schema_id,
MAX( cts.contragent_name ) as contragent_name
FROM cte_transaction_subconto cts
INNER JOIN ourpension.eps_detail ed
ON ed.id = cts.eps_detail_id
GROUP BY
cts.operation_id,
cts.incoming_order_id,
cts.eps_detail_id,
ed.account_dt,
cts.kind_sub_dt1,
cts.kind_sub_dt2,
cts.kind_sub_dt3,
ed.account_ct,
cts.kind_sub_ct1,
cts.kind_sub_ct2,
cts.kind_sub_ct3,
cts.strategy_id,
cts.oper_date
)
SELECT
e.id as eps_id,
c_os.eps_detail_id,
e.code as eps_code,
e.service_type,
e.name as eps_name,
ed.line_number,
e.contract_model_label,
ed.account_dt,
c_os.kind_sub_dt1,
c_os.kind_sub_dt2,
c_os.kind_sub_dt3,
ed.account_ct,
c_os.kind_sub_ct1,
c_os.kind_sub_ct2,
c_os.kind_sub_ct3,
ed.oper_content,
ed.is_main_transaction,
ed.trans_description,
c_os.operation_id,
c_os.oper_date::date as operation_date,
c_os.operation_sum,
CASE
WHEN c_os.operation_id IS NOT NULL THEN ot.name
WHEN c_os.incoming_order_id IS NOT NULL THEN CONCAT( 'ВХ ПП ', bs."number", ' от ', TO_CHAR( bs."date",'dd.MM.yyyy' ) )
END as operation_name,
c_os.strategy_id,
e.classification as classification_id,
c_os.individual_id,
c_os.entity_id,
c_os.citizenship_country_code,
c_os.contract_id,
c_os.pension_schema_id,
c_os.incoming_order_id,
bs."number" as incoming_order_number,
c_os.contragent_name,
e.periodicity,
c_os.href_sub_dt1,
c_os.href_sub_dt2,
c_os.href_sub_dt3,
c_os.href_sub_ct1,
c_os.href_sub_ct2,
c_os.href_sub_ct3,
bs.payer_account_number as account_number
FROM cte_oper_sum c_os
INNER JOIN ourpension.eps_detail ed
ON ed.id = c_os.eps_detail_id
INNER JOIN ourpension.eps e
ON e.id = ed.eps_id
LEFT JOIN back_office.operation o
ON o.id = c_os.operation_id
LEFT JOIN back_office.operation_type ot
ON ot.id = o.operation_type_id
LEFT JOIN "data".bank_statement_load_data bs
ON bs.payorderid = c_os.incoming_order_id
;
END;
$function$