create or replace package UDO_PKG_EQUIPTCF as /* Формирование дерева состава оборудования */ procedure EQCONFIG_HIER ( NEQPARENT in number, -- Рег. номер родительского узла состава оборудования COUT out clob -- Сериализованное XML-представление дерева ); /* Условия отбора технических объектов */ procedure EQCONFIG_THOBJ_LIST_COND; /* Формирование списка технических объектов для выбранного узла состава оборудования */ procedure EQCONFIG_THOBJ_LIST ( NEQPARENT in number, -- Рег. номер родительского узла состава оборудования NPAGE_NUMBER in number, -- Номер страницы (игнорируется при NPAGE_SIZE=0) NPAGE_SIZE in number, -- Количество записей на странице (0 - все) CFILTERS in clob, -- Фильтры CORDERS in clob, -- Сортировки NINCLUDE_DEF in number, -- Признак включения описания колонок таблицы в ответ COUT out clob -- Сериализованная таблица данных ); /* Получение даты следующего технического обслуживания технического объекта */ function EQCONFIG_THOBJ_GET_NXTEQTCHSRV ( NEQCONFIG in number, -- Рег. номер технического объекта NSTATE in number := null -- Состояние (null - любое) ) return date; -- Дата следующего технического обслуживания /* Выбор графиков технического обслуживания и ремонта технического объекта */ procedure EQCONFIG_THOBJ_SELECT_EQTCHSRV ( NEQTCHSRV in number := null, -- Рег. номер графика ТО и ремонтов (null - любой) NEQCONFIG in number := null, -- Рег. номер технического объекта (null - любой) NSTATE in number := null, -- Состояние (null - любое) NIDENT out number -- Идентификатор списка ); /* Получение даты следующего ремонта по ремонтной ведомости технического объекта */ function EQCONFIG_THOBJ_GET_NXTEQRPSHT ( NEQCONFIG in number, -- Рег. номер технического объекта NSTATE in number := null -- Состояние (null - любое) ) return date; -- Дата следующего ремонта по ведомости /* Выбор ремонтных ведомостей технического объекта */ procedure EQCONFIG_THOBJ_SELECT_EQRPSHT ( NEQRPSHEETS in number := null, -- Рег. номер ремонтной ведосочти (null - любой) NEQCONFIG in number := null, -- Рег. номер технического объекта (null - любой) NSTATE in number := null, -- Состояние (null - любое) NIDENT out number -- Идентификатор списка ); /* Формирование карточки технического объекта */ procedure EQCONFIG_THOBJ_CARD ( NEQCONFIG in number, -- Рег. номер технического объекта COUT out clob -- Сериализованная карточка ); /* Отправка запроса на формирование прогноза технического объекта */ procedure EQCONFIG_THOBJ_FORECAST ( NEQCONFIG in number, -- Рег. номер технического объекта NEQUIPDSCMML in number -- Рег. номер модели ); /* Формирование цвета прогноза для технического объекта */ function EQCONFIG_THOBJ_FORECAST_CLR ( NMODE in number := 0, -- Режим работы (0 - для подсказки в колонке таблицы, 1 - для колонки таблицы, 2 - для карточки детализации NVALUE in number :=0 -- Значение для подсветки ) return varchar2; -- Запрошенное значение в зависимости от режима /* Формирование детальной карточки прогноза для технического объекта */ procedure EQCONFIG_THOBJ_FORECAST_CRD ( NEQCONFIG in number, -- Рег. номер позиции состава оборудования DFORECAST_DATE in date, -- Дата получения прогноза NFORECAST in number, -- Прогнозное значение, полученное от фреймворка SDICMUNTS in varchar2, -- Единица измерения выборки STASK in varchar2, -- Задача (см. константы UDO_PKG_EQUIPDS_BASE.CMML_TASK_*) COUT out clob -- Данные детальной карточки прогноза ); /* Извлечение сведений из детальной карточки прогноза для технического объекта */ procedure EQCONFIG_THOBJ_FORECAST_CRDP ( CFORECAST in clob, -- Данные детальной карточки прогноза SFORECAST_DESC out varchar2, -- Описание прогноза SFORECAST_DESC_COLOR out varchar2 -- Цвет заливки прогноза ); /* Вероятность выхода единицы оборудования из строя с учётом графика ТО и ремонтов и RUL-прогноза */ function EQCONFIG_THOBJ_TCHSRV_BRKDPROB ( NEQCONFIG in number -- Рег. номер технического объекта ) return number; -- Вероятность выхода из строя /* Модификация графика ТО и ремонтов для технического объекта */ procedure EQCONFIG_THOBJ_CHNG_EQTCHSRV ( NEQCONFIG in number, -- Рег. номер технического объекта NEQTCHSRV in number, -- Рег. номер графика ТО и ремонтов DPLANDATE_FROM in date -- Уточнённая плановая дата начала ремонта ); /* Формирование ремонтной ведомости для технического объекта */ procedure EQCONFIG_THOBJ_MAKE_EQRPSHEET ( NEQCONFIG in number, -- Рег. номер технического объекта SACATALOG in varchar2, -- Каталог размещения ведомости SEQTECSRVKIND in varchar2, -- Вид ремонта DPLANDATE_FROM in date, -- Плановая дата начала ремонта NIDENT out number -- Идентификатор списка сформированных ведомостей ); end UDO_PKG_EQUIPTCF; / create or replace package body UDO_PKG_EQUIPTCF as /* TODO: owner="root" created="02.08.2024" text="Проверка прав доступа при формировании таблицы и карточки ТО" */ /* Формирование ветки дерева состава оборудования */ function EQCONFIG_HIER_NODE ( NCUR in integer, -- Курсор документа для результата NCOMPANY in number, -- Рег. номер организации NEQPARENT in number -- Рег. номер родительского узла состава оборудования ) return PKG_XMAKE.TNODE -- XML-описание веток дерева is XLEAF PKG_XMAKE.TNODE; -- Текущий лист XCHILD PKG_XMAKE.TNODE; -- Дочерние листы текущего XRES PKG_XMAKE.TNODE; -- Буфер для результата begin /* Обходим состав оборудования с заданного корня */ for C in (select M.RN NRN, M.EQPARENT NHRN, DECODE(M.FICT_REC, 0, M.NAME, DECODE(OL.RN, null, M.NAME, OL.NAME)) SNAME, case when exists (select null from EQCONFIG C where C.EQPARENT = M.RN and exists (select null from V_USERPRIV_HIER_SINGL UP where UP.HIERARCHY = C.RN)) then 1 else 0 end NHASCHILDREN, M.OBJ_KIND NOBJ_KIND from EQCONFIG M, EQOBJLEVEL OL where M.PR_OBJ_LEVEL = OL.RN(+) and ((M.FICT_REC = 0) or ((M.FICT_REC = 1) and (CMP_VC2(M.NAME, F_EQCONFIG_EXTRANAME(0)) = 1))) and exists (select null from V_USERPRIV_HIER_SINGL UP where UP.HIERARCHY = M.RN) and COALESCE(M.EQPARENT, 0) = NEQPARENT and M.COMPANY = NCOMPANY order by 3) loop /* Если есть дочерние ветки */ if (C.NHASCHILDREN = 1) then /* Добавим фиктивную дочернюю запись для индикации наличия дочерних на клиенте */ XCHILD := PKG_XMAKE.ELEMENT(ICURSOR => NCUR, SNAME => 'children', RATTRIBUTES => PKG_XMAKE.ATTRIBUTES(ICURSOR => NCUR, RATTRIBUTE00 => PKG_XMAKE.ATTRIBUTE(ICURSOR => NCUR, SNAME => 'id', SVALUE => C.NRN || '_loader'), RATTRIBUTE01 => PKG_XMAKE.ATTRIBUTE(ICURSOR => NCUR, SNAME => 'label', SVALUE => 'Минуточку...'))); /* Соберём лист */ XLEAF := PKG_XMAKE.ELEMENT(ICURSOR => NCUR, SNAME => 'children', RATTRIBUTES => PKG_XMAKE.ATTRIBUTES(ICURSOR => NCUR, RATTRIBUTE00 => PKG_XMAKE.ATTRIBUTE(ICURSOR => NCUR, SNAME => 'id', SVALUE => C.NRN), RATTRIBUTE01 => PKG_XMAKE.ATTRIBUTE(ICURSOR => NCUR, SNAME => 'label', SVALUE => C.SNAME)), RNODE00 => XCHILD); /* Соберём листы в ветку */ XRES := PKG_XMAKE.CONCAT(ICURSOR => NCUR, RNODE00 => XRES, RNODE01 => XLEAF); end if; end loop; /* Вернём собранное */ return XRES; end EQCONFIG_HIER_NODE; /* Формирование дерева состава оборудования */ procedure EQCONFIG_HIER ( NEQPARENT in number, -- Рег. номер родительского узла состава оборудования COUT out clob -- Сериализованное XML-представление дерева ) is NCOMPANY PKG_STD.TREF := GET_SESSION_COMPANY(); -- Рег. номер организации NCUR integer; -- Курсор документа для результата XDOC PKG_XMAKE.TNODE; -- Документ для результата begin /* Открываем документ */ NCUR := PKG_XMAKE.OPEN_CURSOR(); /* Формируем XML-представление ветки для запрошенного родителя */ XDOC := PKG_XMAKE.ELEMENT(ICURSOR => NCUR, SNAME => 'XDATA', RNODE00 => EQCONFIG_HIER_NODE(NCUR => NCUR, NCOMPANY => NCOMPANY, NEQPARENT => NEQPARENT)); /* Конвертируем в 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 EQCONFIG_HIER; /* Условия отбора технических объектов */ procedure EQCONFIG_THOBJ_LIST_COND is begin /* Установка главной таблицы */ PKG_COND_BROKER.SET_TABLE(STABLE_NAME => 'EQCONFIG'); /* Обозначение */ PKG_COND_BROKER.ADD_CONDITION_CODE(SCOLUMN_NAME => 'CODE', SCONDITION_NAME => 'SCODEFrom'); /* Наименование */ PKG_COND_BROKER.ADD_CONDITION_CODE(SCOLUMN_NAME => 'NAME', SCONDITION_NAME => 'SNAMEFrom'); /* Дата ввода в эксплуатацию */ PKG_COND_BROKER.ADD_CONDITION_BETWEEN(SCOLUMN_NAME => 'OPER_DATE', SCONDITION_NAME_FROM => 'DOPER_DATEFrom', SCONDITION_NAME_TO => 'DOPER_DATETo'); /* Состояние */ PKG_COND_BROKER.ADD_CONDITION_CODE(SCOLUMN_NAME => 'CODE', SCONDITION_NAME => 'SUSE_KINDFrom', SJOINS => 'HLSTATETYPES <- RN;HLSTATETYPES'); /* Класс */ PKG_COND_BROKER.ADD_CONDITION_CODE(SCOLUMN_NAME => 'NAME', SCONDITION_NAME => 'SOBJ_KINDFrom', SJOINS => 'OBJ_KIND <- RN;EQOBJKIND'); /* Действия с моделями прогнозирования */ if (PKG_COND_BROKER.CONDITION_EXISTS(SCONDITION_NAME => 'NCMML_STATUSFrom') = 1) then PKG_COND_BROKER.ADD_CLAUSE(SCLAUSE => PKG_SQL_BUILD.PKG_NAME(SNAME => 'UDO_PKG_EQUIPDS.CMML_STATUS_BY_EQCONFIG') || '(RN) = :NCMML_STATUS'); PKG_COND_BROKER.BIND_VARIABLE(SVARIABLE_NAME => 'NCMML_STATUS', SVALUE => PKG_COND_BROKER.GET_CONDITION_NUM(SCONDITION_NAME => 'NCMML_STATUSFrom')); end if; /* Вероятность выхода из строя */ if ((PKG_COND_BROKER.CONDITION_EXISTS(SCONDITION_NAME => 'NBREAKDOWN_PROBFrom') = 1) and (PKG_COND_BROKER.CONDITION_EXISTS(SCONDITION_NAME => 'NBREAKDOWN_PROBTo') = 0)) then PKG_COND_BROKER.ADD_CLAUSE(SCLAUSE => PKG_SQL_BUILD.PKG_NAME(SNAME => 'UDO_PKG_EQUIPTCF.EQCONFIG_THOBJ_TCHSRV_BRKDPROB') || '(RN) >= :NBREAKDOWN_PROBFrom'); PKG_COND_BROKER.BIND_VARIABLE(SVARIABLE_NAME => 'NBREAKDOWN_PROBFrom', NVALUE => PKG_COND_BROKER.GET_CONDITION_NUM(SCONDITION_NAME => 'NBREAKDOWN_PROBFrom')); end if; if ((PKG_COND_BROKER.CONDITION_EXISTS(SCONDITION_NAME => 'NBREAKDOWN_PROBTo') = 1) and (PKG_COND_BROKER.CONDITION_EXISTS(SCONDITION_NAME => 'NBREAKDOWN_PROBFrom') = 0)) then PKG_COND_BROKER.ADD_CLAUSE(SCLAUSE => PKG_SQL_BUILD.PKG_NAME(SNAME => 'UDO_PKG_EQUIPTCF.EQCONFIG_THOBJ_TCHSRV_BRKDPROB') || '(RN) <= :NBREAKDOWN_PROBTo'); PKG_COND_BROKER.BIND_VARIABLE(SVARIABLE_NAME => 'NBREAKDOWN_PROBTo', NVALUE => PKG_COND_BROKER.GET_CONDITION_NUM(SCONDITION_NAME => 'NBREAKDOWN_PROBTo')); end if; if ((PKG_COND_BROKER.CONDITION_EXISTS(SCONDITION_NAME => 'NBREAKDOWN_PROBFrom') = 1) and (PKG_COND_BROKER.CONDITION_EXISTS(SCONDITION_NAME => 'NBREAKDOWN_PROBTo') = 1)) then PKG_COND_BROKER.ADD_CLAUSE(SCLAUSE => PKG_SQL_BUILD.PKG_NAME(SNAME => 'UDO_PKG_EQUIPTCF.EQCONFIG_THOBJ_TCHSRV_BRKDPROB') || '(RN) between :NBREAKDOWN_PROBFrom and :NBREAKDOWN_PROBTo'); PKG_COND_BROKER.BIND_VARIABLE(SVARIABLE_NAME => 'NBREAKDOWN_PROBFrom', NVALUE => PKG_COND_BROKER.GET_CONDITION_NUM(SCONDITION_NAME => 'NBREAKDOWN_PROBFrom')); PKG_COND_BROKER.BIND_VARIABLE(SVARIABLE_NAME => 'NBREAKDOWN_PROBTo', NVALUE => PKG_COND_BROKER.GET_CONDITION_NUM(SCONDITION_NAME => 'NBREAKDOWN_PROBTo')); end if; end EQCONFIG_THOBJ_LIST_COND; /* Формирование списка технических объектов для выбранного узла состава оборудования */ procedure EQCONFIG_THOBJ_LIST ( NEQPARENT in number, -- Рег. номер родительского узла состава оборудования NPAGE_NUMBER in number, -- Номер страницы (игнорируется при NPAGE_SIZE=0) NPAGE_SIZE in number, -- Количество записей на странице (0 - все) CFILTERS in clob, -- Фильтры CORDERS in clob, -- Сортировки NINCLUDE_DEF in number, -- Признак включения описания колонок таблицы в ответ COUT out clob -- Сериализованная таблица данных ) is NCOMPANY PKG_STD.TREF := GET_SESSION_COMPANY(); -- Организация сеанса NIDENT PKG_STD.TREF := GEN_IDENT(); -- Идентификатор отбора RF PKG_P8PANELS_VISUAL.TFILTERS; -- Фильтры RO PKG_P8PANELS_VISUAL.TORDERS; -- Сортировки RDG PKG_P8PANELS_VISUAL.TDATA_GRID; -- Описание таблицы RDG_ROW PKG_P8PANELS_VISUAL.TROW; -- Строка таблицы RCOL_VALS PKG_P8PANELS_VISUAL.TCOL_VALS; -- Предопределённые значения столбцов NROW_FROM PKG_STD.TREF; -- Номер строки с NROW_TO PKG_STD.TREF; -- Номер строки по CSQL clob; -- Буфер для запроса ICURSOR integer; -- Курсор для исполнения запроса NBREAKDOWN_PROB PKG_STD.TNUMBER; -- Вероятность выхода единицы оборудования из строя begin /* Читаем фильтры */ RF := PKG_P8PANELS_VISUAL.TFILTERS_FROM_XML(CFILTERS => CFILTERS); /* Читаем сортировки */ RO := PKG_P8PANELS_VISUAL.TORDERS_FROM_XML(CORDERS => CORDERS); /* Преобразуем номер и размер страницы в номер строк с и по */ PKG_P8PANELS_VISUAL.UTL_ROWS_LIMITS_CALC(NPAGE_NUMBER => NPAGE_NUMBER, NPAGE_SIZE => NPAGE_SIZE, NROW_FROM => NROW_FROM, NROW_TO => NROW_TO); /* Инициализируем таблицу данных */ RDG := PKG_P8PANELS_VISUAL.TDATA_GRID_MAKE(); /* Добавляем в таблицу описание колонок */ PKG_P8PANELS_VISUAL.TDATA_GRID_ADD_COL_DEF(RDATA_GRID => RDG, SNAME => 'NRN', SCAPTION => 'Рег. номер', SDATA_TYPE => PKG_P8PANELS_VISUAL.SDATA_TYPE_NUMB, BVISIBLE => false); PKG_P8PANELS_VISUAL.TDATA_GRID_ADD_COL_DEF(RDATA_GRID => RDG, SNAME => 'SCODE', SCAPTION => 'Обозначение', SDATA_TYPE => PKG_P8PANELS_VISUAL.SDATA_TYPE_STR, BORDER => true, BFILTER => true); PKG_P8PANELS_VISUAL.TDATA_GRID_ADD_COL_DEF(RDATA_GRID => RDG, SNAME => 'SNAME', SCAPTION => 'Наименование', SDATA_TYPE => PKG_P8PANELS_VISUAL.SDATA_TYPE_STR, BORDER => true, BFILTER => true); PKG_P8PANELS_VISUAL.TDATA_GRID_ADD_COL_DEF(RDATA_GRID => RDG, SNAME => 'DOPER_DATE', SCAPTION => 'Дата ввода в эксплуатацию', SDATA_TYPE => PKG_P8PANELS_VISUAL.SDATA_TYPE_DATE, BORDER => true, BFILTER => true); PKG_P8PANELS_VISUAL.TDATA_GRID_ADD_COL_DEF(RDATA_GRID => RDG, SNAME => 'SUSE_KIND', SCAPTION => 'Состояние', SDATA_TYPE => PKG_P8PANELS_VISUAL.SDATA_TYPE_STR, BORDER => true, BFILTER => true); PKG_P8PANELS_VISUAL.TDATA_GRID_ADD_COL_DEF(RDATA_GRID => RDG, SNAME => 'NOBJ_KIND', SCAPTION => 'Рег. номер класса технического объекта', SDATA_TYPE => PKG_P8PANELS_VISUAL.SDATA_TYPE_NUMB, BVISIBLE => false); PKG_P8PANELS_VISUAL.TDATA_GRID_ADD_COL_DEF(RDATA_GRID => RDG, SNAME => 'SOBJ_KIND', SCAPTION => 'Класс', SDATA_TYPE => PKG_P8PANELS_VISUAL.SDATA_TYPE_STR, BORDER => true, BFILTER => true); PKG_P8PANELS_VISUAL.TDATA_GRID_ADD_COL_DEF(RDATA_GRID => RDG, SNAME => 'SOBJ_KIND_FULL_CODE', SCAPTION => 'Класс (полный иерархический код)', SDATA_TYPE => PKG_P8PANELS_VISUAL.SDATA_TYPE_STR, BVISIBLE => false); PKG_P8PANELS_VISUAL.TDATA_GRID_ADD_COL_DEF(RDATA_GRID => RDG, SNAME => 'SUMEAS_RES', SCAPTION => 'Единица измерения ресурса', SDATA_TYPE => PKG_P8PANELS_VISUAL.SDATA_TYPE_STR, BVISIBLE => false); PKG_P8PANELS_VISUAL.TCOL_VALS_ADD(RCOL_VALS => RCOL_VALS, NVALUE => 0, BCLEAR => true); PKG_P8PANELS_VISUAL.TCOL_VALS_ADD(RCOL_VALS => RCOL_VALS, NVALUE => 1); PKG_P8PANELS_VISUAL.TCOL_VALS_ADD(RCOL_VALS => RCOL_VALS, NVALUE => 2); PKG_P8PANELS_VISUAL.TDATA_GRID_ADD_COL_DEF(RDATA_GRID => RDG, SNAME => 'NCMML_STATUS', SCAPTION => 'Модель', SDATA_TYPE => PKG_P8PANELS_VISUAL.SDATA_TYPE_NUMB, BORDER => true, BFILTER => true, RCOL_VALS => RCOL_VALS); PKG_P8PANELS_VISUAL.TDATA_GRID_ADD_COL_DEF(RDATA_GRID => RDG, SNAME => 'NBREAKDOWN_PROB', SCAPTION => 'Вероятность выхода из строя', SDATA_TYPE => PKG_P8PANELS_VISUAL.SDATA_TYPE_NUMB, BORDER => true, BFILTER => true, SHINT => EQCONFIG_THOBJ_FORECAST_CLR(NMODE => 0)); PKG_P8PANELS_VISUAL.TDATA_GRID_ADD_COL_DEF(RDATA_GRID => RDG, SNAME => 'SBREAKDOWN_PROB_COLOR', SCAPTION => 'Цвет вероятности выхода из строя', SDATA_TYPE => PKG_P8PANELS_VISUAL.SDATA_TYPE_STR, BVISIBLE => false); /* Обходим данные */ begin /* Добавляем подсказку совместимости */ CSQL := PKG_SQL_BUILD.COMPATIBLE(SSQL => CSQL); /* Формируем запрос */ PKG_SQL_BUILD.APPEND(SSQL => CSQL, SELEMENT1 => 'select *'); PKG_SQL_BUILD.APPEND(SSQL => CSQL, SELEMENT1 => ' from (select D.*,'); PKG_SQL_BUILD.APPEND(SSQL => CSQL, SELEMENT1 => PKG_SQL_BUILD.SQLROWNUM() || ' NROW'); PKG_SQL_BUILD.APPEND(SSQL => CSQL, SELEMENT1 => ' from (select C.RN NRN,'); PKG_SQL_BUILD.APPEND(SSQL => CSQL, SELEMENT1 => ' C.CODE SCODE,'); PKG_SQL_BUILD.APPEND(SSQL => CSQL, SELEMENT1 => ' C."NAME" SNAME,'); PKG_SQL_BUILD.APPEND(SSQL => CSQL, SELEMENT1 => ' C.OPER_DATE DOPER_DATE,'); PKG_SQL_BUILD.APPEND(SSQL => CSQL, SELEMENT1 => ' ST.CODE SUSE_KIND,'); PKG_SQL_BUILD.APPEND(SSQL => CSQL, SELEMENT1 => ' C.OBJ_KIND NOBJ_KIND,'); PKG_SQL_BUILD.APPEND(SSQL => CSQL, SELEMENT1 => ' OK.NAME SOBJ_KIND,'); PKG_SQL_BUILD.APPEND(SSQL => CSQL, SELEMENT1 => ' FORMAT_HIER_NAME(OK.COMPANY, null, OK.FULLCODE) SOBJ_KIND_FULL_CODE,'); PKG_SQL_BUILD.APPEND(SSQL => CSQL, SELEMENT1 => ' DM.MEAS_MNEMO SUMEAS_RES,'); PKG_SQL_BUILD.APPEND(SSQL => CSQL, SELEMENT1 => PKG_SQL_BUILD.PKG_NAME(SNAME => 'UDO_PKG_EQUIPDS.CMML_STATUS_BY_EQCONFIG') || '(C.RN) NCMML_STATUS,'); PKG_SQL_BUILD.APPEND(SSQL => CSQL, SELEMENT1 => PKG_SQL_BUILD.PKG_NAME(SNAME => 'UDO_PKG_EQUIPTCF.EQCONFIG_THOBJ_TCHSRV_BRKDPROB') || '(C.RN) NBREAKDOWN_PROB'); PKG_SQL_BUILD.APPEND(SSQL => CSQL, SELEMENT1 => ' from EQCONFIG C'); PKG_SQL_BUILD.APPEND(SSQL => CSQL, SELEMENT1 => ' left outer join HLSTATETYPES ST on C.HLSTATETYPES = ST.RN'); PKG_SQL_BUILD.APPEND(SSQL => CSQL, SELEMENT1 => ' left outer join DICMUNTS DM on C.UMEAS_RES = DM.RN,'); PKG_SQL_BUILD.APPEND(SSQL => CSQL, SELEMENT1 => ' EQOBJKIND OK'); PKG_SQL_BUILD.APPEND(SSQL => CSQL, SELEMENT1 => ' where C.EQPARENT = :NEQPARENT'); PKG_SQL_BUILD.APPEND(SSQL => CSQL, SELEMENT1 => ' and C.OBJ_KIND = OK.RN'); PKG_SQL_BUILD.APPEND(SSQL => CSQL, SELEMENT1 => ' and C.RN in (select ID from COND_BROKER_IDSMART where IDENT = :NIDENT) %ORDER_BY%) D) F'); PKG_SQL_BUILD.APPEND(SSQL => CSQL, SELEMENT1 => ' where F.NROW between :NROW_FROM and :NROW_TO'); /* Учтём сортировки */ PKG_P8PANELS_VISUAL.TORDERS_SET_QUERY(RDATA_GRID => RDG, RORDERS => RO, SPATTERN => '%ORDER_BY%', CSQL => CSQL); /* Учтём фильтры */ PKG_P8PANELS_VISUAL.TFILTERS_SET_QUERY(NIDENT => NIDENT, NCOMPANY => NCOMPANY, SUNIT => 'EquipConfiguration', SPROCEDURE => PKG_SQL_BUILD.PKG_NAME(SNAME => 'UDO_PKG_EQUIPTCF.EQCONFIG_THOBJ_LIST_COND'), RDATA_GRID => RDG, RFILTERS => RF); /* Разбираем его */ ICURSOR := PKG_SQL_DML.OPEN_CURSOR(SWHAT => 'SELECT'); PKG_SQL_DML.PARSE(ICURSOR => ICURSOR, SQUERY => CSQL); /* Делаем подстановку параметров */ PKG_SQL_DML.BIND_VARIABLE_NUM(ICURSOR => ICURSOR, SNAME => 'NEQPARENT', NVALUE => NEQPARENT); PKG_SQL_DML.BIND_VARIABLE_NUM(ICURSOR => ICURSOR, SNAME => 'NIDENT', NVALUE => NIDENT); PKG_SQL_DML.BIND_VARIABLE_NUM(ICURSOR => ICURSOR, SNAME => 'NROW_FROM', NVALUE => NROW_FROM); PKG_SQL_DML.BIND_VARIABLE_NUM(ICURSOR => ICURSOR, SNAME => 'NROW_TO', NVALUE => NROW_TO); /* Описываем структуру записи курсора */ PKG_SQL_DML.DEFINE_COLUMN_NUM(ICURSOR => ICURSOR, IPOSITION => 1); PKG_SQL_DML.DEFINE_COLUMN_STR(ICURSOR => ICURSOR, IPOSITION => 2); PKG_SQL_DML.DEFINE_COLUMN_STR(ICURSOR => ICURSOR, IPOSITION => 3); PKG_SQL_DML.DEFINE_COLUMN_DATE(ICURSOR => ICURSOR, IPOSITION => 4); PKG_SQL_DML.DEFINE_COLUMN_STR(ICURSOR => ICURSOR, IPOSITION => 5); PKG_SQL_DML.DEFINE_COLUMN_NUM(ICURSOR => ICURSOR, IPOSITION => 6); PKG_SQL_DML.DEFINE_COLUMN_STR(ICURSOR => ICURSOR, IPOSITION => 7); PKG_SQL_DML.DEFINE_COLUMN_STR(ICURSOR => ICURSOR, IPOSITION => 8); PKG_SQL_DML.DEFINE_COLUMN_STR(ICURSOR => ICURSOR, IPOSITION => 9); PKG_SQL_DML.DEFINE_COLUMN_NUM(ICURSOR => ICURSOR, IPOSITION => 10); PKG_SQL_DML.DEFINE_COLUMN_NUM(ICURSOR => ICURSOR, IPOSITION => 11); PKG_SQL_DML.DEFINE_COLUMN_NUM(ICURSOR => ICURSOR, IPOSITION => 12); /* Делаем выборку */ if (PKG_SQL_DML.EXECUTE(ICURSOR => ICURSOR) = 0) then null; end if; /* Обходим выбранные записи */ while (PKG_SQL_DML.FETCH_ROWS(ICURSOR => ICURSOR) > 0) loop /* Добавляем колонки с данными */ PKG_P8PANELS_VISUAL.TROW_ADD_CUR_COLN(RROW => RDG_ROW, SNAME => 'NRN', ICURSOR => ICURSOR, NPOSITION => 1, BCLEAR => true); PKG_P8PANELS_VISUAL.TROW_ADD_CUR_COLS(RROW => RDG_ROW, SNAME => 'SCODE', ICURSOR => ICURSOR, NPOSITION => 2); PKG_P8PANELS_VISUAL.TROW_ADD_CUR_COLS(RROW => RDG_ROW, SNAME => 'SNAME', ICURSOR => ICURSOR, NPOSITION => 3); PKG_P8PANELS_VISUAL.TROW_ADD_CUR_COLD(RROW => RDG_ROW, SNAME => 'DOPER_DATE', ICURSOR => ICURSOR, NPOSITION => 4); PKG_P8PANELS_VISUAL.TROW_ADD_CUR_COLS(RROW => RDG_ROW, SNAME => 'SUSE_KIND', ICURSOR => ICURSOR, NPOSITION => 5); PKG_P8PANELS_VISUAL.TROW_ADD_CUR_COLN(RROW => RDG_ROW, SNAME => 'NOBJ_KIND', ICURSOR => ICURSOR, NPOSITION => 6); PKG_P8PANELS_VISUAL.TROW_ADD_CUR_COLS(RROW => RDG_ROW, SNAME => 'SOBJ_KIND', ICURSOR => ICURSOR, NPOSITION => 7); PKG_P8PANELS_VISUAL.TROW_ADD_CUR_COLS(RROW => RDG_ROW, SNAME => 'SOBJ_KIND_FULL_CODE', ICURSOR => ICURSOR, NPOSITION => 8); PKG_P8PANELS_VISUAL.TROW_ADD_CUR_COLS(RROW => RDG_ROW, SNAME => 'SUMEAS_RES', ICURSOR => ICURSOR, NPOSITION => 9); PKG_P8PANELS_VISUAL.TROW_ADD_CUR_COLN(RROW => RDG_ROW, SNAME => 'NCMML_STATUS', ICURSOR => ICURSOR, NPOSITION => 10); PKG_SQL_DML.COLUMN_VALUE_NUM(ICURSOR => ICURSOR, IPOSITION => 11, NVALUE => NBREAKDOWN_PROB); PKG_P8PANELS_VISUAL.TROW_ADD_COL(RROW => RDG_ROW, SNAME => 'NBREAKDOWN_PROB', NVALUE => NBREAKDOWN_PROB); PKG_P8PANELS_VISUAL.TROW_ADD_COL(RROW => RDG_ROW, SNAME => 'SBREAKDOWN_PROB_COLOR', SVALUE => EQCONFIG_THOBJ_FORECAST_CLR(NMODE => 1, NVALUE => NBREAKDOWN_PROB)); /* Добавляем строку в таблицу */ PKG_P8PANELS_VISUAL.TDATA_GRID_ADD_ROW(RDATA_GRID => RDG, RROW => RDG_ROW); end loop; /* Освобождаем курсор */ PKG_SQL_DML.CLOSE_CURSOR(ICURSOR => ICURSOR); exception when others then PKG_SQL_DML.CLOSE_CURSOR(ICURSOR => ICURSOR); raise; end; /* Сериализуем описание */ COUT := PKG_P8PANELS_VISUAL.TDATA_GRID_TO_XML(RDATA_GRID => RDG, NINCLUDE_DEF => NINCLUDE_DEF); end EQCONFIG_THOBJ_LIST; /* Получение даты следующего технического обслуживания технического объекта */ function EQCONFIG_THOBJ_GET_NXTEQTCHSRV ( NEQCONFIG in number, -- Рег. номер технического объекта NSTATE in number := null -- Состояние (null - любое) ) return date -- Дата следующего технического обслуживания is DRES PKG_STD.TLDATE; -- Буфер для результата begin /* Найдем график ТО и ремонтов, в заданном состоянии, с минимальной датой по данному тех. объекту */ select min(T.DATEPRD_BEG) into DRES from EQTCHSRV T where T.EQCONFIG_TECH = NEQCONFIG and ((NSTATE is null) or ((NSTATE is not null) and (T.STATE = NSTATE))) and T.DATEPRD_BEG >= sysdate; /* Вернём результат */ return DRES; exception when others then return null; end EQCONFIG_THOBJ_GET_NXTEQTCHSRV; /* Выбор графиков технического обслуживания и ремонта технического объекта */ procedure EQCONFIG_THOBJ_SELECT_EQTCHSRV ( NEQTCHSRV in number := null, -- Рег. номер графика ТО и ремонтов (null - любой) NEQCONFIG in number := null, -- Рег. номер технического объекта (null - любой) NSTATE in number := null, -- Состояние (null - любое) NIDENT out number -- Идентификатор списка ) is NTMP PKG_STD.TREF; -- Рег. номер записи буфера отобранных begin /* Обходим графики по тех. объекту */ for C in (select T.RN from EQTCHSRV T where ((NEQTCHSRV is null) or ((NEQTCHSRV is not null) and (T.RN = NEQTCHSRV))) and ((NEQCONFIG is null) or ((NEQCONFIG is not null) and (T.EQCONFIG_TECH = NEQCONFIG))) and ((NEQTCHSRV is not null) or ((NEQTCHSRV is null) and (T.DATEPRD_BEG >= sysdate))) and ((NSTATE is null) or ((NSTATE is not null) and (T.STATE = NSTATE)))) loop /* Формируем идентификатор списка если необходимо */ if (NIDENT is null) then NIDENT := GEN_IDENT(); end if; /* Добавляем отобранное в список */ P_SELECTLIST_INSERT(NIDENT => NIDENT, NDOCUMENT => C.RN, SUNITCODE => 'EquipTechServices', NRN => NTMP); end loop; end EQCONFIG_THOBJ_SELECT_EQTCHSRV; /* Получение даты следующего ремонта по ремонтной ведомости технического объекта */ function EQCONFIG_THOBJ_GET_NXTEQRPSHT ( NEQCONFIG in number, -- Рег. номер технического объекта NSTATE in number := null -- Состояние (null - любое) ) return date -- Дата следующего ремонта по ведомости is DRES PKG_STD.TLDATE; -- Буфер для результата begin /* Найдем график ТО и ремонтов, в заданном состоянии, с минимальной датой по данному тех. объекту */ select min(T.DATEPLAN_BEG) into DRES from EQRPSHEETS T where T.EQCONFIG = NEQCONFIG and ((NSTATE is null) or ((NSTATE is not null) and (T.STATE = NSTATE))) and T.DATEPLAN_BEG >= sysdate; /* Вернём результат */ return DRES; exception when others then return null; end EQCONFIG_THOBJ_GET_NXTEQRPSHT; /* Выбор ремонтных ведомостей технического объекта */ procedure EQCONFIG_THOBJ_SELECT_EQRPSHT ( NEQRPSHEETS in number := null, -- Рег. номер ремонтной ведосочти (null - любой) NEQCONFIG in number := null, -- Рег. номер технического объекта (null - любой) NSTATE in number := null, -- Состояние (null - любое) NIDENT out number -- Идентификатор списка ) is NTMP PKG_STD.TREF; -- Рег. номер записи буфера отобранных begin /* Обходим графики по тех. объекту */ for C in (select T.RN from EQRPSHEETS T where ((NEQRPSHEETS is null) or ((NEQRPSHEETS is not null) and (T.RN = NEQRPSHEETS))) and ((NEQCONFIG is null) or ((NEQCONFIG is not null) and (T.EQCONFIG = NEQCONFIG))) and ((NEQRPSHEETS is not null) or ((NEQRPSHEETS is null) and (T.DATEPLAN_BEG >= sysdate))) and ((NSTATE is null) or ((NSTATE is not null) and (T.STATE = NSTATE)))) loop /* Формируем идентификатор списка если необходимо */ if (NIDENT is null) then NIDENT := GEN_IDENT(); end if; /* Добавляем отобранное в список */ P_SELECTLIST_INSERT(NIDENT => NIDENT, NDOCUMENT => C.RN, SUNITCODE => 'EquipRepairSheets', NRN => NTMP); end loop; end EQCONFIG_THOBJ_SELECT_EQRPSHT; /* Получение даты следующего ремонта по ремонтной ведомости или графику ТО и ремонтов (что раньше) технического объекта */ function EQCONFIG_THOBJ_GEN_NXTRPR ( NEQCONFIG in number -- Рег. номер технического объекта ) return date -- Дата ближайшего ремонта is DNXTEQTCHSRV PKG_STD.TLDATE; -- Дата ближайшего ТО или ремонта по графику DNXTEQRPSHT PKG_STD.TLDATE; -- Дата ближайшего ТО или ремонта по ремонтным ведомостям DRES PKG_STD.TLDATE; -- Буфер для результата begin /* Определим дату ближайшего ТО или ремонта */ DNXTEQTCHSRV := EQCONFIG_THOBJ_GET_NXTEQTCHSRV(NEQCONFIG => NEQCONFIG); /* Определим дату ближайшей ремонтной ведомости */ DNXTEQRPSHT := EQCONFIG_THOBJ_GET_NXTEQRPSHT(NEQCONFIG => NEQCONFIG); /* Берм меньшую */ if ((DNXTEQRPSHT is not null) and (DNXTEQTCHSRV is not null)) then if (DNXTEQRPSHT < DNXTEQTCHSRV) then DRES := DNXTEQRPSHT; else DRES := DNXTEQTCHSRV; end if; else DRES := COALESCE(DNXTEQTCHSRV, DNXTEQRPSHT); end if; /* Вернём результат */ return DRES; end EQCONFIG_THOBJ_GEN_NXTRPR; /* Формирование карточки технического объекта */ procedure EQCONFIG_THOBJ_CARD ( NEQCONFIG in number, -- Рег. номер технического объекта COUT out clob -- Сериализованная карточка ) is NCUR integer; -- Курсор документа для результата XDOC PKG_XMAKE.TNODE; -- Документ для результата XCARD PKG_XMAKE.TNODE; -- XML-карточка begin /* Открываем документ */ NCUR := PKG_XMAKE.OPEN_CURSOR(); /* Обратимся к данным технического объекта */ for C in (select T.RN NRN, T.CODE SCODE, T.NAME SNAME, T.OPER_DATE DOPER_DATE, OK.NAME SEQOBJKIND from EQCONFIG T, EQOBJKIND OK where T.RN = NEQCONFIG and T.OBJ_KIND = OK.RN) loop /* Соберем карточку */ XCARD := PKG_XMAKE.ELEMENT(ICURSOR => NCUR, SNAME => 'techObj', RATTRIBUTES => PKG_XMAKE.ATTRIBUTES(ICURSOR => NCUR, RATTRIBUTE00 => PKG_XMAKE.ATTRIBUTE(ICURSOR => NCUR, SNAME => 'NRN', NVALUE => C.NRN), RATTRIBUTE01 => PKG_XMAKE.ATTRIBUTE(ICURSOR => NCUR, SNAME => 'SCODE', SVALUE => C.SCODE), RATTRIBUTE02 => PKG_XMAKE.ATTRIBUTE(ICURSOR => NCUR, SNAME => 'SNAME', SVALUE => C.SNAME), RATTRIBUTE03 => PKG_XMAKE.ATTRIBUTE(ICURSOR => NCUR, SNAME => 'DOPER_DATE', DVALUE => C.DOPER_DATE), RATTRIBUTE04 => PKG_XMAKE.ATTRIBUTE(ICURSOR => NCUR, SNAME => 'DNEXT_EQTCHSRV', SVALUE => TO_CHAR(EQCONFIG_THOBJ_GET_NXTEQTCHSRV(NEQCONFIG => C.NRN), 'dd.mm.yyyy hh24:mi:ss')), RATTRIBUTE05 => PKG_XMAKE.ATTRIBUTE(ICURSOR => NCUR, SNAME => 'DNEXT_EQRPSHEET', SVALUE => TO_CHAR(EQCONFIG_THOBJ_GET_NXTEQRPSHT(NEQCONFIG => C.NRN), 'dd.mm.yyyy hh24:mi:ss')), RATTRIBUTE06 => PKG_XMAKE.ATTRIBUTE(ICURSOR => NCUR, SNAME => 'SEQOBJKIND', SVALUE => C.SEQOBJKIND))); end loop; /* Формируем XML-представление документа ответа */ XDOC := PKG_XMAKE.ELEMENT(ICURSOR => NCUR, SNAME => 'XDATA', RNODE00 => XCARD); /* Сериализуем документ */ 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 EQCONFIG_THOBJ_CARD; /* Отправка запроса на формирование прогноза технического объекта */ procedure EQCONFIG_THOBJ_FORECAST ( NEQCONFIG in number, -- Рег. номер технического объекта NEQUIPDSCMML in number -- Рег. номер модели ) is NEQUIPDSCMMLH PKG_STD.TREF; -- Рег. номер истории запросов модели CDEMO clob; -- Демо-данные прогноза 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; /* Формирование цвета прогноза для технического объекта */ function EQCONFIG_THOBJ_FORECAST_CLR ( NMODE in number := 0, -- Режим работы (0 - для подсказки в колонке таблицы, 1 - для колонки таблицы, 2 - для карточки детализации NVALUE in number :=0 -- Значение для подсветки ) return varchar2 -- Запрошенное значение в зависимости от режима is begin /* Работаем от режима */ case NMODE /* Для подсказки в колонке таблицы */ when 0 then return 'Опасность - вероятность сбоя более 60%.
' || 'Внимание - вероятность сбоя от 30% до 60%
' || 'В норме - вероятность сбоев менее 30%'; /* Для колонки таблицы */ when 1 then begin if (NVALUE < 30) then return 'success'; else if ((NVALUE >= 30) and (NVALUE < 60)) then return 'warning'; else return 'error'; end if; end if; end; /* Для карточки детализации */ when 2 then begin if (NVALUE < 30) then return 'success.main'; else if ((NVALUE >= 30) and (NVALUE < 60)) then return 'warning.main'; else return 'error.main'; end if; end if; end; /* Неверный режим */ else return null; end case; end EQCONFIG_THOBJ_FORECAST_CLR; /* Формирование детальной карточки прогноза для технического объекта */ procedure EQCONFIG_THOBJ_FORECAST_CRD ( NEQCONFIG in number, -- Рег. номер позиции состава оборудования DFORECAST_DATE in date, -- Дата получения прогноза NFORECAST in number, -- Прогнозное значение, полученное от фреймворка SDICMUNTS in varchar2, -- Единица измерения выборки STASK in varchar2, -- Задача (см. константы UDO_PKG_EQUIPDS_BASE.CMML_TASK_*) COUT out clob -- Данные детальной карточки прогноза ) is NCUR integer; -- Курсор документа для результата XDOC PKG_XMAKE.TNODE; -- Документ для результата XROOT PKG_XMAKE.TNODE; -- Содержимое корневого узла документа RCH PKG_P8PANELS_VISUAL.TCHART; -- График RCH_DS PKG_P8PANELS_VISUAL.TCHART_DATASET; -- Набор данных CCHART clob; -- Сериализованный график NBREAKDOWN_PROB PKG_STD.TNUMBER; -- Вероятность выхода из строя NBREAKDOWN_PROB_CUR PKG_STD.TNUMBER; -- Вероятность выхода из строя (для текущей позиции графика ТО и ремонтов/рем. ведомости) DNEXT_REPAIR PKG_STD.TLDATE; -- Дата ближайшего ТО и ремонта по графику/рем. ведомости begin /* Вычислим вероятность выхода из строя до даты ближайшего ТО/ремонта по графику или рем. ведомости с учётом прогноза */ DNEXT_REPAIR := EQCONFIG_THOBJ_GEN_NXTRPR(NEQCONFIG => NEQCONFIG); if (DNEXT_REPAIR is null) then NBREAKDOWN_PROB := 100; else if (sysdate + NFORECAST > DNEXT_REPAIR) then NBREAKDOWN_PROB := 0; end if; end if; /* Открываем документ */ NCUR := PKG_XMAKE.OPEN_CURSOR(); /* Заполним единицу измерения */ XROOT := PKG_XMAKE.CONCAT(ICURSOR => NCUR, RNODE00 => XROOT, RNODE01 => PKG_XMAKE.ELEMENT(ICURSOR => NCUR, SNAME => 'SDICMUNTS', RVALUE00 => PKG_XMAKE.VALUE(ICURSOR => NCUR, SVALUE => SDICMUNTS))); /* Заполним прогноз */ XROOT := PKG_XMAKE.CONCAT(ICURSOR => NCUR, RNODE00 => XROOT, RNODE01 => PKG_XMAKE.ELEMENT(ICURSOR => NCUR, SNAME => 'NFORECAST', RVALUE00 => PKG_XMAKE.VALUE(ICURSOR => NCUR, NVALUE => NFORECAST))); /* Заполним код задачи прогнозирования */ XROOT := PKG_XMAKE.CONCAT(ICURSOR => NCUR, RNODE00 => XROOT, RNODE01 => PKG_XMAKE.ELEMENT(ICURSOR => NCUR, SNAME => 'STASK', RVALUE00 => PKG_XMAKE.VALUE(ICURSOR => NCUR, SVALUE => STASK))); /* Заполним наименование задачи прогнозирования */ XROOT := PKG_XMAKE.CONCAT(ICURSOR => NCUR, RNODE00 => XROOT, RNODE01 => PKG_XMAKE.ELEMENT(ICURSOR => NCUR, SNAME => 'STASK_NAME', RVALUE00 => PKG_XMAKE.VALUE(ICURSOR => NCUR, SVALUE => UDO_PKG_EQUIPDS_BASE.CMML_TASK_NAME(STASK => STASK)))); /* Заполним дату следующего ТО и ремонта */ XROOT := PKG_XMAKE.CONCAT(ICURSOR => NCUR, RNODE00 => XROOT, RNODE01 => PKG_XMAKE.ELEMENT(ICURSOR => NCUR, SNAME => 'DNEXT_REPAIR', RVALUE00 => PKG_XMAKE.VALUE(ICURSOR => NCUR, DVALUE => DNEXT_REPAIR))); /* Если есть запланированные графики ТО и ремонта или ремонтные ведомости */ if (DNEXT_REPAIR is not null) then /* Строим график вероятностей выхода из строя опираясь на них */ RCH := PKG_P8PANELS_VISUAL.TCHART_MAKE(STYPE => PKG_P8PANELS_VISUAL.SCHART_TYPE_LINE, STITLE => 'Прогноз с учётом графика ТО и ремонтов/ремонтных ведомостей', SLGND_POS => PKG_P8PANELS_VISUAL.SCHART_LGND_POS_TOP); /* Сформируем набор данных */ RCH_DS := PKG_P8PANELS_VISUAL.TCHART_DATASET_MAKE(SCAPTION => 'Вероятность перехода в критическое состояние (%)'); /* Обходим ближайшие 5 позиций графика ТО и ремонтов или ремонтных ведомостей */ for C in (select ROWNUM, D.DDATEPRD_BEG from (select T.DDATEPRD_BEG from (select P.DATEPRD_BEG DDATEPRD_BEG from EQTCHSRV P where P.EQCONFIG_TECH = NEQCONFIG and P.DATEPRD_BEG >= sysdate union select R.DATEPLAN_BEG DDATEPRD_BEG from EQRPSHEETS R where R.EQCONFIG = NEQCONFIG and R.DATEPLAN_BEG >= sysdate) T order by T.DDATEPRD_BEG) D where ROWNUM <= 5) loop /* Добавим метку для графика */ PKG_P8PANELS_VISUAL.TCHART_ADD_LABEL(RCHART => RCH, SLABEL => TO_CHAR(C.DDATEPRD_BEG, 'dd.mm.yyyy')); /* Считаем вероятность выхода из строя в эту дату */ NBREAKDOWN_PROB_CUR := UDO_PKG_EQUIPDS_BASE.CMML_RUL_BREAKDOWN_PROB(NFORECAST => NFORECAST, DFORECAST_DATE => DFORECAST_DATE, DDATE => C.DDATEPRD_BEG); /* Если ещё не фиксировали вероятность для первой даты - сделаем это */ if (NBREAKDOWN_PROB is null) then NBREAKDOWN_PROB := NBREAKDOWN_PROB_CUR; end if; /* Добавим элемент в набор данных */ PKG_P8PANELS_VISUAL.TCHART_DATASET_ADD_ITEM(RDATASET => RCH_DS, NVALUE => NBREAKDOWN_PROB_CUR); end loop; /* Добавим набор данных в график */ PKG_P8PANELS_VISUAL.TCHART_ADD_DATASET(RCHART => RCH, RDATASET => RCH_DS); /* Сериализуем график */ CCHART := PKG_P8PANELS_VISUAL.TCHART_TO_XML(RCHART => RCH, NINCLUDE_DEF => 1); end if; /* Заполним вероятность выхода из стороя до ближайшего ТО с учётом прогноза */ XROOT := PKG_XMAKE.CONCAT(ICURSOR => NCUR, RNODE00 => XROOT, RNODE01 => PKG_XMAKE.ELEMENT(ICURSOR => NCUR, SNAME => 'NBREAKDOWN_PROB', RVALUE00 => PKG_XMAKE.VALUE(ICURSOR => NCUR, NVALUE => NBREAKDOWN_PROB))); /* Заполним цвет вероятности выхода из стороя до ближайшего ТО с учётом прогноза */ XROOT := PKG_XMAKE.CONCAT(ICURSOR => NCUR, RNODE00 => XROOT, RNODE01 => PKG_XMAKE.ELEMENT(ICURSOR => NCUR, SNAME => 'SBREAKDOWN_PROB_COLOR', RVALUE00 => PKG_XMAKE.VALUE(ICURSOR => NCUR, SVALUE => EQCONFIG_THOBJ_FORECAST_CLR(NMODE => 2, NVALUE => NBREAKDOWN_PROB)))); /* Добавляем график в ответ */ XROOT := PKG_XMAKE.CONCAT(ICURSOR => NCUR, RNODE00 => XROOT, RNODE01 => PKG_XMAKE.ELEMENT(ICURSOR => NCUR, SNAME => 'XCHART', RVALUE00 => PKG_XMAKE.VALUE(ICURSOR => NCUR, LCVALUE => CCHART))); /* Формируем 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 EQCONFIG_THOBJ_FORECAST_CRD; /* Извлечение сведений из детальной карточки прогноза для технического объекта */ procedure EQCONFIG_THOBJ_FORECAST_CRDP ( CFORECAST in clob, -- Данные детальной карточки прогноза SFORECAST_DESC out varchar2, -- Описание прогноза SFORECAST_DESC_COLOR out varchar2 -- Цвет заливки прогноза ) is XDOC PKG_XPATH.TDOCUMENT; -- Десериализованный демо-прогноз XROOT PKG_XPATH.TNODE; -- Корневой элемент данных SDICMUNTS PKG_STD.TSTRING; -- Единица измерения выборки NFORECAST PKG_STD.TNUMBER; -- Прогноз по заданной задаче NBREAKDOWN_PROB PKG_STD.TNUMBER; -- Вероятность выхода из строя begin /* Разбираем демо-даные */ XDOC := PKG_XPATH.PARSE_FROM_CLOB(LCXML => CFORECAST); /* Извлекаем корневой элемент */ XROOT := PKG_XPATH.ROOT_NODE(RDOCUMENT => XDOC); /* Читаем единицу измерения */ SDICMUNTS := PKG_XPATH.VALUE(RNODE => PKG_XPATH.SINGLE_NODE(RPARENT_NODE => XROOT, SPATTERN => 'XDATA/SDICMUNTS')); /* Читаем прогноз */ NFORECAST := PKG_XPATH.VALUE_NUM(RNODE => PKG_XPATH.SINGLE_NODE(RPARENT_NODE => XROOT, SPATTERN => 'XDATA/NFORECAST')); /* Читаем вероятность выхода из строя */ NBREAKDOWN_PROB := PKG_XPATH.VALUE_NUM(RNODE => PKG_XPATH.SINGLE_NODE(RPARENT_NODE => XROOT, SPATTERN => 'XDATA/NBREAKDOWN_PROB')); /* Проноз есть */ if (NFORECAST is not null) then /* Возвращаем значение описания */ SFORECAST_DESC := TO_CHAR(ROUND(NFORECAST)) || SDICMUNTS || ' / ' || TO_CHAR(ROUND(NBREAKDOWN_PROB)) || '%'; /* Возвращаем значение цвета заливки описания прогноза */ SFORECAST_DESC_COLOR := EQCONFIG_THOBJ_FORECAST_CLR(NMODE => 1, NVALUE => NBREAKDOWN_PROB); end if; exception when others then null; end EQCONFIG_THOBJ_FORECAST_CRDP; /* Вероятность выхода единицы оборудования из строя с учётом графика ТО и ремонтов и RUL-прогноза */ function EQCONFIG_THOBJ_TCHSRV_BRKDPROB ( NEQCONFIG in number -- Рег. номер технического объекта ) return number -- Вероятность выхода из строя is NRES PKG_STD.TNUMBER; -- Буфер для результата DFORECAST_DATE PKG_STD.TLDATE; -- Дата прогноза NFORECAST PKG_STD.TNUMBER; -- Значение самго свежего прогноза модели DCALC_DATE PKG_STD.TLDATE; -- Дата расчета вероятности begin /* Определим дату ближайшего ТО или ремонта */ DCALC_DATE := EQCONFIG_THOBJ_GEN_NXTRPR(NEQCONFIG => NEQCONFIG); /* Если дата есть */ if (DCALC_DATE is not null) then /* Вынем самый свежий прогноз */ for C in (select T.RQ_DATE DFORECAST_DATE, T.FORECAST from UDO_T_EQUIPDSCMMLH T, UDO_T_EQUIPDSCMML CMML where T.EQCONFIG = NEQCONFIG and T.PRN = CMML.RN and CMML.TASK = UDO_PKG_EQUIPDS_BASE.SCMML_TASK_RUL order by T.RQ_DATE desc) loop DFORECAST_DATE := C.DFORECAST_DATE; UDO_PKG_EQUIPDS.CMMLH_PARSE_FORECAST(CFORECAST => BLOB2CLOB(LBDATA => C.FORECAST), NFORECAST => NFORECAST); exit; end loop; /* Если есть и прогноз */ if (NFORECAST is not null) then NRES := UDO_PKG_EQUIPDS_BASE.CMML_RUL_BREAKDOWN_PROB(NFORECAST => NFORECAST, DFORECAST_DATE => DFORECAST_DATE, DDATE => DCALC_DATE); end if; end if; /* Вернём то, что собрали */ return NRES; end EQCONFIG_THOBJ_TCHSRV_BRKDPROB; /* Модификация графика ТО и ремонтов для технического объекта */ procedure EQCONFIG_THOBJ_CHNG_EQTCHSRV ( NEQCONFIG in number, -- Рег. номер технического объекта NEQTCHSRV in number, -- Рег. номер графика ТО и ремонтов DPLANDATE_FROM in date -- Уточнённая плановая дата начала ремонта ) is REQTCHSRV EQTCHSRV%rowtype; -- Запись графика ТО и ремонтов RDSCMMLH UDO_T_EQUIPDSCMMLH%rowtype; -- Запись истории прогнозов NDIFF PKG_STD.TNUMBER; -- Отклонение старой и новой дат DDATEPRD_BEG PKG_STD.TLDATE; -- Новая дата начала DDATEPRD_END PKG_STD.TLDATE; -- Новая дата окончания SNOTE PKG_STD.TSTRING; -- Новое примечание begin /* Считаем график */ begin select T.* into REQTCHSRV from EQTCHSRV T where T.RN = NEQTCHSRV; exception when NO_DATA_FOUND then PKG_MSG.RECORD_NOT_FOUND(NFLAG_SMART => 0, NDOCUMENT => NEQTCHSRV, SUNIT_TABLE => 'EquipTechServices'); end; /* Считаем запись истории прогнозов */ begin select T.* into RDSCMMLH from UDO_T_EQUIPDSCMMLH T where T.RN = (select max(TT.RN) from UDO_T_EQUIPDSCMMLH TT where TT.EQCONFIG = NEQCONFIG); exception when others then P_EXCEPTION(0, 'Не удалось определить запись-основание истории прогнозов модели.'); end; /* Проверим, что из графика не сформирована ремонтная ведомость */ if (F_DOCLINKS_LINK_OUT_DOC(SIN_UNITCODE => 'EquipTechServices', NIN_DOCUMENT => REQTCHSRV.RN, SOUT_UNITCODE => 'EquipRepairSheets') is not null) then P_EXCEPTION(0, 'Из графика ТО и ремонтов (RN: %s) уже создана ремонтная ведомость.', TO_CHAR(REQTCHSRV.RN)); end if; /* Проверим, что есть на что менять */ if (TRUNC(DPLANDATE_FROM) = TRUNC(REQTCHSRV.DATEPRD_BEG)) then P_EXCEPTION(0, 'Выбранный график ТО и ремонтов уже запланирован на %s', TO_CHAR(DPLANDATE_FROM, 'dd.mm.yyyy')); end if; /* Сбросим состояние графика */ if (REQTCHSRV.STATE <> 0) then P_EQTCHSRV_SET_STATE(NCOMPANY => REQTCHSRV.COMPANY, NRN => REQTCHSRV.RN, NSTATE => 0, DDATE => sysdate); end if; /* Определим отклонение и новые даты графика */ NDIFF := DPLANDATE_FROM - REQTCHSRV.DATEPRD_BEG; DDATEPRD_BEG := REQTCHSRV.DATEPRD_BEG + NDIFF; DDATEPRD_END := REQTCHSRV.DATEPRD_END + NDIFF; /* Формируем новое примечание */ SNOTE := 'Автоматически перенесён с "' || TO_CHAR(REQTCHSRV.DATEPRD_BEG, 'dd.mm.yyyy hh24:mi:ss') || '" на "' || TO_CHAR(DDATEPRD_BEG, 'dd.mm.yyyy hh24:mi:ss') || '" на основании прогноза от "' || TO_CHAR(RDSCMMLH.RQ_DATE, 'dd.mm.yyyy hh24:mi:ss') || '" (RN: ' || TO_CHAR(RDSCMMLH.RN) || ', пользователь: ' || RDSCMMLH.RQ_AUTHID || ').'; /* Изменим заголовок графика */ update EQTCHSRV T set T.DATEPRD_BEG = DDATEPRD_BEG, T.DATEPRD_END = DDATEPRD_END, T.NOTE = SNOTE where T.RN = REQTCHSRV.RN; /* Сдвинем работы */ P_EQTCHSRV_MOVE_WORK(NCOMPANY => REQTCHSRV.COMPANY, NRN => REQTCHSRV.RN, NDUP_RN => null, DDATEPRD_BEG => DDATEPRD_BEG, DOLD_DATEPRD_BEG => REQTCHSRV.DATEPRD_BEG, DDATEPRD_END => DDATEPRD_END, NPERIOD => null, NMODE => 1); /* Восстановим состояние графика */ if (REQTCHSRV.STATE <> 0) then P_EQTCHSRV_SET_STATE(NCOMPANY => REQTCHSRV.COMPANY, NRN => REQTCHSRV.RN, NSTATE => REQTCHSRV.STATE, DDATE => sysdate); end if; end EQCONFIG_THOBJ_CHNG_EQTCHSRV; /* Формирование ремонтной ведомости для технического объекта */ procedure EQCONFIG_THOBJ_MAKE_EQRPSHEET ( NEQCONFIG in number, -- Рег. номер технического объекта SACATALOG in varchar2, -- Каталог размещения ведомости SEQTECSRVKIND in varchar2, -- Вид ремонта DPLANDATE_FROM in date, -- Плановая дата начала ремонта NIDENT out number -- Идентификатор списка сформированных ведомостей ) is NCOMPANY PKG_STD.TREF := GET_SESSION_COMPANY(); -- Рег. номер организации NCRN PKG_STD.TREF; -- Рег. номер каталога размещения ведомости SJURPERSONS PKG_STD.TSTRING; -- Юридическая принадлежность технического объекта SCURRENCY PKG_STD.TSTRING; -- Валюта ведомости SDOCTYPES PKG_STD.TSTRING; -- Тип документа ведомости SPREF PKG_STD.TSTRING; -- Префикс ведосмости SNUMB PKG_STD.TSTRING; -- Номер ведомости NEQRPSHEET PKG_STD.TREF; -- Рег. номер сформированной ведомости begin /* Определяем юридическую принадлежность технического объекта */ begin select JP.CODE into SJURPERSONS from EQCONFIG T, JURPERSONS JP where T.RN = NEQCONFIG and T.JUR_PERS = JP.RN; exception when NO_DATA_FOUND then PKG_MSG.RECORD_NOT_FOUND(NFLAG_SMART => 0, NDOCUMENT => NEQCONFIG, SUNIT_TABLE => 'EquipConfiguration'); end; /* Читаем валюту документа по-умолчанию из параметров */ SCURRENCY := GET_OPTIONS_STR(SCODE => 'Equip_RepairSheets_Currency'); /* Читаем тип документа по-умолчанию из параметров */ SDOCTYPES := GET_OPTIONS_STR(SCODE => 'Equip_RepairSheets_DocType'); /* Читаем префикс документа по-умолчанию из параметров */ SPREF := GET_OPTIONS_STR(SCODE => 'Equip_RepairSheets_DocPref'); /* Формируем очередной номер документа */ P_EQRPSHEETS_GETNEXTNUMB(NCOMPANY => NCOMPANY, SPREF => SPREF, SDOCTYPES => SDOCTYPES, SNUMB => SNUMB); /* Определяем каталог размещения */ FIND_ACATALOG_NAME(NFLAG_SMART => 0, NCOMPANY => NCOMPANY, NVERSION => null, SUNITCODE => 'EquipRepairSheets', SNAME => SACATALOG, NRN => NCRN); /* Формируем ведомость */ P_EQRPSHEETS_MAKE_EQRPSHEET(NCOMPANY => NCOMPANY, NCRN => NCRN, SDOCTYPES => SDOCTYPES, SPREF => SPREF, SNUMB => SNUMB, DDOCDATE => sysdate, SJURPERSONS => SJURPERSONS, DPLANDATE_FROM => DPLANDATE_FROM, DPLANDATE_TO => DPLANDATE_FROM, SCURRENCY => SCURRENCY, NCOURSE => 1, SEQTECSRVKIND => SEQTECSRVKIND, NPR_OBJ => null, NTECH_OBJ => NEQCONFIG, STECH_SRV_DIV => null, SRESP_DIV => null, SPERF_DIV => null, SPERFORM_AGN => null, SLEVEL => null, SEQOBJKIND => null, NRN => NEQRPSHEET); /* Добавим ведомость в список */ EQCONFIG_THOBJ_SELECT_EQRPSHT(NEQRPSHEETS => NEQRPSHEET, NIDENT => NIDENT); end EQCONFIG_THOBJ_MAKE_EQRPSHEET; end UDO_PKG_EQUIPTCF; /