create or replace package UDO_PKG_EQUIPTCF as

  /* Формирование дерева состава оборудования */
  procedure EQCONFIG_HIER
  (
    NEQPARENT               in number,  -- Рег. номер родительского узла состава оборудования
    COUT                    out clob    -- Сериализованное XML-представление дерева
  );

  /* Условия отбора технических объектов */
  procedure EQCONFIG_THOBJ_LIST_COND;
  
  /* Формирование списка технических объектов для выбранного узла состава оборудования */
  procedure EQCONFIG_THOBJ_LIST
  (
    NEQPARENT               in number,  -- Рег. номер родительского узла состава оборудования
    NPAGE_NUMBER            in number,  -- Номер страницы (игнорируется при NPAGE_SIZE=0)
    NPAGE_SIZE              in number,  -- Количество записей на странице (0 - все)
    CFILTERS                in clob,    -- Фильтры
    CORDERS                 in clob,    -- Сортировки
    NINCLUDE_DEF            in number,  -- Признак включения описания колонок таблицы в ответ
    COUT                    out clob    -- Сериализованная таблица данных
  );
  
  /* Получение даты следующего технического обслуживания технического объекта */
  function EQCONFIG_THOBJ_GET_NXTEQTCHSRV
  (
    NEQCONFIG               in number,        -- Рег. номер технического объекта
    NSTATE                  in number := null -- Состояние (null - любое)
  ) return                  date;             -- Дата следующего технического обслуживания
  
  /* Выбор графиков технического обслуживания и ремонта технического объекта */
  procedure EQCONFIG_THOBJ_SELECT_EQTCHSRV
  (
    NEQTCHSRV               in number := null, -- Рег. номер графика ТО и ремонтов (null - любой)
    NEQCONFIG               in number := null, -- Рег. номер технического объекта (null - любой)
    NSTATE                  in number := null, -- Состояние (null - любое)    
    NIDENT                  out number         -- Идентификатор списка
  );
  
  /* Получение даты следующего ремонта по ремонтной ведомости технического объекта */
  function EQCONFIG_THOBJ_GET_NXTEQRPSHT
  (
    NEQCONFIG               in number,        -- Рег. номер технического объекта
    NSTATE                  in number := null -- Состояние (null - любое)
  ) return                  date;             -- Дата следующего ремонта по ведомости

  /* Выбор ремонтных ведомостей технического объекта */
  procedure EQCONFIG_THOBJ_SELECT_EQRPSHT
  (
    NEQRPSHEETS             in number := null, -- Рег. номер ремонтной ведосочти (null - любой)
    NEQCONFIG               in number := null, -- Рег. номер технического объекта (null - любой)
    NSTATE                  in number := null, -- Состояние (null - любое)
    NIDENT                  out number         -- Идентификатор списка
  );
  
  /* Формирование карточки технического объекта */
  procedure EQCONFIG_THOBJ_CARD
  (
    NEQCONFIG               in number,  -- Рег. номер технического объекта
    COUT                    out clob    -- Сериализованная карточка
  );
  
  /* Отправка запроса на формирование прогноза технического объекта */
  procedure EQCONFIG_THOBJ_FORECAST
  (
    NEQCONFIG               in number,  -- Рег. номер технического объекта
    NEQUIPDSCMML            in number   -- Рег. номер модели
  );

  /* Подготовка запроса на формирование прогноза технического объекта  */
  procedure EQCONFIG_THOBJ_FORECAST_PRLG
  (
    NEQCONFIG               in number,    -- Рег. номер технического объекта
    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_*)
  );
  
  /* Подчистка после исполнения запроса на формирование прогноза технического объекта */
  procedure EQCONFIG_THOBJ_FORECAST_EPLG
  (
    NDATASET_IDENT          in number,  -- Идентификатор буфера данных
    NDATASET_CONFIG_IDENT   in number   -- Идентификатор буфера описания данных
  );

  /* Формирование цвета прогноза для технического объекта */
  function EQCONFIG_THOBJ_FORECAST_CLR
  (
    NMODE                   in number := 0, -- Режим работы (0 - для подсказки в колонке таблицы, 1 - для колонки таблицы, 2 - для карточки детализации
    NVALUE                  in number :=0   -- Значение для подсветки
  ) return                  varchar2;       -- Запрошенное значение в зависимости от режима
  
  /* Формирование детальной карточки прогноза для технического объекта */
  procedure EQCONFIG_THOBJ_FORECAST_CRD
  (
    NEQCONFIG               in number,   -- Рег. номер позиции состава оборудования
    DFORECAST_DATE          in date,     -- Дата получения прогноза
    NFORECAST               in number,   -- Прогнозное значение, полученное от фреймворка
    SDICMUNTS               in varchar2, -- Единица измерения выборки
    STASK                   in varchar2, -- Задача (см. константы UDO_PKG_EQUIPDS_BASE.CMML_TASK_*)
    COUT                    out clob     -- Данные детальной карточки прогноза
  );
  
  /* Извлечение сведений из детальной карточки прогноза для технического объекта */
  procedure EQCONFIG_THOBJ_FORECAST_CRDP
  (
    CFORECAST               in clob,      -- Данные детальной карточки прогноза
    SFORECAST_DESC          out varchar2, -- Описание прогноза
    SFORECAST_DESC_COLOR    out varchar2  -- Цвет заливки прогноза
  );

  /* Вероятность выхода единицы оборудования из строя с учётом графика ТО и ремонтов и RUL-прогноза */
  function EQCONFIG_THOBJ_TCHSRV_BRKDPROB
  (
    NEQCONFIG               in number   -- Рег. номер технического объекта
  ) return                  number;     -- Вероятность выхода из строя
  
  /* Модификация графика ТО и ремонтов для технического объекта */
  procedure EQCONFIG_THOBJ_CHNG_EQTCHSRV
  (
    NEQCONFIG               in number,  -- Рег. номер технического объекта
    NEQTCHSRV               in number,  -- Рег. номер графика ТО и ремонтов
    DPLANDATE_FROM          in date     -- Уточнённая плановая дата начала ремонта
  );

  /* Формирование ремонтной ведомости для технического объекта */
  procedure EQCONFIG_THOBJ_MAKE_EQRPSHEET
  (
    NEQCONFIG               in number,   -- Рег. номер технического объекта
    SACATALOG               in varchar2, -- Каталог размещения ведомости
    SEQTECSRVKIND           in varchar2, -- Вид ремонта
    DPLANDATE_FROM          in date,     -- Плановая дата начала ремонта
    NIDENT                  out number   -- Идентификатор списка сформированных ведомостей
  );
  
end UDO_PKG_EQUIPTCF;
/
create or replace package body UDO_PKG_EQUIPTCF as

/*
TODO: owner="root" created="02.08.2024"
text="Проверка прав доступа при формировании таблицы и карточки ТО"
*/

  /* Формирование ветки дерева состава оборудования */
  function EQCONFIG_HIER_NODE
  (
    NCUR                    in integer,      -- Курсор документа для результата    
    NCOMPANY                in number,       -- Рег. номер организации
    NEQPARENT               in number        -- Рег. номер родительского узла состава оборудования 
  ) return                  PKG_XMAKE.TNODE  -- XML-описание веток дерева
  is
    XLEAF                   PKG_XMAKE.TNODE; -- Текущий лист
    XCHILD                  PKG_XMAKE.TNODE; -- Дочерние листы текущего
    XRES                    PKG_XMAKE.TNODE; -- Буфер для результата
  begin
    /* Обходим состав оборудования с заданного корня */
    for C in (select M.RN NRN,
                     M.EQPARENT NHRN,
                     DECODE(M.FICT_REC, 0, M.NAME, DECODE(OL.RN, null, M.NAME, OL.NAME)) SNAME,
                     case
                       when exists
                        (select null
                               from EQCONFIG C
                              where C.EQPARENT = M.RN
                                and exists (select null from V_USERPRIV_HIER_SINGL UP where UP.HIERARCHY = C.RN)) then
                        1
                       else
                        0
                     end NHASCHILDREN,
                     M.OBJ_KIND NOBJ_KIND
                from EQCONFIG   M,
                     EQOBJLEVEL OL
               where M.PR_OBJ_LEVEL = OL.RN(+)
                 and ((M.FICT_REC = 0) or ((M.FICT_REC = 1) and (CMP_VC2(M.NAME, F_EQCONFIG_EXTRANAME(0)) = 1)))
                 and exists (select null from V_USERPRIV_HIER_SINGL UP where UP.HIERARCHY = M.RN)
                 and COALESCE(M.EQPARENT, 0) = NEQPARENT
                 and M.COMPANY = NCOMPANY
               order by 3)
    loop
      /* Если есть дочерние ветки */
      if (C.NHASCHILDREN = 1) then
        /* Добавим фиктивную дочернюю запись для индикации наличия дочерних на клиенте */
        XCHILD := PKG_XMAKE.ELEMENT(ICURSOR     => NCUR,
                                    SNAME       => 'children',
                                    RATTRIBUTES => PKG_XMAKE.ATTRIBUTES(ICURSOR      => NCUR,
                                                                        RATTRIBUTE00 => PKG_XMAKE.ATTRIBUTE(ICURSOR => NCUR,
                                                                                                            SNAME   => 'id',
                                                                                                            SVALUE  => C.NRN ||
                                                                                                                       '_loader'),
                                                                        RATTRIBUTE01 => PKG_XMAKE.ATTRIBUTE(ICURSOR => NCUR,
                                                                                                            SNAME   => 'label',
                                                                                                            SVALUE  => 'Минуточку...')));
        /* Соберём лист */
        XLEAF := PKG_XMAKE.ELEMENT(ICURSOR     => NCUR,
                                   SNAME       => 'children',
                                   RATTRIBUTES => PKG_XMAKE.ATTRIBUTES(ICURSOR      => NCUR,
                                                                       RATTRIBUTE00 => PKG_XMAKE.ATTRIBUTE(ICURSOR => NCUR,
                                                                                                           SNAME   => 'id',
                                                                                                           SVALUE  => C.NRN),
                                                                       RATTRIBUTE01 => PKG_XMAKE.ATTRIBUTE(ICURSOR => NCUR,
                                                                                                           SNAME   => 'label',
                                                                                                           SVALUE  => C.SNAME)),
                                   RNODE00     => XCHILD);
        /* Соберём листы в ветку */
        XRES := PKG_XMAKE.CONCAT(ICURSOR => NCUR, RNODE00 => XRES, RNODE01 => XLEAF);
      end if;
    end loop;
    /* Вернём собранное */
    return XRES;
  end EQCONFIG_HIER_NODE;
  
  /* Формирование дерева состава оборудования */
  procedure EQCONFIG_HIER
  (
    NEQPARENT               in number,                             -- Рег. номер родительского узла состава оборудования
    COUT                    out clob                               -- Сериализованное XML-представление дерева
  )
  is    
    NCOMPANY                PKG_STD.TREF := GET_SESSION_COMPANY(); -- Рег. номер организации
    NCUR                    integer;                               -- Курсор документа для результата
    XDOC                    PKG_XMAKE.TNODE;                       -- Документ для результата
  begin
    /* Открываем документ */
    NCUR := PKG_XMAKE.OPEN_CURSOR();
    /* Формируем XML-представление ветки для запрошенного родителя */
    XDOC := PKG_XMAKE.ELEMENT(ICURSOR => NCUR,
                              SNAME   => 'XDATA',
                              RNODE00 => EQCONFIG_HIER_NODE(NCUR => NCUR, NCOMPANY => NCOMPANY, NEQPARENT => NEQPARENT));
    /* Конвертируем в CLOB */
    COUT := PKG_XMAKE.SERIALIZE_TO_CLOB(ICURSOR => NCUR,
                                        ITYPE   => PKG_XMAKE.CONTENT_,
                                        RNODE   => XDOC,
                                        RHEADER => PKG_XHEADER.WRAP_ALL(SVERSION    => PKG_XHEADER.VERSION_1_0_,
                                                                        SENCODING   => PKG_XHEADER.ENCODING_UTF_,
                                                                        SSTANDALONE => PKG_XHEADER.STANDALONE_YES_));
    /* Закрываем документ */
    PKG_XMAKE.CLOSE_CURSOR(ICURSOR => NCUR);
  end EQCONFIG_HIER;

  /* Условия отбора технических объектов */
  procedure EQCONFIG_THOBJ_LIST_COND
  is
  begin
    /* Установка главной таблицы */
    PKG_COND_BROKER.SET_TABLE(STABLE_NAME => 'EQCONFIG');
    /* Обозначение */
    PKG_COND_BROKER.ADD_CONDITION_CODE(SCOLUMN_NAME => 'CODE', SCONDITION_NAME => 'SCODEFrom');
    /* Наименование */
    PKG_COND_BROKER.ADD_CONDITION_CODE(SCOLUMN_NAME => 'NAME', SCONDITION_NAME => 'SNAMEFrom');
    /* Дата ввода в эксплуатацию */
    PKG_COND_BROKER.ADD_CONDITION_BETWEEN(SCOLUMN_NAME         => 'OPER_DATE',
                                          SCONDITION_NAME_FROM => 'DOPER_DATEFrom',
                                          SCONDITION_NAME_TO   => 'DOPER_DATETo');
    /* Состояние */
    PKG_COND_BROKER.ADD_CONDITION_CODE(SCOLUMN_NAME    => 'CODE',
                                       SCONDITION_NAME => 'SUSE_KINDFrom',
                                       SJOINS          => 'HLSTATETYPES <- RN;HLSTATETYPES');
    /* Класс */
    PKG_COND_BROKER.ADD_CONDITION_CODE(SCOLUMN_NAME    => 'NAME',
                                       SCONDITION_NAME => 'SOBJ_KINDFrom',
                                       SJOINS          => 'OBJ_KIND <- RN;EQOBJKIND');
    /* Действия с моделями прогнозирования */
    if (PKG_COND_BROKER.CONDITION_EXISTS(SCONDITION_NAME => 'NCMML_STATUSFrom') = 1) then
      PKG_COND_BROKER.ADD_CLAUSE(SCLAUSE => PKG_SQL_BUILD.PKG_NAME(SNAME => 'UDO_PKG_EQUIPDS.CMML_STATUS_BY_EQCONFIG') ||
                                            '(RN) = :NCMML_STATUS');
      PKG_COND_BROKER.BIND_VARIABLE(SVARIABLE_NAME => 'NCMML_STATUS',
                                    SVALUE         => PKG_COND_BROKER.GET_CONDITION_NUM(SCONDITION_NAME => 'NCMML_STATUSFrom'));
    end if;
    /* Вероятность выхода из строя */
    if ((PKG_COND_BROKER.CONDITION_EXISTS(SCONDITION_NAME => 'NBREAKDOWN_PROBFrom') = 1) and
       (PKG_COND_BROKER.CONDITION_EXISTS(SCONDITION_NAME => 'NBREAKDOWN_PROBTo') = 0)) then
      PKG_COND_BROKER.ADD_CLAUSE(SCLAUSE => PKG_SQL_BUILD.PKG_NAME(SNAME => 'UDO_PKG_EQUIPTCF.EQCONFIG_THOBJ_TCHSRV_BRKDPROB') ||
                                            '(RN) >= :NBREAKDOWN_PROBFrom');
      PKG_COND_BROKER.BIND_VARIABLE(SVARIABLE_NAME => 'NBREAKDOWN_PROBFrom',
                                    NVALUE         => PKG_COND_BROKER.GET_CONDITION_NUM(SCONDITION_NAME => 'NBREAKDOWN_PROBFrom'));
    end if;
    if ((PKG_COND_BROKER.CONDITION_EXISTS(SCONDITION_NAME => 'NBREAKDOWN_PROBTo') = 1) and
       (PKG_COND_BROKER.CONDITION_EXISTS(SCONDITION_NAME => 'NBREAKDOWN_PROBFrom') = 0)) then
      PKG_COND_BROKER.ADD_CLAUSE(SCLAUSE => PKG_SQL_BUILD.PKG_NAME(SNAME => 'UDO_PKG_EQUIPTCF.EQCONFIG_THOBJ_TCHSRV_BRKDPROB') ||
                                            '(RN) <= :NBREAKDOWN_PROBTo');
      PKG_COND_BROKER.BIND_VARIABLE(SVARIABLE_NAME => 'NBREAKDOWN_PROBTo',
                                    NVALUE         => PKG_COND_BROKER.GET_CONDITION_NUM(SCONDITION_NAME => 'NBREAKDOWN_PROBTo'));
    end if;
    if ((PKG_COND_BROKER.CONDITION_EXISTS(SCONDITION_NAME => 'NBREAKDOWN_PROBFrom') = 1) and
       (PKG_COND_BROKER.CONDITION_EXISTS(SCONDITION_NAME => 'NBREAKDOWN_PROBTo') = 1)) then
      PKG_COND_BROKER.ADD_CLAUSE(SCLAUSE => PKG_SQL_BUILD.PKG_NAME(SNAME => 'UDO_PKG_EQUIPTCF.EQCONFIG_THOBJ_TCHSRV_BRKDPROB') ||
                                            '(RN) between :NBREAKDOWN_PROBFrom and :NBREAKDOWN_PROBTo');
      PKG_COND_BROKER.BIND_VARIABLE(SVARIABLE_NAME => 'NBREAKDOWN_PROBFrom',
                                    NVALUE         => PKG_COND_BROKER.GET_CONDITION_NUM(SCONDITION_NAME => 'NBREAKDOWN_PROBFrom'));
      PKG_COND_BROKER.BIND_VARIABLE(SVARIABLE_NAME => 'NBREAKDOWN_PROBTo',
                                    NVALUE         => PKG_COND_BROKER.GET_CONDITION_NUM(SCONDITION_NAME => 'NBREAKDOWN_PROBTo'));
    end if;
  end EQCONFIG_THOBJ_LIST_COND;
  
  /* Формирование списка технических объектов для выбранного узла состава оборудования */
  procedure EQCONFIG_THOBJ_LIST
  (
    NEQPARENT               in number,                             -- Рег. номер родительского узла состава оборудования
    NPAGE_NUMBER            in number,                             -- Номер страницы (игнорируется при NPAGE_SIZE=0)
    NPAGE_SIZE              in number,                             -- Количество записей на странице (0 - все)
    CFILTERS                in clob,                               -- Фильтры
    CORDERS                 in clob,                               -- Сортировки
    NINCLUDE_DEF            in number,                             -- Признак включения описания колонок таблицы в ответ
    COUT                    out clob                               -- Сериализованная таблица данных
  )
  is
    NCOMPANY                PKG_STD.TREF := GET_SESSION_COMPANY(); -- Организация сеанса
    NIDENT                  PKG_STD.TREF := GEN_IDENT();           -- Идентификатор отбора
    RF                      PKG_P8PANELS_VISUAL.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
  (
    NEQCONFIG               in number,    -- Рег. номер технического объекта
    NEQUIPDSCMML            in number     -- Рег. номер модели
  )
  is
    NEQUIPDSCMMLH           PKG_STD.TREF; -- Рег. номер истории запросов модели
    CDEMO                   clob;         -- Демо-данные прогноза
  begin
    /* Добавляем запись истории запросов */
    UDO_PKG_EQUIPDS_BASE.CMMLH_INS(NPRN       => NEQUIPDSCMML,
                                   NEQCONFIG  => NEQCONFIG,
                                   SRQ_AUTHID => UTILIZER(),
                                   DRQ_DATE   => sysdate,
                                   BRQ        => null,
                                   NRN        => NEQUIPDSCMMLH);
    /* Добавим демо-данные */
    for C in (select T.TASK        STASK,
                     DM.MEAS_MNEMO SDICMUNTS
                from UDO_T_EQUIPDSCMML T,
                     UDO_T_EQUIPDSCM   CM,
                     DICMUNTS          DM
               where T.RN = NEQUIPDSCMML
                 and T.PRN = CM.RN
                 and CM.DICMUNTS = DM.RN)
    loop
      UDO_PKG_EQUIPDS.CMMLH_BUILD_FORECAST(COUT => CDEMO);
      UDO_PKG_EQUIPDS_BASE.CMMLH_SET_FORECAST(NRN => NEQUIPDSCMMLH, BFORECAST => CLOB2BLOB(LCDATA => CDEMO));
    end loop;
  end EQCONFIG_THOBJ_FORECAST;
  
  /* Подготовка запроса на формирование прогноза технического объекта  */
  procedure EQCONFIG_THOBJ_FORECAST_PRLG
  (
    NEQCONFIG               in number,       -- Рег. номер технического объекта
    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
    NCNT                    PKG_STD.TNUMBER; -- Буфер для количества файлов данных
  begin
    /* Проверим данные о наработках */
    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 > 0) 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;
    /* Формируем URL для запроса */
    SURL := 'https://parus.cadred.ru/API/forecast/metadata';
    /* Формируем токен для аутентификации */
    SAUTH_TOKEN := to_char(base64_encode(clob2blob('parus_remote:CreateNewAccount_787898')));
  end EQCONFIG_THOBJ_FORECAST_PRLG;

  /* Подчистка после исполнения запроса на формирование прогноза технического объекта */
  procedure EQCONFIG_THOBJ_FORECAST_EPLG
  (
    NDATASET_IDENT          in number,  -- Идентификатор буфера данных
    NDATASET_CONFIG_IDENT   in number   -- Идентификатор буфера описания данных
  )
  is
  begin
    /* Очистим данные в файловом буфере */
    P_FILE_BUFFER_CLEAR(NIDENT => NDATASET_IDENT);
    P_FILE_BUFFER_CLEAR(NIDENT => NDATASET_CONFIG_IDENT);
  end EQCONFIG_THOBJ_FORECAST_EPLG;
  
  /* Формирование цвета прогноза для технического объекта */
  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;
/
