diff --git a/db/UDO_PKG_EQUIPDS.pck b/db/UDO_PKG_EQUIPDS.pck index d107dc3..79e24e2 100644 --- a/db/UDO_PKG_EQUIPDS.pck +++ b/db/UDO_PKG_EQUIPDS.pck @@ -191,12 +191,6 @@ create or replace package UDO_PKG_EQUIPDS as COUT out clob -- Сериализованная таблица данных ); - /* Формирование данных прогноза "Выборки данных оборудования (классы оборудования, модели, история запросов)" */ - procedure CMMLH_BUILD_FORECAST - ( - COUT out clob -- Данные прогноза - ); - /* Извлечение описания из данных прогноза "Выборки данных оборудования (классы оборудования, модели, история запросов)" */ procedure CMMLH_PARSE_FORECAST ( @@ -1484,41 +1478,7 @@ create or replace package body UDO_PKG_EQUIPDS as end loop; /* Сериализуем описание */ COUT := PKG_P8PANELS_VISUAL.TDG_TO_XML(RDATA_GRID => RDG, NINCLUDE_DEF => 1); - end CMML_LIST_BY_EQCONFIG; - - /* Формирование данных прогноза "Выборки данных оборудования (классы оборудования, модели, история запросов)" */ - procedure CMMLH_BUILD_FORECAST - ( - COUT out clob -- Данные прогноза - ) - is - NCUR integer; -- Курсор документа для результата - XDOC PKG_XMAKE.TNODE; -- Документ для результата - XROOT PKG_XMAKE.TNODE; -- Содержимое корневого узла документа - NFORECAST PKG_STD.TNUMBER; -- Прогноз по заданной задаче - begin - /* Вычислим прогноз - количество периодов в указанных ЕИ до достижения предельного состояния */ - NFORECAST := ROUND(DBMS_RANDOM.VALUE(10, 60)); - /* Открываем документ */ - NCUR := PKG_XMAKE.OPEN_CURSOR(); - /* Заполним прогноз */ - XROOT := PKG_XMAKE.CONCAT(ICURSOR => NCUR, - RNODE00 => XROOT, - RNODE01 => PKG_XMAKE.ELEMENT(ICURSOR => NCUR, - SNAME => 'NFORECAST', - RVALUE00 => PKG_XMAKE.VALUE(ICURSOR => NCUR, NVALUE => NFORECAST))); - /* Формируем XML-представление ответа */ - XDOC := PKG_XMAKE.ELEMENT(ICURSOR => NCUR, SNAME => 'XDATA', RNODE00 => XROOT); - /* Конвертируем в CLOB */ - COUT := PKG_XMAKE.SERIALIZE_TO_CLOB(ICURSOR => NCUR, - ITYPE => PKG_XMAKE.CONTENT_, - RNODE => XDOC, - RHEADER => PKG_XHEADER.WRAP_ALL(SVERSION => PKG_XHEADER.VERSION_1_0_, - SENCODING => PKG_XHEADER.ENCODING_UTF_, - SSTANDALONE => PKG_XHEADER.STANDALONE_YES_)); - /* Закрываем документ */ - PKG_XMAKE.CLOSE_CURSOR(ICURSOR => NCUR); - end CMMLH_BUILD_FORECAST; + end CMML_LIST_BY_EQCONFIG; /* Извлечение описания из данных прогноза "Выборки данных оборудования (классы оборудования, модели, история запросов)" */ procedure CMMLH_PARSE_FORECAST diff --git a/db/UDO_PKG_EQUIPTCF.pck b/db/UDO_PKG_EQUIPTCF.pck index da01359..02759d6 100644 --- a/db/UDO_PKG_EQUIPTCF.pck +++ b/db/UDO_PKG_EQUIPTCF.pck @@ -61,17 +61,19 @@ create or replace package UDO_PKG_EQUIPTCF as COUT out clob -- Сериализованная карточка ); - /* Отправка запроса на формирование прогноза технического объекта */ - procedure EQCONFIG_THOBJ_FORECAST + /* Подчистка после исполнения запроса на формирование прогноза технического объекта */ + procedure EQCONFIG_THOBJ_FORECAST_EPLG ( - NEQCONFIG in number, -- Рег. номер технического объекта - NEQUIPDSCMML in number -- Рег. номер модели + NDATASET_IDENT in number, -- Идентификатор буфера данных + NDATASET_CONFIG_IDENT in number, -- Идентификатор буфера описания данных + NEQCONFIG in number := null, -- Рег. номер технического объекта + NEQUIPDSCMML in number := null, -- Рег. номер модели + CFORECAST in clob := null -- Данные прогноза ); /* Подготовка запроса на формирование прогноза технического объекта */ procedure EQCONFIG_THOBJ_FORECAST_PRLG ( - NEQCONFIG in number, -- Рег. номер технического объекта NEQUIPDSCMML in number, -- Рег. номер модели NDATASET_IDENT in number, -- Идентификатор буфера данных NDATASET_CONFIG_IDENT in number, -- Идентификатор буфера описания данных @@ -84,13 +86,6 @@ create or replace package UDO_PKG_EQUIPTCF as STASK out varchar2 -- Задача для запроса (см. константы UDO_PKG_EQUIPDS_BASE.SCMML_TASK_*) ); - /* Подчистка после исполнения запроса на формирование прогноза технического объекта */ - procedure EQCONFIG_THOBJ_FORECAST_EPLG - ( - NDATASET_IDENT in number, -- Идентификатор буфера данных - NDATASET_CONFIG_IDENT in number -- Идентификатор буфера описания данных - ); - /* Формирование цвета прогноза для технического объекта */ function EQCONFIG_THOBJ_FORECAST_CLR ( @@ -150,6 +145,10 @@ TODO: owner="root" created="02.08.2024" text="Проверка прав доступа при формировании таблицы и карточки ТО" */ + /* Константы - адреса API фреймворка прогнозирования */ + SFW_API_ROOT constant PKG_STD.TSTRING := '/API'; -- Корень API + SFW_API_FORECAST constant PKG_STD.TSTRING := '/forecast/metadata'; -- Адрес функции прогнозирования (относительно корня) + /* Формирование ветки дерева состава оборудования */ function EQCONFIG_HIER_NODE ( @@ -727,56 +726,93 @@ text="Проверка прав доступа при формировании PKG_XMAKE.CLOSE_CURSOR(ICURSOR => NCUR); end EQCONFIG_THOBJ_CARD; - /* Отправка запроса на формирование прогноза технического объекта */ - procedure EQCONFIG_THOBJ_FORECAST + /* Подчистка после исполнения запроса на формирование прогноза технического объекта */ + procedure EQCONFIG_THOBJ_FORECAST_EPLG ( - NEQCONFIG in number, -- Рег. номер технического объекта - NEQUIPDSCMML in number -- Рег. номер модели + NDATASET_IDENT in number, -- Идентификатор буфера данных + NDATASET_CONFIG_IDENT in number, -- Идентификатор буфера описания данных + NEQCONFIG in number := null, -- Рег. номер технического объекта + NEQUIPDSCMML in number := null, -- Рег. номер модели + CFORECAST in clob := null -- Данные прогноза ) is - NEQUIPDSCMMLH PKG_STD.TREF; -- Рег. номер истории запросов модели - CDEMO clob; -- Демо-данные прогноза + NEQUIPDSCMMLH PKG_STD.TREF; -- Рег. номер истории запросов модели begin - /* Добавляем запись истории запросов */ - UDO_PKG_EQUIPDS_BASE.CMMLH_INS(NPRN => NEQUIPDSCMML, - NEQCONFIG => NEQCONFIG, - SRQ_AUTHID => UTILIZER(), - DRQ_DATE => sysdate, - BRQ => null, - NRN => NEQUIPDSCMMLH); - /* Добавим демо-данные */ - for C in (select T.TASK STASK, - DM.MEAS_MNEMO SDICMUNTS - from UDO_T_EQUIPDSCMML T, - UDO_T_EQUIPDSCM CM, - DICMUNTS DM - where T.RN = NEQUIPDSCMML - and T.PRN = CM.RN - and CM.DICMUNTS = DM.RN) - loop - UDO_PKG_EQUIPDS.CMMLH_BUILD_FORECAST(COUT => CDEMO); - UDO_PKG_EQUIPDS_BASE.CMMLH_SET_FORECAST(NRN => NEQUIPDSCMMLH, BFORECAST => CLOB2BLOB(LCDATA => CDEMO)); - end loop; - end EQCONFIG_THOBJ_FORECAST; + /* Очистим данные в файловом буфере */ + P_FILE_BUFFER_CLEAR(NIDENT => NDATASET_IDENT); + P_FILE_BUFFER_CLEAR(NIDENT => NDATASET_CONFIG_IDENT); + /* Если указаны данные технического объекта */ + if ((NEQCONFIG is not null) and (NEQUIPDSCMML is not null)) then + /* Добавляем запись истории запросов */ + UDO_PKG_EQUIPDS_BASE.CMMLH_INS(NPRN => NEQUIPDSCMML, + NEQCONFIG => NEQCONFIG, + SRQ_AUTHID => UTILIZER(), + DRQ_DATE => sysdate, + BRQ => null, + NRN => NEQUIPDSCMMLH); + /* Сохраним данные прогноза */ + UDO_PKG_EQUIPDS_BASE.CMMLH_SET_FORECAST(NRN => NEQUIPDSCMMLH, BFORECAST => BASE64_DECODE(LCSRCE => CFORECAST)); + end if; + end EQCONFIG_THOBJ_FORECAST_EPLG; + + /* Подчистка после исполнения запроса на формирование прогноза технического объекта (в автономной транзакции) */ + procedure EQCONFIG_THOBJ_FORECAST_EPLGAT + ( + NDATASET_IDENT in number, -- Идентификатор буфера данных + NDATASET_CONFIG_IDENT in number -- Идентификатор буфера описания данных + ) + is + RPROC_PARAMS PKG_CONTPRMLOC.TCONTAINER; -- Параметры процедуры + begin + /* Очищаем контейнер с параметрами */ + PKG_CONTPRMLOC.PURGE(RCONTAINER => RPROC_PARAMS); + /* Собираем параметры процедуры */ + PKG_CONTPRMLOC.PUTN(RCONTAINER => RPROC_PARAMS, + SNAME => 'NDATASET_IDENT', + NVALUE => NDATASET_IDENT, + NIN_OUT => PKG_STD.PARAM_TYPE_IN()); + PKG_CONTPRMLOC.PUTN(RCONTAINER => RPROC_PARAMS, + SNAME => 'NDATASET_CONFIG_IDENT', + NVALUE => NDATASET_CONFIG_IDENT, + NIN_OUT => PKG_STD.PARAM_TYPE_IN()); + /* Подчищаем (в автономной транзакции) */ + PKG_SQL_CALL.EXECUTE_STORED_AT(SSTORED_NAME => 'UDO_PKG_EQUIPTCF.EQCONFIG_THOBJ_FORECAST_EPLG', + RPARAM_CONTAINER => RPROC_PARAMS, + BOVERLOAD_ENV => true); + /* Очищаем контейнер с параметрами */ + PKG_CONTPRMLOC.PURGE(RCONTAINER => RPROC_PARAMS); + end EQCONFIG_THOBJ_FORECAST_EPLGAT; /* Подготовка запроса на формирование прогноза технического объекта */ procedure EQCONFIG_THOBJ_FORECAST_PRLG ( - NEQCONFIG in number, -- Рег. номер технического объекта - NEQUIPDSCMML in number, -- Рег. номер модели - NDATASET_IDENT in number, -- Идентификатор буфера данных - NDATASET_CONFIG_IDENT in number, -- Идентификатор буфера описания данных - SURL out varchar2, -- Адрес для запроса - SAUTH_TOKEN out varchar2, -- Токен аутентификации для запроса - SDATASET_ID out varchar2, -- Идентификатор выборки данных запроса - CDATASET_CONFIG out clob, -- Описание данных о наработках - SDATASET_URL out varchar2, -- Адрес для получения данных о наработках - SCLASS_MACHINE out varchar2, -- Код класса оборудования для запроса - STASK out varchar2 -- Задача для запроса (см. константы UDO_PKG_EQUIPDS_BASE.SCMML_TASK_*) + NEQUIPDSCMML in number, -- Рег. номер модели + NDATASET_IDENT in number, -- Идентификатор буфера данных + NDATASET_CONFIG_IDENT in number, -- Идентификатор буфера описания данных + SURL out varchar2, -- Адрес для запроса + SAUTH_TOKEN out varchar2, -- Токен аутентификации для запроса + SDATASET_ID out varchar2, -- Идентификатор выборки данных запроса + CDATASET_CONFIG out clob, -- Описание данных о наработках + SDATASET_URL out varchar2, -- Адрес для получения данных о наработках + SCLASS_MACHINE out varchar2, -- Код класса оборудования для запроса + STASK out varchar2 -- Задача для запроса (см. константы UDO_PKG_EQUIPDS_BASE.SCMML_TASK_*) ) is - NCNT PKG_STD.TNUMBER; -- Буфер для количества файлов данных + REQUIPDSCMML UDO_T_EQUIPDSCMML%rowtype; -- Запись модели + REQUIPDSCM UDO_T_EQUIPDSCM%rowtype; -- Запись класса оборудования выборки данных, родительской для модели + REXSSERVICEFN_SEND_RQ EXSSERVICEFN%rowtype; -- Запись функции обмена для обучения модели + REXSSERVICE_SEND_RQ EXSSERVICE%rowtype; -- Запись сервиса обмена для обучения модели + REXSSERVICEFN_FRCST_MD EXSSERVICEFN%rowtype; -- Запись функции обмена для публикации сведений о наработке единицы оборудования при получении прогноза + REXSSERVICE_FRCST_MD EXSSERVICE%rowtype; -- Запись сервиса обмена для публикации сведений о наработке единицы оборудования при получении прогноза + NAPI_ROOT_INDEX PKG_STD.TNUMBER; -- Символ вхождения корня API в адрес сервера внешней системы + NCNT PKG_STD.TNUMBER; -- Буфер для количества файлов данных begin + /* Определим адрес сервера приложений */ + SDATASET_URL := GET_OPTIONS_STR(SCODE => 'EXSService_AppServer'); + if (SDATASET_URL is null) then + P_EXCEPTION(0, + 'В настройках Системы не задан параметр "Адрес сервера приложений (сервисы обмена)" (номер - 1929, код - "EXSService_AppServer").'); + end if; /* Проверим данные о наработках */ begin select count(T.RN) @@ -788,45 +824,81 @@ text="Проверка прав доступа при формировании when others then P_EXCEPTION(0, 'Не удалось проверить выборку данных для прогноза.'); end; - if (NCNT > 0) then + if (NCNT > 1) then P_EXCEPTION(0, 'Процедура формирования данных для прогноза вернула более одного набора сведений о наработках.'); end if; if (NCNT = 0) then P_EXCEPTION(0, 'Процедура формирования данных для прогноза не вернула сведений о наработках.'); - end if; - /* Читаем описание данных о наработках */ + end if; + /* Читаем описание данных о наработках */ for C in (select T.DATA CDATA from FILE_BUFFER T where T.IDENT = NDATASET_CONFIG_IDENT) loop if (CDATASET_CONFIG is not null) then P_EXCEPTION(0, 'Процедура формирования данных для прогноза вернула более одного описания сведений о наработках.'); - end if; + end if; CDATASET_CONFIG := C.CDATA; - end loop; + end loop; if (CDATASET_CONFIG is null) then P_EXCEPTION(0, 'Процедура формирования данных для прогноза не вернула описания сведений о наработках.'); end if; + /* Читаем запись модели */ + REQUIPDSCMML := UDO_PKG_EQUIPDS_BASE.CMML_GET(NFLAG_SMART => 0, NRN => NEQUIPDSCMML); + if (REQUIPDSCMML.STATUS <> UDO_PKG_EQUIPDS_BASE.NCMML_STATUS_PROCESSED) then + P_EXCEPTION(0, + 'Модель (регистрационный номер %s) находится в состоянии отличном от "Обучена".', + TO_CHAR(REQUIPDSCMML.RN)); + end if; + /* Читаем запись её родительского класса оборудования */ + REQUIPDSCM := UDO_PKG_EQUIPDS_BASE.CM_GET(NFLAG_SMART => 0, NRN => REQUIPDSCMML.PRN); + /* Читаем функию и сервис обмена, применяемые для обучения модели */ + REXSSERVICEFN_SEND_RQ := GET_EXSSERVICEFN_ID(NFLAG_SMART => 0, NRN => REQUIPDSCM.EXSSERVICEFN_SEND_RQ); + REXSSERVICE_SEND_RQ := GET_EXSSERVICE_ID(NFLAG_SMART => 0, NRN => REXSSERVICEFN_SEND_RQ.PRN); /* Формируем URL для запроса */ - SURL := 'https://parus.cadred.ru/API/forecast/metadata'; + NAPI_ROOT_INDEX := INSTR(REXSSERVICE_SEND_RQ.SRV_ROOT, SFW_API_ROOT); + if (NAPI_ROOT_INDEX = 0) then + P_EXCEPTION(0, + 'Неожиданный формат адреса внешней системы "%s" - не удалось определить корень API ("%s").', + REXSSERVICE_SEND_RQ.SRV_ROOT, + SFW_API_ROOT); + end if; + SURL := SUBSTR(REXSSERVICE_SEND_RQ.SRV_ROOT, 1, NAPI_ROOT_INDEX - 1) || SFW_API_ROOT || SFW_API_FORECAST; /* Формируем токен для аутентификации */ - SAUTH_TOKEN := to_char(base64_encode(clob2blob('parus_remote:CreateNewAccount_787898'))); + SAUTH_TOKEN := TO_CHAR(BASE64_ENCODE(CLOB2BLOB(REXSSERVICE_SEND_RQ.SRV_USER || ':' || + BLOB2CLOB(BASE64_DECODE(REXSSERVICE_SEND_RQ.SRV_PASS))))); + /* Формируем идентификатор выборки данных для запроса (в данном случае - просто уникальный идентификатор выборки, ссылка на которую будет передана в "data_url" с запросом на прогноз) */ + SDATASET_ID := TO_CHAR(NDATASET_IDENT); + /* Читаем функию и сервис обмена, применяемые для публикации данных наработки модели */ + REXSSERVICEFN_FRCST_MD := GET_EXSSERVICEFN_ID(NFLAG_SMART => 0, NRN => REQUIPDSCM.EXSSERVICEFN_FRCST_MD); + REXSSERVICE_FRCST_MD := GET_EXSSERVICE_ID(NFLAG_SMART => 0, NRN => REXSSERVICEFN_FRCST_MD.PRN); + /* Формируем адрес для получения фреймворком данных о наработках (по ним будет строиться прогоз, их мы готовили предварительно, вызовом ПП) */ + if ((SUBSTR(SDATASET_URL, -1) <> '/') and (SUBSTR(REXSSERVICE_FRCST_MD.SRV_ROOT, 1, 1) <> '/')) then + SDATASET_URL := SDATASET_URL || '/'; + end if; + SDATASET_URL := SDATASET_URL || REXSSERVICE_FRCST_MD.SRV_ROOT; + if ((SUBSTR(SDATASET_URL, -1) <> '/') and (SUBSTR(REXSSERVICEFN_FRCST_MD.FN_URL, 1, 1) <> '/')) then + SDATASET_URL := SDATASET_URL || '/'; + end if; + SDATASET_URL := SDATASET_URL || REXSSERVICEFN_FRCST_MD.FN_URL || '?NDATASET_IDENT=' || TO_CHAR(NDATASET_IDENT); + /* Код класса оборудования для запроса */ + begin + select T.CODE into SCLASS_MACHINE from EQOBJKIND T where T.RN = REQUIPDSCM.EQOBJKIND; + exception + when NO_DATA_FOUND then + PKG_MSG.RECORD_NOT_FOUND(NFLAG_SMART => 0, NDOCUMENT => REQUIPDSCM.EQOBJKIND, SUNIT_TABLE => 'EQOBJKIND'); + end; + /* Задача для запроса */ + STASK := REQUIPDSCMML.TASK; + exception + when others then + /* Подчистим буферы */ + EQCONFIG_THOBJ_FORECAST_EPLGAT(NDATASET_IDENT => NDATASET_IDENT, NDATASET_CONFIG_IDENT => NDATASET_CONFIG_IDENT); + /* Пробросим ошибку */ + raise; end EQCONFIG_THOBJ_FORECAST_PRLG; - - /* Подчистка после исполнения запроса на формирование прогноза технического объекта */ - procedure EQCONFIG_THOBJ_FORECAST_EPLG - ( - NDATASET_IDENT in number, -- Идентификатор буфера данных - NDATASET_CONFIG_IDENT in number -- Идентификатор буфера описания данных - ) - is - begin - /* Очистим данные в файловом буфере */ - P_FILE_BUFFER_CLEAR(NIDENT => NDATASET_IDENT); - P_FILE_BUFFER_CLEAR(NIDENT => NDATASET_CONFIG_IDENT); - end EQCONFIG_THOBJ_FORECAST_EPLG; /* Формирование цвета прогноза для технического объекта */ function EQCONFIG_THOBJ_FORECAST_CLR diff --git a/db/UDO_P_EQCONFIG_DATASET_MAKE.prc b/db/UDO_P_EQCONFIG_DATASET_MAKE.prc index b8b1a8a..9f8cff9 100644 --- a/db/UDO_P_EQCONFIG_DATASET_MAKE.prc +++ b/db/UDO_P_EQCONFIG_DATASET_MAKE.prc @@ -9,11 +9,30 @@ create or replace procedure UDO_P_EQCONFIG_DATASET_MAKE ) is begin + /* НАЧАЛО: Временная заглушка с отладочными данными (удалить) */ + /* create table UDO_T_FILE_BUFFER as select * from FILE_BUFFER; */ + for C in (select T.* from UDO_T_FILE_BUFFER T) + loop + if (C.BDATA is null) then + NDATASET_CONFIG_IDENT := GEN_IDENT(); + P_FILE_BUFFER_INSERT(NIDENT => NDATASET_CONFIG_IDENT, + CFILENAME => C.FILENAME, + CDATA => C.DATA, + BLOBDATA => C.BDATA); + else + NDATASET_IDENT := GEN_IDENT(); + P_FILE_BUFFER_INSERT(NIDENT => NDATASET_IDENT, CFILENAME => C.FILENAME, CDATA => C.DATA, BLOBDATA => C.BDATA); + end if; + end loop; + return; + /* КОНЕЦ: Временная заглушка с отладочными данными (удалить) */ + /* Обратимся к еденице оборудования */ for C in (select T.COMPANY, T.RN from EQCONFIG T where T.RN = NEQCONFIG) loop + /* Соберём данные */ UDO_PKG_EQUIPDS_DATAPROCESS.DATASET_CONF_SET(NCOMPANY => C.COMPANY, NEQCONFIG => C.RN, DBEG => DBEG, diff --git a/panels/eqs_tech_cond_forecast/forecast_tab.js b/panels/eqs_tech_cond_forecast/forecast_tab.js index b26185b..a1fa103 100644 --- a/panels/eqs_tech_cond_forecast/forecast_tab.js +++ b/panels/eqs_tech_cond_forecast/forecast_tab.js @@ -33,7 +33,7 @@ import { useTechObjForecastHistList, needLoadLevel } from "./forecast_tab_hooks"; //Вспомогательные хуки -import { xml2JSON } from "../../core/utils"; //Вспомогательные функции +import { xml2JSON, object2Base64XML } from "../../core/utils"; //Вспомогательные функции //--------- //Константы @@ -87,10 +87,10 @@ const STYLES = { //Закладка прогнозирования const ForecastTab = ({ onGoToAdmin }) => { //Подключение к контексту взаимодействия с сервером - const { executeStored } = useContext(BackEndСtx); + const { executeStored, SERV_DATA_TYPE_CLOB } = useContext(BackEndСtx); //Подключение к контексту сообщений - const { InlineMsgInfo } = useContext(MessagingСtx); + const { InlineMsgInfo, showLoader, hideLoader, showMsgErr } = useContext(MessagingСtx); //Подключение к контексту приложения const { pOnlineShowUnit, pOnlineShowDictionary, pOnlineUserProcedure } = useContext(ApplicationСtx); @@ -172,26 +172,97 @@ const ForecastTab = ({ onGoToAdmin }) => { //При запросе прогноза по модели из карточки технического объекта const handleTechObjCardGetPrediction = async model => { - console.log(model); - const j = await xml2JSON({ - xmlDoc: `` - }); - console.log(j.data_config.item.map(itm => ({ col_name: itm.col_code, data_type: itm.data_type }))); - /*pOnlineUserProcedure({ + //Подготовим данные о наработках + pOnlineUserProcedure({ code: model.SUSERPROCS_FRCST_DATA, inputParameters: [{ name: "NEQCONFIG", value: techObj.id }], callBack: async res => { + //Данные подготовлены успешно if (res.success) { - const wrkData = await executeStored({ - stored: "UDO_PKG_EQUIPTCF.EQCONFIG_THOBJ_WRKDATA", - args: { NDATASET_CONFIG_IDENT: res.outParameters.NDATASET_CONFIG_IDENT, NDATASET_IDENT: res.outParameters.NDATASET_IDENT } + //Подготовим запрос к фреймворку прогнозирования + const forecastReqData = await executeStored({ + stored: "UDO_PKG_EQUIPTCF.EQCONFIG_THOBJ_FORECAST_PRLG", + args: { + NEQUIPDSCMML: model.NRN, + NDATASET_CONFIG_IDENT: res.outParameters.NDATASET_CONFIG_IDENT, + NDATASET_IDENT: res.outParameters.NDATASET_IDENT + }, + tagValueProcessor: (name, value) => (name === "VALUE" ? undefined : value) }); - console.log(wrkData); + forecastReqData.CDATASET_CONFIG = (await xml2JSON({ xmlDoc: forecastReqData.CDATASET_CONFIG })).data_config.item.map(itm => ({ + col_name: itm.col_code, + data_type: itm.data_type + })); + //Выполним запрос прогноза + try { + const body = { + dataset_ID: forecastReqData.SDATASET_ID, + data_config: forecastReqData.CDATASET_CONFIG, + data_url: forecastReqData.SDATASET_URL, + class_machine: forecastReqData.SCLASS_MACHINE, + task: forecastReqData.STASK, + precision: 100 + }; + //Выполняем запрос + showLoader("Прогнозирование..."); + const response = await fetch(forecastReqData.SURL, { + method: "POST", + body: JSON.stringify(body), + headers: { + Authorization: `Basic ${forecastReqData.SAUTH_TOKEN}`, + Accept: "*/*", + "Content-Type": "application/json", + "User-Agent": "Parus" + } + }); + //Обработаем результаты + if (response.status === 200) { + let responseJson; + try { + responseJson = await response.json(); + } catch (e) { + throw new Error("Неожиданный ответ системы прогнозирования: ответ неверного формата!"); + } + if (response) { + if (responseJson?.status && responseJson.status == "ERR") + throw new Error(`Ошибка формирования прогноза: ${responseJson.message}`); + if (responseJson?.forecast && Array.isArray(responseJson?.forecast)) { + await executeStored({ + stored: "UDO_PKG_EQUIPTCF.EQCONFIG_THOBJ_FORECAST_EPLG", + args: { + NDATASET_IDENT: res.outParameters.NDATASET_IDENT, + NDATASET_CONFIG_IDENT: res.outParameters.NDATASET_CONFIG_IDENT, + NEQCONFIG: techObj.id, + NEQUIPDSCMML: model.NRN, + CFORECAST: { + VALUE: object2Base64XML(responseJson, { arrayNodeName: "forecast" }), + SDATA_TYPE: SERV_DATA_TYPE_CLOB + } + }, + loader: false + }); + hideLoader(); + setRefresh(pv => ({ ...pv, techObjForecastHistList: pv.techObjForecastHistList + 1 })); + } else throw new Error("Неожиданный ответ системы прогнозирования: ответ не содержит данных прогноза!"); + } else throw new Error("Неожиданный ответ системы прогнозирования: ответ не содержит данных!"); + } else throw new Error(`Ошибка (${response.status}) при взаимодейтсвии с системой прогнозирования!`); + } catch (e) { + hideLoader(); + showMsgErr(e.message); + executeStored({ + stored: "UDO_PKG_EQUIPTCF.EQCONFIG_THOBJ_FORECAST_EPLG", + args: { + NDATASET_IDENT: res.outParameters.NDATASET_IDENT, + NDATASET_CONFIG_IDENT: res.outParameters.NDATASET_CONFIG_IDENT + }, + loader: false, + showErrorMessage: false, + throwError: false + }); + } } } - });*/ - //await executeStored({ stored: "UDO_PKG_EQUIPTCF.EQCONFIG_THOBJ_FORECAST", args: { NEQCONFIG: techObj.id, NEQUIPDSCMML: model.NRN } }); - //setRefresh(pv => ({ ...pv, techObjForecastHistList: pv.techObjForecastHistList + 1 })); + }); }; //При закрытии карточки технического объекта