Постоянно меняющиеся требования со стороны Центробанка и Росфинмониторинга заставляют финансовые организации уделять пристальное внимание своим клиентам с точки зрения их благонадежности. Каждый день производится ряд проверок, позволяющих оценить риски обслуживания организаций и физических лиц. В связи с этим появилась необходимость не просто автоматизировать данный процесс, но как-то его систематизировать и сделать удобным для сопровождения.
Общая схема комплексного анализа выглядит следующим образом:

На первом шаге вводятся данные анализируемого субъекта. Источником может выступать как внешний сервис, так и внутренняя база клиентов или ручной ввод. Далее выбираются контроли из списка или из категории. Процесс анализа заключается в последовательном выполнении всех проверок с сохранением результата и выводом в отчет. Проверка может выполнять различные действия, в основном это поиск по «неблагонадежным» справочникам, анализ истории операций и т.д. В связи с чем с точки зрения архитектуры реализацию данного процесса целесообразно вынести в хранимые процедуры СУБД, чтобы быть «поближе к данным».
В базе создаем справочники проверок и категорий, куда будем заводить собственные проверки.

В каждой проверке есть свой блок кода алгоритма, который будет динамически выполняться на каждой итерации. Результатом выполнения будет статус – пройдено/нет – и дополнительные показатели для вывода в отчет.
За запуск динамического кода отвечает процедура EXEC_PLSQL_BL. Все примеры реализации приведены на языке PL/SQL. На вход ей передается исполняемый код, куда биндится параметр – id субъекта:
PROCEDURE EXEC_PLSQL_BL(cErr OUT varchar2, iRef_id OUT NUMBER, iSubj_Id IN NUMBER, CSQLSTR IN CLOB) IS iExecute INTEGER; iCursor INTEGER := NULL; BEGIN IF LENGTH(CSQLSTR) is not NULL THEN BEGIN IF NOT DBMS_SQL.Is_Open (iCursor) THEN iCursor := DBMS_SQL.Open_Cursor; end if; DBMS_SQL.Parse( iCursor, CSQLSTR, DBMS_SQL.Native ); DBMS_SQL.Bind_Variable( iCursor, 'p1', iSubj_Id); DBMS_SQL.Bind_Variable( iCursor, 'o1', iRef_id); iExecute := DBMS_SQL.Execute( iCursor ); DBMS_SQL.Variable_Value( iCursor, 'o1', iRef_id); DBMS_SQL.Close_Cursor(iCursor); EXCEPTION WHEN OTHERS THEN cERR:=SubStr(SQLERRM,1,255); DBMS_SQL.Close_Cursor(iCursor); END; END IF; END EXEC_PLSQL_BL;
Здесь используется стандартный пакет Oracle DBMS_SQL, но можно применить и команду EXECUTE IMMEDIATE. Последняя обычно используется в случае большого количества ее вызовов.
Таблицы «Анализ» и «Совпадения» являются своего рода хранилищем истории проверок, а таблица «Субъекты» - база субъектов, когда-либо приходивших на обслуживание.
Процедура анализа субъекта выглядит следующим образом. На вход она получает id записи из таблицы «Анализ» и массив проверок (id из таблицы «Проверки»), которые нужно выполнить. Перед ее вызовом происходит заведение новых сущностей в таблицы «Анализ» и «Субъекты».
PROCEDURE analyze_sbj(cErr OUT varchar2, p_chk_id IN NUMBER, p_mrk_id IN T_TAB_NUMBERS) IS vRefId NUMBER; vSubjId NUMBER := SBJ_CTRL_UTL.Get_Chk_Subj_Id(p_chk_id); -- получить id cубъекта vCntRefBuff INTEGER := 0; -- заполнен ли буфер совпадений BEGIN FOR rCtrl IN (SELECT c.* FROM sbj_ctrl c JOIN TABLE(p_mrk_id) t ON VALUE(t) = c.iid ORDER BY c.iid ) LOOP delete from rp_id_tmp; -- Очищаем буфер с совпадениями IF NOT EXEC_PLSQL_BL(cErr,vRefId,vSubjId,rCtrl.cPL) THEN cErr := 'При выполнении проверки ID="' ||rCtrl.IID|| '" произошла ошибка: ' || cErr; raise_application_error(-20000,cErr); exit; ELSE -- сохраняем проверку SELECT CASE WHEN EXISTS (SELECT NULL FROM rp_id_tmp) THEN 1 ELSE 0 END INTO vCntRefBuff FROM dual; IF vCntRefBuff > 0 THEN FOR rRef IN (SELECT inum FROM rp_id_tmp) LOOP SBJ_CTRL_FLR.Ins_Sbj_Suspect(p_chk_id, rCtrl.IID, rRef.Inum); END LOOP; ELSE SBJ_CTRL_FLR.Ins_Sbj_Suspect(p_chk_id, rCtrl.IID, vRefId); END IF; END IF; END LOOP; END;
Процедура в цикле запускает проверки и сохраняет результаты в журнале выявлений. На основе полученных данных можно реализовать любой отчет в требуемом бизнесу виде.
Полученный механизм организации комплексного анализа заметно облегчил поддержку в актуальном состоянии необходимого перечня проверок над субъектами, а также позволил хранить историю.
З.Ы. При настройке проверок на совпадения с различными списками можно пользоваться решением, описанным в статье «Справочник объектов поиска и анализа».

