diff --git a/db/UDO_PKG_EQUIPDS.pck b/db/UDO_PKG_EQUIPDS.pck
index 40c0707..d4a25f2 100644
--- a/db/UDO_PKG_EQUIPDS.pck
+++ b/db/UDO_PKG_EQUIPDS.pck
@@ -135,11 +135,17 @@ create or replace package UDO_PKG_EQUIPDS as
COUT out clob -- Сериализованная таблица данных
);
- /* Формирование демо-прогноза */
- procedure CMMLH_DEMO_BUILD
+ /* Формирование данных прогноза "Выборки данных оборудования (классы оборудования, модели, история запросов)" */
+ procedure CMMLH_BUILD_FORECAST
(
- STASK in varchar2, -- Задача
- COUT out clob -- Данные демо-прогноза
+ COUT out clob -- Данные прогноза
+ );
+
+ /* Извлечение описания из данных прогноза "Выборки данных оборудования (классы оборудования, модели, история запросов)" */
+ procedure CMMLH_PARSE_FORECAST
+ (
+ CFORECAST in clob, -- Данные прогноза
+ NFORECAST out number -- Значение прогноза
);
/* Список "Выборки данных оборудования (классы оборудования, модели, история запросов)" по единице оборудования */
@@ -757,7 +763,7 @@ text="Проверка прав доступа на работу с ""Выбор
/* Возвращаем результат */
return NRES;
end CMML_STATUS_BY_EQCONFIG;
-
+
/* Список "Выборки данных оборудования (классы оборудования, модели)" по единице оборудования */
procedure CMML_LIST_BY_EQCONFIG
(
@@ -853,45 +859,46 @@ text="Проверка прав доступа на работу с ""Выбор
COUT := PKG_P8PANELS_VISUAL.TDATA_GRID_TO_XML(RDATA_GRID => RDG, NINCLUDE_DEF => 1);
end CMML_LIST_BY_EQCONFIG;
- /* Формирование демо-прогноза */
- procedure CMMLH_DEMO_BUILD
+ /* Формирование данных прогноза "Выборки данных оборудования (классы оборудования, модели, история запросов)" */
+ procedure CMMLH_BUILD_FORECAST
(
- STASK in varchar2, -- Задача
- COUT out clob -- Данные демо-прогноза
+ COUT out clob -- Данные прогноза
)
is
- RCH PKG_P8PANELS_VISUAL.TCHART; -- График
- RCH_DS PKG_P8PANELS_VISUAL.TCHART_DATASET; -- Набор данных
- DMONTH date; -- Месяц прогноза
+ NCUR integer; -- Курсор документа для результата
+ XDOC PKG_XMAKE.TNODE; -- Документ для результата
+ XROOT PKG_XMAKE.TNODE; -- Содержимое корневого узла документа
+ NFORECAST PKG_STD.TNUMBER; -- Прогноз по заданной задаче
begin
- /* Сформируем заголовок графика */
- RCH := PKG_P8PANELS_VISUAL.TCHART_MAKE(STYPE => PKG_P8PANELS_VISUAL.SCHART_TYPE_LINE,
- STITLE => 'Прогноз на 5 месяцев',
- SLGND_POS => PKG_P8PANELS_VISUAL.SCHART_LGND_POS_RIGHT);
- /* Сформируем набор данных */
- RCH_DS := PKG_P8PANELS_VISUAL.TCHART_DATASET_MAKE(SCAPTION => STASK);
- /* Генерируем случайные данные */
- for I in 1 .. 5
- loop
- /* Добавим метку для месяца */
- DMONTH := ADD_MONTHS(sysdate, I);
- PKG_P8PANELS_VISUAL.TCHART_ADD_LABEL(RCHART => RCH,
- SLABEL => F_GET_MONTH(NVALUE => EXTRACT(month from DMONTH)) || ' ' ||
- TO_CHAR(DMONTH, 'yyyy'));
- /* Добавим месяц в набор данных */
- PKG_P8PANELS_VISUAL.TCHART_DATASET_ADD_ITEM(RDATASET => RCH_DS, NVALUE => ROUND(DBMS_RANDOM.VALUE(1, 100)));
- end loop;
- /* Добавим набор данных в график */
- PKG_P8PANELS_VISUAL.TCHART_ADD_DATASET(RCHART => RCH, RDATASET => RCH_DS);
- /* Сериализуем описание */
- COUT := PKG_P8PANELS_VISUAL.TCHART_TO_XML(RCHART => RCH, NINCLUDE_DEF => 1);
- end CMMLH_DEMO_BUILD;
+ /* Вычислим прогноз - количество периодов в указанных ЕИ до достижения предельного состояния */
+ NFORECAST := ROUND(DBMS_RANDOM.VALUE(10, 60));
+ /* Открываем документ */
+ NCUR := PKG_XMAKE.OPEN_CURSOR();
+ /* Заполним прогноз */
+ XROOT := PKG_XMAKE.CONCAT(ICURSOR => NCUR,
+ RNODE00 => XROOT,
+ RNODE01 => PKG_XMAKE.ELEMENT(ICURSOR => NCUR,
+ SNAME => 'NFORECAST',
+ RVALUE00 => PKG_XMAKE.VALUE(ICURSOR => NCUR, NVALUE => NFORECAST)));
+ /* Формируем XML-представление ответа */
+ XDOC := PKG_XMAKE.ELEMENT(ICURSOR => NCUR, SNAME => 'XDATA', RNODE00 => XROOT);
+ /* Конвертируем в CLOB */
+ COUT := PKG_XMAKE.SERIALIZE_TO_CLOB(ICURSOR => NCUR,
+ ITYPE => PKG_XMAKE.CONTENT_,
+ RNODE => XDOC,
+ RHEADER => PKG_XHEADER.WRAP_ALL(SVERSION => PKG_XHEADER.VERSION_1_0_,
+ SENCODING => PKG_XHEADER.ENCODING_UTF_,
+ SSTANDALONE => PKG_XHEADER.STANDALONE_YES_));
+ /* Закрываем документ */
+ PKG_XMAKE.CLOSE_CURSOR(ICURSOR => NCUR);
+ end CMMLH_BUILD_FORECAST;
- /* Извлечение прогноза из демо-данных */
- function CMMLH_DEMO_FORECAST_PARSE
+ /* Извлечение описания из данных прогноза "Выборки данных оборудования (классы оборудования, модели, история запросов)" */
+ procedure CMMLH_PARSE_FORECAST
(
- CFORECAST in clob -- Данные демо-прогноза
- ) return number -- Прогнозное значение
+ CFORECAST in clob, -- Данные прогноза
+ NFORECAST out number -- Значение прогноза
+ )
is
XDOC PKG_XPATH.TDOCUMENT; -- Десериализованный демо-прогноз
XROOT PKG_XPATH.TNODE; -- Корневой элемент данных
@@ -900,13 +907,12 @@ text="Проверка прав доступа на работу с ""Выбор
XDOC := PKG_XPATH.PARSE_FROM_CLOB(LCXML => CFORECAST);
/* Извлекаем корневой элемент */
XROOT := PKG_XPATH.ROOT_NODE(RDOCUMENT => XDOC);
- /* Возвращаем значение за ближайший месяц */
- return PKG_XPATH.VALUE_NUM(RNODE => PKG_XPATH.SINGLE_NODE(RPARENT_NODE => XROOT,
- SPATTERN => 'XDATA/XCHART/datasets/data'));
+ /* Читаем прогноз */
+ NFORECAST := PKG_XPATH.VALUE_NUM(RNODE => PKG_XPATH.SINGLE_NODE(RPARENT_NODE => XROOT, SPATTERN => 'XDATA/NFORECAST'));
exception
when others then
- return null;
- end CMMLH_DEMO_FORECAST_PARSE;
+ null;
+ end CMMLH_PARSE_FORECAST;
/* Список "Выборки данных оборудования (классы оборудования, модели, история запросов)" по единице оборудования */
procedure CMMLH_LIST_BY_EQCONFIG
@@ -948,41 +954,62 @@ text="Проверка прав доступа на работу с ""Выбор
SCAPTION => 'Точность (факт)',
SDATA_TYPE => PKG_P8PANELS_VISUAL.SDATA_TYPE_NUMB);
PKG_P8PANELS_VISUAL.TDATA_GRID_ADD_COL_DEF(RDATA_GRID => RDG,
- SNAME => 'NFORECAST',
+ SNAME => 'STO_FORECAST_DESC',
SCAPTION => 'Прогноз',
- SDATA_TYPE => PKG_P8PANELS_VISUAL.SDATA_TYPE_NUMB,
- SHINT => 'Опасность - вероятность сбоя более 60%.
' ||
- 'Внимание - вероятность сбоя от 30% до 60%
' ||
- 'В норме - вероятность сбоев менее 30%');
+ SDATA_TYPE => PKG_P8PANELS_VISUAL.SDATA_TYPE_STR,
+ SHINT => 'Формат прогноза: "XXЕИ / YY%", где
' ||
+ 'XXЕИ - время до перехода в критическое состояние в ЕИ ресурса единицы оборудования (часы/дни/месяцы/рабочие циклы и т.п.)
' ||
+ 'YY% - вероятность перехода в критическое состояние до следующего ТО и ремонта
' ||
+ 'Цвет прогноза:
' || UDO_PKG_EQUIPTCF.EQCONFIG_THOBJ_FORECAST_CLR(NMODE => 0));
PKG_P8PANELS_VISUAL.TDATA_GRID_ADD_COL_DEF(RDATA_GRID => RDG,
- SNAME => 'SFORECAST',
- SCAPTION => 'Данные прогноза',
+ SNAME => 'STO_FORECAST_DESC_COLOR',
+ SCAPTION => 'Цвет прогноза',
+ SDATA_TYPE => PKG_P8PANELS_VISUAL.SDATA_TYPE_STR,
+ BVISIBLE => false);
+ PKG_P8PANELS_VISUAL.TDATA_GRID_ADD_COL_DEF(RDATA_GRID => RDG,
+ SNAME => 'STO_FORECAST',
+ SCAPTION => 'Данные карточки прогноза для конкретного технического объекта',
SDATA_TYPE => PKG_P8PANELS_VISUAL.SDATA_TYPE_STR,
BVISIBLE => false);
/* Обходим данные */
for C in (select T.RN NRN,
T.RQ_AUTHID SRQ_AUTHID,
+ T.RQ_DATE DRQ_DATE,
TO_CHAR(T.RQ_DATE, 'dd.mm.yyyy hh24:mi:ss') SRQ_DATE,
DS.CODE SEQUIPDS_CODE,
ML.TASK SEQUIPDSCMML_TASK,
ML.PRECISION_F NEQUIPDSCMML_PRECISION_F,
+ DM.MEAS_MNEMO SDICMUNTS,
+ T.FORECAST BFORECAST,
null NFORECAST,
- null SFORECAST,
- T.FORECAST BFORECAST
+ null STO_FORECAST_DESC,
+ null STO_FORECAST_DESC_COLOR,
+ null STO_FORECAST
from UDO_T_EQUIPDSCMMLH T,
UDO_T_EQUIPDSCMML ML,
UDO_T_EQUIPDSCM CM,
- UDO_T_EQUIPDS DS
+ UDO_T_EQUIPDS DS,
+ DICMUNTS DM
where T.EQCONFIG = NEQCONFIG
and T.PRN = ML.RN
and ML.PRN = CM.RN
and CM.PRN = DS.RN
+ and CM.DICMUNTS = DM.RN
order by T.RN desc)
loop
- /* Конвертируем данные прогноза */
- C.SFORECAST := BLOB2CLOB(LBDATA => C.BFORECAST);
- /* Извлекаем прогноз */
- C.NFORECAST := CMMLH_DEMO_FORECAST_PARSE(CFORECAST => C.SFORECAST);
+ /* Извлекаем данные из прогноза фреймворка */
+ CMMLH_PARSE_FORECAST(CFORECAST => BLOB2CLOB(LBDATA => C.BFORECAST), NFORECAST => C.NFORECAST);
+ /* Формируем данные карточки прогноза для конкретного тех. объекта */
+ UDO_PKG_EQUIPTCF.EQCONFIG_THOBJ_FORECAST_CRD(NEQCONFIG => NEQCONFIG,
+ DFORECAST_DATE => C.DRQ_DATE,
+ NFORECAST => C.NFORECAST,
+ SDICMUNTS => C.SDICMUNTS,
+ STASK => C.SEQUIPDSCMML_TASK,
+ COUT => C.STO_FORECAST);
+ /* Извлекаем прогноз и цвет для видимой колонки таблицы из карточки прогноза для конкретного тех. объекта */
+ UDO_PKG_EQUIPTCF.EQCONFIG_THOBJ_FORECAST_CRDP(CFORECAST => C.STO_FORECAST,
+ SFORECAST_DESC => C.STO_FORECAST_DESC,
+ SFORECAST_DESC_COLOR => C.STO_FORECAST_DESC_COLOR);
/* Добавляем колонки с данными */
PKG_P8PANELS_VISUAL.TROW_ADD_COL(RROW => RDG_ROW, SNAME => 'NRN', NVALUE => C.NRN, BCLEAR => true);
PKG_P8PANELS_VISUAL.TROW_ADD_COL(RROW => RDG_ROW, SNAME => 'SRQ_AUTHID', SVALUE => C.SRQ_AUTHID);
@@ -992,8 +1019,11 @@ text="Проверка прав доступа на работу с ""Выбор
PKG_P8PANELS_VISUAL.TROW_ADD_COL(RROW => RDG_ROW,
SNAME => 'NEQUIPDSCMML_PRECISION_F',
NVALUE => C.NEQUIPDSCMML_PRECISION_F);
- PKG_P8PANELS_VISUAL.TROW_ADD_COL(RROW => RDG_ROW, SNAME => 'NFORECAST', NVALUE => C.NFORECAST);
- PKG_P8PANELS_VISUAL.TROW_ADD_COL(RROW => RDG_ROW, SNAME => 'SFORECAST', SVALUE => C.SFORECAST);
+ PKG_P8PANELS_VISUAL.TROW_ADD_COL(RROW => RDG_ROW, SNAME => 'STO_FORECAST_DESC', SVALUE => C.STO_FORECAST_DESC);
+ PKG_P8PANELS_VISUAL.TROW_ADD_COL(RROW => RDG_ROW,
+ SNAME => 'STO_FORECAST_DESC_COLOR',
+ SVALUE => C.STO_FORECAST_DESC_COLOR);
+ PKG_P8PANELS_VISUAL.TROW_ADD_COL(RROW => RDG_ROW, SNAME => 'STO_FORECAST', SVALUE => C.STO_FORECAST);
/* Добавляем строку в таблицу */
PKG_P8PANELS_VISUAL.TDATA_GRID_ADD_ROW(RDATA_GRID => RDG, RROW => RDG_ROW);
end loop;
diff --git a/db/UDO_PKG_EQUIPDS_BASE.pck b/db/UDO_PKG_EQUIPDS_BASE.pck
index 1919b93..568c4f4 100644
--- a/db/UDO_PKG_EQUIPDS_BASE.pck
+++ b/db/UDO_PKG_EQUIPDS_BASE.pck
@@ -189,6 +189,12 @@ create or replace package UDO_PKG_EQUIPDS_BASE as
SERR in varchar2 -- Сообщение об ошибке
);
+ /* Формирование наименования для задачи "Выборки данных оборудования (классы оборудования, модели)" */
+ function CMML_TASK_NAME
+ (
+ STASK in varchar2 -- Задача (TCF - оценка технического состояния (Technical Condition Forecast), RUL - прогнозирование остаточного ресурса (Remaining Useful Life), FP - Прогнозирование отказа (Failure Predict)) */
+ ) return varchar2; -- Наименование задачи
+
/* Формирование подсказки для задачи "Выборки данных оборудования (классы оборудования, модели)" */
function CMML_TASK_HINT
return varchar2; -- Подсказка для задачи
@@ -687,12 +693,33 @@ create or replace package body UDO_PKG_EQUIPDS_BASE as
where T.RN = NRN;
end CMML_SET_STATUS;
+ /* Формирование наименования для задачи "Выборки данных оборудования (классы оборудования, модели)" */
+ function CMML_TASK_NAME
+ (
+ STASK in varchar2 -- Задача (TCF - оценка технического состояния (Technical Condition Forecast), RUL - прогнозирование остаточного ресурса (Remaining Useful Life), FP - Прогнозирование отказа (Failure Predict)) */
+ ) return varchar2 -- Наименование задачи
+ is
+ begin
+ case STASK
+ when 'TCF' then
+ return 'Оценка технического состояния';
+ when 'RUL' then
+ return 'Прогноз остаточного ресурса';
+ when 'FP' then
+ return 'Прогноз отказа';
+ else
+ return 'Вид задачи оценки не поддерживается';
+ end case;
+ end CMML_TASK_NAME;
+
/* Формирование подсказки для задачи "Выборки данных оборудования (классы оборудования, модели)" */
function CMML_TASK_HINT
return varchar2 -- Подсказка для задачи
is
begin
- return 'TCF - Оценка технического состояния (Technical Condition Forecast)
' || 'RUL - Прогнозирование остаточного ресурса (Remaining Useful Life)
' || 'FP - Прогнозирование отказа (Failure Predict)';
+ return 'TCF - ' || CMML_TASK_NAME(STASK => 'TCF') || ' (Technical Condition Forecast)
' ||
+ 'RUL - ' || CMML_TASK_NAME(STASK => 'RUL') || ' (Remaining Useful Life)
' ||
+ 'FP - ' || CMML_TASK_NAME(STASK => 'FP') || ' (Failure Predict)';
end CMML_TASK_HINT;
/* Базовое добавление "Выборки данных оборудования (классы оборудования, модели, история запросов)" */
diff --git a/db/UDO_PKG_EQUIPTCF.pck b/db/UDO_PKG_EQUIPTCF.pck
index 382df1c..8d22dbf 100644
--- a/db/UDO_PKG_EQUIPTCF.pck
+++ b/db/UDO_PKG_EQUIPTCF.pck
@@ -22,6 +22,13 @@ create or replace package UDO_PKG_EQUIPTCF as
COUT out clob -- Сериализованная таблица данных
);
+ /* Получение даты следующего технического обслуживания технического объекта */
+ function EQCONFIG_THOBJ_GET_NXTEQTCHSRV
+ (
+ NEQCONFIG in number, -- Рег. номер технического объекта
+ NSTATE in number := null -- Состояние (null - любое)
+ ) return date; -- Дата следующего технического обслуживания
+
/* Выбор графиков технического обслуживания и ремонта технического объекта */
procedure EQCONFIG_THOBJ_SELECT_EQTCHSRV
(
@@ -31,6 +38,22 @@ create or replace package UDO_PKG_EQUIPTCF as
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
(
@@ -45,6 +68,38 @@ create or replace package UDO_PKG_EQUIPTCF as
NEQUIPDSCMML in number -- Рег. номер модели
);
+ /* Формирование цвета прогноза для технического объекта */
+ function EQCONFIG_THOBJ_FORECAST_CLR
+ (
+ NMODE in number := 0, -- Режим работы (0 - для подсказки в колонке таблицы, 1 - для колонки таблицы, 2 - для карточки детализации
+ NVALUE in number :=0 -- Значение для подсветки
+ ) return varchar2; -- Запрошенное значение в зависимости от режима
+
+ /* Формирование детальной карточки прогноза для технического объекта */
+ procedure EQCONFIG_THOBJ_FORECAST_CRD
+ (
+ NEQCONFIG in number, -- Рег. номер позиции состава оборудования
+ DFORECAST_DATE in date, -- Дата получения прогноза
+ NFORECAST in number, -- Прогнозное значение, полученное от фреймворка
+ SDICMUNTS in varchar2, -- Единица измерения выборки
+ STASK in varchar2, -- Задача (TCF - оценка технического состояния (Technical Condition Forecast), RUL - прогнозирование остаточного ресурса (Remaining Useful Life), FP - Прогнозирование отказа (Failure Predict)) */
+ 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
(
@@ -62,7 +117,7 @@ create or replace package UDO_PKG_EQUIPTCF as
DPLANDATE_FROM in date, -- Плановая дата начала ремонта
NIDENT out number -- Идентификатор списка сформированных ведомостей
);
-
+
end UDO_PKG_EQUIPTCF;
/
create or replace package body UDO_PKG_EQUIPTCF as
@@ -197,6 +252,30 @@ text="Проверка прав доступа при формировании
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;
/* Формирование списка технических объектов для выбранного узла состава оборудования */
@@ -222,6 +301,7 @@ text="Проверка прав доступа при формировании
NROW_TO PKG_STD.TREF; -- Номер строки по
CSQL clob; -- Буфер для запроса
ICURSOR integer; -- Курсор для исполнения запроса
+ NBREAKDOWN_PROB PKG_STD.TNUMBER; -- Вероятность выхода единицы оборудования из строя
begin
/* Читаем фильтры */
RF := PKG_P8PANELS_VISUAL.TFILTERS_FROM_XML(CFILTERS => CFILTERS);
@@ -295,6 +375,18 @@ text="Проверка прав доступа при формировании
BORDER => true,
BFILTER => true,
RCOL_VALS => RCOL_VALS);
+ PKG_P8PANELS_VISUAL.TDATA_GRID_ADD_COL_DEF(RDATA_GRID => RDG,
+ SNAME => 'NBREAKDOWN_PROB',
+ SCAPTION => 'Вероятность выхода из строя',
+ SDATA_TYPE => PKG_P8PANELS_VISUAL.SDATA_TYPE_NUMB,
+ BORDER => true,
+ BFILTER => true,
+ SHINT => EQCONFIG_THOBJ_FORECAST_CLR(NMODE => 0));
+ PKG_P8PANELS_VISUAL.TDATA_GRID_ADD_COL_DEF(RDATA_GRID => RDG,
+ SNAME => 'SBREAKDOWN_PROB_COLOR',
+ SCAPTION => 'Цвет вероятности выхода из строя',
+ SDATA_TYPE => PKG_P8PANELS_VISUAL.SDATA_TYPE_STR,
+ BVISIBLE => false);
/* Обходим данные */
begin
/* Добавляем подсказку совместимости */
@@ -312,10 +404,11 @@ text="Проверка прав доступа при формировании
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_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 => ' 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');
@@ -350,6 +443,7 @@ text="Проверка прав доступа при формировании
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;
@@ -388,11 +482,16 @@ text="Проверка прав доступа при формировании
PKG_P8PANELS_VISUAL.TROW_ADD_CUR_COLS(RROW => RDG_ROW,
SNAME => 'SUMEAS_RES',
ICURSOR => ICURSOR,
- NPOSITION => 9);
+ NPOSITION => 9);
PKG_P8PANELS_VISUAL.TROW_ADD_CUR_COLN(RROW => RDG_ROW,
SNAME => 'NCMML_STATUS',
ICURSOR => ICURSOR,
NPOSITION => 10);
+ PKG_SQL_DML.COLUMN_VALUE_NUM(ICURSOR => ICURSOR, IPOSITION => 11, NVALUE => NBREAKDOWN_PROB);
+ PKG_P8PANELS_VISUAL.TROW_ADD_COL(RROW => RDG_ROW, SNAME => 'NBREAKDOWN_PROB', NVALUE => NBREAKDOWN_PROB);
+ PKG_P8PANELS_VISUAL.TROW_ADD_COL(RROW => RDG_ROW,
+ SNAME => 'SBREAKDOWN_PROB_COLOR',
+ SVALUE => EQCONFIG_THOBJ_FORECAST_CLR(NMODE => 1, NVALUE => NBREAKDOWN_PROB));
/* Добавляем строку в таблицу */
PKG_P8PANELS_VISUAL.TDATA_GRID_ADD_ROW(RDATA_GRID => RDG, RROW => RDG_ROW);
end loop;
@@ -416,7 +515,7 @@ text="Проверка прав доступа при формировании
is
DRES PKG_STD.TLDATE; -- Буфер для результата
begin
- /* Найдем график ТО и ремонтов, утвержденный, с минимальной датой по данному тех. объекту */
+ /* Найдем график ТО и ремонтов, в заданном состоянии, с минимальной датой по данному тех. объекту */
select min(T.DATEPRD_BEG)
into DRES
from EQTCHSRV T
@@ -458,6 +557,57 @@ text="Проверка прав доступа при формировании
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;
+
/* Формирование карточки технического объекта */
procedure EQCONFIG_THOBJ_CARD
(
@@ -503,6 +653,10 @@ text="Проверка прав доступа при формировании
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;
@@ -537,13 +691,282 @@ text="Проверка прав доступа при формировании
BRQ => null,
NRN => NEQUIPDSCMMLH);
/* Добавим демо-данные */
- for C in (select T.TASK from UDO_T_EQUIPDSCMML T where T.RN = NEQUIPDSCMML)
+ for C in (select T.TASK STASK,
+ DM.MEAS_MNEMO SDICMUNTS
+ from UDO_T_EQUIPDSCMML T,
+ UDO_T_EQUIPDSCM CM,
+ DICMUNTS DM
+ where T.RN = NEQUIPDSCMML
+ and T.PRN = CM.RN
+ and CM.DICMUNTS = DM.RN)
loop
- UDO_PKG_EQUIPDS.CMMLH_DEMO_BUILD(STASK => C.TASK, COUT => CDEMO);
+ UDO_PKG_EQUIPDS.CMMLH_BUILD_FORECAST(COUT => CDEMO);
UDO_PKG_EQUIPDS_BASE.CMMLH_SET_FORECAST(NRN => NEQUIPDSCMMLH, BFORECAST => CLOB2BLOB(LCDATA => CDEMO));
end loop;
end EQCONFIG_THOBJ_FORECAST;
+ /* Формирование цвета прогноза для технического объекта */
+ function EQCONFIG_THOBJ_FORECAST_CLR
+ (
+ NMODE in number := 0, -- Режим работы (0 - для подсказки в колонке таблицы, 1 - для колонки таблицы, 2 - для карточки детализации
+ NVALUE in number :=0 -- Значение для подсветки
+ ) return varchar2 -- Запрошенное значение в зависимости от режима
+ is
+ begin
+ /* Работаем от режима */
+ case NMODE
+ /* Для подсказки в колонке таблицы */
+ when 0 then
+ return 'Опасность - вероятность сбоя более 60%.
' || 'Внимание - вероятность сбоя от 30% до 60%
' || 'В норме - вероятность сбоев менее 30%';
+ /* Для колонки таблицы */
+ when 1 then
+ begin
+ if (NVALUE < 30) then
+ return 'success';
+ else
+ if ((NVALUE >= 30) and (NVALUE < 60)) then
+ return 'warning';
+ else
+ return 'error';
+ end if;
+ end if;
+ end;
+ /* Для карточки детализации */
+ when 2 then
+ begin
+ if (NVALUE < 30) then
+ return 'success.main';
+ else
+ if ((NVALUE >= 30) and (NVALUE < 60)) then
+ return 'warning.main';
+ else
+ return 'error.main';
+ end if;
+ end if;
+ end;
+ /* Неверный режим */
+ else
+ return null;
+ end case;
+ end EQCONFIG_THOBJ_FORECAST_CLR;
+
+ /* Формирование детальной карточки прогноза для технического объекта */
+ procedure EQCONFIG_THOBJ_FORECAST_CRD
+ (
+ NEQCONFIG in number, -- Рег. номер позиции состава оборудования
+ DFORECAST_DATE in date, -- Дата получения прогноза
+ NFORECAST in number, -- Прогнозное значение, полученное от фреймворка
+ SDICMUNTS in varchar2, -- Единица измерения выборки
+ STASK in varchar2, -- Задача (TCF - оценка технического состояния (Technical Condition Forecast), RUL - прогнозирование остаточного ресурса (Remaining Useful Life), FP - Прогнозирование отказа (Failure Predict)) */
+ 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 := UDO_PKG_EQUIPTCF.EQCONFIG_THOBJ_GET_NXTEQTCHSRV(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.SEQTCHSRV,
+ D.DDATEPRD_BEG
+ from (select trim(COALESCE(K.CODE, ' ') || ' ' || TO_CHAR(T.DATEPRD_BEG, 'dd.mm.yyyy')) SEQTCHSRV,
+ T.DATEPRD_BEG DDATEPRD_BEG
+ from EQTCHSRV T,
+ EQTECSRVKIND K
+ where T.EQCONFIG_TECH = NEQCONFIG
+ and T.DATEPRD_BEG >= sysdate
+ and T.EQTECSRVKIND = K.RN(+)
+ order by T.DATEPRD_BEG) D
+ where ROWNUM <= 5)
+ loop
+ /* Добавим метку для графика */
+ PKG_P8PANELS_VISUAL.TCHART_ADD_LABEL(RCHART => RCH, SLABEL => C.SEQTCHSRV);
+ /* Добавим график в набор данных */
+ if (sysdate + NFORECAST > C.DDATEPRD_BEG) then
+ NBREAKDOWN_PROB_CUR := 0;
+ else
+ NBREAKDOWN_PROB_CUR := 100 - ROUND((NFORECAST - (TRUNC(sysdate) - TRUNC(DFORECAST_DATE))) /
+ (C.DDATEPRD_BEG - sysdate) * 100);
+ if (NBREAKDOWN_PROB_CUR > 100) then
+ NBREAKDOWN_PROB_CUR := 100;
+ end if;
+ if (NBREAKDOWN_PROB is null) then
+ NBREAKDOWN_PROB := NBREAKDOWN_PROB_CUR;
+ end if;
+ 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; -- Значение самго свежего прогноза модели
+ DNXTEQTCHSRV PKG_STD.TLDATE; -- Дата ближайшего ТО или ремонта
+ begin
+ /* Определим дату ближайшего ТО или ремонта */
+ DNXTEQTCHSRV := EQCONFIG_THOBJ_GET_NXTEQTCHSRV(NEQCONFIG => NEQCONFIG);
+ /* Если дата есть */
+ if (DNXTEQTCHSRV 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 = '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 := 100 - ROUND((NFORECAST - (TRUNC(sysdate) - TRUNC(DFORECAST_DATE))) / (DNXTEQTCHSRV - sysdate) * 100);
+ end if;
+ end if;
+ /* Вернём то, что собрали */
+ return NRES;
+ end EQCONFIG_THOBJ_TCHSRV_BRKDPROB;
+
/* Модификация графика ТО и ремонтов для технического объекта */
procedure EQCONFIG_THOBJ_CHNG_EQTCHSRV
(
@@ -591,6 +1014,10 @@ text="Проверка прав доступа при формировании
'Выбранный график ТО и ремонтов уже запланирован на %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;
@@ -615,6 +1042,13 @@ text="Проверка прав доступа при формировании
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;
/* Формирование ремонтной ведомости для технического объекта */
@@ -635,8 +1069,7 @@ text="Проверка прав доступа при формировании
SDOCTYPES PKG_STD.TSTRING; -- Тип документа ведомости
SPREF PKG_STD.TSTRING; -- Префикс ведосмости
SNUMB PKG_STD.TSTRING; -- Номер ведомости
- NEQRPSHEET PKG_STD.TREF; -- Рег. номер сформированной ведомости
- NSELECTLIST PKG_STD.TREF; -- Рег. номер позиции списк сформированных ведомостей
+ NEQRPSHEET PKG_STD.TREF; -- Рег. номер сформированной ведомости
begin
/* Определяем юридическую принадлежность технического объекта */
begin
@@ -688,12 +1121,8 @@ text="Проверка прав доступа при формировании
SEQOBJKIND => null,
NRN => NEQRPSHEET);
/* Добавим ведомость в список */
- NIDENT := GEN_IDENT();
- P_SELECTLIST_INSERT(NIDENT => NIDENT,
- NDOCUMENT => NEQRPSHEET,
- SUNITCODE => 'EquipRepairSheets',
- NRN => NSELECTLIST);
+ EQCONFIG_THOBJ_SELECT_EQRPSHT(NEQRPSHEETS => NEQRPSHEET, NIDENT => NIDENT);
end EQCONFIG_THOBJ_MAKE_EQRPSHEET;
-
+
end UDO_PKG_EQUIPTCF;
/
diff --git a/panels/eqs_tech_cond_forecast/forecast_tab.js b/panels/eqs_tech_cond_forecast/forecast_tab.js
index 6d08e6c..7e341d1 100644
--- a/panels/eqs_tech_cond_forecast/forecast_tab.js
+++ b/panels/eqs_tech_cond_forecast/forecast_tab.js
@@ -50,7 +50,7 @@ const DIALOGS_INITIAL = { makeEqRpSheet: false, makeEqDataSet: false, techObjCar
//Начальное состояние спецификации технических объектов
const TECH_OBJ_SPEC_INITIAL = {
- parent: 8938140,
+ parent: null,
filters: [],
orders: [],
pageNumber: 1
@@ -92,7 +92,7 @@ const ForecastTab = ({ onGoToAdmin }) => {
const { InlineMsgInfo } = useContext(MessagingСtx);
//Подключение к контексту приложения
- const { pOnlineShowUnit } = useContext(ApplicationСtx);
+ const { pOnlineShowUnit, pOnlineShowDictionary } = useContext(ApplicationСtx);
//Собственное состояние - текущая загружаемая ветка
const [loadingTreeItem, setLoadingTreeItem] = useState(0);
@@ -130,6 +130,12 @@ const ForecastTab = ({ onGoToAdmin }) => {
//Загрузчик истории прогнозов выбранного технического объекта
const { techObjForecastHistList } = useTechObjForecastHistList(techObj.id, refresh.techObjForecastHistList);
+ //Принудительное обновление текущей спецификации технических обхектов
+ const refreshTechObjSpec = () => {
+ if (techObjSpec.pageNumber == 1) setRefresh(pv => ({ ...pv, techObjSpec: pv.techObjSpec + 1 }));
+ else setTechObjSpec(pv => ({ ...pv, pageNumber: 1 }));
+ };
+
//Обработка развёртывания/свёртывания уровня дерева
const handleTreeItemExpansionToggle = (event, itemId, isExpanded) =>
isExpanded && needLoadLevel(eQconfigTree, itemId) ? setLoadingTreeItem(parseInt(itemId)) : null;
@@ -171,6 +177,7 @@ const ForecastTab = ({ onGoToAdmin }) => {
//При закрытии карточки технического объекта
const handleTechObjeCardClose = () => {
+ refreshTechObjSpec();
setDialogs(pv => ({ ...pv, techObjCard: false }));
setTechObj(TECH_OBJ_INITIAL);
};
@@ -196,7 +203,12 @@ const ForecastTab = ({ onGoToAdmin }) => {
}
});
setDialogs(pv => ({ ...pv, makeEqRpSheet: false }));
- pOnlineShowUnit({ unitCode: "EquipRepairSheets", showMethod: "main_selected", inputParameters: [{ name: "in_Ident", value: data.NIDENT }] });
+ pOnlineShowDictionary({
+ unitCode: "EquipRepairSheets",
+ showMethod: "main_selected",
+ inputParameters: [{ name: "in_Ident", value: data.NIDENT }],
+ callBack: handleCardDataRefresh
+ });
};
//При нажитии "Отмена" в диалоге формирования ремонтной ведомости
@@ -212,14 +224,16 @@ const ForecastTab = ({ onGoToAdmin }) => {
DPLANDATE_FROM: new Date(values.planDateFrom)
}
});
- handleCardDataRefresh();
+ setRefresh(pv => ({ ...pv, techObjForecastHistList: pv.techObjForecastHistList + 1, techObjCard: pv.techObjCard + 1 }));
setDialogs(pv => ({ ...pv, changeEqTchSrv: false }));
- const data = await executeStored({ stored: "UDO_PKG_EQUIPTCF.EQCONFIG_THOBJ_SELECT_EQTCHSRV", args: { NEQTCHSRV: values.eQTchSrv } });
- if (data.NIDENT)
- pOnlineShowUnit({
- unitCode: "EquipTechServices",
- inputParameters: [{ name: "in_SelectList_Ident", value: data.NIDENT }]
- });
+ if (values?.showEqTchSrv == 1) {
+ const data = await executeStored({ stored: "UDO_PKG_EQUIPTCF.EQCONFIG_THOBJ_SELECT_EQTCHSRV", args: { NEQTCHSRV: values.eQTchSrv } });
+ if (data.NIDENT)
+ pOnlineShowUnit({
+ unitCode: "EquipTechServices",
+ inputParameters: [{ name: "in_SelectList_Ident", value: data.NIDENT }]
+ });
+ }
};
//При нажитии "Отмена" в диалоге корректировки графика ТО и ремонтов
@@ -246,8 +260,7 @@ const ForecastTab = ({ onGoToAdmin }) => {
});
setDialogs(pv => ({ ...pv, makeEqDataSet: false }));
if (onGoToAdmin) onGoToAdmin(data.NEQUIPDS, data.NEQUIPDSCM);
- if (techObjSpec.pageNumber == 1) setRefresh(pv => ({ ...pv, techObjSpec: pv.techObjSpec + 1 }));
- else setTechObjSpec(pv => ({ ...pv, pageNumber: 1 }));
+ refreshTechObjSpec();
};
//При нажитии "Отмена" в диалоге формирования выборки данных
diff --git a/panels/eqs_tech_cond_forecast/forecast_tab_layout.js b/panels/eqs_tech_cond_forecast/forecast_tab_layout.js
index 710dd50..02c06fa 100644
--- a/panels/eqs_tech_cond_forecast/forecast_tab_layout.js
+++ b/panels/eqs_tech_cond_forecast/forecast_tab_layout.js
@@ -9,7 +9,7 @@
import React, { useState, useEffect, useContext } from "react"; //Классы React
import PropTypes from "prop-types"; //Контроль свойств компонента
-import { Stack, Card, CardContent, Typography, Button, Link, Dialog, DialogTitle, DialogContent, DialogActions } from "@mui/material"; //Интерфейсные компоненты
+import { Stack, Card, CardContent, Typography, Button, Link, Dialog, DialogTitle, DialogContent, DialogActions, Paper, Box } from "@mui/material"; //Интерфейсные компоненты
import { useTheme } from "@mui/material/styles"; //Темы оформления
import { ApplicationСtx } from "../../context/application"; //Контекст приложения
import { BackEndСtx } from "../../context/backend"; //Контекст взаимодействия с серверомs
@@ -46,7 +46,7 @@ const STYLES = {
...SCROLL_STYLES
},
TECH_OBJ_FORECAST_DETAIL_DIALOG: { maxWidth: "600px" },
- TECH_OBJ_FORECAST_DETAIL_CHART: { width: "550px", display: "flex", justifyContent: "center" },
+ TECH_OBJ_FORECAST_DETAIL_CHART: { width: "550px", display: "flex", justifyContent: "center", paddingTop: "20px" },
TECH_OBJ_MAKE_DATASET_DIALOG_CONTENT: { ...SCROLL_STYLES }
};
@@ -98,35 +98,56 @@ const techObjCardModelsTableDataCellRender = ({ row, columnDef, theme, onGoToMod
}
};
+//Форматирование заголовка таблицы истории прогнозов класса оборудования выборки данных
+const techObjCardForecastListTableHeadCellRender = ({ columnDef }) => {
+ switch (columnDef.name) {
+ case "STO_FORECAST_DESC":
+ return {
+ stackProps: { justifyContent: "right" },
+ cellProps: { align: "right" }
+ };
+ }
+};
+
//Форматирование колонок таблицы истории прогнозов класса оборудования выборки данных
const techObjCardForecastListTableDataCellRender = ({ row, columnDef, onShowForecastDetail }) => {
switch (columnDef.name) {
- case "NFORECAST":
+ case "STO_FORECAST_DESC":
return {
- data: (
-
)
};
+ case "NBREAKDOWN_PROB":
+ return {
+ data: row[columnDef.name] ? (
+ (onCMMLStatus ? onCMMLStatus(event, row) : null)}>
+ {`${row[columnDef.name]}%`}
+
+ ) : null
+ };
}
};
@@ -234,20 +295,33 @@ const TechObjCard = ({
//При нажатии на отображение деталей прогноза
const handleShowForecastDetailClick = modelHist => {
- setState(pv => ({ ...pv, forecastDetail: modelHist.SFORECAST, forecastDate: modelHist.SRQ_DATE }));
+ setState(pv => ({ ...pv, forecastDetail: modelHist.STO_FORECAST, forecastDate: modelHist.SRQ_DATE }));
};
//При нажатии на закрытие деталей прогноза
const handleCloseForecastDetailClick = () => setState(pv => ({ ...pv, forecastDetail: null, forecastDate: null }));
- //При нажатии на дату следующего обслуживания
+ //При нажатии на дату следующего обслуживания согласно графику ТО и ремонтов
const handleNextRepairClick = async () => {
const data = await executeStored({ stored: "UDO_PKG_EQUIPTCF.EQCONFIG_THOBJ_SELECT_EQTCHSRV", args: { NEQCONFIG: cardData.NRN } });
if (data.NIDENT)
pOnlineShowDictionary({
unitCode: "EquipTechServices",
inputParameters: [{ name: "in_SelectList_Ident", value: data.NIDENT }],
- callBack: res => (res.success && onCardDataRefresh ? onCardDataRefresh() : null)
+ callBack: () => (onCardDataRefresh ? onCardDataRefresh() : null)
+ });
+ else showMsgErr(TEXTS.NO_DATA_FOUND);
+ };
+
+ //При нажатии надату следующего ремонта согласно ремнтной ведомости
+ const handleNextRepairSheetClick = async () => {
+ const data = await executeStored({ stored: "UDO_PKG_EQUIPTCF.EQCONFIG_THOBJ_SELECT_EQRPSHT", args: { NEQCONFIG: cardData.NRN } });
+ if (data.NIDENT)
+ pOnlineShowDictionary({
+ unitCode: "EquipRepairSheets",
+ showMethod: "main_selected",
+ inputParameters: [{ name: "in_Ident", value: data.NIDENT }],
+ callBack: () => (onCardDataRefresh ? onCardDataRefresh() : null)
});
else showMsgErr(TEXTS.NO_DATA_FOUND);
};
@@ -267,14 +341,30 @@ const TechObjCard = ({
{`${formatDateRF(cardData.DOPER_DATE)}, ${cardData.SEQOBJKIND}`}
- {cardData.DNEXT_EQTCHSRV ? (
-
- Следующее ТО:{" "}
+
+ Следующее ТО/ремонт по графику (план):{" "}
+ {cardData.DNEXT_EQTCHSRV ? (
{cardData.DNEXT_EQTCHSRV}
-
- ) : null}
+ ) : (
+
+ Нет графиков ТО и ремонтов
+
+ )}
+
+
+ Включен в ремонты на (факт):{" "}
+ {cardData.DNEXT_EQRPSHEET ? (
+
+ {cardData.DNEXT_EQRPSHEET}
+
+ ) : (
+
+ Нет ремонтных ведомостей
+
+ )}
+
{modelsList.init ? (
@@ -319,6 +409,7 @@ const TechObjCard = ({
morePages={false}
fixedHeader={true}
reloading={false}
+ headCellRender={techObjCardForecastListTableHeadCellRender}
dataCellRender={prms =>
techObjCardForecastListTableDataCellRender({
...prms,
@@ -376,7 +467,8 @@ const TechObjChangeEqTchSrv = ({ eQConfig, onOk, onCancel }) => {
const [values, setValues] = useState({
eQTchSrv: "",
eQTchSrvDesc: "",
- planDateFrom: ""
+ planDateFrom: "",
+ showEqTchSrv: 0
});
//Отработка воода значения в форму
@@ -433,6 +525,16 @@ const TechObjChangeEqTchSrv = ({ eQConfig, onOk, onCancel }) => {
onChange={handleValueChanged}
type={"date"}
/>
+
(onOk ? onOk(values) : null)}>{BUTTONS.OK}