TCF-Framework-Integration/db/UDO_PKG_EQUIPTCF.pck

1199 lines
80 KiB
SQL
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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 -- Идентификатор списка
);
/* Получение даты следующего ремонта по ремонтной ведомости или графику ТО и ремонтов (что раньше) технического объекта */
function EQCONFIG_THOBJ_GEN_NXTRPR
(
NEQCONFIG in number -- Рег. номер технического объекта
) return date; -- Дата ближайшего ремонта
/* Формирование карточки технического объекта */
procedure EQCONFIG_THOBJ_CARD
(
NEQCONFIG in number, -- Рег. номер технического объекта
COUT out clob -- Сериализованная карточка
);
/* Подчистка буферов после исполнения запроса на формирование прогноза технического объекта */
procedure EQCONFIG_THOBJ_FORECAST_BCLR
(
NDATASET_IDENT in number, -- Идентификатор буфера данных
NDATASET_CONFIG_IDENT in number, -- Идентификатор буфера описания данных
NREQUEST_CONFIG_IDENT in number -- Идентификатор буфера описания запроса
);
/* Подготовка запроса на формирование прогноза технического объекта */
procedure EQCONFIG_THOBJ_FORECAST_PRLG
(
NEQUIPDSCMML in number, -- Рег. номер модели
NDATASET_IDENT in number, -- Идентификатор буфера данных
NDATASET_CONFIG_IDENT in number, -- Идентификатор буфера описания данных
NREQUEST_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_*)
);
/* Финализация исполнения запроса на формирование прогноза технического объекта */
procedure EQCONFIG_THOBJ_FORECAST_EPLG
(
NDATASET_IDENT in number, -- Идентификатор буфера данных
NDATASET_CONFIG_IDENT in number, -- Идентификатор буфера описания данных
NREQUEST_CONFIG_IDENT in number, -- Идентификатор буфера описания запроса
NEQCONFIG in number := null, -- Рег. номер технического объекта
NEQUIPDSCMML in number := null, -- Рег. номер модели
CFORECAST in clob := null -- Данные прогноза
);
/* Вероятность выхода единицы оборудования из строя с учётом графика ТО и ремонтов и 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="Проверка прав доступа при формировании таблицы и карточки ТО"
*/
/* Константы - адреса API фреймворка прогнозирования */
SFW_API_ROOT constant PKG_STD.TSTRING := '/API'; -- Корень API
SFW_API_FORECAST constant PKG_STD.TSTRING := '/forecast/metadata'; -- Адрес функции прогнозирования (относительно корня)
/* Формирование ветки дерева состава оборудования */
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.TDG_FILTERS; -- Фильтры
RO PKG_P8PANELS_VISUAL.TDG_ORDERS; -- Сортировки
RDG PKG_P8PANELS_VISUAL.TDG; -- Описание таблицы
RDG_ROW PKG_P8PANELS_VISUAL.TDG_ROW; -- Строка таблицы
RCOL_VALS PKG_P8PANELS_VISUAL.TDG_COL_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.TDG_FILTERS_FROM_XML(CFILTERS => CFILTERS);
/* Читаем сортировки */
RO := PKG_P8PANELS_VISUAL.TDG_ORDERS_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.TDG_MAKE();
/* Добавляем в таблицу описание колонок */
PKG_P8PANELS_VISUAL.TDG_ADD_COL_DEF(RDATA_GRID => RDG,
SNAME => 'NRN',
SCAPTION => 'Рег. номер',
SDATA_TYPE => PKG_P8PANELS_VISUAL.SDATA_TYPE_NUMB,
BVISIBLE => false);
PKG_P8PANELS_VISUAL.TDG_ADD_COL_DEF(RDATA_GRID => RDG,
SNAME => 'SCODE',
SCAPTION => 'Обозначение',
SDATA_TYPE => PKG_P8PANELS_VISUAL.SDATA_TYPE_STR,
BORDER => true,
BFILTER => true);
PKG_P8PANELS_VISUAL.TDG_ADD_COL_DEF(RDATA_GRID => RDG,
SNAME => 'SNAME',
SCAPTION => 'Наименование',
SDATA_TYPE => PKG_P8PANELS_VISUAL.SDATA_TYPE_STR,
BORDER => true,
BFILTER => true);
PKG_P8PANELS_VISUAL.TDG_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.TDG_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.TDG_ADD_COL_DEF(RDATA_GRID => RDG,
SNAME => 'NOBJ_KIND',
SCAPTION => 'Рег. номер класса технического объекта',
SDATA_TYPE => PKG_P8PANELS_VISUAL.SDATA_TYPE_NUMB,
BVISIBLE => false);
PKG_P8PANELS_VISUAL.TDG_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.TDG_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.TDG_ADD_COL_DEF(RDATA_GRID => RDG,
SNAME => 'SUMEAS_RES',
SCAPTION => 'Единица измерения ресурса',
SDATA_TYPE => PKG_P8PANELS_VISUAL.SDATA_TYPE_STR,
BVISIBLE => false);
PKG_P8PANELS_VISUAL.TDG_COL_VALS_ADD(RCOL_VALS => RCOL_VALS, NVALUE => 0, BCLEAR => true);
PKG_P8PANELS_VISUAL.TDG_COL_VALS_ADD(RCOL_VALS => RCOL_VALS, NVALUE => 1);
PKG_P8PANELS_VISUAL.TDG_COL_VALS_ADD(RCOL_VALS => RCOL_VALS, NVALUE => 2);
PKG_P8PANELS_VISUAL.TDG_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.TDG_ADD_COL_DEF(RDATA_GRID => RDG,
SNAME => 'NBREAKDOWN_PROB',
SCAPTION => 'Вероятность выхода из строя',
SDATA_TYPE => PKG_P8PANELS_VISUAL.SDATA_TYPE_NUMB,
BORDER => true,
BFILTER => true,
SHINT => UDO_PKG_EQUIPDS.CMMLH_FORECAST_COLOR(NMODE => 0));
PKG_P8PANELS_VISUAL.TDG_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.TDG_ORDERS_SET_QUERY(RDATA_GRID => RDG,
RORDERS => RO,
SPATTERN => '%ORDER_BY%',
CSQL => CSQL);
/* Учтём фильтры */
PKG_P8PANELS_VISUAL.TDG_FILTERS_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.TDG_ROW_ADD_CUR_COLN(RROW => RDG_ROW,
SNAME => 'NRN',
ICURSOR => ICURSOR,
NPOSITION => 1,
BCLEAR => true);
PKG_P8PANELS_VISUAL.TDG_ROW_ADD_CUR_COLS(RROW => RDG_ROW, SNAME => 'SCODE', ICURSOR => ICURSOR, NPOSITION => 2);
PKG_P8PANELS_VISUAL.TDG_ROW_ADD_CUR_COLS(RROW => RDG_ROW, SNAME => 'SNAME', ICURSOR => ICURSOR, NPOSITION => 3);
PKG_P8PANELS_VISUAL.TDG_ROW_ADD_CUR_COLD(RROW => RDG_ROW,
SNAME => 'DOPER_DATE',
ICURSOR => ICURSOR,
NPOSITION => 4);
PKG_P8PANELS_VISUAL.TDG_ROW_ADD_CUR_COLS(RROW => RDG_ROW,
SNAME => 'SUSE_KIND',
ICURSOR => ICURSOR,
NPOSITION => 5);
PKG_P8PANELS_VISUAL.TDG_ROW_ADD_CUR_COLN(RROW => RDG_ROW,
SNAME => 'NOBJ_KIND',
ICURSOR => ICURSOR,
NPOSITION => 6);
PKG_P8PANELS_VISUAL.TDG_ROW_ADD_CUR_COLS(RROW => RDG_ROW,
SNAME => 'SOBJ_KIND',
ICURSOR => ICURSOR,
NPOSITION => 7);
PKG_P8PANELS_VISUAL.TDG_ROW_ADD_CUR_COLS(RROW => RDG_ROW,
SNAME => 'SOBJ_KIND_FULL_CODE',
ICURSOR => ICURSOR,
NPOSITION => 8);
PKG_P8PANELS_VISUAL.TDG_ROW_ADD_CUR_COLS(RROW => RDG_ROW,
SNAME => 'SUMEAS_RES',
ICURSOR => ICURSOR,
NPOSITION => 9);
PKG_P8PANELS_VISUAL.TDG_ROW_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.TDG_ROW_ADD_COL(RROW => RDG_ROW, SNAME => 'NBREAKDOWN_PROB', NVALUE => NBREAKDOWN_PROB);
PKG_P8PANELS_VISUAL.TDG_ROW_ADD_COL(RROW => RDG_ROW,
SNAME => 'SBREAKDOWN_PROB_COLOR',
SVALUE => UDO_PKG_EQUIPDS.CMMLH_FORECAST_COLOR(NMODE => 1, NVALUE => NBREAKDOWN_PROB));
/* Добавляем строку в таблицу */
PKG_P8PANELS_VISUAL.TDG_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.TDG_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_BCLR
(
NDATASET_IDENT in number, -- Идентификатор буфера данных
NDATASET_CONFIG_IDENT in number, -- Идентификатор буфера описания данных
NREQUEST_CONFIG_IDENT in number -- Идентификатор буфера описания запроса
)
is
begin
/* Очистим данные в файловом буфере */
P_FILE_BUFFER_CLEAR(NIDENT => NDATASET_IDENT);
P_FILE_BUFFER_CLEAR(NIDENT => NDATASET_CONFIG_IDENT);
P_FILE_BUFFER_CLEAR(NIDENT => NREQUEST_CONFIG_IDENT);
end EQCONFIG_THOBJ_FORECAST_BCLR;
/* Подчистка буферов после исполнения запроса на формирование прогноза технического объекта (в автономной транзакции) */
procedure EQCONFIG_THOBJ_FORECAST_BCLRAT
(
NDATASET_IDENT in number, -- Идентификатор буфера данных
NDATASET_CONFIG_IDENT in number, -- Идентификатор буфера описания данных
NREQUEST_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_CONTPRMLOC.PUTN(RCONTAINER => RPROC_PARAMS,
SNAME => 'NREQUEST_CONFIG_IDENT',
NVALUE => NREQUEST_CONFIG_IDENT,
NIN_OUT => PKG_STD.PARAM_TYPE_IN());
/* Подчищаем (в автономной транзакции) */
PKG_SQL_CALL.EXECUTE_STORED_AT(SSTORED_NAME => 'UDO_PKG_EQUIPTCF.EQCONFIG_THOBJ_FORECAST_BCLR',
RPARAM_CONTAINER => RPROC_PARAMS,
BOVERLOAD_ENV => true);
/* Очищаем контейнер с параметрами */
PKG_CONTPRMLOC.PURGE(RCONTAINER => RPROC_PARAMS);
end EQCONFIG_THOBJ_FORECAST_BCLRAT;
/* Подготовка запроса на формирование прогноза технического объекта */
procedure EQCONFIG_THOBJ_FORECAST_PRLG
(
NEQUIPDSCMML in number, -- Рег. номер модели
NDATASET_IDENT in number, -- Идентификатор буфера данных
NDATASET_CONFIG_IDENT in number, -- Идентификатор буфера описания данных
NREQUEST_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
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)
into NCNT
from FILE_BUFFER T
where T.IDENT = NDATASET_IDENT
and T.BDATA is not null;
exception
when others then
P_EXCEPTION(0, 'Не удалось проверить набор данных о наработках.');
end;
if (NCNT > 1) then
P_EXCEPTION(0, 'Набор данных о наработках определён неоднозначно.');
end if;
if (NCNT = 0) then
P_EXCEPTION(0, 'Набор данных о наработках не определён.');
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;
CDATASET_CONFIG := C.CDATA;
end loop;
if (CDATASET_CONFIG is null) then
P_EXCEPTION(0, 'Описание набора данных о наработках не определёно.');
end if;
/* Проверим данные конфигурации запроса */
begin
select count(T.RN)
into NCNT
from FILE_BUFFER T
where T.IDENT = NREQUEST_CONFIG_IDENT
and T.DATA is not null;
exception
when others then
P_EXCEPTION(0,
'Не удалось проверить параметры запроса на прогнозирование.');
end;
if (NCNT > 1) then
P_EXCEPTION(0,
'Параметры запроса на прогнозирование определёны неоднозначно.');
end if;
if (NCNT = 0) 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 для запроса */
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(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_BCLRAT(NDATASET_IDENT => NDATASET_IDENT,
NDATASET_CONFIG_IDENT => NDATASET_CONFIG_IDENT,
NREQUEST_CONFIG_IDENT => NREQUEST_CONFIG_IDENT);
/* Пробросим ошибку */
raise;
end EQCONFIG_THOBJ_FORECAST_PRLG;
/* Финализация исполнения запроса на формирование прогноза технического объекта */
procedure EQCONFIG_THOBJ_FORECAST_EPLG
(
NDATASET_IDENT in number, -- Идентификатор буфера данных
NDATASET_CONFIG_IDENT in number, -- Идентификатор буфера описания данных
NREQUEST_CONFIG_IDENT in number, -- Идентификатор буфера описания запроса
NEQCONFIG in number, -- Рег. номер технического объекта
NEQUIPDSCMML in number, -- Рег. номер модели
CFORECAST in clob -- Данные прогноза
)
is
NEQUIPDSCMMLH PKG_STD.TREF; -- Рег. номер истории запросов модели
CRQ clob; -- Описание параметров запроса на прогноз
DFORECAST_DATE PKG_STD.TLDATE; -- Дата прогноза (последняя)
NFORECAST_DAYS PKG_STD.TNUMBER; -- Прогноз (дней до выхода из строя на дату прогноза)
DBEG PKG_STD.TLDATE; -- Дата окончания интервала сбора данных для прогноза
DEND PKG_STD.TLDATE; -- Дата начала интервала сбора данных для прогноза
NINTERVAL PKG_STD.TLNUMBER; -- Размер (в днях) интервала измерения
XFORECAST PKG_XPATH.TDOCUMENT; -- XML-документ прогноза
XROOT PKG_XPATH.TNODE; -- Корневой элемент документа прогноза
XFCTS PKG_XPATH.TNODES; -- Массив предсказаний
XLAST_FCT PKG_XPATH.TNODE; -- Последний элемент массива предсказаний
NLAST PKG_STD.TNUMBER; -- Номер последней позиции массива предсказаний
NLAST_INTERVALS PKG_STD.TLNUMBER; -- Значение (количество интервалов измерения до выхода из строя) последней записи массива предсказаний
begin
/* Считаем параметры сделанного запроса */
begin
select T.DATA
into CRQ
from FILE_BUFFER T
where T.IDENT = NREQUEST_CONFIG_IDENT
and T.DATA is not null;
exception
when NO_DATA_FOUND then
P_EXCEPTION(0,
'Параметры запроса на прогнозирование не определёны.');
when TOO_MANY_ROWS then
P_EXCEPTION(0,
'Параметры запроса на прогнозирование определёны неоднозначно.');
end;
/* Добавляем запись истории запросов */
UDO_PKG_EQUIPDS_BASE.CMMLH_INS(NPRN => NEQUIPDSCMML,
NEQCONFIG => NEQCONFIG,
SRQ_AUTHID => UTILIZER(),
DRQ_DATE => sysdate,
BRQ => CLOB2BLOB(LCDATA => CRQ),
NRN => NEQUIPDSCMMLH);
/* Пробуем разобрать прогноз */
begin
/* Читаем параметры с которыми делался прогноз */
UDO_PKG_EQUIPDS_BASE.UTL_FORECAST_RQ_PARSE_CFG(CRQ_CFG => CRQ,
DBEG => DBEG,
DEND => DEND,
NINTERVAL => NINTERVAL);
/* Разбираем данные прогноза */
XFORECAST := PKG_XPATH.PARSE_FROM_BLOB(LBXML => BASE64_DECODE(LCSRCE => CFORECAST));
XROOT := PKG_XPATH.ROOT_NODE(RDOCUMENT => XFORECAST);
XFCTS := PKG_XPATH.LIST_NODES(RPARENT_NODE => XROOT, SPATTERN => 'XDATA/XFORECAST');
/* Читаем последнее значение из массива предсказаний (оно соответствует дате окончания из параметров прогноза) */
NLAST := PKG_XPATH.COUNT_NODES(RNODES => XFCTS);
XLAST_FCT := PKG_XPATH.ITEM_NODE(RNODES => XFCTS, INUMBER => NLAST);
NLAST_INTERVALS := PKG_XPATH.VALUE_NUM(RNODE => XLAST_FCT, SPATTERN => 'VALUE');
if (NLAST_INTERVALS < 0) then
NLAST_INTERVALS := 0;
end if;
/* Освобождаем документ */
PKG_XPATH.FREE(RDOCUMENT => XFORECAST);
/* Сформируем дату прогноза и количество дней до выхода из строя на эту дату */
DFORECAST_DATE := DEND;
NFORECAST_DAYS := NINTERVAL * NLAST_INTERVALS;
exception
when others then
null;
end;
/* Сохраним данные прогноза */
UDO_PKG_EQUIPDS_BASE.CMMLH_SET_FORECAST(NRN => NEQUIPDSCMMLH,
BFORECAST => BASE64_DECODE(LCSRCE => CFORECAST),
DFORECAST_DATE => DFORECAST_DATE,
NFORECAST_DAYS => NFORECAST_DAYS);
/* Подчистим буферы */
EQCONFIG_THOBJ_FORECAST_BCLR(NDATASET_IDENT => NDATASET_IDENT,
NDATASET_CONFIG_IDENT => NDATASET_CONFIG_IDENT,
NREQUEST_CONFIG_IDENT => NREQUEST_CONFIG_IDENT);
exception
when others then
/* Подчистим буферы */
EQCONFIG_THOBJ_FORECAST_BCLRAT(NDATASET_IDENT => NDATASET_IDENT,
NDATASET_CONFIG_IDENT => NDATASET_CONFIG_IDENT,
NREQUEST_CONFIG_IDENT => NREQUEST_CONFIG_IDENT);
/* Пробросим ошибку */
raise;
end EQCONFIG_THOBJ_FORECAST_EPLG;
/* Вероятность выхода единицы оборудования из строя с учётом графика ТО и ремонтов и RUL-прогноза */
function EQCONFIG_THOBJ_TCHSRV_BRKDPROB
(
NEQCONFIG in number -- Рег. номер технического объекта
) return number -- Вероятность выхода из строя
is
NRES PKG_STD.TNUMBER; -- Буфер для результата
DFORECAST_DATE PKG_STD.TLDATE; -- Дата прогноза
NFORECAST_DAYS PKG_STD.TNUMBER; -- Значение самго свежего прогноза модели
DCALC_DATE PKG_STD.TLDATE; -- Дата расчета вероятности
begin
/* Определим дату ближайшего ТО или ремонта */
DCALC_DATE := EQCONFIG_THOBJ_GEN_NXTRPR(NEQCONFIG => NEQCONFIG);
/* Вынем самый свежий прогноз */
for C in (select T.FORECAST_DATE DFORECAST_DATE,
T.FORECAST_DAYS NFORECAST_DAYS
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;
NFORECAST_DAYS := C.NFORECAST_DAYS;
exit;
end loop;
/* Если есть прогноз */
if ((DFORECAST_DATE is not null) and (NFORECAST_DAYS is not null)) then
/* Если и дата ТО есть */
if (DCALC_DATE is not null) then
/* Вычислим вероятность */
NRES := UDO_PKG_EQUIPDS_BASE.CMMLH_RUL_BREAKDOWN_PROB(DFORECAST_DATE => DFORECAST_DATE,
NFORECAST_DAYS => NFORECAST_DAYS,
DDATE => DCALC_DATE);
else
/* Запланированных ремонтов или ТО нет, но прогноз есть - значит точно выйдет из строя */
NRES := 100;
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 => TRUNC(DPLANDATE_FROM),
DPLANDATE_TO => (TRUNC(DPLANDATE_FROM) + 1) - 1/24/60,
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;
/