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;
/