Расчет вероятности выхода из строи и формирование прогноза с учетом и графиков ремонтов и ремонтных ведомостей
This commit is contained in:
parent
355a53261e
commit
e59247fd2d
@ -199,6 +199,14 @@ create or replace package UDO_PKG_EQUIPDS_BASE as
|
||||
function CMML_TASK_HINT
|
||||
return varchar2; -- Подсказка для задачи
|
||||
|
||||
/* Вычисление вероятности выхода из строя на дату по RUL-прогнозу */
|
||||
function CMML_RUL_BREAKDOWN_PROB
|
||||
(
|
||||
NFORECAST in number, -- RUL-прогноз (интервалов до перехода в предельное состояние)
|
||||
DFORECAST_DATE in date, -- Дата прогноза
|
||||
DDATE in date -- Дата на
|
||||
) return number; -- Значение вероятности
|
||||
|
||||
/* Базовое добавление "Выборки данных оборудования (классы оборудования, модели, история запросов)" */
|
||||
procedure CMMLH_INS
|
||||
(
|
||||
@ -722,6 +730,41 @@ create or replace package body UDO_PKG_EQUIPDS_BASE as
|
||||
'<b>FP</b> - ' || CMML_TASK_NAME(STASK => 'FP') || ' (<b>F</b>ailure <b>P</b>redict)';
|
||||
end CMML_TASK_HINT;
|
||||
|
||||
/* Вычисление вероятности выхода из строя на дату по RUL-прогнозу */
|
||||
function CMML_RUL_BREAKDOWN_PROB
|
||||
(
|
||||
NFORECAST in number, -- RUL-прогноз (интервалов до перехода в предельное состояние)
|
||||
DFORECAST_DATE in date, -- Дата прогноза
|
||||
DDATE in date -- Дата на
|
||||
) return number -- Значение вероятности
|
||||
is
|
||||
NRES PKG_STD.TNUMBER; -- Буфер для результата
|
||||
begin
|
||||
/* Проверим параметры */
|
||||
if ((NFORECAST is null) or (DFORECAST_DATE is null) or (DDATE is null) or (DDATE < DFORECAST_DATE) or
|
||||
(DFORECAST_DATE > sysdate) or (DDATE < sysdate)) then
|
||||
return null;
|
||||
end if;
|
||||
/* Проверяем пограничные значения */
|
||||
if (NFORECAST = 0) or ((DDATE - sysdate) = 0) then
|
||||
return 100;
|
||||
end if;
|
||||
if (sysdate + NFORECAST > DDATE) then
|
||||
return 0;
|
||||
end if;
|
||||
/* Вычисляем */
|
||||
NRES := 100 - ROUND((NFORECAST - (TRUNC(sysdate) - TRUNC(DFORECAST_DATE))) / (DDATE - sysdate) * 100);
|
||||
/* Корректируем флуктуации */
|
||||
if (NRES > 100) then
|
||||
NRES := 100;
|
||||
end if;
|
||||
if (NRES < 0) then
|
||||
NRES := 0;
|
||||
end if;
|
||||
/* Возвращаем результат */
|
||||
return NRES;
|
||||
end CMML_RUL_BREAKDOWN_PROB;
|
||||
|
||||
/* Базовое добавление "Выборки данных оборудования (классы оборудования, модели, история запросов)" */
|
||||
procedure CMMLH_INS
|
||||
(
|
||||
|
@ -608,6 +608,34 @@ text="Проверка прав доступа при формировании
|
||||
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
|
||||
(
|
||||
@ -768,11 +796,11 @@ text="Проверка прав доступа при формировании
|
||||
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; -- Дата ближайшего ТО и ремонта
|
||||
NBREAKDOWN_PROB_CUR PKG_STD.TNUMBER; -- Вероятность выхода из строя (для текущей позиции графика ТО и ремонтов/рем. ведомости)
|
||||
DNEXT_REPAIR PKG_STD.TLDATE; -- Дата ближайшего ТО и ремонта по графику/рем. ведомости
|
||||
begin
|
||||
/* Вычислим вероятность выхода из строя до даты ближайшего ТО с учётом прогноза */
|
||||
DNEXT_REPAIR := UDO_PKG_EQUIPTCF.EQCONFIG_THOBJ_GET_NXTEQTCHSRV(NEQCONFIG => NEQCONFIG);
|
||||
/* Вычислим вероятность выхода из строя до даты ближайшего ТО/ремонта по графику или рем. ведомости с учётом прогноза */
|
||||
DNEXT_REPAIR := EQCONFIG_THOBJ_GEN_NXTRPR(NEQCONFIG => NEQCONFIG);
|
||||
if (DNEXT_REPAIR is null) then
|
||||
NBREAKDOWN_PROB := 100;
|
||||
else
|
||||
@ -814,43 +842,41 @@ text="Проверка прав доступа при формировании
|
||||
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 => 'Прогноз с учётом графика ТО и ремонтов',
|
||||
STITLE => 'Прогноз с учётом графика ТО и ремонтов/ремонтных ведомостей',
|
||||
SLGND_POS => PKG_P8PANELS_VISUAL.SCHART_LGND_POS_TOP);
|
||||
/* Сформируем набор данных */
|
||||
RCH_DS := PKG_P8PANELS_VISUAL.TCHART_DATASET_MAKE(SCAPTION => 'Вероятность перехода в критическое состояние (%)');
|
||||
/* Обходим ближайшие 5 позиций графика ТО и ремонтов */
|
||||
/* Обходим ближайшие 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
|
||||
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 => 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;
|
||||
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;
|
||||
/* Добавим набор данных в график */
|
||||
@ -932,18 +958,18 @@ text="Проверка прав доступа при формировании
|
||||
/* Вероятность выхода единицы оборудования из строя с учётом графика ТО и ремонтов и RUL-прогноза */
|
||||
function EQCONFIG_THOBJ_TCHSRV_BRKDPROB
|
||||
(
|
||||
NEQCONFIG in number -- Рег. номер технического объекта
|
||||
) return number -- Вероятность выхода из строя
|
||||
NEQCONFIG in number -- Рег. номер технического объекта
|
||||
) return number -- Вероятность выхода из строя
|
||||
is
|
||||
NRES PKG_STD.TNUMBER; -- Буфер для результата
|
||||
DFORECAST_DATE PKG_STD.TLDATE;
|
||||
NFORECAST PKG_STD.TNUMBER; -- Значение самго свежего прогноза модели
|
||||
DNXTEQTCHSRV PKG_STD.TLDATE; -- Дата ближайшего ТО или ремонта
|
||||
NRES PKG_STD.TNUMBER; -- Буфер для результата
|
||||
DFORECAST_DATE PKG_STD.TLDATE; -- Дата прогноза
|
||||
NFORECAST PKG_STD.TNUMBER; -- Значение самго свежего прогноза модели
|
||||
DCALC_DATE PKG_STD.TLDATE; -- Дата расчета вероятности
|
||||
begin
|
||||
/* Определим дату ближайшего ТО или ремонта */
|
||||
DNXTEQTCHSRV := EQCONFIG_THOBJ_GET_NXTEQTCHSRV(NEQCONFIG => NEQCONFIG);
|
||||
DCALC_DATE := EQCONFIG_THOBJ_GEN_NXTRPR(NEQCONFIG => NEQCONFIG);
|
||||
/* Если дата есть */
|
||||
if (DNXTEQTCHSRV is not null) then
|
||||
if (DCALC_DATE is not null) then
|
||||
/* Вынем самый свежий прогноз */
|
||||
for C in (select T.RQ_DATE DFORECAST_DATE,
|
||||
T.FORECAST
|
||||
@ -960,7 +986,9 @@ text="Проверка прав доступа при формировании
|
||||
end loop;
|
||||
/* Если есть и прогноз */
|
||||
if (NFORECAST is not null) then
|
||||
NRES := 100 - ROUND((NFORECAST - (TRUNC(sysdate) - TRUNC(DFORECAST_DATE))) / (DNXTEQTCHSRV - sysdate) * 100);
|
||||
NRES := UDO_PKG_EQUIPDS_BASE.CMML_RUL_BREAKDOWN_PROB(NFORECAST => NFORECAST,
|
||||
DFORECAST_DATE => DFORECAST_DATE,
|
||||
DDATE => DCALC_DATE);
|
||||
end if;
|
||||
end if;
|
||||
/* Вернём то, что собрали */
|
||||
|
@ -189,7 +189,8 @@ const ForecastTab = ({ onGoToAdmin }) => {
|
||||
const handleTechObjeCardMakeEqRpSheet = () => setDialogs(pv => ({ ...pv, makeEqRpSheet: true }));
|
||||
|
||||
//При необходимости обновления карточки технического объекта
|
||||
const handleCardDataRefresh = () => setRefresh(pv => ({ ...pv, techObjCard: pv.techObjCard + 1 }));
|
||||
const handleCardDataRefresh = () =>
|
||||
setRefresh(pv => ({ ...pv, techObjCard: pv.techObjCard + 1, techObjForecastHistList: pv.techObjForecastHistList + 1 }));
|
||||
|
||||
//При нажатии "ОК" в диалоге формирования ремонтной ведомости
|
||||
const handleTechObjMakeEqRpSheetOk = async values => {
|
||||
@ -202,6 +203,7 @@ const ForecastTab = ({ onGoToAdmin }) => {
|
||||
DPLANDATE_FROM: new Date(values.planDateFrom)
|
||||
}
|
||||
});
|
||||
setRefresh(pv => ({ ...pv, techObjForecastHistList: pv.techObjForecastHistList + 1, techObjCard: pv.techObjCard + 1 }));
|
||||
setDialogs(pv => ({ ...pv, makeEqRpSheet: false }));
|
||||
pOnlineShowDictionary({
|
||||
unitCode: "EquipRepairSheets",
|
||||
|
@ -47,7 +47,8 @@ const STYLES = {
|
||||
},
|
||||
TECH_OBJ_FORECAST_DETAIL_DIALOG: { maxWidth: "600px" },
|
||||
TECH_OBJ_FORECAST_DETAIL_CHART: { width: "550px", display: "flex", justifyContent: "center", paddingTop: "20px" },
|
||||
TECH_OBJ_MAKE_DATASET_DIALOG_CONTENT: { ...SCROLL_STYLES }
|
||||
TECH_OBJ_MAKE_DATASET_DIALOG_CONTENT: { ...SCROLL_STYLES },
|
||||
FORECAST_DETAIL_NOTE: { display: "block", marginTop: "-5px" }
|
||||
};
|
||||
|
||||
//------------------------------------
|
||||
@ -162,19 +163,24 @@ const ForecastDetail = ({ date, forecast, onClose }) => {
|
||||
{datails.taskName}: <b>{`${datails.forecast} ${datails.meas}`}</b>
|
||||
</Typography>
|
||||
<Stack direction={"row"}>
|
||||
<Typography variant="subtitle1">Дата следующего ТО/ремонта по графику: </Typography>
|
||||
<Typography variant="subtitle1">Дата следующего ТО/ремонта: </Typography>
|
||||
<Typography variant="subtitle1" color={datails.nextRepair ? "" : "error.main"}>
|
||||
<b>{datails.nextRepair ? formatDateRF(datails.nextRepair) : "Нет графиков ТО и ремонтов"}</b>
|
||||
<b>{datails.nextRepair ? `${formatDateRF(datails.nextRepair)}*` : "Нет графиков ТО и ремонтов/ремонтых ведомостей"}</b>
|
||||
</Typography>
|
||||
</Stack>
|
||||
{datails.nextRepair ? (
|
||||
<Typography variant="caption" color={"text.secondary"} sx={STYLES.FORECAST_DETAIL_NOTE}>
|
||||
*по графику/ремонтной ведомости
|
||||
</Typography>
|
||||
) : null}
|
||||
<Stack direction={"row"}>
|
||||
<Typography variant="subtitle1">Bероятность перехода в критическое состояние: </Typography>
|
||||
<Typography variant="subtitle1" color={datails.breakDownColor}>
|
||||
<b>{`${datails.breakDown}%*`}</b>
|
||||
</Typography>
|
||||
</Stack>
|
||||
<Typography variant="caption" color={"text.secondary"}>
|
||||
*до даты следующего ТО/ремонта по графику
|
||||
<Typography variant="caption" color={"text.secondary"} sx={STYLES.FORECAST_DETAIL_NOTE}>
|
||||
*до даты следующего ТО/ремонта по графику/ремонтной ведомости
|
||||
</Typography>
|
||||
{chart.loaded ? <P8PChart {...chart} style={STYLES.TECH_OBJ_FORECAST_DETAIL_CHART} /> : null}
|
||||
{!chart.available ? (
|
||||
@ -182,7 +188,7 @@ const ForecastDetail = ({ date, forecast, onClose }) => {
|
||||
<Paper elevation={6}>
|
||||
<Box p={5}>
|
||||
<Typography variant="body" color={"text.secondary"}>
|
||||
Зарегистрируйте графики ТО и ремонтов <br />
|
||||
Зарегистрируйте графики ТО и ремонтов/ремонтные ведомости <br />
|
||||
для отображения диаграммы прогнозирования.
|
||||
</Typography>
|
||||
</Box>
|
||||
@ -242,11 +248,16 @@ const eqConfigTechObjTableDataCellRender = ({ row, columnDef, onCMMLStatus }) =>
|
||||
};
|
||||
case "NBREAKDOWN_PROB":
|
||||
return {
|
||||
data: row[columnDef.name] ? (
|
||||
<Button variant="outlined" color={row.SBREAKDOWN_PROB_COLOR} onClick={event => (onCMMLStatus ? onCMMLStatus(event, row) : null)}>
|
||||
{`${row[columnDef.name]}%`}
|
||||
</Button>
|
||||
) : null
|
||||
data:
|
||||
row[columnDef.name] !== null && row[columnDef.name] !== "" ? (
|
||||
<Button
|
||||
variant="outlined"
|
||||
color={row.SBREAKDOWN_PROB_COLOR}
|
||||
onClick={event => (onCMMLStatus ? onCMMLStatus(event, row) : null)}
|
||||
>
|
||||
{`${row[columnDef.name]}%`}
|
||||
</Button>
|
||||
) : null
|
||||
};
|
||||
}
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user