TCF-Framework-Integration/db/UDO_PKG_EQUIPTCF.pck

1324 lines
89 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 -- Идентификатор списка
);
/* Формирование карточки технического объекта */
procedure EQCONFIG_THOBJ_CARD
(
NEQCONFIG in number, -- Рег. номер технического объекта
COUT out clob -- Сериализованная карточка
);
/* Подчистка после исполнения запроса на формирование прогноза технического объекта */
procedure EQCONFIG_THOBJ_FORECAST_EPLG
(
NDATASET_IDENT in number, -- Идентификатор буфера данных
NDATASET_CONFIG_IDENT in number, -- Идентификатор буфера описания данных
NEQCONFIG in number := null, -- Рег. номер технического объекта
NEQUIPDSCMML in number := null, -- Рег. номер модели
CFORECAST in clob := null -- Данные прогноза
);
/* Подготовка запроса на формирование прогноза технического объекта */
procedure EQCONFIG_THOBJ_FORECAST_PRLG
(
NEQUIPDSCMML in number, -- Рег. номер модели
NDATASET_IDENT in number, -- Идентификатор буфера данных
NDATASET_CONFIG_IDENT in number, -- Идентификатор буфера описания данных
SURL out varchar2, -- Адрес для запроса
SAUTH_TOKEN out varchar2, -- Токен аутентификации для запроса
SDATASET_ID out varchar2, -- Идентификатор выборки данных запроса
CDATASET_CONFIG out clob, -- Описание данных о наработках
SDATASET_URL out varchar2, -- Адрес для получения данных о наработках
SCLASS_MACHINE out varchar2, -- Код класса оборудования для запроса
STASK out varchar2 -- Задача для запроса (см. константы UDO_PKG_EQUIPDS_BASE.SCMML_TASK_*)
);
/* Формирование цвета прогноза для технического объекта */
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="Проверка прав доступа при формировании таблицы и карточки ТО"
*/
/* Константы - адреса 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 => EQCONFIG_THOBJ_FORECAST_CLR(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 => EQCONFIG_THOBJ_FORECAST_CLR(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_EPLG
(
NDATASET_IDENT in number, -- Идентификатор буфера данных
NDATASET_CONFIG_IDENT in number, -- Идентификатор буфера описания данных
NEQCONFIG in number := null, -- Рег. номер технического объекта
NEQUIPDSCMML in number := null, -- Рег. номер модели
CFORECAST in clob := null -- Данные прогноза
)
is
NEQUIPDSCMMLH PKG_STD.TREF; -- Рег. номер истории запросов модели
begin
/* Очистим данные в файловом буфере */
P_FILE_BUFFER_CLEAR(NIDENT => NDATASET_IDENT);
P_FILE_BUFFER_CLEAR(NIDENT => NDATASET_CONFIG_IDENT);
/* Если указаны данные технического объекта */
if ((NEQCONFIG is not null) and (NEQUIPDSCMML is not null)) then
/* Добавляем запись истории запросов */
UDO_PKG_EQUIPDS_BASE.CMMLH_INS(NPRN => NEQUIPDSCMML,
NEQCONFIG => NEQCONFIG,
SRQ_AUTHID => UTILIZER(),
DRQ_DATE => sysdate,
BRQ => null,
NRN => NEQUIPDSCMMLH);
/* Сохраним данные прогноза */
UDO_PKG_EQUIPDS_BASE.CMMLH_SET_FORECAST(NRN => NEQUIPDSCMMLH, BFORECAST => BASE64_DECODE(LCSRCE => CFORECAST));
end if;
end EQCONFIG_THOBJ_FORECAST_EPLG;
/* Подчистка после исполнения запроса на формирование прогноза технического объекта (в автономной транзакции) */
procedure EQCONFIG_THOBJ_FORECAST_EPLGAT
(
NDATASET_IDENT in number, -- Идентификатор буфера данных
NDATASET_CONFIG_IDENT in number -- Идентификатор буфера описания данных
)
is
RPROC_PARAMS PKG_CONTPRMLOC.TCONTAINER; -- Параметры процедуры
begin
/* Очищаем контейнер с параметрами */
PKG_CONTPRMLOC.PURGE(RCONTAINER => RPROC_PARAMS);
/* Собираем параметры процедуры */
PKG_CONTPRMLOC.PUTN(RCONTAINER => RPROC_PARAMS,
SNAME => 'NDATASET_IDENT',
NVALUE => NDATASET_IDENT,
NIN_OUT => PKG_STD.PARAM_TYPE_IN());
PKG_CONTPRMLOC.PUTN(RCONTAINER => RPROC_PARAMS,
SNAME => 'NDATASET_CONFIG_IDENT',
NVALUE => NDATASET_CONFIG_IDENT,
NIN_OUT => PKG_STD.PARAM_TYPE_IN());
/* Подчищаем (в автономной транзакции) */
PKG_SQL_CALL.EXECUTE_STORED_AT(SSTORED_NAME => 'UDO_PKG_EQUIPTCF.EQCONFIG_THOBJ_FORECAST_EPLG',
RPARAM_CONTAINER => RPROC_PARAMS,
BOVERLOAD_ENV => true);
/* Очищаем контейнер с параметрами */
PKG_CONTPRMLOC.PURGE(RCONTAINER => RPROC_PARAMS);
end EQCONFIG_THOBJ_FORECAST_EPLGAT;
/* Подготовка запроса на формирование прогноза технического объекта */
procedure EQCONFIG_THOBJ_FORECAST_PRLG
(
NEQUIPDSCMML in number, -- Рег. номер модели
NDATASET_IDENT in number, -- Идентификатор буфера данных
NDATASET_CONFIG_IDENT in number, -- Идентификатор буфера описания данных
SURL out varchar2, -- Адрес для запроса
SAUTH_TOKEN out varchar2, -- Токен аутентификации для запроса
SDATASET_ID out varchar2, -- Идентификатор выборки данных запроса
CDATASET_CONFIG out clob, -- Описание данных о наработках
SDATASET_URL out varchar2, -- Адрес для получения данных о наработках
SCLASS_MACHINE out varchar2, -- Код класса оборудования для запроса
STASK out varchar2 -- Задача для запроса (см. константы UDO_PKG_EQUIPDS_BASE.SCMML_TASK_*)
)
is
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;
/* Читаем запись модели */
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_EPLGAT(NDATASET_IDENT => NDATASET_IDENT, NDATASET_CONFIG_IDENT => NDATASET_CONFIG_IDENT);
/* Пробросим ошибку */
raise;
end EQCONFIG_THOBJ_FORECAST_PRLG;
/* Формирование цвета прогноза для технического объекта */
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 '<b style="color:red">Опасность</b> - вероятность сбоя более 60%.<br>' || '<b style="color:orange">Внимание</b> - вероятность сбоя от 30% до 60%<br>' || '<b style="color:green">В норме</b> - вероятность сбоев менее 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;
/