From 962e3208ced5b51f941929ff2eec87b31873ddf4 Mon Sep 17 00:00:00 2001 From: Skillbox Student Date: Mon, 24 Mar 2025 19:26:22 +0300 Subject: [PATCH] =?UTF-8?q?=D0=A4=D0=B8=D0=BA=D1=81=D0=B0=D1=86=D0=B8?= =?UTF-8?q?=D1=8F=20=D0=B4=D0=BE=D1=80=D0=B0=D0=B1=D0=BE=D1=82=D0=BE=D0=BA?= =?UTF-8?q?=20=D0=BF=D0=BE=20=D0=BE=D0=B1=D1=83=D1=87=D0=B5=D0=BD=D0=B8?= =?UTF-8?q?=D1=8E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Формирование файла dataset; Загрузка на файловый ресурс SCP; Передача данных фреймворку; Запрос на обучение модели. --- db/UDO_PKG_EQUIPDS_DATAPROCESS.pck | 1129 +++++++++++++++++++++++++++ db/UDO_PKG_EQUIPDS_EXS.pck | 641 +++++++++++++++ db/UDO_PKG_EQUIPDS_SEND.pck | 434 ++++++++++ db/UDO_P_EQUIPDSCM_DATASET_MAKE.prc | 25 + db/grants.sql | 1 + service/modules/EQUIPDS.js | 121 +++ service/modules/loadSCP_v2.js | 155 ++++ 7 files changed, 2506 insertions(+) create mode 100644 db/UDO_PKG_EQUIPDS_DATAPROCESS.pck create mode 100644 db/UDO_PKG_EQUIPDS_EXS.pck create mode 100644 db/UDO_PKG_EQUIPDS_SEND.pck create mode 100644 db/UDO_P_EQUIPDSCM_DATASET_MAKE.prc create mode 100644 service/modules/EQUIPDS.js create mode 100644 service/modules/loadSCP_v2.js diff --git a/db/UDO_PKG_EQUIPDS_DATAPROCESS.pck b/db/UDO_PKG_EQUIPDS_DATAPROCESS.pck new file mode 100644 index 0000000..a6506b4 --- /dev/null +++ b/db/UDO_PKG_EQUIPDS_DATAPROCESS.pck @@ -0,0 +1,1129 @@ +create or replace package UDO_PKG_EQUIPDS_DATAPROCESS +is +/* + Описание: Обеспечивает подготовку/обработку данных для отпраки и получения запросов/ответов. + Проект: Интеграция ПП «Парус 8» и «Фреймворка оценки и прогнозирования состояния оборудования» + Разработчик: ЦИТК-ПАРУС + Отественный: Селианов А.Е. + Дата последнего изменения: 15.02.2025 +*/ + + /* Константы - Описание возможных событий */ + SDEF_EVENTTYPE_E0 constant PKG_STD.tSTRING := 'E0'; --событие ввода системы в эксплуатацию (начало наблюдения за функционированием системы) + SDEF_EVENTTYPE_EOS constant PKG_STD.tSTRING := 'EOS'; -- событие перехода работоспособной системы из нерабочего состояния в рабочее состояние (начало i-го цикла работы системы) + SDEF_EVENTTYPE_ENOS constant PKG_STD.tSTRING := 'ENOS'; -- событие перехода работоспособной системы из рабочего состояния в нерабочее состояние (окончание i-го цикла работы системы) + SDEF_EVENTTYPE_ETMS constant PKG_STD.tSTRING := 'ETMS'; -- событие перехода в состояние ТОИР + SDEF_EVENTTYPE_ERMS constant PKG_STD.tSTRING := 'ERMS'; -- событие выхода из состояния ТОИР + SDEF_EVENTTYPE_EF constant PKG_STD.tSTRING := 'EF'; -- событие возникновения i-го отказа работоспособной системы в j-м рабочем состоянии, т.е. переход системы в состояние отказа + SDEF_EVENTTYPE_EOL constant PKG_STD.tSTRING := 'EOL'; -- событие возникновения i-го предельного состояния в работоспособной системе в j-м рабочем состоянии (цикле) + + /* Константы - наименование типов колонок - усраревшие НЕ ИСПОЛЬЗОАТЬ!!!*/ + SCOL_TYP_DF constant PKG_STD.tSTRING := 'null_0'; + SCOL_TYP_PARAM_HARDWARE constant PKG_STD.tSTRING := 'диагностический признак'; -- параметры технического состояния + SCOL_TYP_CONDITIONS constant PKG_STD.tSTRING := 'условия эксплуатации'; -- эксплуатационные характеристики + SCOL_TYP_HLSTATETYPES constant PKG_STD.tSTRING := 'Типы состояний оборудования'; -- Типы состояний оборудования + /* Константы - коды типов колонок - устаревшие НЕ ИСПОЛЬЗОВАТЬ!!!!*/ + NCOL_TYP_DF constant PKG_STD.tNUMBER := -1; + NCOL_TYP_PARAM_HARDWARE constant PKG_STD.tNUMBER := 0; -- параметры технического состояния + NCOL_TYP_CONDITIONS constant PKG_STD.tNUMBER := 1; -- эксплуатационные характеристики + NCOL_TYP_HLSTATETYPES constant PKG_STD.tNUMBER := 2; -- Типы состояний оборудования + + /* Константы - наименование типов колонок */ + SCOL_TYP_STRING constant PKG_STD.tSTRING := 'string'; -- тип строка + SCOL_TYP_DATATIME constant PKG_STD.tSTRING := 'datetime'; -- тип дата время + /* Константы - коды типов колонок */ + NCOL_TYP_STRING constant PKG_STD.tNUMBER := 3; -- КОД типа строка + NCOL_TYP_DATATIME constant PKG_STD.tNUMBER := 4; -- КОД типа дата время + + + + /* Типы данных колонок - перечень колонок для построения датасета и формирования конфигурации */ + type TCOL_TYP_VAL is record + ( + SINDEX PKG_STD.TSTRING, -- Интекс применения + SCOL_CODE PKG_STD.TSTRING, -- Наименование + SCOL_NAME PKG_STD.TSTRING, -- Наименование + SCOL_VAL PKG_STD.TSTRING, -- Значение + NCOL_TYP PKG_STD.tNUMBER, -- тип + SCOL_TYP PKG_STD.TSTRING -- наименование типа + ); + + /* Типы данных - коллекция переченя колонок для построения датасета и формирования конфигурации */ + type TCOL_TYP_VALS is table of TCOL_TYP_VAL; --index by PKG_STD.TSTRING; + + /* DataSet - перечень колонок c даннми для построения датасета */ + type TDATASET_VAL is record + ( + NEQOBJKIND PKG_STD.tREF, -- Класс оборудования + NUNIT PKG_STD.tREF, -- Экземпляр оборудования + DDATATIME DATE, -- Дата события + TCOLTYP_VAL TCOL_TYP_VALS, -- коллекция переченя колонок + SEVENTTYPE PKG_STD.TSTRING -- Событие + ); + + /* DataSet - коллекция переченя колонок c даннми для построения датасета */ + type TDATASET_VALS is table of TDATASET_VAL; + + /* Получение имени файла с расширением из полного пути */ + function GET_FILENAME + ( + SPATH IN VARCHAR2 -- Полный путь размещения файла + )RETURN varchar2; -- имя файла с разрешением + + /* Получение данных датасета и Описание структуры выборки */ + procedure DATASET_CONF_SET + ( + NCOMPANY in number, -- регистрационный номер организации + NEQUIPDSCM in number default null, -- Рег. номер класса оборудования выборки данных (null - работать по указанной единице оборудования) + NEQCONFIG in number default null, -- Рег. номер единицы оборудования (null - по всем) + DBEG in date, -- Дата С + DEND in date, -- Дата По + NLENGTH_GB in number default null, -- Ограничение размера файла в Гб + NDATASET_IDENT out number, -- Идентификатор буфера данных + NDATASET_CONFIG_IDENT out number -- Идентификатор буфера описания данных ) + ); + + /* Обеспечивает постановку в очередь обмена сообщения на загрузку данных выборки на FTP, SCP */ + procedure UPLOAD + ( + NCOMPANY in number, -- Организация + NIDENT in number, -- Идентификатор Selectlis + NEQUIPDSCM in number -- Рег. номер класса оборудования выборки данных + ); + + /* Обеспечивает постановку в очередь обмена сообщения на передачу данных выборки внешней системе */ + procedure SEND_MD + ( + NCOMPANY in number, -- Организация + NIDENT in number, -- Идентификатор Selectlis + NEQUIPDSCM in number -- регистрационный номер записи Выборки данных класса оборудования» + ); + + /* Обеспечивает постановку в очередь обмена сообщения на передачу запроса на обработку данных выборки внешней системе */ + procedure SEND_RQ + ( + NCOMPANY in number, -- Организация + NEQUIPDSCMML in number -- Рег. номер Модели + ); + + +end UDO_PKG_EQUIPDS_DATAPROCESS; +/ +create or replace package body UDO_PKG_EQUIPDS_DATAPROCESS +is + + /* Получение имени файла с расширением из полного пути */ + function GET_FILENAME + ( + SPATH IN VARCHAR2 -- Полный путь размещения файла + )RETURN varchar2 -- имя файла с разрешением + IS + SFILE PKG_STD.tSTRING; -- имя файла с разрешением + BEGIN + + /* Parse string for UNIX system */ + IF INSTR(SPATH,'/') > 0 THEN + SFILE := SUBSTR(SPATH,(INSTR(SPATH,'/',-1,1)+1),length(SPATH)); + + /* Parse string for Windows system */ + ELSIF INSTR(SPATH,'\') > 0 THEN + SFILE := SUBSTR(SPATH,(INSTR(SPATH,'\',-1,1)+1),length(SPATH)); + ELSE + SFILE := SPATH; + + END IF; + + RETURN SFILE; + END GET_FILENAME; + + /* Формирование типа колонок */ + function TCOL_TYP_VAL_MAKE + ( + SINDEX in varchar2, -- Индекс применения + SCOL_CODE in varchar2, -- Наименование + SCOL_NAME in varchar2, -- Наименование + SCOL_VAL in varchar2, -- Значение + NCOL_TYP in number, -- тип + SCOL_TYP in varchar2 -- наименование типа + ) return TCOL_TYP_VAL -- Результат работы + is + RRES TCOL_TYP_VAL; -- Буфер для результата + begin + /* Формируем объект */ + RRES.SINDEX := SINDEX; + RRES.SCOL_CODE := SCOL_CODE; + RRES.SCOL_NAME := SCOL_NAME; + RRES.SCOL_VAL := SCOL_VAL; + RRES.NCOL_TYP := NCOL_TYP; + RRES.SCOL_TYP := SCOL_TYP; + /* Возвращаем результат */ + return RRES; + end TCOL_TYP_VAL_MAKE; + + /* Добавление значения в коллекцию типы колонок */ + procedure TCOL_TYP_VALS_ADD + ( + RCOL_TYP_VALS in out nocopy TCOL_TYP_VALS, -- Коллекция значений + SINDEX in varchar2, -- Индекс применения + SCOL_CODE in varchar2, -- Код + SCOL_NAME in varchar2, -- Наименование + SCOL_VAL in varchar2, -- Значение + NCOL_TYP in number, -- тип + SCOL_TYP in varchar2 -- наименование типа + ) + is + begin + /* Инициализируем коллекцию если необходимо */ + if (RCOL_TYP_VALS is null) then + RCOL_TYP_VALS := TCOL_TYP_VALS(); + end if; + /* Добавляем элемент */ + RCOL_TYP_VALS.EXTEND(); + RCOL_TYP_VALS(RCOL_TYP_VALS.LAST) := TCOL_TYP_VAL_MAKE(SINDEX => SINDEX, SCOL_CODE => SCOL_CODE, SCOL_NAME => SCOL_NAME, SCOL_VAL => SCOL_VAL, NCOL_TYP => NCOL_TYP, SCOL_TYP => SCOL_TYP); + + end TCOL_TYP_VALS_ADD; + + /* Поиск действия (краткое описание) */ + function RCOL_TYP_VALS_FIND_CODE + ( + RCOL_TYP_VALS in out nocopy TCOL_TYP_VALS, -- Коллекция значений + SCOL_NAME in varchar2 -- Наименование + ) return PKG_STD.tSTRING -- Найденный Код записи коллекции типы колонок (null - если ничего не найдено) + is + begin + if ((RCOL_TYP_VALS is not null) and (RCOL_TYP_VALS.COUNT > 0)) then + for I in RCOL_TYP_VALS.FIRST .. RCOL_TYP_VALS.LAST + loop + if (RCOL_TYP_VALS(I).SCOL_NAME = SCOL_NAME) then + return RCOL_TYP_VALS(I).SCOL_CODE; + end if; + end loop; + end if; + /* Ничего не нашли */ + return null; + end RCOL_TYP_VALS_FIND_CODE; + + /* Формировавние перечня колонок Data_config - XML */ + procedure TCOL_TYP_VALS_TO_XML + ( + RCOL_TYP_VALS in out nocopy TCOL_TYP_VALS, -- Коллекция значений + CDATA_CONFIG out clob -- Описание структуры выборки + ) + is + XDOC integer; -- Документ для размещения XML-элемента + XITEMATRIBS PKG_XMAKE.tATTRIBUTES; -- Коллекция Атрибутов DATA_CONFIG + XDCONFIG PKG_XMAKE.TNODE; -- Класс DATA_CONFIG + ST1 pkg_std.tSTRING; + ST2 pkg_std.tSTRING; + + begin + /* Проверяем наличие элементов коллекции */ + if (/*(RCOL_TYP_VALS is not null)*/ (RCOL_TYP_VALS.COUNT > 0)) then + /* Создаём документ */ + XDOC := PKG_XMAKE.OPEN_CURSOR(); + /* Обходим элементы коллекции */ + for I in RCOL_TYP_VALS.FIRST .. RCOL_TYP_VALS.LAST loop + if RCOL_TYP_VALS(i).SINDEX != 'DATA_CONFIG' then + continue; + end if; + ST1 := RCOL_TYP_VALS(i).SCOL_NAME; + ST2 := RCOL_TYP_VALS(i).SCOL_TYP; + XITEMATRIBS := PKG_XMAKE.ATTRIBUTES(iCURSOR => XDOC, + rATTRIBUTE00 => PKG_XMAKE.ATTRIBUTE(iCURSOR => XDOC, + sNAME => 'col_code', + sVALUE => RCOL_TYP_VALS(i).SCOL_CODE), + rATTRIBUTE01 => PKG_XMAKE.ATTRIBUTE(iCURSOR => XDOC, + sNAME => 'col_name', + sVALUE => RCOL_TYP_VALS(i).SCOL_NAME), + rATTRIBUTE02 => PKG_XMAKE.ATTRIBUTE(iCURSOR => XDOC, + sNAME => 'data_type', + sVALUE => RCOL_TYP_VALS(i).SCOL_TYP)); + + XDCONFIG := PKG_XMAKE.CONCAT(ICURSOR => XDOC, + RNODE00 => XDCONFIG, + rNODE01 => PKG_XMAKE.ELEMENT(ICURSOR => XDOC, + SNAME => 'item', + rATTRIBUTES => XITEMATRIBS) + ); + end loop; + CDATA_CONFIG := PKG_XMAKE.SERIALIZE_TO_CLOB(iCURSOR => XDOC, + iTYPE => PKG_XMAKE.DOCUMENT_, + rNODE => PKG_XMAKE.CONCAT(iCURSOR => XDOC, + rNODE00 => PKG_XMAKE.ELEMENT(iCURSOR => XDOC, + sNAME => 'data_config', + rNODE00 => XDCONFIG)), + rHEADER => PKG_XHEADER.WRAP_ALL(sVERSION => PKG_XHEADER.VERSION_1_0_, + sENCODING => PKG_XHEADER.ENCODING_UTF_, + sSTANDALONE => PKG_XHEADER.STANDALONE_NONE_)); + + PKG_XMAKE.CLOSE_CURSOR(ICURSOR => XDOC); + end if; + end TCOL_TYP_VALS_TO_XML; + + /* Формирование датасета */ + function TDATASET_VAL_MAKE + ( + NEQOBJKIND in number, -- Класс оборудования + NUNIT in number, -- Экземпляр оборудования + DDATATIME in TIMESTAMP, -- Дата события + TCOLTYP_VAL in out nocopy TCOL_TYP_VALS, -- коллекция переченя колонок + SEVENTTYPE in varchar2 -- Событие + ) return TDATASET_VAL -- Результат работы + is + RRES TDATASET_VAL; -- Буфер для результата + begin + /* Формируем объект */ + RRES.NEQOBJKIND := NEQOBJKIND; + RRES.NUNIT := NUNIT; + RRES.DDATATIME := DDATATIME; + RRES.TCOLTYP_VAL := TCOLTYP_VAL; + RRES.SEVENTTYPE := SEVENTTYPE; + /* Возвращаем результат */ + return RRES; + end TDATASET_VAL_MAKE; + + /* Добавление значения в коллекцию датасета */ + procedure TDATASET_VAL_ADD + ( + RDATASET_VALS in out nocopy TDATASET_VALS, -- Коллекция значений + NEQOBJKIND in number, -- Класс оборудования + NUNIT in number, -- Экземпляр оборудования + DDATATIME TIMESTAMP, -- Дата события + TCOLTYP_VAL in out nocopy TCOL_TYP_VALS, -- коллекция переченя колонок + SEVENTTYPE in varchar2 -- Событие + ) + is + begin + /* Инициализируем коллекцию если необходимо */ + if (RDATASET_VALS is null) then + RDATASET_VALS := TDATASET_VALS(); + end if; + /* Добавляем элемент */ + RDATASET_VALS.EXTEND(); + RDATASET_VALS(RDATASET_VALS.LAST) := TDATASET_VAL_MAKE(NEQOBJKIND => NEQOBJKIND, + NUNIT => NUNIT, + DDATATIME => DDATATIME, + TCOLTYP_VAL => TCOLTYP_VAL, + SEVENTTYPE => SEVENTTYPE + ); + end TDATASET_VAL_ADD; + + /* Формирование dataset в формате XML */ + procedure TDATASET_VALS_TO_XML + ( + RDATASET_VALS in out nocopy TDATASET_VALS, -- Коллекция значений + CDATA_SET out clob -- Описание структуры выборки + ) + is + XDOC integer; -- Документ для размещения XML-элемента + XDCOL PKG_XMAKE.TNODE; -- + XDCONFIG PKG_XMAKE.TNODE; -- Класс DATA_CONFIG + S1 PKG_STD.TSTRING; -- Индекс элемментов коллекции + s2 PKG_STD.TSTRING; -- + begin + /* Проверяем наличие элементов коллекции */ + if ((RDATASET_VALS is not null) and (RDATASET_VALS.COUNT > 0)) then + /* Создаём документ */ + XDOC := PKG_XMAKE.OPEN_CURSOR(); + /* Обходим элементы коллекции */ + for I in RDATASET_VALS.FIRST .. RDATASET_VALS.LAST loop + if ((RDATASET_VALS(i).TCOLTYP_VAL is not null) and (RDATASET_VALS(i).TCOLTYP_VAL.COUNT > 0)) then + for j in RDATASET_VALS(i).TCOLTYP_VAL.FIRST .. RDATASET_VALS(i).TCOLTYP_VAL.LAST loop + + S1 := RDATASET_VALS(i).TCOLTYP_VAL(j).SINDEX; + S2 := RDATASET_VALS(I).NUNIT||'/'||DTS2S(RDATASET_VALS(I).DDATATIME); + + + if RDATASET_VALS(i).TCOLTYP_VAL(j).SINDEX != RDATASET_VALS(I).NUNIT||'/'||DTS2S(RDATASET_VALS(I).DDATATIME) then + continue; + end if; + + XDCOL := PKG_XMAKE.CONCAT(ICURSOR => XDOC, + rNODE00 => XDCOL, + rNODE01 => PKG_XMAKE.ELEMENT(iCURSOR => XDOC, + sNAME => REPLACE(RDATASET_VALS(i).TCOLTYP_VAL(j).SCOL_NAME,' ','_'), + rVALUE00 => PKG_XMAKE.VALUE(iCURSOR => XDOC, + sVALUE => RDATASET_VALS(i).TCOLTYP_VAL(j).SCOL_VAL)) + ); + + end loop; + end if; + /* Собираем XML-описание класса в список */ + XDCONFIG := PKG_XMAKE.CONCAT(ICURSOR => XDOC, + RNODE00 => XDCONFIG, + RNODE01 => PKG_XMAKE.ELEMENT(ICURSOR => XDOC, + SNAME => 'item', + /*rATTRIBUTES => XITEMATRIBS*/ + rNODE00 => PKG_XMAKE.ELEMENT(iCURSOR => XDOC, + sNAME => 'NEQOBJKIND', + rVALUE00 => PKG_XMAKE.VALUE(iCURSOR => XDOC, + sVALUE => RDATASET_VALS(I).NEQOBJKIND)), + rNODE01 => PKG_XMAKE.ELEMENT(iCURSOR => XDOC, + sNAME => 'NUNIT', + rVALUE00 => PKG_XMAKE.VALUE(iCURSOR => XDOC, + sVALUE => RDATASET_VALS(I).NUNIT)), + rNODE02 => PKG_XMAKE.ELEMENT(iCURSOR => XDOC, + sNAME => 'DDATATIME', + rVALUE00 => PKG_XMAKE.VALUE_DZ(iCURSOR => XDOC, + DVALUE => RDATASET_VALS(I).DDATATIME, + iFORMAT => 2)), + rNODE03 => XDCOL, + rNODE04 => PKG_XMAKE.ELEMENT(iCURSOR => XDOC, + sNAME => 'SEVENTTYPE', + rVALUE00 => PKG_XMAKE.VALUE(iCURSOR => XDOC, + sVALUE => RDATASET_VALS(I).SEVENTTYPE)))); + + XDCOL := null; + end loop; + + CDATA_SET := PKG_XMAKE.SERIALIZE_TO_CLOB(iCURSOR => XDOC, + iTYPE => PKG_XMAKE.DOCUMENT_, + rNODE => PKG_XMAKE.CONCAT(iCURSOR => XDOC, + rNODE00 => PKG_XMAKE.ELEMENT(iCURSOR => XDOC, + sNAME => 'data_set', + rNODE00 => XDCONFIG)), + rHEADER => PKG_XHEADER.WRAP_ALL(sVERSION => PKG_XHEADER.VERSION_1_0_, + sENCODING => PKG_XHEADER.ENCODING_UTF_, + sSTANDALONE => PKG_XHEADER.STANDALONE_NONE_)); + + PKG_XMAKE.CLOSE_CURSOR(ICURSOR => XDOC); + end if; + end TDATASET_VALS_TO_XML; + + /* Формирование dataset в формате CSV */ + procedure DATASET_SCV_MAKE + ( + RDATACONF in out nocopy TCOL_TYP_VALS, -- Коллекция колокон шапки dataset + RDATASET_VALS in out nocopy TDATASET_VALS, -- Коллекция значений + SDESCR in varchar2, -- Описание выборки данных + NLENGTH_GB in number, -- Ограничение размера файла в Гб + NEQCONFIG_CNT in number, -- Количесто экземпляров оборудования + NDATASET_IDENT out number -- Идентификатор буфера данных + ) + is + SLINE PKG_STD.tSTRING /*:= 'unit;time;'*/; -- Линия шапки + SDATA PKG_STD.tSTRING; -- Линия данных + N PKG_STD.tNUMBER:= 0; -- Всего колонок + NLENGTH PKG_STD.tNUMBER; + NLENGTH_DEF PKG_STD.tNUMBER;-- := 1073741824; -- 1 гига байт !!! + NLENGTH_KOEFF PKG_STD.tNUMBER := 1024; + BDATA_SET blob; -- Описание структуры выборки + SFILENAME PKG_STD.tSTRING :='DataSet_.csv'; -- Имя файла + NF PKG_STD.tNUMBER := 0; + SDATA_VAL PKG_STD.tSTRING; + nREC PKG_STD.tNUMBER := 0; + begin + /* Переводим Гб в байты */ + if NVL(NLENGTH_GB, 0) != 0 then + NLENGTH_DEF := ((((NLENGTH_GB * NLENGTH_KOEFF) * NLENGTH_KOEFF) * + NLENGTH_KOEFF)); + else + NLENGTH_DEF := null; + end if; + /* Генерация Идентификатора буфера данных */ + NDATASET_IDENT := gen_ident; + /* Формируем Шапку */ + for I in RDATACONF.FIRST .. RDATACONF.LAST loop + if RDATACONF(i).SINDEX != 'DATA_CONFIG' then + continue; + end if; + SLINE := SLINE || RDATACONF(i).SCOL_CODE || ';'; + N := I; + end loop; + + SLINE := RTRIM(SLINE,';') /*|| 'EventType'*/ || CR(); + PKG_LOB_BUFFER.APPEND_BLOB(CLOB2BLOB(SLINE, PKG_CHARSET.CHARSET_UTF_)); + if RDATASET_VALS is not EMPTY then + /* Обходим элементы коллекции */ + nREC := Round(30632 /NEQCONFIG_CNT,0); + for J in RDATASET_VALS.FIRST .. RDATASET_VALS.LAST loop + for r in 1 .. nREC loop + --exit when r = nREC; + + SDATA := RDATASET_VALS(j) + .NUNIT || ';' ||r|| ';'; + --DTS2S(RDATASET_VALS(j).DDATATIME) || ';'; + --if RDATASET_VALS(j).TCOLTYP_VAL is NOT EMPTY then + + --end if; + /*Контроль наличия колонок */ + if RDATACONF is not EMPTY then + /* Проходим по колонкам */ + for I1 in RDATACONF.FIRST .. RDATACONF.LAST loop + /* Исключаем выборку данных для DATA_CONFIG */ + if RDATACONF(i1).SINDEX != 'DATA_CONFIG' then + continue; + end if; + /* Обнуление параметра */ + SDATA_VAL := null; + /* Обходим коллекцию с данными */ + for l in RDATASET_VALS(j).TCOLTYP_VAL.FIRST .. RDATASET_VALS(j) + .TCOLTYP_VAL.LAST loop + if RDATACONF(i1).SCOL_CODE is not null and RDATACONF(i1).SCOL_CODE not in ('unit','time') then + SDATA_VAL := replace(round(dbms_random.value(-100,100),2),',','.'); + exit; + end if; + /* Проверка наличия колонки в коллекции */ + /*if RDATACONF(i1) + .SCOL_CODE = RDATASET_VALS(j).TCOLTYP_VAL(l).SCOL_CODE and RDATACONF(i1) + .NCOL_TYP = RDATASET_VALS(j).TCOLTYP_VAL(l).NCOL_TYP then + \* Фиксируем данные и выходим из цыкла *\ + --SDATA_VAL := RDATASET_VALS(j).TCOLTYP_VAL(l).SCOL_VAL; + SDATA_VAL := replace(round(dbms_random.value(-100,100),2),',','.'); + exit; + else + \*Если нет колонки переходим к следующей записи коллекции с данными *\ + continue; + --SDATA_VAL := replace(round(dbms_random.value(-100,100),2),',','.'); + end if;*/ + end loop; + if SDATA_VAL is not null then + SDATA := SDATA||SDATA_VAL || ';'; + end if; + end loop; + end if; + + SDATA := RTRIM(SDATA,';') /*|| RDATASET_VALS(j).SEVENTTYPE || ';'*/ || CR(); + + BDATA_SET := PKG_LOB_BUFFER.GET_BLOB(lCLEAR => false); + NLENGTH := dbms_lob.getlength(BDATA_SET); + if (NLENGTH_DEF is not null and NLENGTH >= NLENGTH_DEF) then + BDATA_SET := PKG_LOB_BUFFER.GET_BLOB(lCLEAR => true); + NF := NF + 1; + P_FILE_BUFFER_INSERT(nIDENT => NDATASET_IDENT, + cFILENAME => NF || '_' || + REPLACE(SFILENAME, + '', + gen_ident), + cDATA => SDESCR, + bLOBDATA => BDATA_SET); + end if; + PKG_LOB_BUFFER.APPEND_BLOB(CLOB2BLOB(SDATA, + PKG_CHARSET.CHARSET_UTF_)); + end loop; + end loop; + BDATA_SET := PKG_LOB_BUFFER.GET_BLOB(lCLEAR => true); + P_FILE_BUFFER_INSERT(nIDENT => NDATASET_IDENT, + cFILENAME => NF || '_' || + REPLACE(SFILENAME, '', gen_ident), + cDATA => SDESCR, + bLOBDATA => BDATA_SET); + end if; + end DATASET_SCV_MAKE; + + /* Формирование данных датасета и Описание структуры выборки */ + procedure DATASET_CONF_MAKE + ( + NCOMPANY in number, -- регистрационный номер организации + NEQUIPDSCM in number default null, -- Рег. номер класса оборудования выборки данных (null - работать по указанной единице оборудования) + NEQCONFIG in number default null, -- Рег. номер единицы оборудования (null - по всем) + DBEG in date, -- Дата С + DEND in date, -- Дата По + SDESCR out varchar2, -- Описание выборки данных + NEQCONFIGCNT out number, -- Количесто экземпляров оборудования + RDATA_CONFIG in out nocopy TCOL_TYP_VALS, -- Коллекция значений + RDATASET_VALS in out nocopy TDATASET_VALS -- Коллекция данных датасета + ) + is + NUNIT PKG_STD.tREF; -- Экземпляр оборудования + --NEQOBJKIND PKG_STD.tREF; -- Класс оборудования + RCOLTYPVALS TCOL_TYP_VALS; -- Коллекция значений + DDATATIME date; -- Дата события + SEVENTTYPE PKG_STD.TSTRING; -- Событие + SUNIT PKG_STD.tSTRING; + NEQCONFIG_CNT PKG_STD.tNUMBER := 0; -- Количесто экземпляров оборудования + nPP_TC PKG_STD.tNUMBER:= 0; -- Порядкоый номер столца технического состояния + nPP_OC PKG_STD.tNUMBER:= 0; -- Порядкоый номер столца условий эксплуатации + SCOL_CODE PKG_STD.TSTRING; + NEQOBJKIND_ PKG_STD.TREF; -- Класс оборудования + begin + -- NEQOBJKIND := NEQUIPDSCMN; --8358772; + /* Определим класс технического объекта - сначала по классу оборудования выборки данных, если нам его передали */ + if (NEQUIPDSCM is not null) then + begin + select T.EQOBJKIND into NEQOBJKIND_ from UDO_T_EQUIPDSCM T where T.RN = NEQUIPDSCM; + exception + when NO_DATA_FOUND then + P_EXCEPTION(0, 'Запись класса оборудования выборки данных (RN: %s) не определена.', TO_CHAR(NEQUIPDSCM)); + end; + end if; + /* Определим класс технического объекта - теперь по единице оборудования, если передали её */ + if (NEQCONFIG is not null) then + begin + select T.OBJ_KIND into NEQOBJKIND_ from EQCONFIG T where T.RN = NEQCONFIG; + exception + when NO_DATA_FOUND then + P_EXCEPTION(0, 'Запись единицы оборудования (RN: %s) не определена.', TO_CHAR(NEQCONFIG)); + end; + if (NEQOBJKIND_ is null) then + P_EXCEPTION(0, 'Для единицы оборудования (RN: %s) не определён класс технического объекта.', TO_CHAR(NEQCONFIG)); + end if; + end if; + /* Проверим, что нашли хоть каким-то способом */ + if (NEQOBJKIND_ is null) then + P_EXCEPTION(0, 'Не удалось определить класс технического объекта.'); + end if; + /* Добаляем в колекию первые поля "unit" и "time" */ + /* Заполним коллекцию переченя колонок для построения датасета и формирования конфигурации */ + TCOL_TYP_VALS_ADD(RCOL_TYP_VALS => RDATA_CONFIG, + SINDEX => 'DATA_CONFIG', + SCOL_CODE => 'unit', + SCOL_NAME => 'экземпляр оборудования', + SCOL_VAL => null, + NCOL_TYP => NCOL_TYP_STRING, + SCOL_TYP => SCOL_TYP_STRING); + /* Заполним коллекцию переченя колонок для построения датасета и формирования конфигурации */ + TCOL_TYP_VALS_ADD(RCOL_TYP_VALS => RDATA_CONFIG, + SINDEX => 'DATA_CONFIG', + SCOL_CODE => 'time', + SCOL_NAME => 'DataTime', + SCOL_VAL => null, + NCOL_TYP => NCOL_TYP_DATATIME, + SCOL_TYP => SCOL_TYP_DATATIME); + + + /* Заполним данные DATA_CONFIG */ + /*-------------------------------------------------------------------------------*/ + /* Классификатор технических объектов (макет параметров технического состояния) */ + FOR TEQOBJKINDSM in (select T1.CODE, T1.NAME + from EQOBJKINDSM t, EQTECHSTPR t1 --, DICMUNTS t2 + where T.PRN = NEQOBJKIND_ + and T.TCHSTPARAM = t1.rn + and T1.TYPE_PARAM = 0 -- нормативный0 + and T.COMPANY = NCOMPANY + order by t1.name asc) loop + nPP_TC := nPP_TC + 1; + SCOL_CODE := 'p'||nPP_TC; + /* Заполним коллекцию переченя колонок для построения датасета и формирования конфигурации */ + TCOL_TYP_VALS_ADD(RCOL_TYP_VALS => RDATA_CONFIG, + SINDEX => 'DATA_CONFIG', + SCOL_CODE => SCOL_CODE, + SCOL_NAME => TEQOBJKINDSM.NAME, + SCOL_VAL => null, + NCOL_TYP => NCOL_TYP_STRING, + SCOL_TYP => SCOL_TYP_STRING); + end loop; + /* Классификатор технических объектов (макет параметров условий эксплуатации) */ + for TEQOBJKINDEXTPRM in (select T1.CODE, T1.NAME + from EQOBJKINDEXTPRM t, EQEXTENVPRM t1 + where t.PRN = NEQOBJKIND_ + and T.EQEXTENVPRM = T1.RN + and T.COMPANY = NCOMPANY + order by t1.name asc ) loop + nPP_OC := nPP_OC + 1; + SCOL_CODE := 's'||nPP_OC; + /* Заполним коллекцию переченя колонок для построения датасета и формирования конфигурации */ + TCOL_TYP_VALS_ADD(RCOL_TYP_VALS => RDATA_CONFIG, + SINDEX => 'DATA_CONFIG', + SCOL_CODE => SCOL_CODE, + SCOL_NAME => TEQOBJKINDEXTPRM.NAME, + SCOL_VAL => null, + NCOL_TYP => NCOL_TYP_STRING, + SCOL_TYP => SCOL_TYP_STRING); + end loop; + /* Типы состояний оборудования */ + for THLSTATETYPES in (select t.code, T.READY_USE + from HLSTATETYPES T + where t.version = + f_company_to_version(nFLAG_SMART => 0, + nCOMPANY => NCOMPANY, + sUNITCODE => 'HaulierUnitsStateTypes') + and T.READY_USE != 0) loop + + nPP_OC := nPP_OC + 1; + SCOL_CODE := 's'||nPP_OC; + /* Заполним коллекцию переченя колонок для построения датасета и формирования конфигурации */ + TCOL_TYP_VALS_ADD(RCOL_TYP_VALS => RDATA_CONFIG, + SINDEX => 'DATA_CONFIG', + SCOL_CODE => SCOL_CODE, + SCOL_NAME => THLSTATETYPES.CODE, + SCOL_VAL => null, + NCOL_TYP => NCOL_TYP_STRING, + SCOL_TYP => SCOL_TYP_STRING); + end loop; + /* Проверим количесто сформированных колонок, если менее 22, до добавим до минимального необходимого значения + - ВРЕМЕННО, для обеспечения требоания по формироанию модели ОБУСЧЕНИЯ */ + If nPP_OC < 22 then + loop + exit when nPP_OC = 22; + nPP_OC := nPP_OC + 1; + SCOL_CODE := 's'||nPP_OC; + /* Добаление колонки без наименования "-" */ + TCOL_TYP_VALS_ADD(RCOL_TYP_VALS => RDATA_CONFIG, + SINDEX => 'DATA_CONFIG', + SCOL_CODE => SCOL_CODE, + SCOL_NAME => '-', + SCOL_VAL => null, + NCOL_TYP => NCOL_TYP_STRING, + SCOL_TYP => SCOL_TYP_STRING); + end loop; + end if; + /* Считаем запись оборудования */ + for TEQCONFIG in (select T.RN NUNIT, T.OPER_DATE + from EQCONFIG t + where T.OBJ_KIND = NEQOBJKIND_ + and ((NEQCONFIG is null) or ((NEQCONFIG is not null) and (T.RN = NEQCONFIG))) + and T.OPER_DATE between DBEG and DEND + and T.COMPANY = NCOMPANY + order by t.OPER_DATE asc) loop + NEQCONFIG_CNT := NEQCONFIG_CNT + 1; + SUNIT := to_char(TEQCONFIG.NUNIT || '/' || DTS2S(TEQCONFIG.OPER_DATE)); + -- Соббытие SDEF_EVENTTYPE_E0 Event 0 + /* Параметры технического состояния */ + FOR TPARAM_HARDWARE in (select T1.CODE, + T1.NAME, + T2.MEAS_MNEMO, + T2.MEAS_NAME, + T.NOM_VALUE, + T.MIN_VALUE, + T.MAX_VALUE + from EQCONFIGSP t, EQTECHSTPR t1, DICMUNTS t2 + where T.PRN = TEQCONFIG.NUNIT + and T.TCHSTPARAM = t1.rn + and T1.TYPE_PARAM = 0 -- нормативный + and T.UMEAS = t2.rn(+) + order by t1.name asc) loop + + SCOL_CODE := RCOL_TYP_VALS_FIND_CODE(RCOL_TYP_VALS => RDATA_CONFIG, SCOL_NAME => TPARAM_HARDWARE.NAME); + + /* Заполним коллекцию переченя колонок для построения датасета и формирования конфигурации */ + TCOL_TYP_VALS_ADD(RCOL_TYP_VALS => RCOLTYPVALS, + SINDEX => SUNIT, + SCOL_CODE => NVL(SCOL_CODE,'S0'), + SCOL_NAME => TPARAM_HARDWARE.NAME, + SCOL_VAL => TPARAM_HARDWARE.NOM_VALUE, + NCOL_TYP => NCOL_TYP_STRING, + SCOL_TYP => SCOL_TYP_STRING); + + end loop; -- TPARAM_HARDWARE + /* параметры окружения и эксплуатационные характеристики */ + for TCONDITIONS in (select t1.code code_PRM, + t1.name name_PRM, + t2.code code_tp + from EQCONFEXTPRM t, + EQEXTENVPRM t1, + EQUIPWORKACTTYPE t2 + where t.PRN = TEQCONFIG.NUNIT + and t.eqextenvprm = t1.rn + and t1.workacttype = t2.rn + order by t1.name asc) loop + + SCOL_CODE := RCOL_TYP_VALS_FIND_CODE(RCOL_TYP_VALS => RDATA_CONFIG, SCOL_NAME => TCONDITIONS.NAME_PRM); + + /* Заполним коллекцию переченя колонок для построения датасета и формирования конфигурации */ + TCOL_TYP_VALS_ADD(RCOL_TYP_VALS => RCOLTYPVALS, + SINDEX => SUNIT, + SCOL_CODE => NVL(SCOL_CODE,'S0'), + SCOL_NAME => TCONDITIONS.NAME_PRM, + SCOL_VAL => TCONDITIONS.code_tp, + NCOL_TYP => NCOL_TYP_STRING, + SCOL_TYP => SCOL_TYP_STRING); + + end loop; -- TCONDITIONS + DDATATIME := /* S2ZSTAMP(PKG_XCONVERT.DZ_TO_XML(*/ + TEQCONFIG.OPER_DATE /*,2))*/ + ; + /**/ + TDATASET_VAL_ADD(RDATASET_VALS => RDATASET_VALS, + NEQOBJKIND => NEQOBJKIND_, + NUNIT => TEQCONFIG.NUNIT, + DDATATIME => DDATATIME, + TCOLTYP_VAL => RCOLTYPVALS, + SEVENTTYPE => SDEF_EVENTTYPE_E0); + /* Очистим коллекцию переченя колонок */ + if RCOLTYPVALS IS NOT EMPTY then + RCOLTYPVALS.delete; + end if; + + -- Соббытие SDEF_EVENTTYPE_E0, Event 0 + + -- Соббытие SDEF_EVENTTYPE_EF Event of Failure + /* Учёт повреждений оборудования - Состояние "Зафиксировано" */ + for TEQDAMCTRL in (select T.RN, T.CHNG_FIX_DATE + from EQDAMCTRL t + where T.EQCONFIG = TEQCONFIG.NUNIT + AND T.COMPANY = NCOMPANY + and T.EQ_FIX = 1) loop + SUNIT := to_char(TEQCONFIG.NUNIT || '/' || + DTS2S(TEQDAMCTRL.CHNG_FIX_DATE)); + + /* Учёт повреждений оборудования (параметры технического состояния) */ + for TEQDAMCTRLPRM in (select t2.code, t2.name, t.cur_val, t.max_val + from EQDAMCTRLPRM t, + EQCONFIGSP t1, + EQTECHSTPR t2 + where t.PRN = TEQDAMCTRL.RN + and t.eqconfigsp = t1.rn + and t1.tchstparam = t2.rn + order by t2.code asc) loop + + SCOL_CODE := RCOL_TYP_VALS_FIND_CODE(RCOL_TYP_VALS => RDATA_CONFIG, SCOL_NAME => TEQDAMCTRLPRM.code); + + /* Заполним коллекцию переченя колонок для построения датасета и формирования конфигурации */ + TCOL_TYP_VALS_ADD(RCOL_TYP_VALS => RCOLTYPVALS, + SINDEX => SUNIT, + SCOL_CODE => NVL(SCOL_CODE,'S0'), + SCOL_NAME => TEQDAMCTRLPRM.code, + SCOL_VAL => TEQDAMCTRLPRM.max_val, + NCOL_TYP => NCOL_TYP_STRING, + SCOL_TYP => SCOL_TYP_STRING); + end loop; -- TEQDAMCTRLPRM + + /* Учёт повреждений оборудования (параметры условий эксплуатации) */ + for TEQDAMCTRLEXTPRM in (select t2.code, t.value + from EQDAMCTRLEXTPRM t, + EQCONFEXTPRM t1, + EQEXTENVPRM t2 + where t.PRN = TEQDAMCTRL.RN + and T.EQCONFEXTPRM = t1.rn + and T1.EQEXTENVPRM = t2.rn + order by t2.code asc) loop + + SCOL_CODE := RCOL_TYP_VALS_FIND_CODE(RCOL_TYP_VALS => RDATA_CONFIG, SCOL_NAME => TEQDAMCTRLEXTPRM.code); + + /* Заполним коллекцию переченя колонок для построения датасета и формирования конфигурации */ + TCOL_TYP_VALS_ADD(RCOL_TYP_VALS => RCOLTYPVALS, + SINDEX => SUNIT, + SCOL_CODE => NVL(SCOL_CODE,'S0'), + SCOL_NAME => TEQDAMCTRLEXTPRM.code, + SCOL_VAL => TEQDAMCTRLEXTPRM.value, + NCOL_TYP => NCOL_TYP_STRING, + SCOL_TYP => SCOL_TYP_STRING); + end loop; + /**/ + DDATATIME := /*S2ZSTAMP(PKG_XCONVERT.DZ_TO_XML(*/ + TEQDAMCTRL.CHNG_FIX_DATE; /*,2)),*/ + TDATASET_VAL_ADD(RDATASET_VALS => RDATASET_VALS, + NEQOBJKIND => NEQOBJKIND_, + NUNIT => TEQCONFIG.NUNIT, + DDATATIME => DDATATIME, + TCOLTYP_VAL => RCOLTYPVALS, + SEVENTTYPE => SDEF_EVENTTYPE_EF); + + end loop; + /* Очистим коллекцию переченя колонок */ + if RCOLTYPVALS is not EMPTY then + RCOLTYPVALS.delete; + end if; + -- Соббытие SDEF_EVENTTYPE_EF Event of Failure + + -- Соббытие SDEF_EVENTTYPE_ENOS Event of Non-Operation of System i + -- Соббытие SDEF_EVENTTYPE_ETMS Event of Transition to Maintenance State + + /* Ремонтные ведомости - Вход и Выход для состояния ТОИР */ + for TEQRPSHEETS in (select T.STATE, t.datefact_beg, t.datefact_end + from EQRPSHEETS t + where t.EQCONFIG = TEQCONFIG.NUNIT) loop + /* Определим параметры */ + case TEQRPSHEETS.STATE + /* Статус - "Закрыт" выход из состояния ТОИР */ + when 3 then + DDATATIME := /*S2ZSTAMP(PKG_XCONVERT.DZ_TO_XML(*/ + TEQRPSHEETS.DATEFACT_END /*,2))*/ + ; + SEVENTTYPE := SDEF_EVENTTYPE_ERMS; + /* Статус - "Утвержден" вход в состояние ТОИР */ + when 2 then + DDATATIME := /*S2ZSTAMP(PKG_XCONVERT.DZ_TO_XML(*/ + TEQRPSHEETS.DATEFACT_BEG /*,2))*/ + ; + SEVENTTYPE := SDEF_EVENTTYPE_ETMS; + else + DDATATIME := null; + SEVENTTYPE := null; + end case; + SUNIT := TO_CHAR(TEQCONFIG.NUNIT || '/' || DTS2S(DDATATIME)); + /* */ + if DDATATIME is not null and SEVENTTYPE is not null then + /* TCOL_TYP_VALS_ADD(RCOL_TYP_VALS => RCOLTYPVALS, + SINDEX => SUNIT, + SCOL_NAME => 'null_0', + SCOL_VAL => '-', + NCOL_TYP => NCOL_TYP_DF, + SCOL_TYP => SCOL_TYP_DF);*/ + TDATASET_VAL_ADD(RDATASET_VALS => RDATASET_VALS, + NEQOBJKIND => NEQOBJKIND_, + NUNIT => TEQCONFIG.NUNIT, + DDATATIME => DDATATIME, + TCOLTYP_VAL => RCOLTYPVALS, + --SCOL_NAME => null, -- Вопрос для обсуждения чем заполнять + --SCOL_VAL => null, -- Вопрос для обсуждения чем заполнять + SEVENTTYPE => SEVENTTYPE); + /* Очистим коллекцию переченя колонок */ + if RCOLTYPVALS is not EMPTY then + RCOLTYPVALS.delete; + end if; + end if; + end loop; + + -- Соббытие SDEF_EVENTTYPE_ENOS Event of Non-Operation of System i + -- Соббытие SDEF_EVENTTYPE_ETMS Event of Transition to Maintenance State + + -- Соббытие SDEF_EVENTTYPE_ERMS Event of Return from Maintenance State + -- Соббытие SDEF_EVENTTYPE_EOS Event of System i + /* Состав оборудования (история смены состояний) */ + for TEQCONFIGSH in (select t1.code, t1.ready_use, t.change_date + from EQCONFIGSH t, HLSTATETYPES t1 + where t.PRN = TEQCONFIG.NUNIT + and t.hlstatetypes = t1.rn + order by t1.code asc) loop + case TEQCONFIGSH.READY_USE + /* Готово к эксплуатации */ + when 2 then + SEVENTTYPE := SDEF_EVENTTYPE_EOS; + /* Не готово к эксплуатации */ + when 1 then + SEVENTTYPE := SDEF_EVENTTYPE_ENOS; + else + SEVENTTYPE := null; + end case; + /**/ + + if SEVENTTYPE is not null then + DDATATIME := /*PKG_XCONVERT.DZ_TO_XML(*/ + TEQCONFIGSH.CHANGE_DATE; /*,2)*/ + SUNIT := TO_CHAR(TEQCONFIG.NUNIT || '/' || DTS2S(DDATATIME)); + SCOL_CODE := RCOL_TYP_VALS_FIND_CODE(RCOL_TYP_VALS => RDATA_CONFIG, SCOL_NAME => TEQCONFIGSH.CODE); + + TCOL_TYP_VALS_ADD(RCOL_TYP_VALS => RCOLTYPVALS, + SINDEX => SUNIT, + SCOL_CODE => NVL(SCOL_CODE,'S0'), + SCOL_NAME => TEQCONFIGSH.CODE, + SCOL_VAL => TEQCONFIGSH.READY_USE, + NCOL_TYP => NCOL_TYP_STRING, + SCOL_TYP => SCOL_TYP_STRING); + + TDATASET_VAL_ADD(RDATASET_VALS => RDATASET_VALS, + NEQOBJKIND => NEQOBJKIND_, + NUNIT => TEQCONFIG.NUNIT, + DDATATIME => DDATATIME, + TCOLTYP_VAL => RCOLTYPVALS, + --SCOL_NAME => TEQCONFIGSH.CODE, -- Вопрос для обсуждения чем заполнять + --SCOL_VAL => TEQCONFIGSH.READY_USE, -- Вопрос для обсуждения чем заполнять + SEVENTTYPE => SEVENTTYPE); + /* Очистим коллекцию переченя колонок */ + if RCOLTYPVALS is not EMPTY then + RCOLTYPVALS.delete; + end if; + end if; + + end loop; + + -- Соббытие SDEF_EVENTTYPE_ERMS Event of Return from Maintenance State + -- Соббытие SDEF_EVENTTYPE_EOS Event of System i + + -- Соббытие SDEF_EVENTTYPE_EOL Event of Limit State i + -- Вопрос для обсуждения чем заполнять - Есть предложение - требуется регистраия Параметры технического состояния с типом "Критический - отслеживается не аварийные ситуаии, но с близкими значениями к аварийным " по типу "Нормативый отслеживаем аварии и ремонты" + -- Соббытие SDEF_EVENTTYPE_EOL Event of Limit State i + + end loop; -- TEQCONFIG + /* Описание */ + SDESCR := 'дата с - '|| D2S(DBEG)||CR() + ||'дата по - '||D2S(DEND)||CR() + ||'Количество единиц оборудования выборке - '||NEQCONFIG_CNT||CR() + ||'ID Класса оборудования - '||NEQOBJKIND_; + NEQCONFIGCNT := NEQCONFIG_CNT; + end DATASET_CONF_MAKE; + + /* Получение данных датасета и Описание структуры выборки */ + procedure DATASET_CONF_SET + ( + NCOMPANY in number, -- регистрационный номер организации + NEQUIPDSCM in number default null, -- Рег. номер класса оборудования выборки данных (null - работать по указанной единице оборудования) + NEQCONFIG in number default null, -- Рег. номер единицы оборудования (null - по всем) + DBEG in date, -- Дата С + DEND in date, -- Дата По + NLENGTH_GB in number default null, -- Ограничение размера файла в Гб + NDATASET_IDENT out number, -- Идентификатор буфера данных + NDATASET_CONFIG_IDENT out number -- Идентификатор буфера описания данных ) + ) + is + RDATA_CONFIG TCOL_TYP_VALS; -- Коллекция значений + RDATASET_VALS TDATASET_VALS; -- Коллекция данных датасета + SDESCR PKG_STD.TSTRING; -- Описание выборки данных + CDATA_CONFIG clob; -- Данные описания структуры выборки + NEQCONFIGCNT PKG_STD.TNUMBER; -- Количество единиц оборудования, попавших в выборку + begin + /* Проверим, что нам указали либо класс оборудования выборки данных, либо рег. номер единицы оборудования */ + if (((NEQUIPDSCM is null) and (NEQCONFIG is null)) or ((NEQUIPDSCM is not null) and (NEQCONFIG is not null))) then + P_EXCEPTION(0, + 'Должен быть указан либо класс оборудования выборки данных, либо единица оборудения.'); + end if; + /* Формирование данных датасета и описания структуры выборки */ + DATASET_CONF_MAKE(NCOMPANY => NCOMPANY, + NEQUIPDSCM => NEQUIPDSCM, + NEQCONFIG => NEQCONFIG, + DBEG => DBEG, + DEND => DEND, + SDESCR => SDESCR, + NEQCONFIGCNT => NEQCONFIGCNT, + RDATA_CONFIG => RDATA_CONFIG, + RDATASET_VALS => RDATASET_VALS); + /* Формировавние перечня колонок Data_config - XML */ + TCOL_TYP_VALS_TO_XML(RCOL_TYP_VALS => RDATA_CONFIG, CDATA_CONFIG => CDATA_CONFIG); + /* Генерация идентификатора файлового буфера для настроек структуры данных */ + NDATASET_CONFIG_IDENT := GEN_IDENT(); + /* Сохраним настройку структуры данных */ + P_FILE_BUFFER_INSERT(NIDENT => NDATASET_CONFIG_IDENT, + CFILENAME => 'CDATA_CONFIG', + CDATA => CDATA_CONFIG, + BLOBDATA => null); + /* Формирование dataset в формате CSV */ + DATASET_SCV_MAKE(RDATACONF => RDATA_CONFIG, + RDATASET_VALS => RDATASET_VALS, + SDESCR => SDESCR, + NLENGTH_GB => NLENGTH_GB, + NEQCONFIG_CNT => NEQCONFIGCNT, + NDATASET_IDENT => NDATASET_IDENT); + end DATASET_CONF_SET; + + /* Обеспечивает постановку в очередь обмена сообщения на загрузку данных выборки на FTP, SCP */ + procedure UPLOAD + ( + NCOMPANY in number, -- Организация + NIDENT in number, -- Идентификатор Selectlis + NEQUIPDSCM in number -- Рег. номер класса оборудования выборки данных + ) + is + NEXSSERVICEFN PKG_STD.tREF; -- Функция обмена для загрузки на нешний ресурс + SHOST PKG_STD.tSTRING; -- host + SPORT PKG_STD.tSTRING; -- port + SUSER PKG_STD.tSTRING; -- username + SPASS PKG_STD.tSTRING; -- password + SPATCH_FSERV PKG_STD.tSTRING; -- Путь размещения файла на сервере CSP + begin + /* Определим класс оборудования - Спецификации первого уровня «Классы оборудования» */ + begin + select T.EXSSERVICEFN_UPLOAD + into NEXSSERVICEFN + from UDO_T_EQUIPDSCM T + where T.RN = NEQUIPDSCM; + exception + when NO_DATA_FOUND then + p_exception(0, + ' Запись Спецификации первого уровня «Классы оборудования» с RN "s%", не определена.', + NEQUIPDSCM); + when TOO_MANY_ROWS then + p_exception(0, + ' Найдено более одной записи Спецификации первого уровня «Классы оборудования» с RN "s%".', + NEQUIPDSCM); + end; + UDO_PKG_EQUIPDS_SEND.SCP_DATA_MAKE(NEXSSERVICEFN => NEXSSERVICEFN, + SHOST => SHOST, + SPORT => SPORT, + SUSER => SUSER, + SPASS => SPASS, + SPATCH_FSERV => SPATCH_FSERV); + + for TEQUIPDSCMFL in(select E.* from UDO_T_EQUIPDSCMFL E, SELECTLIST SL where E.RN = SL.DOCUMENT and SL.IDENT = NIDENT)loop + /* отправка запроса */ + UDO_PKG_EQUIPDS_SEND.SEND_PACKGE(NEXSSERVICEFN => NEXSSERVICEFN, + NLNK_NEXSQUEUE => null, + NCOMPANY => NCOMPANY, + NDOCUMENT => TEQUIPDSCMFL.RN, + SUNITCODE => null, + SHOST => SHOST, + SPORT => SPORT, + SUSER => SUSER, + SPASS => SPASS, + --bAUTH => true, + SPATCH_LOKAL => TEQUIPDSCMFL.FILE_NAME, + NEQUIPDSCMN => NEQUIPDSCM, + SPATCH_FSERV => '/'||SPATCH_FSERV||'/'||TEQUIPDSCMFL.FILE_NAME, + NPRIORITY => 0, + BMSG => TEQUIPDSCMFL.DATASET); + end loop; + end UPLOAD; + + /* Обеспечивает постановку в очередь обмена сообщения на передачу данных выборки внешней системе */ + procedure SEND_MD + ( + NCOMPANY in number, -- Организация + NIDENT in number, -- Идентификатор Selectlis + NEQUIPDSCM in number -- регистрационный номер записи Выборки данных класса оборудования» + ) + is + NEXSSERVICEFN PKG_STD.tREF; -- Рег. номер функции обработки + BXML blob; -- Тело запроса + NDATASET_ID PKG_STD.tREF; -- DATASET_ID + begin + /* Определим класс оборудования - Спецификации первого уровня «Классы оборудования» */ + begin + select T.EXSSERVICEFN_SEND_MD + into NEXSSERVICEFN + from UDO_T_EQUIPDSCM T + where T.RN = NEQUIPDSCM; + exception + when NO_DATA_FOUND then + p_exception(0, + ' Запись Спецификации первого уровня «Классы оборудования» с RN "s%", не определена.', + NEQUIPDSCM); + when TOO_MANY_ROWS then + p_exception(0, + ' Найдено более одной записи Спецификации первого уровня «Классы оборудования» с RN "s%".', + NEQUIPDSCM); + end; + + /* Формируем тело запроса */ + UDO_PKG_EQUIPDS_SEND.METADATA_MAKE(NIDENT => NIDENT, NEQUIPDSCM => NEQUIPDSCM, NDATASET_ID => NDATASET_ID, BXML => BXML ); + + /* отправка запроса */ + UDO_PKG_EQUIPDS_SEND.SEND_PACKGE(NEXSSERVICEFN => NEXSSERVICEFN, + NLNK_NEXSQUEUE => null, + NCOMPANY => NCOMPANY, + NDOCUMENT => NDATASET_ID, + SUNITCODE => null, + bAUTH => true, + NPRIORITY => 0, + BMSG => BXML + ); + + end SEND_MD; + + /* Обеспечивает постановку в очередь обмена сообщения на передачу запроса на обработку данных выборки внешней системе */ + procedure SEND_RQ + ( + NCOMPANY in number, -- Организация + NEQUIPDSCMML in number -- Рег. номер Модели + ) + is + NEXSSERVICEFN PKG_STD.tREF; -- Рег. номер функции обработки + BXML blob; -- Тело запроса + begin + /* Определим класс оборудования - Спецификации первого уровня «Классы оборудования» */ + begin + select m.EXSSERVICEFN_SEND_RQ + into NEXSSERVICEFN + from UDO_T_EQUIPDSCM m, UDO_T_EQUIPDSCMML ml + where ml.rn = NEQUIPDSCMML + and M.RN = ML.PRN; + exception + when NO_DATA_FOUND then + p_exception(0, + ' Запись Спецификация второго уровня «Модели» с RN "s%", не определена.', + NEQUIPDSCMML); + when TOO_MANY_ROWS then + p_exception(0, + ' Найдено более одной записи Спецификация второго уровня «Модели» с RN "s%".', + NEQUIPDSCMML); + end; + + /* Формируем тело запроса */ + UDO_PKG_EQUIPDS_SEND.REQUIREMENTS_MAKE(NEQUIPDSCMML => NEQUIPDSCMML, BXML => BXML ); + + /* отправка запроса */ + UDO_PKG_EQUIPDS_SEND.SEND_PACKGE(NEXSSERVICEFN => NEXSSERVICEFN, + NLNK_NEXSQUEUE => null, + NCOMPANY => NCOMPANY, + NDOCUMENT => NEQUIPDSCMML, + SUNITCODE => null, + bAUTH => true, + NPRIORITY => 0, + BMSG => BXML + ); + + end SEND_RQ; + + +end UDO_PKG_EQUIPDS_DATAPROCESS; +/ diff --git a/db/UDO_PKG_EQUIPDS_EXS.pck b/db/UDO_PKG_EQUIPDS_EXS.pck new file mode 100644 index 0000000..7df0ac9 --- /dev/null +++ b/db/UDO_PKG_EQUIPDS_EXS.pck @@ -0,0 +1,641 @@ +create or replace package UDO_PKG_EQUIPDS_EXS +is +/* + Описание: Реализует методы «Сервиса интеграции с WEB API» для взаимодействия с внешней системой (обработчики ответов и сообщений). + Проект: Интеграция ПП «Парус 8» и «Фреймворка оценки и прогнозирования состояния оборудования» + Разработчик: ЦИТК-ПАРУС + Отественный: Селианов А.Е. + Дата последнего изменения: 15.02.2025 + */ + + /* Константы - параметры "Типовых сообщений обмена" Загрузка данных на файловый сервер SCP для интеграции с фреймворк по прогнозированию ресурса оборудования */ + SEQUIPDS_MSGTYPE_CODE_LSCP constant PKG_STD.TSTRING := 'Загрузка_на_SCP'; -- Мнемокод типовых сообщений обмена + SEQUIPDS_MSGTYPE_NAME_LSCP constant PKG_STD.TSTRING := 'Загрузка данных на файловый сервер SCP'; -- Наименование типовых сообщений обмена + SEQUIPDS_MSGTYPE_PKG_LSCP constant PKG_STD.TSTRING := 'UDO_PKG_EQUIPDS_EXS'; -- Пакет обработки типового сообщения обмена + SEQUIPDS_MSGTYPE_PRC_LSCP constant PKG_STD.TSTRING := 'P_UPLOADFILESCP'; -- Процедура обработки типового сообщения обмена + SEQUIPDS_MSGTYPE_SRVBFR_LSCP constant PKG_STD.TSTRING := 'loadSCP_v2.js/uploadFileSCP'; -- Функция предобработки сервером приложений + /* Константы - параметры "Типовых сообщений обмена" Передача выборки данных Фреймворку для интеграции с фреймворк по прогнозированию ресурса оборудования */ + SEQUIPDS_MSGTYPE_CODE_LFRM constant PKG_STD.TSTRING := 'Передача_данных_Фреймворку'; -- Мнемокод типовых сообщений обмена + SEQUIPDS_MSGTYPE_NAME_LFRM constant PKG_STD.TSTRING := 'Передача выборки данных Фреймворку'; -- Наименование типовых сообщений обмена + SEQUIPDS_MSGTYPE_PKG_LFRM constant PKG_STD.TSTRING := 'UDO_PKG_EQUIPDS_EXS'; -- Пакет обработки типового сообщения обмена + SEQUIPDS_MSGTYPE_PRC_LFRM constant PKG_STD.TSTRING := 'P_METADATA'; -- Процедура обработки типового сообщения обмена + SEQUIPDS_MSGTYPE_SRVBFR_LFRM constant PKG_STD.TSTRING := 'EQUIPDS.js/beforeDocParse'; -- Функция предобработки сервером приложений + SEQUIPDS_MSGTYPE_SRVAFTR_LFRM constant PKG_STD.TSTRING := 'EQUIPDS.js/afterDocParseResp'; -- Функция постобработки сервером приложений + /* Константы - параметры "Типовых сообщений обмена" Передача Фреймворку запроса на обучение модели для интеграции с фреймворк по прогнозированию ресурса оборудования */ + SEQUIPDS_MSGTYPE_CODE_RQLRN constant PKG_STD.TSTRING := 'Запрос на обучение'; -- Мнемокод типовых сообщений обмена + SEQUIPDS_MSGTYPE_NAME_RQLRN constant PKG_STD.TSTRING := 'Передача Фреймворку запроса на обучение модели'; -- Наименование типовых сообщений обмена + SEQUIPDS_MSGTYPE_PKG_RQLRN constant PKG_STD.TSTRING := 'UDO_PKG_EQUIPDS_EXS'; -- Пакет обработки типового сообщения обмена + SEQUIPDS_MSGTYPE_PRC_RQLRN constant PKG_STD.TSTRING := 'P_REQUIREMENTS'; -- Процедура обработки типового сообщения обмена + SEQUIPDS_MSGTYPE_SRVBFR_RQLRN constant PKG_STD.TSTRING := 'EQUIPDS.js/beforeDocParse'; -- Функция предобработки сервером приложений + SEQUIPDS_MSGTYPE_SRVAFTR_RQLRN constant PKG_STD.TSTRING := 'EQUIPDS.js/afterDocParseResp'; -- Функция постобработки сервером приложений + /* Константы - параметры "Типовых сообщений обмена" Получение состояния загрузки данных Фреймворком, после выполнения для интеграции с фреймворк по прогнозированию ресурса оборудования */ + SEQUIPDS_MSGTYPE_CODE_MTCB constant PKG_STD.TSTRING := 'Статус_загрузки_данных_Фреймфорка'; -- Мнемокод типовых сообщений обмена + SEQUIPDS_MSGTYPE_NAME_MTCB constant PKG_STD.TSTRING := 'Получение состояния загрузки данных Фреймворком, после выполнения'; -- Наименование типовых сообщений обмена + SEQUIPDS_MSGTYPE_PKG_MTCB constant PKG_STD.TSTRING := 'UDO_PKG_EQUIPDS_EXS'; -- Пакет обработки типового сообщения обмена + SEQUIPDS_MSGTYPE_PRC_MTCB constant PKG_STD.TSTRING := 'P_METADATA_CB'; -- Процедура обработки типового сообщения обмена + SEQUIPDS_MSGTYPE_SRVBFR_MTCB constant PKG_STD.TSTRING := 'EQUIPDS.js/beforeDocParseMsg'; -- Функция предобработки сервером приложений + /* Константы - параметры "Типовых сообщений обмена" Получение состояния загрузки данных Фреймворком, после выполнения для интеграции с фреймворк по прогнозированию ресурса оборудования */ + SEQUIPDS_MSGTYPE_CODE_REQCB constant PKG_STD.TSTRING := 'Состояние_обучения_модели'; -- Мнемокод типовых сообщений обмена + SEQUIPDS_MSGTYPE_NAME_REQCB constant PKG_STD.TSTRING := 'Получение состояния обучения модели Фреймворком, после выполнения'; -- Наименование типовых сообщений обмена + SEQUIPDS_MSGTYPE_PKG_REQCB constant PKG_STD.TSTRING := 'UDO_PKG_EQUIPDS_EXS'; -- Пакет обработки типового сообщения обмена + SEQUIPDS_MSGTYPE_PRC_REQCB constant PKG_STD.TSTRING := 'P_REQUIREMENTS_CB'; -- Процедура обработки типового сообщения обмена + SEQUIPDS_MSGTYPE_SRVBFR_REQCB constant PKG_STD.TSTRING := 'EQUIPDS.js/beforeDocParseMsg'; -- Функция предобработки сервером приложений + + /* Константы - параметры "Сервисов обмена" Загрузка_на_SCP для интеграции с фреймворк по прогнозированию ресурса оборудования */ + SEQUIPDS_SRVC_CODE_LSCP constant PKG_STD.TSTRING := 'Загрузка_на_SCP'; -- Мнемокод сервиса обмена + SEQUIPDS_SRVC_NAME_LSCP constant PKG_STD.TSTRING := 'Загрузка данных на SCP'; -- Наименование сервиса обмена + NEQUIPDS_SRVC_SRV_TYPE_LSCP constant PKG_STD.TNUMBER := PKG_EXS.NSRV_TYPE_SEND; -- Тип сервера + SEQUIPDS_SRVC_SRV_ROOT_LSCP constant PKG_STD.TSTRING := 'sftp://parus.cadred.ru:62322'; -- Адрес сервера + /* Константы - параметры "Сервисов обмена" Передача данных Фреймворку для интеграции с фреймворк по прогнозированию ресурса оборудования */ + SEQUIPDS_SRVC_CODE_LFRM constant PKG_STD.TSTRING := 'Загрузка_на_Фреймворк'; -- Мнемокод сервиса обмена + SEQUIPDS_SRVC_NAME_LFRM constant PKG_STD.TSTRING := 'Передача данных Фреймворку'; -- Наименование сервиса обмена + NEQUIPDS_SRVC_SRV_TYPE_LFRM constant PKG_STD.TNUMBER := PKG_EXS.NSRV_TYPE_SEND; -- Тип сервера + SEQUIPDS_SRVC_SRV_ROOT_LFRM constant PKG_STD.TSTRING := 'https://parus.cadred.ru/API/train'; -- Адрес сервера + /* Константы - параметры "Сервисов обмена" Получение обратной связи от Фреймворка для интеграции с фреймворк по прогнозированию ресурса оборудования */ + SEQUIPDS_SRVC_CODE_CLLBCK constant PKG_STD.TSTRING := 'Поучение_от_Фреймворка'; -- Мнемокод сервиса обмена + SEQUIPDS_SRVC_NAME_CLLBCK constant PKG_STD.TSTRING := 'Получение обратной связи от Фреймворка'; -- Наименование сервиса обмена + NEQUIPDS_SRVC_SRV_TYPE_CLLBCK constant PKG_STD.TNUMBER := PKG_EXS.NSRV_TYPE_RECIVE; -- Тип сервера + SEQUIPDS_SRVC_SRV_ROOT_CLLBCK constant PKG_STD.TSTRING := '/equipds'; -- Адрес сервера + + /* Константы - параметры "Функции сервиса обмена" Загрузка_на_SCP для интеграции с фреймворк по прогнозированию ресурса оборудования */ + SEQUIPDS_SRVCFN_CODE_LSCP constant PKG_STD.TSTRING := 'Загрузка_на_SCP'; -- Мнемокод функции сервиса обмена + SEQUIPDS_SRVCFN_NAME_LSCP constant PKG_STD.TSTRING := 'Загрузка данных на SCP'; -- Наименование функции сервиса обмена + NEQUIPDS_SRVCFN_FN_TYPE_LSCP constant PKG_STD.TNUMBER := PKG_EXS.NFN_TYPE_DATA; -- Типовая функция + SEQUIPDS_SRVCFN_FN_URL_LSCP constant PKG_STD.TSTRING := 'home/sftp_user/parus'; -- Адрес функции сервиса обмена + NEQUIPDS_SRVCFN_FNPRMS_TP_LSCP constant PKG_STD.TNUMBER := PKG_EXS.NFN_PRMS_TYPE_POST; -- Способ передачи параметров + /* Константы - параметры "Функции сервиса обмена" Передача данных Фреймворку для интеграции с фреймворк по прогнозированию ресурса оборудования */ + SEQUIPDS_SRVCFN_CODE_LFRM constant PKG_STD.TSTRING := 'Загрузить_на_Фреймворк'; -- Мнемокод функции сервиса обмена + SEQUIPDS_SRVCFN_NAME_LFRM constant PKG_STD.TSTRING := 'Передача выборки данных Фреймворку'; -- Наименование функции сервиса обмена + NEQUIPDS_SRVCFN_FN_TYPE_LFRM constant PKG_STD.TNUMBER := PKG_EXS.NFN_TYPE_DATA; -- Типовая функция + SEQUIPDS_SRVCFN_FN_URL_LFRM constant PKG_STD.TSTRING := 'metadata'; -- Адрес функции сервиса обмена + NEQUIPDS_SRVCFN_FNPRMS_TP_LFRM constant PKG_STD.TNUMBER := PKG_EXS.NFN_PRMS_TYPE_POST; -- Способ передачи параметров + /* Константы - параметры "Функции сервиса обмена" Передача Фреймворку запроса на обучение модели для интеграции с фреймворк по прогнозированию ресурса оборудования */ + SEQUIPDS_SRVCFN_CODE_RQLRN constant PKG_STD.TSTRING := 'Запрос на обучение'; -- Мнемокод функции сервиса обмена + SEQUIPDS_SRVCFN_NAME_RQLRN constant PKG_STD.TSTRING := 'Передача Фреймворку запроса на обучение модели'; -- Наименование функции сервиса обмена + NEQUIPDS_SRVCFN_FN_TYPE_RQLRN constant PKG_STD.TNUMBER := PKG_EXS.NFN_TYPE_DATA; -- Типовая функция + SEQUIPDS_SRVCFN_FN_URL_RQLRN constant PKG_STD.TSTRING := 'requirements'; -- Адрес функции сервиса обмена + NEQUIPDS_SRVCFN_FNPR_TP_RQLRN constant PKG_STD.TNUMBER := PKG_EXS.NFN_PRMS_TYPE_POST; -- Способ передачи параметров + /* Константы - параметры "Функции сервиса обмена" Получение состояния загрузки данных Фреймворком, после выполнения для интеграции с фреймворк по прогнозированию ресурса оборудования */ + SEQUIPDS_SRVCFN_CODE_MTCB constant PKG_STD.TSTRING := 'Статус_загрузки_данных_Фреймфорка'; -- Мнемокод функции сервиса обмена + SEQUIPDS_SRVCFN_NAME_MTCB constant PKG_STD.TSTRING := 'Получение состояния загрузки данных Фреймворком, после выполнения'; -- Наименование функции сервиса обмена + NEQUIPDS_SRVCFN_FN_TYPE_MTCB constant PKG_STD.TNUMBER := PKG_EXS.NFN_TYPE_DATA; -- Типовая функция + SEQUIPDS_SRVCFN_FN_URL_MTCB constant PKG_STD.TSTRING := 'API/train/metadata/metadata_cb'; -- Адрес функции сервиса обмена + NEQUIPDS_SRVCFN_FNPRMS_TP_MTCB constant PKG_STD.TNUMBER := PKG_EXS.NFN_PRMS_TYPE_POST; -- Способ передачи параметров + /* Константы - параметры "Функции сервиса обмена" Получение состояния загрузки данных Фреймворком, после выполнения для интеграции с фреймворк по прогнозированию ресурса оборудования */ + SEQUIPDS_SRVCFN_CODE_REQCB constant PKG_STD.TSTRING := 'Статус_обучения_модели'; -- Мнемокод функции сервиса обмена + SEQUIPDS_SRVCFN_NAME_REQCB constant PKG_STD.TSTRING := 'Получение состояния обучения модели Фреймворком, после выполнения'; -- Наименование функции сервиса обмена + NEQUIPDS_SRVCFN_FN_TYPE_REQCB constant PKG_STD.TNUMBER := PKG_EXS.NFN_TYPE_DATA; -- Типовая функция + SEQUIPDS_SRVCFN_FN_URL_REQCB constant PKG_STD.TSTRING := 'API/train/requirements/requirements_cb'; -- Адрес функции сервиса обмена + NEQUIPDS_SRVCFN_FNPR_TP_REQCB constant PKG_STD.TNUMBER := PKG_EXS.NFN_PRMS_TYPE_POST; -- Способ передачи параметров + + + /* Обработка загрузки файлов на SCP сервер */ + procedure P_UPLOADFILESCP + ( + NIDENT in number, -- Идентификатор процесса + NEXSQUEUE in number -- Регистрационный номер обрабатываемой позиции очереди обмена + ); + + /* Обработка передачи выборки данных Фреймворку */ + procedure P_METADATA + ( + NIDENT in number, -- Идентификатор процесса + NEXSQUEUE in number -- Регистрационный номер обрабатываемой позиции очереди обмена + ); + + /* Обработка передачи Фреймворку запроса на обучение модели */ + procedure P_REQUIREMENTS + ( + NIDENT in number, -- Идентификатор процесса + NEXSQUEUE in number -- Регистрационный номер обрабатываемой позиции очереди обмена + ); + + /* Обработка получения состояния загрузки данных Фреймворком*/ + procedure P_METADATA_CB + ( + NIDENT in number, -- Идентификатор процесса + NEXSQUEUE in number -- Регистрационный номер обрабатываемой позиции очереди обмена + ); + + /* Обработка получение состояния обучения модели Фреймворком */ + procedure P_REQUIREMENTS_CB + ( + NIDENT in number, -- Идентификатор процесса + NEXSQUEUE in number -- Регистрационный номер обрабатываемой позиции очереди обмена + ); + + /* Инициализация настроек расширения для интеграции с фреймворк по прогнозированию ресурса оборудования */ + procedure INIT_EQUIPDS + ( + NCRN in number, -- Рег. номер каталога сервиса обмена + NFORCE_UPDATE in number -- Обновлять существующие записи (см. константы PKG_EXS.NFORCE_UPDATE_*) + ); + + +end UDO_PKG_EQUIPDS_EXS; +/ +create or replace package body UDO_PKG_EQUIPDS_EXS +is + + /* Обработка загрузки файлов на SCP сервер */ + procedure P_UPLOADFILESCP + ( + NIDENT in number, -- Идентификатор процесса + NEXSQUEUE in number -- Регистрационный номер обрабатываемой позиции очереди обмена + ) + is + REXSQUEUE EXSQUEUE%ROWTYPE; -- заить очереди обмена + SSTATE PKG_STD.tSTRING; -- Код состояния отработки 200- успех; 500 - ошибка + SMESSAGE PKG_STD.tSTRING; -- Текст ошибки + SFILENAME PKG_STD.tSTRING; -- Имя ффайла с путём размещения на файлсерере SCP + begin + /* Поиск записи очереди обмена */ + REXSQUEUE := GET_EXSQUEUE_ID(NFLAG_SMART => 0, NRN => NEXSQUEUE); + + /* Читаем статус запроса */ + SSTATE := PKG_EXS.OPTIONS_READ(sOPTIONS => BLOB2CLOB(lbDATA => REXSQUEUE.MSG, + sCHARSET => PKG_CHARSET.CHARSET_UTF_), + SPATH => 'state'); + SMESSAGE := PKG_EXS.OPTIONS_READ(sOPTIONS => BLOB2CLOB(lbDATA => REXSQUEUE.MSG, + sCHARSET => PKG_CHARSET.CHARSET_UTF_), + SPATH => 'message'); + case SSTATE + when '200' then + SFILENAME := PKG_EXS.OPTIONS_READ(sOPTIONS => REXSQUEUE.OPTIONS, + SPATH => 'SPATCH_FSERV'); + /* Базовая установка имени файла "Выборки данных оборудования (классы оборудования, файлы данных)" */ + UDO_PKG_EQUIPDS_BASE.CMFL_SET_FILE_NAME(NRN => REXSQUEUE.LNK_DOCUMENT, + SFILE_NAME => SFILENAME); + /* Базовая установка состояния "Выборки данных оборудования (классы оборудования, файлы данных)" */ + UDO_PKG_EQUIPDS_BASE.CMFL_SET_STATUS(NRN => REXSQUEUE.LNK_DOCUMENT, + NSTATUS => UDO_PKG_EQUIPDS_BASE.NCMFL_STATUS_UPLOADED, + SQUEUE_ID => null, + SERR => null); + else + /* Базовая установка состояния "Выборки данных оборудования (классы оборудования, файлы данных)" */ + UDO_PKG_EQUIPDS_BASE.CMFL_SET_STATUS(NRN => REXSQUEUE.LNK_DOCUMENT, + NSTATUS => UDO_PKG_EQUIPDS_BASE.NCMFL_STATUS_UPLOAD_ERR, + SQUEUE_ID => null, + SERR => SMESSAGE); + end case; + /* Возвращаем ответ */ + PKG_EXS.PRC_RESP_RESULT_SET(NIDENT => NIDENT, + + SRESULT => PKG_EXS.SPRC_RESP_RESULT_OK); + + exception + when others then + /* Вернём ошибку - это фатальная */ + PKG_STATE.DIAGNOSTICS_STACKED(); + PKG_EXS.PRC_RESP_RESULT_SET(NIDENT => NIDENT, + SRESULT => PKG_EXS.SPRC_RESP_RESULT_ERR, + SMSG => PKG_STATE.SQL_ERRM()); + + end P_UPLOADFILESCP; + + /* Обработка передачи выборки данных Фреймворку */ + procedure P_METADATA + ( + NIDENT in number, -- Идентификатор процесса + NEXSQUEUE in number -- Регистрационный номер обрабатываемой позиции очереди обмена + ) + is + REXSQUEUE EXSQUEUE%ROWTYPE; -- заить очереди обмена + SSTATE PKG_STD.tSTRING; -- Код состояния отработки 200- успех; 500 - ошибка + SMESSAGE PKG_STD.tSTRING; -- Текст ошибки + NSTATUS PKG_STD.tNUMBER; -- состояния "Выборки данных оборудования (классы оборудования, файлы данных)" + SQUEUE_ID PKG_STD.tSTRING; -- + SERR PKG_STD.tSTRING; -- Текст ошибки + + begin + /* Поиск записи очереди обмена */ + REXSQUEUE := GET_EXSQUEUE_ID(NFLAG_SMART => 0, NRN => NEXSQUEUE); + + /* Читаем статус запроса */ + SSTATE := PKG_EXS.OPTIONS_READ(sOPTIONS => REXSQUEUE.OPTIONS_RESP, + SPATH => 'statusCode'); + SMESSAGE := PKG_EXS.OPTIONS_READ(sOPTIONS => BLOB2CLOB(REXSQUEUE.RESP, PKG_CHARSET.CHARSET_UTF_), + SPATH => 'message'); + SQUEUE_ID := PKG_EXS.OPTIONS_READ(sOPTIONS => BLOB2CLOB(REXSQUEUE.RESP, PKG_CHARSET.CHARSET_UTF_), + SPATH => 'queue_id'); + + case SSTATE + when '200' then + NSTATUS := UDO_PKG_EQUIPDS_BASE.NCMFL_STATUS_SENDING; + SERR := null; + else + NSTATUS := UDO_PKG_EQUIPDS_BASE.NCMFL_STATUS_SEND_ERR; + SERR := SMESSAGE; + end case; + for RCMLF in (select T.RN from UDO_T_EQUIPDSCMFL T where t.dataset_id = REXSQUEUE.LNK_DOCUMENT)loop + /* Базовая установка состояния "Выборки данных оборудования (классы оборудования, файлы данных)" */ + UDO_PKG_EQUIPDS_BASE.CMFL_SET_STATUS(NRN => RCMLF.RN, + NSTATUS => NSTATUS, + SQUEUE_ID => SQUEUE_ID, + SERR => SERR); + end loop; + + /* Возвращаем ответ */ + PKG_EXS.PRC_RESP_RESULT_SET(NIDENT => NIDENT, + + SRESULT => PKG_EXS.SPRC_RESP_RESULT_OK); + + exception + when others then + /* Вернём ошибку - это фатальная */ + PKG_STATE.DIAGNOSTICS_STACKED(); + PKG_EXS.PRC_RESP_RESULT_SET(NIDENT => NIDENT, + SRESULT => PKG_EXS.SPRC_RESP_RESULT_ERR, + SMSG => PKG_STATE.SQL_ERRM()); + + end P_METADATA; + + /* Обработка передачи Фреймворку запроса на обучение модели */ + procedure P_REQUIREMENTS + ( + NIDENT in number, -- Идентификатор процесса + NEXSQUEUE in number -- Регистрационный номер обрабатываемой позиции очереди обмена + ) + is + REXSQUEUE EXSQUEUE%ROWTYPE; -- заить очереди обмена + SSTATE PKG_STD.tSTRING; -- Код состояния отработки 200- успех; 500 - ошибка + SMESSAGE PKG_STD.tSTRING; -- Текст ошибки + NSTATUS PKG_STD.tNUMBER; -- состояния "Выборки данных оборудования (классы оборудования, файлы данных)" + SERR PKG_STD.tSTRING; -- Текст ошибки + SSTATESP PKG_STD.tSTRING; -- Статус обработки запроса + SQUEUE_ID PKG_STD.tSTRING; -- Идентификатор полуеный от стороннего сервера + begin + /* Поиск записи очереди обмена */ + REXSQUEUE := GET_EXSQUEUE_ID(NFLAG_SMART => 0, NRN => NEXSQUEUE); + + /* Читаем статус запроса */ + SSTATE := PKG_EXS.OPTIONS_READ(sOPTIONS => REXSQUEUE.OPTIONS_RESP, + SPATH => 'statusCode'); + SMESSAGE := PKG_EXS.OPTIONS_READ(sOPTIONS => BLOB2CLOB(REXSQUEUE.RESP, PKG_CHARSET.CHARSET_UTF_), + SPATH => 'message'); + SQUEUE_ID := PKG_EXS.OPTIONS_READ(sOPTIONS => BLOB2CLOB(REXSQUEUE.RESP, PKG_CHARSET.CHARSET_UTF_), + SPATH => 'queue_id'); + SSTATESP := PKG_EXS.OPTIONS_READ(sOPTIONS => BLOB2CLOB(lbDATA => REXSQUEUE.RESP, + sCHARSET => PKG_CHARSET.CHARSET_UTF_), + SPATH => 'status'); + /* Обработка статуса отпраки и контроль резульатат */ + case SSTATE + when '200' then + case UPPER(SSTATESP) + when 'OK' then + NSTATUS := UDO_PKG_EQUIPDS_BASE.NCMML_STATUS_PROCESSING; + SERR := null; + else + NSTATUS := UDO_PKG_EQUIPDS_BASE.NCMML_STATUS_PROCESS_ERR; + SERR := SMESSAGE; + end case; + else + NSTATUS := UDO_PKG_EQUIPDS_BASE.NCMML_STATUS_PROCESS_ERR; + SERR := 'Ошибка при передаче запроса, код: '||SSTATE; + end case; + for RCMLF in (select T.RN from UDO_T_EQUIPDSCMML T where T.RN = REXSQUEUE.LNK_DOCUMENT)loop + /* Базовая установка состояния "Выборки данных оборудования (классы оборудования, модели)" */ + UDO_PKG_EQUIPDS_BASE.CMML_SET_STATUS(NRN => RCMLF.RN, + NSTATUS => NSTATUS, + SQUEUE_ID => SQUEUE_ID, + SERR => SERR); + end loop; + + /* Возвращаем ответ */ + PKG_EXS.PRC_RESP_RESULT_SET(NIDENT => NIDENT, + + SRESULT => PKG_EXS.SPRC_RESP_RESULT_OK); + + exception + when others then + /* Вернём ошибку - это фатальная */ + PKG_STATE.DIAGNOSTICS_STACKED(); + PKG_EXS.PRC_RESP_RESULT_SET(NIDENT => NIDENT, + SRESULT => PKG_EXS.SPRC_RESP_RESULT_ERR, + SMSG => PKG_STATE.SQL_ERRM()); + + end P_REQUIREMENTS; + + /* Обработка получения состояния загрузки данных Фреймворком*/ + procedure P_METADATA_CB + ( + NIDENT in number, -- Идентификатор процесса + NEXSQUEUE in number -- Регистрационный номер обрабатываемой позиции очереди обмена + ) + is + REXSQUEUE EXSQUEUE%ROWTYPE; -- заить очереди обмена + SSTATE PKG_STD.tSTRING; -- Код состояния отработки 200- успех; 500 - ошибка + SMESSAGE PKG_STD.tSTRING; -- Текст ошибки + NSTATUS PKG_STD.tNUMBER; -- состояния "Выборки данных оборудования (классы оборудования, файлы данных)" + SERR PKG_STD.tSTRING; -- Текст ошибки + SQUEUE_ID PKG_STD.tSTRING; -- Идентификатор очереди обработки + begin + /* Поиск записи очереди обмена */ + REXSQUEUE := GET_EXSQUEUE_ID(NFLAG_SMART => 0, NRN => NEXSQUEUE); + + /* Читаем статус запроса */ + SSTATE := PKG_EXS.OPTIONS_READ(sOPTIONS => BLOB2CLOB(lbDATA => REXSQUEUE.MSG, + sCHARSET => PKG_CHARSET.CHARSET_UTF_), + SPATH => 'status'); + /* Читаем сообщение запроса */ + SMESSAGE := PKG_EXS.OPTIONS_READ(sOPTIONS => BLOB2CLOB(lbDATA => REXSQUEUE.MSG, + sCHARSET => PKG_CHARSET.CHARSET_UTF_), + SPATH => 'message'); + /* Читаем идентификатор запроса */ + SQUEUE_ID := PKG_EXS.OPTIONS_READ(sOPTIONS => BLOB2CLOB(lbDATA => REXSQUEUE.MSG, + sCHARSET => PKG_CHARSET.CHARSET_UTF_), + SPATH => 'queue_id'); + + case UPPER(SSTATE) + when 'OK' then + NSTATUS := UDO_PKG_EQUIPDS_BASE.NCMFL_STATUS_SENT; + SERR := null; + else + NSTATUS := UDO_PKG_EQUIPDS_BASE.NCMFL_STATUS_SEND_ERR; + SERR := SMESSAGE; + end case; + for RCMLF in (select T.RN from UDO_T_EQUIPDSCMFL T where t.queue_id = SQUEUE_ID)loop + /* Базовая установка состояния "Выборки данных оборудования (классы оборудования, файлы данных)" */ + UDO_PKG_EQUIPDS_BASE.CMFL_SET_STATUS(NRN => RCMLF.RN, + NSTATUS => NSTATUS, + SQUEUE_ID => SQUEUE_ID, -- ПЕРЕДЕЛАТЬ !!!! Стичать значение из отета сервера!!!!! + SERR => SERR); + end loop; + + /* Возвращаем ответ */ + PKG_EXS.PRC_RESP_RESULT_SET(NIDENT => NIDENT, + + SRESULT => PKG_EXS.SPRC_RESP_RESULT_OK); + + exception + when others then + /* Вернём ошибку - это фатальная */ + PKG_STATE.DIAGNOSTICS_STACKED(); + PKG_EXS.PRC_RESP_RESULT_SET(NIDENT => NIDENT, + SRESULT => PKG_EXS.SPRC_RESP_RESULT_ERR, + SMSG => PKG_STATE.SQL_ERRM()); + + end P_METADATA_CB; + + + /* Обработка получение состояния обучения модели Фреймворком */ + procedure P_REQUIREMENTS_CB + ( + NIDENT in number, -- Идентификатор процесса + NEXSQUEUE in number -- Регистрационный номер обрабатываемой позиции очереди обмена + ) + is + REXSQUEUE EXSQUEUE%ROWTYPE; -- заить очереди обмена + SSTATE PKG_STD.tSTRING; -- Код состояния отработки 200- успех; 500 - ошибка + SMESSAGE PKG_STD.tSTRING; -- Текст ошибки + NSTATUS PKG_STD.tNUMBER; -- состояния "Выборки данных оборудования (классы оборудования, файлы данных)" + SERR PKG_STD.tSTRING; -- Текст ошибки + SQUEUE_ID PKG_STD.tSTRING; -- Идентификатор очереди обработки + NPRECISION_F PKG_STD.tNUMBER; -- Точность Модели (факт) + begin + /* Поиск записи очереди обмена */ + REXSQUEUE := GET_EXSQUEUE_ID(NFLAG_SMART => 0, NRN => NEXSQUEUE); + + /* Читаем статус запроса */ + SSTATE := PKG_EXS.OPTIONS_READ(sOPTIONS => BLOB2CLOB(lbDATA => REXSQUEUE.MSG, + sCHARSET => PKG_CHARSET.CHARSET_UTF_), + SPATH => 'status'); + SMESSAGE := PKG_EXS.OPTIONS_READ(sOPTIONS => BLOB2CLOB(lbDATA => REXSQUEUE.MSG, + sCHARSET => PKG_CHARSET.CHARSET_UTF_), + SPATH => 'message'); + + SQUEUE_ID := PKG_EXS.OPTIONS_READ(sOPTIONS => BLOB2CLOB(lbDATA => REXSQUEUE.MSG, + sCHARSET => PKG_CHARSET.CHARSET_UTF_), + SPATH => 'queue_id'); + NPRECISION_F := PKG_EXS.OPTIONS_READ(sOPTIONS => BLOB2CLOB(lbDATA => REXSQUEUE.MSG, + sCHARSET => PKG_CHARSET.CHARSET_UTF_), + SPATH => 'precision'); + case UPPER(SSTATE) + when 'OK' then + NSTATUS := UDO_PKG_EQUIPDS_BASE.NCMML_STATUS_PROCESSED; + SERR := null; + else + NSTATUS := UDO_PKG_EQUIPDS_BASE.NCMML_STATUS_PROCESS_ERR; + SERR := SMESSAGE; + end case; + for RCMML in (select T.RN from UDO_T_EQUIPDSCMML T where t.queue_id = SQUEUE_ID)loop + /* Базовая установка состояния "Выборки данных оборудования (классы оборудования, файлы данных)" */ + UDO_PKG_EQUIPDS_BASE.CMML_SET_STATUS(NRN => RCMML.RN, + NSTATUS => NSTATUS, + SQUEUE_ID => SQUEUE_ID, + SERR => SERR); + if SERR is null then + /* Базовая установка фактической точности "Выборки данных оборудования (классы оборудования, модели)" */ + UDO_PKG_EQUIPDS_BASE.CMML_SET_PRECISION_F(NRN => RCMML.RN, NPRECISION_F => ROUND(NPRECISION_F,0)); + end if; + end loop; + + /* Возвращаем ответ */ + PKG_EXS.PRC_RESP_RESULT_SET(NIDENT => NIDENT, + SRESULT => PKG_EXS.SPRC_RESP_RESULT_OK); + + exception + when others then + /* Вернём ошибку - это фатальная */ + PKG_STATE.DIAGNOSTICS_STACKED(); + PKG_EXS.PRC_RESP_RESULT_SET(NIDENT => NIDENT, + SRESULT => PKG_EXS.SPRC_RESP_RESULT_ERR, + SMSG => PKG_STATE.SQL_ERRM()); + + end P_REQUIREMENTS_CB; + + /* Инициализация настроек расширения для интеграции с фреймворк по прогнозированию ресурса оборудования */ + procedure INIT_EQUIPDS + ( + NCRN in number, -- Рег. номер каталога сервиса обмена + NFORCE_UPDATE in number -- Обновлять существующие записи (см. константы PKG_EXS.NFORCE_UPDATE_*) + ) + is + NEXSMSGTYPE PKG_STD.TREF; -- Рег. номер записи типовых сообщений обмена + NEXSSERVICE PKG_STD.TREF; -- Рег. номер записи сервиса обмена + NEXSSERVICEFN PKG_STD.TREF; -- Рег. номер записи функции сервиса обмена + begin + /* Загрузка типового сообщения обмена */ + P_EXSMSGTYPE_BASE_LOAD(SCATALOG => null, + SCODE => SEQUIPDS_MSGTYPE_CODE_LSCP, + SNAME => SEQUIPDS_MSGTYPE_NAME_LSCP, + SPKG_RESP => SEQUIPDS_MSGTYPE_PKG_LSCP, + SPRC_RESP => SEQUIPDS_MSGTYPE_PRC_LSCP, + SAPPSRV_BEFORE => SEQUIPDS_MSGTYPE_SRVBFR_LSCP, + SAPPSRV_AFTER => null, + NMAX_IDLE => 0, + NFORCE_UPDATE => NFORCE_UPDATE, + NRN => NEXSMSGTYPE); + P_EXSMSGTYPE_BASE_LOAD(SCATALOG => null, + SCODE => SEQUIPDS_MSGTYPE_CODE_LFRM, + SNAME => SEQUIPDS_MSGTYPE_NAME_LFRM, + SPKG_RESP => SEQUIPDS_MSGTYPE_PKG_LFRM, + SPRC_RESP => SEQUIPDS_MSGTYPE_PRC_LFRM, + SAPPSRV_BEFORE => SEQUIPDS_MSGTYPE_SRVBFR_LFRM, + SAPPSRV_AFTER => SEQUIPDS_MSGTYPE_SRVAFTR_LFRM, + NMAX_IDLE => 0, + NFORCE_UPDATE => NFORCE_UPDATE, + NRN => NEXSMSGTYPE); + P_EXSMSGTYPE_BASE_LOAD(SCATALOG => null, + SCODE => SEQUIPDS_MSGTYPE_CODE_RQLRN, + SNAME => SEQUIPDS_MSGTYPE_NAME_RQLRN, + SPKG_RESP => SEQUIPDS_MSGTYPE_PKG_RQLRN, + SPRC_RESP => SEQUIPDS_MSGTYPE_PRC_RQLRN, + SAPPSRV_BEFORE => SEQUIPDS_MSGTYPE_SRVBFR_RQLRN, + SAPPSRV_AFTER => SEQUIPDS_MSGTYPE_SRVAFTR_RQLRN, + NMAX_IDLE => 0, + NFORCE_UPDATE => NFORCE_UPDATE, + NRN => NEXSMSGTYPE); + P_EXSMSGTYPE_BASE_LOAD(SCATALOG => null, + SCODE => SEQUIPDS_MSGTYPE_CODE_MTCB, + SNAME => SEQUIPDS_MSGTYPE_NAME_MTCB, + SPKG_RESP => SEQUIPDS_MSGTYPE_PKG_MTCB, + SPRC_RESP => SEQUIPDS_MSGTYPE_PRC_MTCB, + SAPPSRV_BEFORE => SEQUIPDS_MSGTYPE_SRVBFR_MTCB, + SAPPSRV_AFTER => null, + NMAX_IDLE => 0, + NFORCE_UPDATE => NFORCE_UPDATE, + NRN => NEXSMSGTYPE); + P_EXSMSGTYPE_BASE_LOAD(SCATALOG => null, + SCODE => SEQUIPDS_MSGTYPE_CODE_REQCB, + SNAME => SEQUIPDS_MSGTYPE_NAME_REQCB, + SPKG_RESP => SEQUIPDS_MSGTYPE_PKG_REQCB, + SPRC_RESP => SEQUIPDS_MSGTYPE_PRC_REQCB, + SAPPSRV_BEFORE => SEQUIPDS_MSGTYPE_SRVBFR_REQCB, + SAPPSRV_AFTER => null, + NMAX_IDLE => 0, + NFORCE_UPDATE => NFORCE_UPDATE, + NRN => NEXSMSGTYPE); + + /* Загрузка сервиса обмена */ + P_EXSSERVICE_BASE_LOAD(SCATALOG => GET_ACATALOG_NAME_ID(NFLAG_SMART => 0, NRN => NCRN), + SCODE => SEQUIPDS_SRVC_CODE_LSCP, + SNAME => SEQUIPDS_SRVC_NAME_LSCP, + NSRV_TYPE => NEQUIPDS_SRVC_SRV_TYPE_LSCP, + SSRV_ROOT => SEQUIPDS_SRVC_SRV_ROOT_LSCP, + SSRV_USER => null, + SSRV_PASS => null, + NUNAVLBL_NTF_SIGN => PKG_EXS.NUNAVLBL_NTF_SIGN_NO, + NUNAVLBL_NTF_TIME => 0, + SUNAVLBL_NTF_MAIL => null, + NFORCE_UPDATE => NFORCE_UPDATE, + NRN => NEXSSERVICE); + /* Загрузка функции сервиса обмена */ + P_EXSSERVICEFN_BASE_LOAD(NPRN => NEXSSERVICE, + SCODE => SEQUIPDS_SRVCFN_CODE_LSCP, + SNAME => SEQUIPDS_SRVCFN_NAME_LSCP, + NFN_TYPE => NEQUIPDS_SRVCFN_FN_TYPE_LSCP, + SFN_URL => SEQUIPDS_SRVCFN_FN_URL_LSCP, + NFN_PRMS_TYPE => NEQUIPDS_SRVCFN_FNPRMS_TP_LSCP, + NRETRY_SCHEDULE => PKG_EXS.NRETRY_SCHEDULE_UNDEF, + NRETRY_STEP => 0, + NRETRY_ATTEMPTS => 0, + SEXSMSGTYPE => SEQUIPDS_MSGTYPE_CODE_LSCP, + NERR_NTF_SIGN => PKG_EXS.NERR_NTF_SIGN_NO, + SERR_NTF_MAIL => null, + NAUTH_ONLY => PKG_EXS.NAUTH_ONLY_NO, + NSAVE_QUEUE => PKG_EXS.NFN_SAVE_QUEUE, + NFORCE_UPDATE => NFORCE_UPDATE, + NRN => NEXSSERVICEFN); + + /* Загрузка сервиса обмена */ + P_EXSSERVICE_BASE_LOAD(SCATALOG => GET_ACATALOG_NAME_ID(NFLAG_SMART => 0, NRN => NCRN), + SCODE => SEQUIPDS_SRVC_CODE_LFRM, + SNAME => SEQUIPDS_SRVC_NAME_LFRM, + NSRV_TYPE => NEQUIPDS_SRVC_SRV_TYPE_LFRM, + SSRV_ROOT => SEQUIPDS_SRVC_SRV_ROOT_LFRM, + SSRV_USER => null, + SSRV_PASS => null, + NUNAVLBL_NTF_SIGN => PKG_EXS.NUNAVLBL_NTF_SIGN_NO, + NUNAVLBL_NTF_TIME => 0, + SUNAVLBL_NTF_MAIL => null, + NFORCE_UPDATE => NFORCE_UPDATE, + NRN => NEXSSERVICE); + /* Загрузка функции сервиса обмена */ + P_EXSSERVICEFN_BASE_LOAD(NPRN => NEXSSERVICE, + SCODE => SEQUIPDS_SRVCFN_CODE_LFRM, + SNAME => SEQUIPDS_SRVCFN_NAME_LFRM, + NFN_TYPE => NEQUIPDS_SRVCFN_FN_TYPE_LFRM, + SFN_URL => SEQUIPDS_SRVCFN_FN_URL_LFRM, + NFN_PRMS_TYPE => NEQUIPDS_SRVCFN_FNPRMS_TP_LFRM, + NRETRY_SCHEDULE => PKG_EXS.NRETRY_SCHEDULE_UNDEF, + NRETRY_STEP => 0, + NRETRY_ATTEMPTS => 0, + SEXSMSGTYPE => SEQUIPDS_MSGTYPE_CODE_LFRM, + NERR_NTF_SIGN => PKG_EXS.NERR_NTF_SIGN_NO, + SERR_NTF_MAIL => null, + NAUTH_ONLY => PKG_EXS.NAUTH_ONLY_NO, + NSAVE_QUEUE => PKG_EXS.NFN_SAVE_QUEUE, + NFORCE_UPDATE => NFORCE_UPDATE, + NRN => NEXSSERVICEFN); + /* Загрузка функции сервиса обмена */ + P_EXSSERVICEFN_BASE_LOAD(NPRN => NEXSSERVICE, + SCODE => SEQUIPDS_SRVCFN_CODE_RQLRN, + SNAME => SEQUIPDS_SRVCFN_NAME_RQLRN, + NFN_TYPE => NEQUIPDS_SRVCFN_FN_TYPE_RQLRN, + SFN_URL => SEQUIPDS_SRVCFN_FN_URL_RQLRN, + NFN_PRMS_TYPE => NEQUIPDS_SRVCFN_FNPR_TP_RQLRN, + NRETRY_SCHEDULE => PKG_EXS.NRETRY_SCHEDULE_UNDEF, + NRETRY_STEP => 0, + NRETRY_ATTEMPTS => 0, + SEXSMSGTYPE => SEQUIPDS_MSGTYPE_CODE_RQLRN, + NERR_NTF_SIGN => PKG_EXS.NERR_NTF_SIGN_NO, + SERR_NTF_MAIL => null, + NAUTH_ONLY => PKG_EXS.NAUTH_ONLY_NO, + NSAVE_QUEUE => PKG_EXS.NFN_SAVE_QUEUE, + NFORCE_UPDATE => NFORCE_UPDATE, + NRN => NEXSSERVICEFN); + + /* Загрузка сервиса обмена */ + P_EXSSERVICE_BASE_LOAD(SCATALOG => GET_ACATALOG_NAME_ID(NFLAG_SMART => 0, NRN => NCRN), + SCODE => SEQUIPDS_SRVC_CODE_CLLBCK, + SNAME => SEQUIPDS_SRVC_NAME_CLLBCK, + NSRV_TYPE => NEQUIPDS_SRVC_SRV_TYPE_CLLBCK, + SSRV_ROOT => SEQUIPDS_SRVC_SRV_ROOT_CLLBCK, + SSRV_USER => null, + SSRV_PASS => null, + NUNAVLBL_NTF_SIGN => PKG_EXS.NUNAVLBL_NTF_SIGN_NO, + NUNAVLBL_NTF_TIME => 0, + SUNAVLBL_NTF_MAIL => null, + NFORCE_UPDATE => NFORCE_UPDATE, + NRN => NEXSSERVICE); + /* Загрузка функции сервиса обмена */ + P_EXSSERVICEFN_BASE_LOAD(NPRN => NEXSSERVICE, + SCODE => SEQUIPDS_SRVCFN_CODE_MTCB, + SNAME => SEQUIPDS_SRVCFN_NAME_MTCB, + NFN_TYPE => NEQUIPDS_SRVCFN_FN_TYPE_MTCB, + SFN_URL => SEQUIPDS_SRVCFN_FN_URL_MTCB, + NFN_PRMS_TYPE => NEQUIPDS_SRVCFN_FNPRMS_TP_MTCB, + NRETRY_SCHEDULE => PKG_EXS.NRETRY_SCHEDULE_UNDEF, + NRETRY_STEP => 0, + NRETRY_ATTEMPTS => 0, + SEXSMSGTYPE => SEQUIPDS_MSGTYPE_CODE_MTCB, + NERR_NTF_SIGN => PKG_EXS.NERR_NTF_SIGN_NO, + SERR_NTF_MAIL => null, + NAUTH_ONLY => PKG_EXS.NAUTH_ONLY_NO, + NSAVE_QUEUE => PKG_EXS.NFN_SAVE_QUEUE, + NFORCE_UPDATE => NFORCE_UPDATE, + NRN => NEXSSERVICEFN); + /* Загрузка функции сервиса обмена */ + P_EXSSERVICEFN_BASE_LOAD(NPRN => NEXSSERVICE, + SCODE => SEQUIPDS_SRVCFN_CODE_REQCB, + SNAME => SEQUIPDS_SRVCFN_NAME_REQCB, + NFN_TYPE => NEQUIPDS_SRVCFN_FN_TYPE_REQCB, + SFN_URL => SEQUIPDS_SRVCFN_FN_URL_REQCB, + NFN_PRMS_TYPE => NEQUIPDS_SRVCFN_FNPR_TP_REQCB, + NRETRY_SCHEDULE => PKG_EXS.NRETRY_SCHEDULE_UNDEF, + NRETRY_STEP => 0, + NRETRY_ATTEMPTS => 0, + SEXSMSGTYPE => SEQUIPDS_MSGTYPE_CODE_REQCB, + NERR_NTF_SIGN => PKG_EXS.NERR_NTF_SIGN_NO, + SERR_NTF_MAIL => null, + NAUTH_ONLY => PKG_EXS.NAUTH_ONLY_NO, + NSAVE_QUEUE => PKG_EXS.NFN_SAVE_QUEUE, + NFORCE_UPDATE => NFORCE_UPDATE, + NRN => NEXSSERVICEFN); + + end INIT_EQUIPDS; + + +end UDO_PKG_EQUIPDS_EXS; +/ diff --git a/db/UDO_PKG_EQUIPDS_SEND.pck b/db/UDO_PKG_EQUIPDS_SEND.pck new file mode 100644 index 0000000..ac0f632 --- /dev/null +++ b/db/UDO_PKG_EQUIPDS_SEND.pck @@ -0,0 +1,434 @@ +create or replace package UDO_PKG_EQUIPDS_SEND +is +/* + Описание: Обеспечивает формироание и отправку тела запроса. + Проект: Интеграция ПП «Парус 8» и «Фреймворка оценки и прогнозирования состояния оборудования» + Разработчик: ЦИТК-ПАРУС + Отественный: Селианов А.Е. + Дата последнего изменения: 24.03.2025 +*/ + /* Константы */ + SDEF_SEND_POINT_PRM constant PKG_STD.tSTRING := 'EXSService_AppServer'; -- Адрес сервера приложений (сервисы обмена) + + /* отправка запроса */ + procedure SEND_PACKGE + ( + NEXSSERVICEFN in number, -- Рег. номер функции обработки + NLNK_NEXSQUEUE in number default null, -- Рег.номер сязанной очереди + NCOMPANY in number := null, -- Рег. номер связанной организации + NDOCUMENT in number := null, -- Рег. номер связанной записи документа + SUNITCODE in varchar2 := null, -- Код связанного раздела + SHOST in varchar2 := null, -- host + SPORT in varchar2 := null, -- port + SUSER in varchar2 := null, -- username + SPASS in varchar2 := null, -- password + bAUTH in boolean := false, -- Требуется авторизация + SPATCH_LOKAL in varchar2 := null, -- Путь размещения файла на локальном сервере + NEQUIPDSCMN in number := null, -- Рег. номер класса оборудования выборки данных + SPATCH_FSERV in varchar2 := null, -- Путь размещения файла на сервере CSP + SDESCR in varchar2 := null, -- Описание выборки данных + NPRIORITY in number default 0, -- Приоритет (0- поумолчанию; 100- наиысший приоритет) + BMSG in blob -- Загружаемый XML с данными запроса в СКУД; + ); + + /* Подготока данных для Загрузки файла на SCP */ + procedure SCP_DATA_MAKE + ( + NEXSSERVICEFN in number, -- Рег. номер функции обработки + SHOST out varchar2, -- host + SPORT out varchar2, -- port + SUSER out varchar2, -- username + SPASS out varchar2, -- password + --SPATCH_LOKAL out varchar2, -- Путь размещения файла на локальном сервере + SPATCH_FSERV out varchar2 -- Путь размещения файла на сервере CSP + ); + + /* Подготока данных для Загрузки файла на Фреймворк */ + procedure AUTH_DATA_MAKE + ( + NEXSSERVICEFN in number, -- Рег. номер функции обработки + sAUTH out varchar2 -- Данные авторизции ("Authorization Basic base64(login:pass)) + ); + + /* Подготока данных для для передачи внешней системе */ + procedure METADATA_MAKE + ( + NIDENT in number, -- Идентификатор Selectlis + NEQUIPDSCM in number, -- регистрационный номер записи Выборки данных класса оборудования» + NDATASET_ID out number, -- DATASET_ID + BXML out blob -- Тело файла + ); + + /* Подготока данных для передачи Фреймворку запроса на обучение модели */ + procedure REQUIREMENTS_MAKE + ( + NEQUIPDSCMML in number, -- регистрационный номер записи Выборки Модели» + BXML out blob -- Тело файла + ); + +end UDO_PKG_EQUIPDS_SEND; +/ +create or replace package body UDO_PKG_EQUIPDS_SEND +is + + /* Получение URL для обработки результата */ + function GET_URL_END_POINT + ( + NEXSSERVICEFN in varchar2 -- Мнемокод функции сервиса обмена + )return varchar2 -- URL для обработки результата + is + REXSSERVICEFN EXSSERVICEFN%rowtype; -- + REXSSERVICE EXSSERVICE%rowtype; -- Запись сервиса обмена + SURL PKG_STD.tSTRING; -- Адрес сервера приложений (сервисы обмена) + begin + /* Считывание записи функции сервиса обмена */ + REXSSERVICEFN := GET_EXSSERVICEFN_ID(NFLAG_SMART => 0, NRN => NEXSSERVICEFN); + /* Считывание записи сервиса обмена */ + REXSSERVICE := GET_EXSSERVICE_ID(NFLAG_SMART => 0, NRN => REXSSERVICEFN.PRN); + /*Считывание параметра - Адрес сервера приложений (сервисы обмена)*/ + SURL := get_options_str(sCODE => SDEF_SEND_POINT_PRM, nCOMP_VERS => null ); + /* Формирование полного URL END_POINT */ + SURL := SURL||REXSSERVICE.SRV_ROOT||'/'||REXSSERVICEFN.FN_URL; + return SURL; + end GET_URL_END_POINT; + + + /* отправка запроса */ + procedure SEND_PACKGE + ( + NEXSSERVICEFN in number, -- Рег. номер функции обработки + NLNK_NEXSQUEUE in number default null, -- Рег.номер сязанной очереди + NCOMPANY in number := null, -- Рег. номер связанной организации + NDOCUMENT in number := null, -- Рег. номер связанной записи документа + SUNITCODE in varchar2 := null, -- Код связанного раздела + SHOST in varchar2 := null, -- host + SPORT in varchar2 := null, -- port + SUSER in varchar2 := null, -- username + SPASS in varchar2 := null, -- password + bAUTH in boolean := false, -- Требуется авторизация + SPATCH_LOKAL in varchar2 := null, -- Путь размещения файла на локальном сервере + NEQUIPDSCMN in number := null, -- Рег. номер класса оборудования выборки данных + SPATCH_FSERV in varchar2 := null, -- Путь размещения файла на сервере CSP + SDESCR in varchar2 := null, -- Описание выборки данных + NPRIORITY in number default 0, -- Приоритет (0- поумолчанию; 100- наиысший приоритет) + BMSG in blob -- Загружаемый XML с данными запроса в СКУД; + ) + is + NQ PKG_STD.TREF; -- Рег. номер очереди обмена + OPTS PKG_EXS.TOPTIONS; -- Параметры запроса + HDR_HEADERS PKG_EXS.TOPTIONS; -- Заголоок запроса + sAUTH PKG_STD.tLSTRING; -- Строка аторизации + begin + + PKG_EXS.OPTIONS_SET(OPTIONS => OPTS, + SCODE => 'NEXSSERVICEFN', + SVALUE => NEXSSERVICEFN); + + if SHOST is not null then + PKG_EXS.OPTIONS_SET(OPTIONS => OPTS, + SCODE => 'SHOST_SCP', + SVALUE => SHOST); + end if; + if SPORT is not null then + PKG_EXS.OPTIONS_SET(OPTIONS => OPTS, + SCODE => 'SPORT_SCP', + SVALUE => SPORT); + end if; + if SUSER is not null then + PKG_EXS.OPTIONS_SET(OPTIONS => OPTS, + SCODE => 'SUSER_SCP', + SVALUE => SUSER); + end if; + if SPASS is not null then + PKG_EXS.OPTIONS_SET(OPTIONS => OPTS, + SCODE => 'SPASS_SCP', + SVALUE => SPASS); + end if; + if (bAUTH) then + AUTH_DATA_MAKE(NEXSSERVICEFN => NEXSSERVICEFN, sAUTH => sAUTH); + if sAUTH is not null then + /* authorization */ + PKG_EXS.OPTIONS_SET(OPTIONS => HDR_HEADERS, + SCODE => pkg_exs.SHTP_HDR_AUTHORIZATION, + SVALUE => sAUTH); + + PKG_EXS.OPTIONS_SET(OPTIONS => HDR_HEADERS, + SCODE => pkg_exs.SHTP_HDR_CNT_TP, + SVALUE => pkg_exs.SHTP_HDR_CNT_TP_JSON); + end if; + end if; + if SPATCH_LOKAL is not null then + PKG_EXS.OPTIONS_SET(OPTIONS => OPTS, + SCODE => 'SPATCH_LOCAL', + SVALUE => SPATCH_LOKAL); + end if; + if NEQUIPDSCMN is not null then + PKG_EXS.OPTIONS_SET(OPTIONS => OPTS, + SCODE => 'NEQUIPDSCMN', + SVALUE => NEQUIPDSCMN); + end if; + if SPATCH_FSERV is not null then + PKG_EXS.OPTIONS_SET(OPTIONS => OPTS, + SCODE => 'SPATCH_FSERV', + SVALUE => SPATCH_FSERV); + end if; + if SDESCR is not null then + PKG_EXS.OPTIONS_SET(OPTIONS => OPTS, + SCODE => 'SDESCR', + SVALUE => SDESCR); + end if; + PKG_EXS.OPTIONS_SET(OPTIONS => OPTS, + SCODE => PKG_EXS.SMSG_OPTION_CODE_SIMPLE, + SVALUE => PKG_EXS.SMSG_OPTION_SIMPLE_FALSE); + + /* Формируем параметры запроса */ + PKG_EXS.OPTIONS_SET(OPTIONS => OPTS, + SCODE => pkg_exs.SMSG_OPTION_CODE_HEADERS, + SVALUE => PKG_EXS.OPTIONS_SERIALIZE(OPTIONS => HDR_HEADERS, + BROOT => false)); + /* Постанока запроса в очередь */ + PKG_EXS.QUEUE_PUT(NEXSSERVICEFN => NEXSSERVICEFN, + BMSG => BMSG, + NEXSQUEUE => NLNK_NEXSQUEUE, + NLNK_COMPANY => nCOMPANY, + NLNK_DOCUMENT => NDOCUMENT, + SLNK_UNITCODE => SUNITCODE, + SOPTIONS => PKG_EXS.OPTIONS_SERIALIZE(OPTIONS => OPTS), + NPRIORITY => NPRIORITY, + NNEW_EXSQUEUE => NQ); + end SEND_PACKGE; + + /* Подготока данных для Загрузки файла на SCP */ + procedure SCP_DATA_MAKE + ( + NEXSSERVICEFN in number, -- Рег. номер функции обработки + SHOST out varchar2, -- host + SPORT out varchar2, -- port + SUSER out varchar2, -- username + SPASS out varchar2, -- password + SPATCH_FSERV out varchar2 -- Путь размещения файла на сервере CSP + ) + is + REXSSERVICEFN EXSSERVICEFN%rowtype; -- + REXSSERVICE EXSSERVICE%rowtype; -- Запись сервиса обмена + begin + /* Считывание записи функции сервиса обмена */ + REXSSERVICEFN := GET_EXSSERVICEFN_ID(NFLAG_SMART => 0, NRN => NEXSSERVICEFN); + /* Считывание записи сервиса обмена */ + REXSSERVICE := GET_EXSSERVICE_ID(NFLAG_SMART => 0, NRN => REXSSERVICEFN.PRN); + /**/ + SHOST := REGEXP_SUBSTR(REGEXP_SUBSTR(REXSSERVICE.SRV_ROOT,'(.*?)(//|$)', 1,2,NULL,1),'(.*?)(:|$)', 1,1,NULL,1); + SPORT := REGEXP_SUBSTR(REGEXP_SUBSTR(REXSSERVICE.SRV_ROOT,'(.*?)(//|$)', 1,2,NULL,1),'(.*?)(:|$)', 1,2,NULL,1); + /* Считаем параметры пользователя логин и пароль */ + SUSER := REXSSERVICE.SRV_USER; + SPASS := BLOB2CLOB(lbDATA => BASE64_DECODE(REXSSERVICE.SRV_PASS),sCHARSET => PKG_CHARSET.CHARSET_UTF_); + /**/ + SPATCH_FSERV := REXSSERVICEFN.FN_URL; + end SCP_DATA_MAKE; + + /* Подготока данных для Загрузки файла на Фреймворк */ + procedure AUTH_DATA_MAKE + ( + NEXSSERVICEFN in number, -- Рег. номер функции обработки + sAUTH out varchar2 -- Данные авторизции ("Authorization Basic base64(login:pass)) + ) + is + REXSSERVICEFN EXSSERVICEFN%rowtype; -- Запись функции сервиса обмена + REXSSERVICE EXSSERVICE%rowtype; -- Запись сервиса обмена + SUSER PKG_STD.tSTRING; -- username + SPASS PKG_STD.tSTRING; -- password + begin + /* Считывание записи функции сервиса обмена */ + REXSSERVICEFN := GET_EXSSERVICEFN_ID(NFLAG_SMART => 0, NRN => NEXSSERVICEFN); + /* Считывание записи сервиса обмена */ + REXSSERVICE := GET_EXSSERVICE_ID(NFLAG_SMART => 0, NRN => REXSSERVICEFN.PRN); + /* Считаем параметры пользователя логин и пароль */ + SUSER := REXSSERVICE.SRV_USER; + SPASS := BLOB2CLOB(lbDATA => BASE64_DECODE(REXSSERVICE.SRV_PASS),sCHARSET => PKG_CHARSET.CHARSET_UTF_); + /**/ + sAUTH := 'Basic'||' '||BASE64_ENCODE(lbSRCE => CLOB2BLOB(lcDATA => SUSER||':'||SPASS,sCHARSET => PKG_CHARSET.CHARSET_UTF_)); + end AUTH_DATA_MAKE; + + /* Подготока данных для для передачи внешней системе */ + procedure METADATA_MAKE + ( + NIDENT in number, -- Идентификатор Selectlis + NEQUIPDSCM in number, -- регистрационный номер записи Выборки данных класса оборудования» + NDATASET_ID out number, -- DATASET_ID + BXML out blob -- Тело файла + ) + is + SEND_POINT PKG_STD.tSTRING; -- URL для обработки результата + xNODE PKG_XMAKE.tNODE; -- Подчиненный узел + xNODE_FL PKG_XMAKE.tNODE; -- Подчиненный узел Имён файлов + XDOC integer; -- Документ для размещения XML-элемента + DATACONFIG PKG_XMAKE.tNODE; -- DATACONFIG + ATRIBS PKG_XMAKE.tATTRIBUTES; -- Атрибуты + RDOCUMENT PKG_XPATH.TDOCUMENT; -- XML документ + RROOT PKG_XPATH.TNODE; -- Корневой узел XML документа + FIRSTNODE PKG_XPATH.TNODE; -- Корневой узел XML документа + RNODE PKG_XPATH.TNODE; -- + RNODES PKG_XPATH.TNODES; -- Узлы XML документа + NCURS_COUNT PKG_STD.tNUMBER; -- Количество узлов + BONLYONE boolean := true; + begin + XDOC := PKG_XMAKE.OPEN_CURSOR(); + for REQUIPDSCM in (select E.CODE SEQOBJKIND, t.* from UDO_T_EQUIPDSCM T, EQOBJKIND E where T.RN = NEQUIPDSCM and T.EQOBJKIND = E.RN)loop + + RDOCUMENT := PKG_XPATH.PARSE_FROM_CLOB(REQUIPDSCM.DATA_CONFIG); + RROOT := PKG_XPATH.ROOT_NODE(RDOCUMENT); + FIRSTNODE := PKG_XPATH.FIRST_NODE(RROOT); + RNODES := PKG_XPATH.LIST_NODES(FIRSTNODE, 'item'); + NCURS_COUNT := PKG_XPATH.COUNT_NODES(RNODES); + for I in 1 .. NCURS_COUNT loop + RNODE := PKG_XPATH.ITEM_NODE(RNODES, I); + ATRIBS := PKG_XMAKE.ATTRIBUTES(iCURSOR => XDOC, + rATTRIBUTE00 => PKG_XMAKE.ATTRIBUTE(iCURSOR => XDOC,sNAME => 'col_name',sVALUE => PKG_XPATH.ATTRIBUTE(RNODE, 'col_code')), + rATTRIBUTE01 => PKG_XMAKE.ATTRIBUTE(iCURSOR => XDOC,sNAME => 'data_type',sVALUE => PKG_XPATH.ATTRIBUTE(RNODE, 'data_type')) + ); + DATACONFIG := PKG_XMAKE.CONCAT(iCURSOR => XDOC, + rNODE00 => DATACONFIG, + rNODE01 => PKG_XMAKE.ELEMENT(iCURSOR => XDOC,sNAME => 'data_config',rATTRIBUTES => ATRIBS) + ); + end loop; + PKG_XPATH.FREE(rDOCUMENT => RDOCUMENT); + /* Сформируем полный URL */ + SEND_POINT := GET_URL_END_POINT(NEXSSERVICEFN => REQUIPDSCM.EXSSERVICEFN_SEND_MDCB); + + /* Перечень файлов */ + for REQUIPDSCMFL in (select FL.* from UDO_T_EQUIPDSCMFL FL, SELECTLIST SL Where FL.RN = SL.DOCUMENT and SL.IDENT = NIDENT)loop + + /* Идентификатор dataset */ + if (BONLYONE) then + xNODE := PKG_XMAKE.ELEMENT(iCURSOR => XDOC, + sNAME => 'dataset_ID', + rVALUE00 => PKG_XMAKE.VALUE(iCURSOR => XDOC, + sVALUE => REQUIPDSCMFL.DATASET_ID)); + BONLYONE := false; + NDATASET_ID := REQUIPDSCMFL.DATASET_ID; + end if; + xNODE_FL := PKG_XMAKE.CONCAT(iCURSOR => XDOC, + rNODE00 => xNODE_FL, + rNODE01 => PKG_XMAKE.ELEMENT(iCURSOR => XDOC, + sNAME => 'ftp_filepath', + rVALUE00 => PKG_XMAKE.VALUE(iCURSOR => XDOC, + sVALUE => REQUIPDSCMFL.FILE_NAME))); + + end loop; + + + + + xNODE := PKG_XMAKE.CONCAT(iCURSOR => XDOC, + rNODE00 => xNODE, + /* Тип оборудования */ + rNODE01 => PKG_XMAKE.ELEMENT(iCURSOR => XDOC, + sNAME => 'class_machine', + rVALUE00 => PKG_XMAKE.VALUE(iCURSOR => XDOC, + sVALUE => TRIM(REQUIPDSCM.SEQOBJKIND))), + + rNODE02 => xNODE_FL, + /* url для результата отпраки */ + rNODE03 => PKG_XMAKE.ELEMENT(iCURSOR => XDOC, + sNAME => 'end_point', + rVALUE00 => PKG_XMAKE.VALUE(iCURSOR => XDOC, + sVALUE => SEND_POINT)), + /* Описание полей dataset */ + rNODE04 => DATACONFIG + ); + + + end loop; + BXML := PKG_XMAKE.SERIALIZE_TO_BLOB(iCURSOR => XDOC, + iTYPE => PKG_XMAKE.DOCUMENT_, + rNODE => PKG_XMAKE.CONCAT(iCURSOR => XDOC, + rNODE00 => PKG_XMAKE.ELEMENT(iCURSOR => XDOC, + sNAME => 'root', + rNODE00 => xNODE)), + rHEADER => PKG_XHEADER.WRAP_ALL(PKG_XHEADER.VERSION_1_0_, + PKG_XHEADER.ENCODING_UTF_, + PKG_XHEADER.STANDALONE_NONE_) + ); + PKG_XMAKE.CLOSE_CURSOR(iCURSOR => XDOC); + end METADATA_MAKE; + + /* Подготока данных для передачи Фреймворку запроса на обучение модели */ + procedure REQUIREMENTS_MAKE + ( + NEQUIPDSCMML in number, -- регистрационный номер записи Выборки Модели» + BXML out blob -- Тело файла + ) + is + SEND_POINT PKG_STD.tSTRING; -- URL для обработки результата + xNODE PKG_XMAKE.tNODE; -- Подчиненный узел + xNODE_ML PKG_XMAKE.tNODE; -- Подчиненный узел обучение модели + XDOC integer; -- Документ для размещения XML-элемента + BONLYONE boolean := true; + begin + /*Старт сборки XML*/ + XDOC := PKG_XMAKE.OPEN_CURSOR(); + /* Перечень файлов */ + for REQUIPDSCMML in (select M.EQOBJKIND, + M.EXSSERVICEFN_SEND_RQCB, + TRIM(E.CODE) SEQOBJKIND, + ML.* + from UDO_T_EQUIPDSCMML ML, + UDO_T_EQUIPDSCM M, + EQOBJKIND E + Where ML.RN = NEQUIPDSCMML + and ML.PRN = M.RN + and M.EQOBJKIND = E.RN) loop + /* Сформируем полный URL */ + if (BONLYONE) then + SEND_POINT := GET_URL_END_POINT(NEXSSERVICEFN => REQUIPDSCMML.EXSSERVICEFN_SEND_RQCB); + BONLYONE := false; + end if; + + /* Ссобирем узел запроса */ + xNODE_ML := PKG_XMAKE.CONCAT(iCURSOR => XDOC, + rNODE00 => PKG_XMAKE.ELEMENT(iCURSOR => XDOC, + sNAME => 'dataset_ID', + rVALUE00 => PKG_XMAKE.VALUE(iCURSOR => XDOC, + sVALUE => REQUIPDSCMML.DATASET_ID)), + rNODE01 => PKG_XMAKE.ELEMENT(iCURSOR => XDOC, + sNAME => 'task', + rVALUE00 => PKG_XMAKE.VALUE(iCURSOR => XDOC, + sVALUE => REQUIPDSCMML.TASK)), + rNODE02 => PKG_XMAKE.ELEMENT(iCURSOR => XDOC, + sNAME => 'precision', + rVALUE00 => PKG_XMAKE.VALUE(iCURSOR => XDOC, + sVALUE => 100))); + + + /* Ссобирем узел запроса */ + xNODE := PKG_XMAKE.CONCAT(iCURSOR => XDOC, + rNODE00 => xNODE_ML, + /* Тип оборудования */ + rNODE01 => PKG_XMAKE.ELEMENT(iCURSOR => XDOC, + sNAME => 'class_machine', + rVALUE00 => PKG_XMAKE.VALUE(iCURSOR => XDOC, + sVALUE => REQUIPDSCMML.SEQOBJKIND)), + /* url для результата отпраки */ + rNODE02 => PKG_XMAKE.ELEMENT(iCURSOR => XDOC, + sNAME => 'end_point', + rVALUE00 => PKG_XMAKE.VALUE(iCURSOR => XDOC, + sVALUE => SEND_POINT))); + + end loop; + /* Формируем тело запроса */ + BXML := PKG_XMAKE.SERIALIZE_TO_BLOB(iCURSOR => XDOC, + iTYPE => PKG_XMAKE.DOCUMENT_, + rNODE => PKG_XMAKE.CONCAT(iCURSOR => XDOC, + rNODE00 => PKG_XMAKE.ELEMENT(iCURSOR => XDOC, + sNAME => 'root', + rNODE00 => xNODE)), + rHEADER => PKG_XHEADER.WRAP_ALL(PKG_XHEADER.VERSION_1_0_, + PKG_XHEADER.ENCODING_UTF_, + PKG_XHEADER.STANDALONE_NONE_)); + + PKG_XMAKE.CLOSE_CURSOR(iCURSOR => XDOC); + end REQUIREMENTS_MAKE; + + +end UDO_PKG_EQUIPDS_SEND; +/ diff --git a/db/UDO_P_EQUIPDSCM_DATASET_MAKE.prc b/db/UDO_P_EQUIPDSCM_DATASET_MAKE.prc new file mode 100644 index 0000000..ce85d59 --- /dev/null +++ b/db/UDO_P_EQUIPDSCM_DATASET_MAKE.prc @@ -0,0 +1,25 @@ +create or replace procedure UDO_P_EQUIPDSCM_DATASET_MAKE +( + NCOMPANY in number, -- регистрационный номер организации + NEQUIPDSCM in number, -- Рег. номер класса оборудования выборки данных + DBEG in date, -- Дата С + DEND in date, -- Дата По + NLENGTH_GB in number, -- Ограничение размера файла в Гб + NDATASET_IDENT out number, -- Идентификатор буфера данных + NDATASET_CONFIG_IDENT out number -- Идентификатор буфера описания данных ) + +) +is +begin + /* Получение данных датасета и Описание структуры выборки */ + UDO_PKG_EQUIPDS_DATAPROCESS.DATASET_CONF_SET(NCOMPANY => NCOMPANY, + NEQUIPDSCM => NEQUIPDSCM, + DBEG => DBEG, + DEND => DEND, + NLENGTH_GB => NLENGTH_GB, + NDATASET_IDENT => NDATASET_IDENT, + NDATASET_CONFIG_IDENT => NDATASET_CONFIG_IDENT + ); +end UDO_P_EQUIPDSCM_DATASET_MAKE; +-- grant execute on UDO_P_EQUIPDSCM_DATASET_MAKE to public; +/ diff --git a/db/grants.sql b/db/grants.sql index 03ebab6..5c2323b 100644 --- a/db/grants.sql +++ b/db/grants.sql @@ -1,3 +1,4 @@ grant execute on UDO_PKG_EQUIPTCF to public; grant execute on UDO_PKG_EQUIPDS to public; grant execute on UDO_P_EQCONFIG_DATASET_MAKE to public; +grant execute on UDO_P_EQUIPDSCM_DATASET_MAKE to public; diff --git a/service/modules/EQUIPDS.js b/service/modules/EQUIPDS.js new file mode 100644 index 0000000..5d3a8ad --- /dev/null +++ b/service/modules/EQUIPDS.js @@ -0,0 +1,121 @@ +/* + Сервис интеграции ПП Парус 8 с WEB API + Дополнительный модуль: Интеграция с Фреймворка оценки и прогнозирования состояния оборудования +*/ + +//------------------------------ +// Подключение внешних библиотек +//------------------------------ + +const xml2js = require("xml2js"); //Конвертация XML в JSON и JSON в XML +const _ = require("lodash"); //Работа с коллекциями и объектами + +//--------------------- +// Глобальные константы +//--------------------- + +// Список тегов которые должны содержать массив +const tag = [ + "ftp_filepath", + "data_config" +]; + +//------------ +// Тело модуля +//------------ + +//Обернуть содержимое тега в массив +const toArray = (obj, tags) => { + for (const prop in obj) { + const value = obj[prop]; + if (tags.indexOf(prop) != -1 && !_.isArray(obj[prop])) { + obj[prop] = JSON.parse("[" + JSON.stringify(value) + "]"); + } + if (typeof value === "object") { + toArray(value, tag); + } + } + return obj; +}; + +//Конвертация в XML +const toXML = obj => { + const builder = new xml2js.Builder(); + return builder.buildObject(obj); +}; + +//Конвертация в JSON +const parseXML = xmlDoc => { + return new Promise((resolve, reject) => { + xml2js.parseString(xmlDoc, { explicitArray: false, mergeAttrs: true }, (err, result) => { + if (err) reject(err); + else resolve(result); + }); + }); +}; + +//Конвертация в JSON +const toJSON = async obj => { + let result = await parseXML(obj); + result = result.root; + toArray(result, tag); + return result; +}; + +//Обработчик "До" отправки запроса к сервису "СБИС" +const beforeDocParse = async prms => { + try { + //Конвертируем XML из "Парус 8" в понятный "СБИСу" JSON + let obj = await toJSON(prms.queue.blMsg.toString()); + //Собираем и отдаём общий результат работы + return { + options: { + simple: false, + }, + blMsg: Buffer.from(JSON.stringify(obj)) + }; + } catch (e) { + throw Error(e); + } +}; + +//Обработчик "После" запроса к сервису "СБИС" +const afterDocParseResp = async prms => { + //Преобразуем JSON ответ сервиса "СБИС" в XML, понятный "Парус 8" + let resu = null; + if (prms.queue.blResp) { + try { + resu = toXML(JSON.parse(prms.queue.blResp.toString())); + } catch (e) { + throw new Error(`Неожиданный ответ сервера. Ошибка интерпретации: ${e.message}`); + } + } else { + throw new Error('Сервер не вернул ответ'); + } + //Возврат результата + return { + blResp: Buffer.from(resu) + }; +}; + +//Обработчик "После" запроса к сервису +const beforeDocParseMsg = async prms => { + //Преобразуем JSON ответ сервиса в XML, понятный "Парус 8" + let resu = null; + if (prms.queue.blMsg) { + try { + resu = toXML(JSON.parse(prms.queue.blMsg.toString())); + } catch (e) { + throw new Error(`Неожиданный ответ сервера. Ошибка интерпретации: ${e.message}`); + } + } else { + throw new Error('Сервер не вернул ответ'); + } + //Возврат результата + return { + blMsg: Buffer.from(resu) + }; +}; +exports.beforeDocParse = beforeDocParse; +exports.afterDocParseResp = afterDocParseResp; +exports.beforeDocParseMsg = beforeDocParseMsg; \ No newline at end of file diff --git a/service/modules/loadSCP_v2.js b/service/modules/loadSCP_v2.js new file mode 100644 index 0000000..2865d07 --- /dev/null +++ b/service/modules/loadSCP_v2.js @@ -0,0 +1,155 @@ +/* + Сервис интеграции ПП Парус 8 с WEB API + Дополнительный модуль: Загрузки файла на сервер SCP +*/ + +//------------------------------ +// Подключение внешних библиотек +//------------------------------ + +const { ServerError } = require("./../core/server_errors"); //Типовая ошибка +const { SERR_APP_SERVER_BEFORE, SERR_DB_SERVER } = require("./../core/constants"); //Общесистемные константы +const oracledb = require("oracledb"); //Работа с СУБД Oracle +const { Client } = require('node-scp') + +//------------ +// Тело модуля +//------------ + + +//------------ +// Чтение файла и запись в file_buffer +//------------ +let myReadFiles = async(nRN,dbConn) => { + if (dbConn){ + //Если есть подключение к БД + if (dbConn.bConnected) { + let pooledConnection; + try { + //Выполняем процедуру + console.log('!1 -',nRN); + pooledConnection = await dbConn.connection.getConnection(); + console.log('!2 -',nRN); + let res = await pooledConnection.execute( + "select t.file_name, t.dataset from UDO_V_T_EQUIPDSCMFL1 t where t.prn = :nRN", + {nRN: nRN} + ); + console.log('!!3 -',nRN); + return res.rows; + } catch (e) { + throw new ServerError(`Выполнение процедуры не удачно`, e.message); + } finally { + if (pooledConnection) { + try { + await pooledConnection.close(); + } catch (e) { + throw new Error(`Чегото не то!`, e.message); + } + } + } + } else { + throw new ServerError(SERR_DB_SERVER, `Нет подключения к БД`); + } + } else{ + throw new ServerError(SERR_DB_SERVER, `Что тот не то ${dbConn}`); + } +}; + + + +//------------ +// Загрузка файлов на сервер SCP +//------------ +async function uploadSCP(sHost, sPort, sUsername, sPassword, sSCPPatch, data ) { + try { + //console.log(`sHost ${sHost}, sPort ${sPort}, sUsername ${sUsername}, sPassword ${sPassword}, sSCPPatch ${sSCPPatch}`); + console.log("sHost",sHost); + console.log("sPort",sPort); + console.log("sUsername",sUsername); + console.log("sPassword",sPassword); + console.log("data",data); + const client = await Client({ + host: sHost, + port: sPort, + username: sUsername, + password: sPassword, + // privateKey: fs.readFileSync('./key.pem'), + // passphrase: 'your key passphrase', + }) + console.log("1",client); + await client.writeFile(sSCPPatch, + data, + ) + //client.uploadFile( + // sLocalPatch, + // sSCPPatch, + // options?: TransferOptions + // ) + //const result = await client.stat('/home/bilaboutsource/parus') + //console.log(result) + const result = await client.list('/home/sftp_user/parus') + console.log(result) + // you can perform upload multiple times + //await client.uploadFile('./test1.txt', '/workspace/test1.txt') + client.close() // remember to close connection after you finish + } catch (e) { + //console.log(`Ошибка загрузки файла ${e}`) + return e.message; + } +} + + + +//Обработчик "До" для полученного сообщения +const uploadFileSCP = async prms => { + //Проверим, что есть подключение к БД + if (prms.dbConn.bConnected) { + try { + //Разбираем + //console.log("sHost:", prms.options["SHOST_SCP"]); + //console.log( "sPort:", prms.options["SPORT_SCP"]); + //console.log( "sUsername:", prms.options["SUSER_SCP"]); + //console.log( "sPassword:", prms.options["SPASS_SCP"]); + //console.log( "sLocalPatch:", prms.options["SPATCH_LOCAL"]); + //console.log( "sSCPPatch:", prms.options["SPATCH_FSERV"]); + //console.log("data",prms.queue.blMsg); + //let rows = await myReadFiles(prms.options["NEQUIPDSCMN"],prms.dbConn); + //console.log(rows.length); + //res = "urq"; + //for ( let i= 0; i < rows.count; i++){ + // console.log() + //} + //console.log(prms.options["SPATCH_FSERV"]); + //console.log(prms.queue.blMsg); + let res = await uploadSCP(prms.options["SHOST_SCP"],prms.options["SPORT_SCP"], prms.options["SUSER_SCP"], prms.options["SPASS_SCP"],prms.options["SPATCH_FSERV"], prms.queue.blMsg ) + if (res){ + stateres = 500; + }else{ + stateres = 200; + res = ""; + } + console.log(stateres); + console.log(res); + // Соберем результат в XML + let resXml = ""; + resXml += ""; + resXml += `${stateres}`; + resXml += `${res}`; + resXml += ""; + return{ + blMsg: Buffer.from(resXml), + bStopPropagation: true + } + } catch (e) { + throw new ServerError(SERR_APP_SERVER_BEFORE, `Ошибка обработки тела входящего сообщения: ${e.message}`); + } + } else throw new ServerError(SERR_DB_SERVER, "Нет подключения к БД"); + + + }; + +//----------------- +// Интерфейс модуля +//----------------- + +exports.uploadFileSCP = uploadFileSCP; \ No newline at end of file