Загрузка данных
CREATE OR REPLACE FUNCTION ourpension.f_process_snv_file_safe(
p_file_id integer,
p_username text,
p_user_id integer
)
RETURNS jsonb
LANGUAGE plpgsql
AS $function$
DECLARE
v_result jsonb;
v_sqlstate text;
v_message text;
v_detail text;
v_folder text;
v_loaded_name text;
v_loaded_bytes bytea;
v_original_name text;
v_candidate record;
v_matches integer := 0;
v_target_path text;
v_log_sid text := uuid_generate_v4()::text;
BEGIN
-- Сначала определяем исходный физический файл.
-- При неоднозначности ничего не обрабатываем и не перемещаем.
BEGIN
SELECT sd.input_folder_name
INTO STRICT v_folder
FROM robot.service_description sd
WHERE sd.name = 'SMEF FNS';
IF v_folder IS NULL OR btrim(v_folder) = '' THEN
RAISE EXCEPTION 'Не настроена входящая папка SMEF FNS';
END IF;
SELECT f.name, f.bytes
INTO STRICT v_loaded_name, v_loaded_bytes
FROM dev.query_datasource_file f
JOIN dev.query_datasource d
ON d.id = f.query_datasource_id
WHERE f.id = p_file_id
AND d.code = 'a33r8zRX';
FOR v_candidate IN
SELECT d.name
FROM utils.get_dir_list(v_folder) d
WHERE d.name = v_loaded_name
OR robot.f_russian_transliteration_code(d.name)
= v_loaded_name
LOOP
IF utils.get_file_content(
v_folder || '/' || v_candidate.name
) = v_loaded_bytes THEN
v_original_name := v_candidate.name;
v_matches := v_matches + 1;
END IF;
END LOOP;
IF v_matches <> 1 THEN
RAISE EXCEPTION
'Для fileId=% найдено исходных файлов: %. Требуется один',
p_file_id, v_matches;
END IF;
EXCEPTION WHEN OTHERS THEN
GET STACKED DIAGNOSTICS
v_sqlstate = RETURNED_SQLSTATE,
v_message = MESSAGE_TEXT,
v_detail = PG_EXCEPTION_DETAIL;
v_result := jsonb_build_object(
'success', false,
'file_id', p_file_id,
'stage', 'find_source_file',
'moved', false,
'sqlstate', v_sqlstate,
'message', v_message,
'detail', NULLIF(v_detail, '')
);
END;
IF v_result IS NULL THEN
-- Ошибка обработки откатывает изменения справок,
-- но не прерывает экшен.
BEGIN
v_result := ourpension.f_process_snv_file(
p_file_id,
p_username,
p_user_id
);
EXCEPTION WHEN OTHERS THEN
GET STACKED DIAGNOSTICS
v_sqlstate = RETURNED_SQLSTATE,
v_message = MESSAGE_TEXT,
v_detail = PG_EXCEPTION_DETAIL;
v_result := jsonb_build_object(
'success', false,
'file_id', p_file_id,
'registered_count', 0,
'stage', 'processing',
'sqlstate', v_sqlstate,
'message', v_message,
'detail', NULLIF(v_detail, '')
);
END;
-- Перемещаем только однозначно найденный исходный файл.
-- Ошибка перемещения не откатывает успешное создание справок.
BEGIN
v_target_path := utils.move_processed_file(
v_folder,
v_original_name,
(v_result->>'success')::boolean
);
v_result := v_result || jsonb_build_object(
'moved', true,
'original_name', v_original_name,
'target_path', v_target_path
);
EXCEPTION WHEN OTHERS THEN
GET STACKED DIAGNOSTICS
v_message = MESSAGE_TEXT,
v_detail = PG_EXCEPTION_DETAIL;
v_result := v_result || jsonb_build_object(
'moved', false,
'original_name', v_original_name,
'move_error', v_message,
'move_error_detail', NULLIF(v_detail, '')
);
END;
END IF;
-- Причина отказа остаётся в журнале без исключения
-- и без уведомления об ошибке конструктора.
BEGIN
PERFORM robot.log_message(
'работа'::varchar,
('СНВ: ' || v_result::text)::varchar,
v_log_sid
);
v_result := v_result || jsonb_build_object(
'log_session_id', v_log_sid
);
EXCEPTION WHEN OTHERS THEN
v_result := v_result || jsonb_build_object(
'log_error', SQLERRM
);
END;
RETURN v_result;
END;
$function$;