create or replace package UDO_PKG_EQUIPDS as

  /* Список "Выборки данных оборудования" */
  procedure LIST
  (
    COUT                    out clob    -- Сериализованная таблица данных  
  );

  /* Клиентское добавление "Выборки данных оборудования" */
  procedure INS
  (
    SCODE                   in varchar2, -- Мнемокод
    SNAME                   in varchar2, -- Наименование
    NRN                     out number   -- Регистрационный номер
  );
  
  /* Клиентское удаление "Выборки данных оборудования" */
  procedure DEL
  (
    NRN                     in number   -- Регистрационный номер
  );
  
  /* Клиентское формирование "Выборки данных оборудования" по классу технического объекта */
  procedure MAKE
  (
    SEQUIPDS                in varchar2, -- Выборка данных оборудования
    SEQOBJKIND              in varchar2, -- Класс оборудования
    SDICMUNTS               in varchar2, -- Единица измерения выборки
    SUSERPROCS_DATA         in varchar2, -- Процедура формирования
    SEXSSERVICE_UPLOAD      in varchar2, -- Сервис обмена для выгрузки данных
    SEXSSERVICEFN_UPLOAD    in varchar2, -- Функция обмена для выгрузки данных
    SEXSSERVICE_SEND_MD     in varchar2, -- Сервис обмена для передачи внешней системе
    SEXSSERVICEFN_SEND_MD   in varchar2, -- Функция обмена для передачи внешней системе
    SEXSSERVICE_SEND_MDCB   in varchar2, -- Сервис обмена для приёма Call-back запросов с результатами передачи внешней системе
    SEXSSERVICEFN_SEND_MDCB in varchar2, -- Функция сервиса обмена для приёма Call-back запросов с результатами передачи внешней системе
    SEXSSERVICE_SEND_RQ     in varchar2, -- Сервис обмена для обработки внешней системой
    SEXSSERVICEFN_SEND_RQ   in varchar2, -- Функция обмена для обработки внешней системой
    SEXSSERVICE_SEND_RQCB   in varchar2, -- Сервис обмена для приёма Call-back запросов с результатами обработки внешней системой
    SEXSSERVICEFN_SEND_RQCB in varchar2, -- Функция сервиса обмена для приёма Call-back запросов с результатами обработки внешней системой
    SEXSSERVICE_FRCST_MD    in varchar2, -- Сервис обмена для публикации данных наработки оборудования при получении прогноза
    SEXSSERVICEFN_FRCST_MD  in varchar2, -- Функция обмена для публикации данных наработки оборудования при получении прогноза
    NEQUIPDS                out number,  -- Регистрационный номер выборки данных оборудования
    NEQUIPDSCM              out number   -- Регистрационный номер класса оборудования выборки данных
  );
  
  /* Карточка "Выборки данных оборудования (классы оборудования)" */
  procedure CM_CARD
  (
    NEQUIPDSCM              in number,  -- Рег. номер класса оборудования выборки данных
    COUT                    out clob    -- Сериализованная карточка  
  );
  
  /* Список "Выборки данных оборудования (классы оборудования)" */
  procedure CM_LIST
  (
    NEQUIPDS                in number,  -- Рег. номер выборки данных
    COUT                    out clob    -- Сериализованный список
  );
  
  /* Клиентское добавление "Выборки данных оборудования (классы оборудования)" */
  procedure CM_INS
  (
    NPRN                    in number,   -- Родитель
    SEQOBJKIND              in varchar2, -- Класс оборудования
    SDICMUNTS               in varchar2, -- Единица измерения выборки
    SUSERPROCS_DATA         in varchar2, -- Процедура формирования
    SEXSSERVICE_UPLOAD      in varchar2, -- Сервис обмена для выгрузки данных
    SEXSSERVICEFN_UPLOAD    in varchar2, -- Функция обмена для выгрузки данных
    SEXSSERVICE_SEND_MD     in varchar2, -- Сервис обмена для передачи внешней системе
    SEXSSERVICEFN_SEND_MD   in varchar2, -- Функция обмена для передачи внешней системе
    SEXSSERVICE_SEND_MDCB   in varchar2, -- Сервис обмена для приёма Call-back запросов с результатами передачи внешней системе
    SEXSSERVICEFN_SEND_MDCB in varchar2, -- Функция сервиса обмена для приёма Call-back запросов с результатами передачи внешней системе
    SEXSSERVICE_SEND_RQ     in varchar2, -- Сервис обмена для обработки внешней системой
    SEXSSERVICEFN_SEND_RQ   in varchar2, -- Функция обмена для обработки внешней системой
    SEXSSERVICE_SEND_RQCB   in varchar2, -- Сервис обмена для приёма Call-back запросов с результатами обработки внешней системой
    SEXSSERVICEFN_SEND_RQCB in varchar2, -- Функция сервиса обмена для приёма Call-back запросов с результатами обработки внешней системой
    SEXSSERVICE_FRCST_MD    in varchar2, -- Сервис обмена для публикации данных наработки оборудования при получении прогноза
    SEXSSERVICEFN_FRCST_MD  in varchar2, -- Функция обмена для публикации данных наработки оборудования при получении прогноза
    NRN                     out number   -- Регистрационный номер
  );
  
  /* Клиентское исправление "Выборки данных оборудования (классы оборудования)" */
  procedure CM_UPD
  (
    NRN                     in number,   -- Регистрационный номер
    SEQOBJKIND              in varchar2, -- Класс оборудования
    SDICMUNTS               in varchar2, -- Единица измерения выборки
    SUSERPROCS_DATA         in varchar2, -- Процедура формирования
    SEXSSERVICE_UPLOAD      in varchar2, -- Сервис обмена для выгрузки данных
    SEXSSERVICEFN_UPLOAD    in varchar2, -- Функция обмена для выгрузки данных
    SEXSSERVICE_SEND_MD     in varchar2, -- Сервис обмена для передачи внешней системе
    SEXSSERVICEFN_SEND_MD   in varchar2, -- Функция обмена для передачи внешней системе
    SEXSSERVICE_SEND_MDCB   in varchar2, -- Сервис обмена для приёма Call-back запросов с результатами передачи внешней системе
    SEXSSERVICEFN_SEND_MDCB in varchar2, -- Функция сервиса обмена для приёма Call-back запросов с результатами передачи внешней системе
    SEXSSERVICE_SEND_RQ     in varchar2, -- Сервис обмена для обработки внешней системой
    SEXSSERVICEFN_SEND_RQ   in varchar2, -- Функция обмена для обработки внешней системой
    SEXSSERVICE_SEND_RQCB   in varchar2, -- Сервис обмена для приёма Call-back запросов с результатами обработки внешней системой
    SEXSSERVICEFN_SEND_RQCB in varchar2, -- Функция сервиса обмена для приёма Call-back запросов с результатами обработки внешней системой
    SEXSSERVICE_FRCST_MD    in varchar2, -- Сервис обмена для публикации данных наработки оборудования при получении прогноза
    SEXSSERVICEFN_FRCST_MD  in varchar2  -- Функция обмена для публикации данных наработки оборудования при получении прогноза
  );
  
  /* Клиентское удаление "Выборки данных оборудования (классы оборудования)" */
  procedure CM_DEL
  (
    NRN                     in number   -- Регистрационный номер
  );
  
  /* Клиентское получение списка доступных выборок данных "Выборки данных оборудования (классы оборудования)" */
  procedure CM_DATASET_LIST
  (
    NRN                     in number,         -- Регистрационный номер
    NSTATUS                 in number := null, -- Статус (null - все, см. константы UDO_PKG_EQUIPDS_BASE.NCMFL_STATUS_*)
    COUT                    out clob           -- Сериализованный список
  );
  
  /* Список "Выборки данных оборудования (классы оборудования, файлы данных)" */
  procedure CMFL_LIST
  (
    NEQUIPDSCM              in number,  -- Рег. номер класса оборудования выборки данных
    COUT                    out clob    -- Сериализованная таблица данных  
  );

  /* Удаление "Выборки данных оборудования (классы оборудования, файлы данных)" */
  procedure CMFL_DEL
  (
    NRN                     in number   -- Регистрационный номер
  );
  
  /* Формирование "Выборки данных оборудования (классы оборудования, файлы данных)" */
  procedure CMFL_MAKE
  (
    NEQUIPDSCM              in number,     -- Рег. номер класса оборудования выборки данных
    NDATASET_IDENT          in number,     -- Идентификатор буфера данных
    NDATASET_CONFIG_IDENT   in number,     -- Идентификатор буфера описания данных
    NCLEAR                  in number := 0 -- Флаг очистки имеющихся файлов данных (0 - не очищать, 1 - очистить)
  );
  
  /* Загрузка на сервер "Выборки данных оборудования (классы оборудования, файлы данных)" */
  procedure CMFL_UPLOAD
  (
    NEQUIPDSCM              in number   -- Рег. номер класса оборудования выборки данных
  );

  /* Передача внешней системе "Выборки данных оборудования (классы оборудования, файлы данных)" */
  procedure CMFL_SEND_MD
  (
    NEQUIPDSCM              in number,  -- Рег. номер класса оборудования выборки данных
    NDATASET_ID             in number   -- Идентификатор выборки
  );

  /* Список "Выборки данных оборудования (классы оборудования, модели)" */
  procedure CMML_LIST
  (
    NEQUIPDSCM              in number,  -- Рег. номер класса оборудования выборки данных
    COUT                    out clob    -- Сериализованная таблица данных  
  );
  
  /* Клиентское добавление "Выборки данных оборудования (классы оборудования, модели)" */
  procedure CMML_INS
  (
    NPRN                    in number,   -- Родитель
    STASK                   in varchar2, -- Задача (см. константы UDO_PKG_EQUIPDS_BASE.SCMML_TASK_*)
    NDATASET_ID             in number,   -- Идентификатор выборки
    SUSERPROCS_FRCST_DATA   in varchar2, -- Пользовательская процедура формирования данных для прогноза
    NRN                     out number   -- Регистрационный номер
  );
  
  /* Клиентское удаление "Выборки данных оборудования (классы оборудования, модели)" */
  procedure CMML_DEL
  (
    NRN                     in number   -- Регистрационный номер
  );
  
  /* Обработка внешней системой "Выборки данных оборудования (классы оборудования, модели)" */
  procedure CMML_SEND_RQ
  (
    NEQUIPDSCMML            in number   -- Рег. номер модели класса оборудования выборки данных
  );
  
  /* Состояние "Выборки данных оборудования (классы оборудования, модели)" по единице оборудования */
  function CMML_STATUS_BY_EQCONFIG
  (
    NEQCONFIG               in number   -- Рег. номер позиции состава оборудования
  ) return                  number;     -- Код действия с моделью (0 - нет моделей, 1 - есть модели в процессе обучения, 2 - есть обученные модели)

  /* Список "Выборки данных оборудования (классы оборудования, модели)" по единице оборудования */
  procedure CMML_LIST_BY_EQCONFIG
  (
    NEQCONFIG               in number,  -- Рег. номер позиции состава оборудования
    COUT                    out clob    -- Сериализованная таблица данных    
  );

  /* Цвет прогноза "Выборки данных оборудования (классы оборудования, модели, история запросов)" */
  function CMMLH_FORECAST_COLOR
  (
    NMODE                   in number := 0, -- Режим работы (0 - для подсказки в колонке таблицы, 1 - для колонки таблицы, 2 - для карточки детализации
    NVALUE                  in number :=0   -- Значение для подсветки
  ) return                  varchar2;       -- Запрошенное значение в зависимости от режима
  
  /* Карточка прогноза "Выборки данных оборудования (классы оборудования, модели, история запросов)" */
  procedure CMMLH_FORECAST_CARD
  (
    NEQUIPDSCMMLH           in number,    -- Рег. номер записи истории запросов модели
    DFORECAST_DATE          in date,      -- Дата получения прогноза
    NFORECAST_DAYS          in number,    -- Прогнозное количество дней до выхода из строя (на дату прогноза)
    STASK                   in varchar2,  -- Задача (см. константы UDO_PKG_EQUIPDS_BASE.CMML_TASK_*)
    SFORECAST               out varchar2, -- Прогноз
    SFORECAST_DESC          out varchar2, -- Интерпретация прогноза
    SFORECAST_DESC_COLOR    out varchar2, -- Цвет заливки интерпретации прогноза
    CFORECAST_CARD          out clob      -- Данные детальной карточки прогноза
  );
  
  /* Список "Выборки данных оборудования (классы оборудования, модели, история запросов)" по единице оборудования */
  procedure CMMLH_LIST_BY_EQCONFIG
  (
    NEQCONFIG               in number,  -- Рег. номер позиции состава оборудования
    COUT                    out clob    -- Сериализованная таблица данных    
  );

end UDO_PKG_EQUIPDS;
/
create or replace package body UDO_PKG_EQUIPDS as

  /* Список "Выборки данных оборудования" */
  procedure LIST
  (
    COUT                    out clob                               -- Сериализованная таблица данных  
  )
  is
    NCOMPANY                PKG_STD.TREF := GET_SESSION_COMPANY(); -- Организация сеанса
    NCUR                    integer;                               -- Курсор документа для результата
    XDOC                    PKG_XMAKE.TNODE;                       -- Документ для результата
    XDS                     PKG_XMAKE.TNODE;                       -- Элемент для выборки данных
    NACCESS                 PKG_STD.TNUMBER := 0;                  -- Флаг наличия доступа к моделям (0 - доступа нет, 1 - доступ есть)
  begin
    /* Проверим права доступа */
    if (UDO_PKG_EQUIPDS_BASE.UTL_ACCESS_CHECK(SUSER   => UTILIZER(),
                                              STABLE  => 'UDO_T_EQUIPDS',
                                              SACTION => 'UDO_EQUIPDS_SELECT')) then
      NACCESS := 1;
    end if;
    /* Открываем документ */
    NCUR := PKG_XMAKE.OPEN_CURSOR();
    /* Обходим выборки данных */
    for C in (select T.RN   NRN,
                     T.CODE SCODE,
                     T.NAME SNAME
                from UDO_T_EQUIPDS T
               where T.COMPANY = NCOMPANY
                 and NACCESS = 1
               order by T.NAME)
    loop
      XDS := PKG_XMAKE.CONCAT(ICURSOR => NCUR,
                              RNODE00 => XDS,
                              RNODE01 => PKG_XMAKE.ELEMENT(ICURSOR     => NCUR,
                                                           SNAME       => 'XDS',
                                                           RATTRIBUTES => PKG_XMAKE.ATTRIBUTES(ICURSOR      => NCUR,
                                                                                               RATTRIBUTE00 => PKG_XMAKE.ATTRIBUTE(ICURSOR => NCUR,
                                                                                                                                   SNAME   => 'NRN',
                                                                                                                                   SVALUE  => C.NRN),
                                                                                               RATTRIBUTE01 => PKG_XMAKE.ATTRIBUTE(ICURSOR => NCUR,
                                                                                                                                   SNAME   => 'SCODE',
                                                                                                                                   SVALUE  => C.SCODE),
                                                                                               RATTRIBUTE02 => PKG_XMAKE.ATTRIBUTE(ICURSOR => NCUR,
                                                                                                                                   SNAME   => 'SNAME',
                                                                                                                                   SVALUE  => C.SNAME))));
    end loop;
    /* Формируем XML-представление ответа */
    XDOC := PKG_XMAKE.ELEMENT(ICURSOR => NCUR,
                              SNAME   => 'XDATA',
                              RNODE00 => XDS,
                              RNODE01 => PKG_XMAKE.ELEMENT(ICURSOR  => NCUR,
                                                           SNAME    => 'NACCESS',
                                                           RVALUE00 => PKG_XMAKE.VALUE(ICURSOR => NCUR, NVALUE => NACCESS)));
    /* Конвертируем в 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 LIST;
  
  /* Клиентское добавление "Выборки данных оборудования" */
  procedure INS
  (
    SCODE                   in varchar2,                           -- Мнемокод
    SNAME                   in varchar2,                           -- Наименование
    NRN                     out number                             -- Регистрационный номер
  )
  is
    NCOMPANY                PKG_STD.TREF := GET_SESSION_COMPANY(); -- Организация
  begin
    /* Проверим параметры */
    if (SCODE is null) then
      P_EXCEPTION(0, 'Не указан мнемокод.');
    end if;
    if (SNAME is null) then
      P_EXCEPTION(0, 'Не указано наименование.');
    end if;
    /* Проверим права доступа */
    UDO_PKG_EQUIPDS_BASE.UTL_ACCESS(STABLE => 'UDO_T_EQUIPDS', SACTION => 'UDO_EQUIPDS_INSERT');
    /* Добавляем запись */
    UDO_PKG_EQUIPDS_BASE.INS(NCOMPANY => NCOMPANY, SCODE => SCODE, SNAME => SNAME, NRN => NRN);
  end INS;

  /* Клиентское удаление "Выборки данных оборудования" */
  procedure DEL
  (
    NRN                     in number                              -- Регистрационный номер
  )
  is
    NCOMPANY                PKG_STD.TREF := GET_SESSION_COMPANY(); -- Организация
  begin
    /* Проверим права доступа */
    UDO_PKG_EQUIPDS_BASE.UTL_ACCESS(STABLE => 'UDO_T_EQUIPDS', SACTION => 'UDO_EQUIPDS_DELETE', NDOCUMENT => NRN);
    /* Удаляем запись */
    UDO_PKG_EQUIPDS_BASE.DEL(NRN => NRN, NCOMPANY => NCOMPANY);
  end DEL;
  
  /* Клиентское формирование "Выборки данных оборудования" по классу технического объекта */
  procedure MAKE
  (
    SEQUIPDS                in varchar2,                           -- Выборка данных оборудования
    SEQOBJKIND              in varchar2,                           -- Класс оборудования
    SDICMUNTS               in varchar2,                           -- Единица измерения выборки
    SUSERPROCS_DATA         in varchar2,                           -- Процедура формирования
    SEXSSERVICE_UPLOAD      in varchar2,                           -- Сервис обмена для выгрузки данных
    SEXSSERVICEFN_UPLOAD    in varchar2,                           -- Функция обмена для выгрузки данных
    SEXSSERVICE_SEND_MD     in varchar2,                           -- Сервис обмена для передачи внешней системе
    SEXSSERVICEFN_SEND_MD   in varchar2,                           -- Функция обмена для передачи внешней системе
    SEXSSERVICE_SEND_MDCB   in varchar2,                           -- Сервис обмена для приёма Call-back запросов с результатами передачи внешней системе
    SEXSSERVICEFN_SEND_MDCB in varchar2,                           -- Функция сервиса обмена для приёма Call-back запросов с результатами передачи внешней системе
    SEXSSERVICE_SEND_RQ     in varchar2,                           -- Сервис обмена для обработки внешней системой
    SEXSSERVICEFN_SEND_RQ   in varchar2,                           -- Функция обмена для обработки внешней системой
    SEXSSERVICE_SEND_RQCB   in varchar2,                           -- Сервис обмена для приёма Call-back запросов с результатами обработки внешней системой
    SEXSSERVICEFN_SEND_RQCB in varchar2,                           -- Функция сервиса обмена для приёма Call-back запросов с результатами обработки внешней системой
    SEXSSERVICE_FRCST_MD    in varchar2,                           -- Сервис обмена для публикации данных наработки оборудования при получении прогноза
    SEXSSERVICEFN_FRCST_MD  in varchar2,                           -- Функция обмена для публикации данных наработки оборудования при получении прогноза
    NEQUIPDS                out number,                            -- Регистрационный номер выборки данных оборудования
    NEQUIPDSCM              out number                             -- Регистрационный номер класса оборудования выборки данных
  )
  is
    NCOMPANY                PKG_STD.TREF := GET_SESSION_COMPANY(); -- Организация    
  begin
    /* Проверим параметры */
    if (SEQUIPDS is null) then
      P_EXCEPTION(0, 'Не указана выборка данных.');
    end if;
    if (SEQOBJKIND is null) then
      P_EXCEPTION(0, 'Не указан класс оборудования.');
    end if;
    if (SDICMUNTS is null) then
      P_EXCEPTION(0, 'Не указана единица измерения выборки.');
    end if;
    if (SUSERPROCS_DATA is null) then
      P_EXCEPTION(0, 'Не указана процедура формирования данных выборки.');
    end if;
    if ((SEXSSERVICE_UPLOAD is null) or (SEXSSERVICEFN_UPLOAD is null)) then
      P_EXCEPTION(0, 'Не указана функция обмена для выгрузки данных.');
    end if;
    if ((SEXSSERVICE_SEND_MD is null) or (SEXSSERVICEFN_SEND_MD is null)) then
      P_EXCEPTION(0,
                  'Не указана функция обмена для передачи внешней системе.');
    end if;
    if ((SEXSSERVICE_SEND_MDCB is null) or (SEXSSERVICEFN_SEND_MDCB is null)) then
      P_EXCEPTION(0,
                  'Не указана функция обмена для приёма обратной связи о передече внешней системе.');
    end if;
    if ((SEXSSERVICE_SEND_RQ is null) or (SEXSSERVICEFN_SEND_RQ is null)) then
      P_EXCEPTION(0,
                  'Не указана функция обмена для обработки внешней системой.');
    end if;
    if ((SEXSSERVICE_SEND_RQCB is null) or (SEXSSERVICEFN_SEND_RQCB is null)) then
      P_EXCEPTION(0,
                  'Не указана функция обмена для приёма обратной связи об обработке внешней системой.');
    end if;
    if ((SEXSSERVICE_FRCST_MD is null) or (SEXSSERVICEFN_FRCST_MD is null)) then
      P_EXCEPTION(0,
                  'Не указана функция обмена для публикации данных наработки оборудования при получении прогноза.');
    end if;
    /* Проверим права доступа */
    UDO_PKG_EQUIPDS_BASE.UTL_ACCESS(STABLE => 'UDO_T_EQUIPDS', SACTION => 'UDO_EQUIPDS_MAKE');
    /* Проверим наличие такой выборки */
    UDO_PKG_EQUIPDS_BASE.FIND_BY_CODE(NFLAG_SMART => 1, NCOMPANY => NCOMPANY, SCODE => SEQUIPDS, NRN => NEQUIPDS);
    /* Выборки нет */
    if (NEQUIPDS is null) then
      /* Добавим выборку данных */
      INS(SCODE => SEQUIPDS, SNAME => SEQUIPDS, NRN => NEQUIPDS);
    else
      /* Выборка есть - надо проверить в ней наличие класса оборудования */
      UDO_PKG_EQUIPDS_BASE.CM_FIND_BY_EQOBJKIND(NFLAG_SMART => 1,
                                                NCOMPANY    => NCOMPANY,
                                                SEQOBJKIND  => SEQOBJKIND,
                                                NRN         => NEQUIPDSCM);
    end if;
    /* Класса оборудования в выборке нет */
    if (NEQUIPDSCM is null) then
      /* Добавляем запись класса оборудования */
      CM_INS(NPRN                    => NEQUIPDS,
             SEQOBJKIND              => SEQOBJKIND,
             SDICMUNTS               => SDICMUNTS,
             SUSERPROCS_DATA         => SUSERPROCS_DATA,
             SEXSSERVICE_UPLOAD      => SEXSSERVICE_UPLOAD,
             SEXSSERVICEFN_UPLOAD    => SEXSSERVICEFN_UPLOAD,
             SEXSSERVICE_SEND_MD     => SEXSSERVICE_SEND_MD,
             SEXSSERVICEFN_SEND_MD   => SEXSSERVICEFN_SEND_MD,
             SEXSSERVICE_SEND_MDCB   => SEXSSERVICE_SEND_MDCB,
             SEXSSERVICEFN_SEND_MDCB => SEXSSERVICEFN_SEND_MDCB,
             SEXSSERVICE_SEND_RQ     => SEXSSERVICE_SEND_RQ,
             SEXSSERVICEFN_SEND_RQ   => SEXSSERVICEFN_SEND_RQ,
             SEXSSERVICE_SEND_RQCB   => SEXSSERVICE_SEND_RQCB,
             SEXSSERVICEFN_SEND_RQCB => SEXSSERVICEFN_SEND_RQCB,
             SEXSSERVICE_FRCST_MD    => SEXSSERVICE_FRCST_MD,
             SEXSSERVICEFN_FRCST_MD  => SEXSSERVICEFN_FRCST_MD,
             NRN                     => NEQUIPDSCM);
    end if;
  end MAKE;
  
  /* Карточка "Выборки данных оборудования (классы оборудования)" */
  procedure CM_CARD
  (
    NEQUIPDSCM              in number,       -- Рег. номер класса оборудования выборки данных
    COUT                    out clob         -- Сериализованная карточка
  )
  is  
    NCUR                    integer;         -- Курсор документа для результата
    XDOC                    PKG_XMAKE.TNODE; -- Документ для результата
    XEQUIPDSCM              PKG_XMAKE.TNODE; -- Элемент для карточки
  begin
    /* Проверим права доступа */
    UDO_PKG_EQUIPDS_BASE.UTL_ACCESS(STABLE => 'UDO_T_EQUIPDSCM', SACTION => 'UDO_EQUIPDSCM_SELECT');
    /* Открываем документ */
    NCUR := PKG_XMAKE.OPEN_CURSOR();
    /* Обращаемся к данным класса оборудования */
    for C in (select T.RN NRN,
                     FORMAT_HIER_NAME(null, null, OK.FULLCODE) SSEQOBJKIND,
                     OK.NAME SNAME,
                     DM.MEAS_MNEMO SDICMUNTS,
                     UP.CODE SUSERPROCS_DATA,
                     SU.CODE SEXSSERVICE_UPLOAD,
                     SFU.CODE SEXSSERVICEFN_UPLOAD,
                     SMD.CODE SEXSSERVICE_SEND_MD,
                     SFMD.CODE SEXSSERVICEFN_SEND_MD,
                     SMDCB.CODE SEXSSERVICE_SEND_MDCB,
                     SFMDCB.CODE SEXSSERVICEFN_SEND_MDCB,
                     SRQ.CODE SEXSSERVICE_SEND_RQ,
                     SFRQ.CODE SEXSSERVICEFN_SEND_RQ,
                     SRQCB.CODE SEXSSERVICE_SEND_RQCB,
                     SFRQCB.CODE SEXSSERVICEFN_SEND_RQCB,
                     SFCMD.CODE SEXSSERVICE_FRCST_MD,
                     SFFCMD.CODE SEXSSERVICEFN_FRCST_MD
                from UDO_T_EQUIPDSCM T,
                     EQOBJKIND       OK,
                     USERPROCS       UP,
                     EXSSERVICE      SU,
                     EXSSERVICEFN    SFU,
                     EXSSERVICE      SMD,
                     EXSSERVICEFN    SFMD,
                     EXSSERVICE      SMDCB,
                     EXSSERVICEFN    SFMDCB,
                     EXSSERVICE      SRQ,
                     EXSSERVICEFN    SFRQ,
                     EXSSERVICE      SRQCB,
                     EXSSERVICEFN    SFRQCB,
                     EXSSERVICE      SFCMD,
                     EXSSERVICEFN    SFFCMD,
                     DICMUNTS        DM
               where T.RN = NEQUIPDSCM
                 and T.EQOBJKIND = OK.RN
                 and T.USERPROCS_DATA = UP.RN
                 and T.EXSSERVICEFN_UPLOAD = SFU.RN
                 and SFU.PRN = SU.RN
                 and T.EXSSERVICEFN_SEND_MD = SFMD.RN
                 and SFMD.PRN = SMD.RN
                 and T.EXSSERVICEFN_SEND_MDCB = SFMDCB.RN
                 and SFMDCB.PRN = SMDCB.RN
                 and T.EXSSERVICEFN_SEND_RQ = SFRQ.RN
                 and SFRQ.PRN = SRQ.RN
                 and T.EXSSERVICEFN_SEND_RQCB = SFRQCB.RN
                 and SFRQCB.PRN = SRQCB.RN                 
                 and T.EXSSERVICEFN_FRCST_MD = SFFCMD.RN
                 and SFFCMD.PRN = SFCMD.RN                 
                 and T.DICMUNTS = DM.RN)
    loop
      /* Собираем карточку класса оборудования */
      XEQUIPDSCM := PKG_XMAKE.ELEMENT(ICURSOR     => NCUR,
                                      SNAME       => 'XEQUIPDSCM',
                                      RATTRIBUTES => PKG_XMAKE.ATTRIBUTES(ICURSOR      => NCUR,
                                                                          RATTRIBUTE00 => PKG_XMAKE.ATTRIBUTE(ICURSOR => NCUR,
                                                                                                              SNAME   => 'NRN',
                                                                                                              SVALUE  => C.NRN),
                                                                          RATTRIBUTE01 => PKG_XMAKE.ATTRIBUTE(ICURSOR => NCUR,
                                                                                                              SNAME   => 'SSEQOBJKIND',
                                                                                                              SVALUE  => C.SSEQOBJKIND),
                                                                          RATTRIBUTE02 => PKG_XMAKE.ATTRIBUTE(ICURSOR => NCUR,
                                                                                                              SNAME   => 'SNAME',
                                                                                                              SVALUE  => C.SNAME),
                                                                          RATTRIBUTE03 => PKG_XMAKE.ATTRIBUTE(ICURSOR => NCUR,
                                                                                                              SNAME   => 'SDICMUNTS',
                                                                                                              SVALUE  => C.SDICMUNTS),
                                                                          RATTRIBUTE04 => PKG_XMAKE.ATTRIBUTE(ICURSOR => NCUR,
                                                                                                              SNAME   => 'SUSERPROCS_DATA',
                                                                                                              SVALUE  => C.SUSERPROCS_DATA),
                                                                          RATTRIBUTE05 => PKG_XMAKE.ATTRIBUTE(ICURSOR => NCUR,
                                                                                                              SNAME   => 'SEXSSERVICE_UPLOAD',
                                                                                                              SVALUE  => C.SEXSSERVICE_UPLOAD),
                                                                          RATTRIBUTE06 => PKG_XMAKE.ATTRIBUTE(ICURSOR => NCUR,
                                                                                                              SNAME   => 'SEXSSERVICEFN_UPLOAD',
                                                                                                              SVALUE  => C.SEXSSERVICEFN_UPLOAD),
                                                                          RATTRIBUTE07 => PKG_XMAKE.ATTRIBUTE(ICURSOR => NCUR,
                                                                                                              SNAME   => 'SEXSSERVICE_SEND_MD',
                                                                                                              SVALUE  => C.SEXSSERVICE_SEND_MD),
                                                                          RATTRIBUTE08 => PKG_XMAKE.ATTRIBUTE(ICURSOR => NCUR,
                                                                                                              SNAME   => 'SEXSSERVICEFN_SEND_MD',
                                                                                                              SVALUE  => C.SEXSSERVICEFN_SEND_MD),
                                                                          RATTRIBUTE09 => PKG_XMAKE.ATTRIBUTE(ICURSOR => NCUR,
                                                                                                              SNAME   => 'SEXSSERVICE_SEND_MDCB',
                                                                                                              SVALUE  => C.SEXSSERVICE_SEND_MDCB),
                                                                          RATTRIBUTE10 => PKG_XMAKE.ATTRIBUTE(ICURSOR => NCUR,
                                                                                                              SNAME   => 'SEXSSERVICEFN_SEND_MDCB',
                                                                                                              SVALUE  => C.SEXSSERVICEFN_SEND_MDCB),
                                                                          RATTRIBUTE11 => PKG_XMAKE.ATTRIBUTE(ICURSOR => NCUR,
                                                                                                              SNAME   => 'SEXSSERVICE_SEND_RQ',
                                                                                                              SVALUE  => C.SEXSSERVICE_SEND_RQ),
                                                                          RATTRIBUTE12 => PKG_XMAKE.ATTRIBUTE(ICURSOR => NCUR,
                                                                                                              SNAME   => 'SEXSSERVICEFN_SEND_RQ',
                                                                                                              SVALUE  => C.SEXSSERVICEFN_SEND_RQ),
                                                                          RATTRIBUTE13 => PKG_XMAKE.ATTRIBUTE(ICURSOR => NCUR,
                                                                                                              SNAME   => 'SEXSSERVICE_SEND_RQCB',
                                                                                                              SVALUE  => C.SEXSSERVICE_SEND_RQCB),
                                                                          RATTRIBUTE14 => PKG_XMAKE.ATTRIBUTE(ICURSOR => NCUR,
                                                                                                              SNAME   => 'SEXSSERVICEFN_SEND_RQCB',
                                                                                                              SVALUE  => C.SEXSSERVICEFN_SEND_RQCB),
                                                                          RATTRIBUTE15 => PKG_XMAKE.ATTRIBUTE(ICURSOR => NCUR,
                                                                                                              SNAME   => 'SEXSSERVICE_FRCST_MD',
                                                                                                              SVALUE  => C.SEXSSERVICE_FRCST_MD),
                                                                          RATTRIBUTE16 => PKG_XMAKE.ATTRIBUTE(ICURSOR => NCUR,
                                                                                                              SNAME   => 'SEXSSERVICEFN_FRCST_MD',
                                                                                                              SVALUE  => C.SEXSSERVICEFN_FRCST_MD)));
    end loop;
    /* Формируем XML-представление ответа */
    XDOC := PKG_XMAKE.ELEMENT(ICURSOR => NCUR, SNAME => 'XDATA', RNODE00 => XEQUIPDSCM);
    /* Конвертируем в 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 CM_CARD;
  
  /* Список "Выборки данных оборудования (классы оборудования)" */
  procedure CM_LIST
  (
    NEQUIPDS                in number,       -- Рег. номер выборки данных
    COUT                    out clob         -- Сериализованный список
  )
  is  
    NCUR                    integer;         -- Курсор документа для результата
    XDOC                    PKG_XMAKE.TNODE; -- Документ для результата
    XDSCM                   PKG_XMAKE.TNODE; -- Элемент для выборки данных
  begin
    /* Проверим права доступа */
    UDO_PKG_EQUIPDS_BASE.UTL_ACCESS(STABLE => 'UDO_T_EQUIPDSCM', SACTION => 'UDO_EQUIPDSCM_SELECT');
    /* Открываем документ */
    NCUR := PKG_XMAKE.OPEN_CURSOR();
    /* Обходим классы оборудования заданной выборки данных */
    for C in (select T.RN          NRN,
                     OK.CODE       SCODE,
                     OK.NAME       SNAME,
                     DM.MEAS_MNEMO SDICMUNTS,
                     UPD.CODE      SUSERPROCS_DATA,
                     UPL.CODE      SEXSSERVICEFN_UPLOAD,
                     SMD.CODE      SEXSSERVICEFN_SEND_MD,
                     SRQ.CODE      SEXSSERVICEFN_SEND_RQ
                from UDO_T_EQUIPDSCM T,
                     EQOBJKIND       OK,
                     DICMUNTS        DM,
                     USERPROCS       UPD,
                     EXSSERVICEFN    UPL,
                     EXSSERVICEFN    SMD,
                     EXSSERVICEFN    SRQ
               where T.PRN = NEQUIPDS
                 and T.EQOBJKIND = OK.RN
                 and T.DICMUNTS = DM.RN
                 and T.USERPROCS_DATA = UPD.RN
                 and T.EXSSERVICEFN_UPLOAD = UPL.RN
                 and T.EXSSERVICEFN_SEND_MD = SMD.RN
                 and T.EXSSERVICEFN_SEND_RQ = SRQ.RN
               order by OK.CODE)
    loop
      XDSCM := PKG_XMAKE.CONCAT(ICURSOR => NCUR,
                                RNODE00 => XDSCM,
                                RNODE01 => PKG_XMAKE.ELEMENT(ICURSOR     => NCUR,
                                                             SNAME       => 'XDSCM',
                                                             RATTRIBUTES => PKG_XMAKE.ATTRIBUTES(ICURSOR      => NCUR,
                                                                                                 RATTRIBUTE00 => PKG_XMAKE.ATTRIBUTE(ICURSOR => NCUR,
                                                                                                                                     SNAME   => 'NRN',
                                                                                                                                     SVALUE  => 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   => 'SDICMUNTS',
                                                                                                                                     SVALUE  => C.SDICMUNTS),
                                                                                                 RATTRIBUTE04 => PKG_XMAKE.ATTRIBUTE(ICURSOR => NCUR,
                                                                                                                                     SNAME   => 'SUSERPROCS_DATA',
                                                                                                                                     SVALUE  => C.SUSERPROCS_DATA),
                                                                                                 RATTRIBUTE05 => PKG_XMAKE.ATTRIBUTE(ICURSOR => NCUR,
                                                                                                                                     SNAME   => 'SEXSSERVICEFN_UPLOAD',
                                                                                                                                     SVALUE  => C.SEXSSERVICEFN_UPLOAD),
                                                                                                 RATTRIBUTE06 => PKG_XMAKE.ATTRIBUTE(ICURSOR => NCUR,
                                                                                                                                     SNAME   => 'SEXSSERVICEFN_SEND_MD',
                                                                                                                                     SVALUE  => C.SEXSSERVICEFN_SEND_MD),
                                                                                                 RATTRIBUTE07 => PKG_XMAKE.ATTRIBUTE(ICURSOR => NCUR,
                                                                                                                                     SNAME   => 'SEXSSERVICEFN_SEND_RQ',
                                                                                                                                     SVALUE  => C.SEXSSERVICEFN_SEND_RQ))));
    end loop;
    /* Формируем XML-представление ответа */
    XDOC := PKG_XMAKE.ELEMENT(ICURSOR => NCUR, SNAME => 'XDATA', RNODE00 => XDSCM);
    /* Конвертируем в 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 CM_LIST;
  
  /* Клиентское добавление "Выборки данных оборудования (классы оборудования)" */
  procedure CM_INS
  (
    NPRN                    in number,                             -- Родитель
    SEQOBJKIND              in varchar2,                           -- Класс оборудования
    SDICMUNTS               in varchar2,                           -- Единица измерения выборки
    SUSERPROCS_DATA         in varchar2,                           -- Процедура формирования
    SEXSSERVICE_UPLOAD      in varchar2,                           -- Сервис обмена для выгрузки данных
    SEXSSERVICEFN_UPLOAD    in varchar2,                           -- Функция обмена для выгрузки данных
    SEXSSERVICE_SEND_MD     in varchar2,                           -- Сервис обмена для передачи внешней системе
    SEXSSERVICEFN_SEND_MD   in varchar2,                           -- Функция обмена для передачи внешней системе
    SEXSSERVICE_SEND_MDCB   in varchar2,                           -- Сервис обмена для приёма Call-back запросов с результатами передачи внешней системе
    SEXSSERVICEFN_SEND_MDCB in varchar2,                           -- Функция сервиса обмена для приёма Call-back запросов с результатами передачи внешней системе
    SEXSSERVICE_SEND_RQ     in varchar2,                           -- Сервис обмена для обработки внешней системой
    SEXSSERVICEFN_SEND_RQ   in varchar2,                           -- Функция обмена для обработки внешней системой
    SEXSSERVICE_SEND_RQCB   in varchar2,                           -- Сервис обмена для приёма Call-back запросов с результатами обработки внешней системой
    SEXSSERVICEFN_SEND_RQCB in varchar2,                           -- Функция сервиса обмена для приёма Call-back запросов с результатами обработки внешней системой
    SEXSSERVICE_FRCST_MD    in varchar2,                           -- Сервис обмена для публикации данных наработки оборудования при получении прогноза
    SEXSSERVICEFN_FRCST_MD  in varchar2,                           -- Функция обмена для публикации данных наработки оборудования при получении прогноза
    NRN                     out number                             -- Регистрационный номер
  )
  is
    NCOMPANY                PKG_STD.TREF := GET_SESSION_COMPANY(); -- Организация
    NEQOBJKIND              PKG_STD.TREF;                          -- Рег. номер класса оборудования
    NDICMUNTS               PKG_STD.TREF;                          -- Рег. номер единицы измерения выборки
    NUSERPROCS_DATA         PKG_STD.TREF;                          -- Рег. номер процедуры формирования
    NEXSSERVICEFN_UPLOAD    PKG_STD.TREF;                          -- Рег. номер функции обмена для выгрузки данных
    NEXSSERVICEFN_SEND_MD   PKG_STD.TREF;                          -- Рег. номер Функции обмена для передачи внешней системе
    NEXSSERVICEFN_SEND_MDCB PKG_STD.TREF;                          -- Рег. номер call-back функции обмена для передачи внешней системе
    NEXSSERVICEFN_SEND_RQ   PKG_STD.TREF;                          -- Рег. номер функции обмена для обработки внешней системой
    NEXSSERVICEFN_SEND_RQCB PKG_STD.TREF;                          -- Рег. номер call-back функции обмена для обработки внешней системой
    NEXSSERVICEFN_FRCST_MD  PKG_STD.TREF;                          -- Рег. номер функции обмена для публикации данных наработки оборудования при получении прогноза
  begin
    /* Проверим параметры */
    if (NPRN is null) then
      P_EXCEPTION(0, 'Не указана родительская выборка данных.');
    end if;
    if (SEQOBJKIND is null) then
      P_EXCEPTION(0, 'Не указан класс оборудования.');
    end if;
    if (SDICMUNTS is null) then
      P_EXCEPTION(0, 'Не указана единица измерения выборки.');
    end if;
    if (SUSERPROCS_DATA is null) then
      P_EXCEPTION(0, 'Не указана процедура формирования данных выборки.');
    end if;
    if ((SEXSSERVICE_UPLOAD is null) or (SEXSSERVICEFN_UPLOAD is null)) then
      P_EXCEPTION(0, 'Не указана функция обмена для выгрузки данных.');
    end if;
    if ((SEXSSERVICE_SEND_MD is null) or (SEXSSERVICEFN_SEND_MD is null)) then
      P_EXCEPTION(0,
                  'Не указана функция обмена для передачи внешней системе.');
    end if;
    if ((SEXSSERVICE_SEND_MDCB is null) or (SEXSSERVICEFN_SEND_MDCB is null)) then
      P_EXCEPTION(0,
                  'Не указана функция обмена для приёма обратной связи о передече внешней системе.');
    end if;
    if ((SEXSSERVICE_SEND_RQ is null) or (SEXSSERVICEFN_SEND_RQ is null)) then
      P_EXCEPTION(0,
                  'Не указана функция обмена для обработки внешней системой.');
    end if;
    if ((SEXSSERVICE_SEND_RQCB is null) or (SEXSSERVICEFN_SEND_RQCB is null)) then
      P_EXCEPTION(0,
                  'Не указана функция обмена для приёма обратной связи об обработке внешней системой.');
    end if;
    if ((SEXSSERVICE_FRCST_MD is null) or (SEXSSERVICEFN_FRCST_MD is null)) then
      P_EXCEPTION(0,
                  'Не указана функция обмена для публикации данных наработки оборудования при получении прогноза.');
    end if;
    /* Проверим права доступа */
    UDO_PKG_EQUIPDS_BASE.UTL_ACCESS(STABLE => 'UDO_T_EQUIPDSCM', SACTION => 'UDO_EQUIPDSCM_INSERT');
    /* Разыменуем ссылки */
    UDO_PKG_EQUIPDS_BASE.CM_JOINS(NCOMPANY                => NCOMPANY,
                                  SEQOBJKIND              => SEQOBJKIND,
                                  SDICMUNTS               => SDICMUNTS,
                                  SUSERPROCS_DATA         => SUSERPROCS_DATA,
                                  SEXSSERVICE_UPLOAD      => SEXSSERVICE_UPLOAD,
                                  SEXSSERVICEFN_UPLOAD    => SEXSSERVICEFN_UPLOAD,
                                  SEXSSERVICE_SEND_MD     => SEXSSERVICE_SEND_MD,
                                  SEXSSERVICEFN_SEND_MD   => SEXSSERVICEFN_SEND_MD,
                                  SEXSSERVICE_SEND_MDCB   => SEXSSERVICE_SEND_MDCB,
                                  SEXSSERVICEFN_SEND_MDCB => SEXSSERVICEFN_SEND_MDCB,
                                  SEXSSERVICE_SEND_RQ     => SEXSSERVICE_SEND_RQ,
                                  SEXSSERVICEFN_SEND_RQ   => SEXSSERVICEFN_SEND_RQ,
                                  SEXSSERVICE_SEND_RQCB   => SEXSSERVICE_SEND_RQCB,
                                  SEXSSERVICEFN_SEND_RQCB => SEXSSERVICEFN_SEND_RQCB,
                                  SEXSSERVICE_FRCST_MD    => SEXSSERVICE_FRCST_MD,
                                  SEXSSERVICEFN_FRCST_MD  => SEXSSERVICEFN_FRCST_MD,
                                  NEQOBJKIND              => NEQOBJKIND,
                                  NDICMUNTS               => NDICMUNTS,
                                  NUSERPROCS_DATA         => NUSERPROCS_DATA,
                                  NEXSSERVICEFN_UPLOAD    => NEXSSERVICEFN_UPLOAD,
                                  NEXSSERVICEFN_SEND_MD   => NEXSSERVICEFN_SEND_MD,
                                  NEXSSERVICEFN_SEND_MDCB => NEXSSERVICEFN_SEND_MDCB,
                                  NEXSSERVICEFN_SEND_RQ   => NEXSSERVICEFN_SEND_RQ,
                                  NEXSSERVICEFN_SEND_RQCB => NEXSSERVICEFN_SEND_RQCB,
                                  NEXSSERVICEFN_FRCST_MD  => NEXSSERVICEFN_FRCST_MD);
    /* Добавляем запись */
    UDO_PKG_EQUIPDS_BASE.CM_INS(NPRN                    => NPRN,
                                NEQOBJKIND              => NEQOBJKIND,
                                NDICMUNTS               => NDICMUNTS,
                                NUSERPROCS_DATA         => NUSERPROCS_DATA,
                                NEXSSERVICEFN_UPLOAD    => NEXSSERVICEFN_UPLOAD,
                                NEXSSERVICEFN_SEND_MD   => NEXSSERVICEFN_SEND_MD,
                                NEXSSERVICEFN_SEND_MDCB => NEXSSERVICEFN_SEND_MDCB,
                                NEXSSERVICEFN_SEND_RQ   => NEXSSERVICEFN_SEND_RQ,
                                NEXSSERVICEFN_SEND_RQCB => NEXSSERVICEFN_SEND_RQCB,
                                NEXSSERVICEFN_FRCST_MD  => NEXSSERVICEFN_FRCST_MD,
                                NRN                     => NRN);
  end CM_INS;

  /* Клиентское исправление "Выборки данных оборудования (классы оборудования)" */
  procedure CM_UPD
  (
    NRN                     in number,                             -- Регистрационный номер
    SEQOBJKIND              in varchar2,                           -- Класс оборудования
    SDICMUNTS               in varchar2,                           -- Единица измерения выборки
    SUSERPROCS_DATA         in varchar2,                           -- Процедура формирования
    SEXSSERVICE_UPLOAD      in varchar2,                           -- Сервис обмена для выгрузки данных
    SEXSSERVICEFN_UPLOAD    in varchar2,                           -- Функция обмена для выгрузки данных
    SEXSSERVICE_SEND_MD     in varchar2,                           -- Сервис обмена для передачи внешней системе
    SEXSSERVICEFN_SEND_MD   in varchar2,                           -- Функция обмена для передачи внешней системе
    SEXSSERVICE_SEND_MDCB   in varchar2,                           -- Сервис обмена для приёма Call-back запросов с результатами передачи внешней системе
    SEXSSERVICEFN_SEND_MDCB in varchar2,                           -- Функция сервиса обмена для приёма Call-back запросов с результатами передачи внешней системе
    SEXSSERVICE_SEND_RQ     in varchar2,                           -- Сервис обмена для обработки внешней системой
    SEXSSERVICEFN_SEND_RQ   in varchar2,                           -- Функция обмена для обработки внешней системой
    SEXSSERVICE_SEND_RQCB   in varchar2,                           -- Сервис обмена для приёма Call-back запросов с результатами обработки внешней системой
    SEXSSERVICEFN_SEND_RQCB in varchar2,                           -- Функция сервиса обмена для приёма Call-back запросов с результатами обработки внешней системой
    SEXSSERVICE_FRCST_MD    in varchar2,                           -- Сервис обмена для публикации данных наработки оборудования при получении прогноза
    SEXSSERVICEFN_FRCST_MD  in varchar2                            -- Функция обмена для публикации данных наработки оборудования при получении прогноза
  )
  is
    NCOMPANY                PKG_STD.TREF := GET_SESSION_COMPANY(); -- Организация
    NEQOBJKIND              PKG_STD.TREF;                          -- Рег. номер класса оборудования
    NDICMUNTS               PKG_STD.TREF;                          -- Рег. номер единицы измерения выборки
    NUSERPROCS_DATA         PKG_STD.TREF;                          -- Рег. номер процедуры формирования
    NEXSSERVICEFN_UPLOAD    PKG_STD.TREF;                          -- Рег. номер функции обмена для выгрузки данных
    NEXSSERVICEFN_SEND_MD   PKG_STD.TREF;                          -- Рег. номер Функции обмена для передачи внешней системе
    NEXSSERVICEFN_SEND_MDCB PKG_STD.TREF;                          -- Рег. номер call-back функции обмена для передачи внешней системе
    NEXSSERVICEFN_SEND_RQ   PKG_STD.TREF;                          -- Рег. номер функции обмена для обработки внешней системой
    NEXSSERVICEFN_SEND_RQCB PKG_STD.TREF;                          -- Рег. номер call-back функции обмена для обработки внешней системой
    NEXSSERVICEFN_FRCST_MD  PKG_STD.TREF;                          -- Рег. номер функции обмена для публикации данных наработки оборудования при получении прогноза
  begin
    /* Проверим параметры */
    if (NRN is null) then
      P_EXCEPTION(0, 'Не указан идентификатор исправляемого класса оборудования выборки данных.');
    end if;
    if (SEQOBJKIND is null) then
      P_EXCEPTION(0, 'Не указан класс оборудования.');
    end if;
    if (SDICMUNTS is null) then
      P_EXCEPTION(0, 'Не указана единица измерения выборки.');
    end if;
    if (SUSERPROCS_DATA is null) then
      P_EXCEPTION(0, 'Не указана процедура формирования данных выборки.');
    end if;
    if ((SEXSSERVICE_UPLOAD is null) or (SEXSSERVICEFN_UPLOAD is null)) then
      P_EXCEPTION(0, 'Не указана функция обмена для выгрузки данных.');
    end if;
    if ((SEXSSERVICE_SEND_MD is null) or (SEXSSERVICEFN_SEND_MD is null)) then
      P_EXCEPTION(0,
                  'Не указана функция обмена для передачи внешней системе.');
    end if;
    if ((SEXSSERVICE_SEND_MDCB is null) or (SEXSSERVICEFN_SEND_MDCB is null)) then
      P_EXCEPTION(0,
                  'Не указана функция обмена для приёма обратной связи о передече внешней системе.');
    end if;
    if ((SEXSSERVICE_SEND_RQ is null) or (SEXSSERVICEFN_SEND_RQ is null)) then
      P_EXCEPTION(0,
                  'Не указана функция обмена для обработки внешней системой.');
    end if;
    if ((SEXSSERVICE_SEND_RQCB is null) or (SEXSSERVICEFN_SEND_RQCB is null)) then
      P_EXCEPTION(0,
                  'Не указана функция обмена для приёма обратной связи об обработке внешней системой.');
    end if;
    if ((SEXSSERVICE_FRCST_MD is null) or (SEXSSERVICEFN_FRCST_MD is null)) then
      P_EXCEPTION(0,
                  'Не указана функция обмена для публикации данных наработки оборудования при получении прогноза.');
    end if;
    /* Проверим права доступа */
    UDO_PKG_EQUIPDS_BASE.UTL_ACCESS(STABLE => 'UDO_T_EQUIPDSCM', SACTION => 'UDO_EQUIPDSCM_UPDATE');
    /* Разыменуем ссылки */
    UDO_PKG_EQUIPDS_BASE.CM_JOINS(NCOMPANY                => NCOMPANY,
                                  SEQOBJKIND              => SEQOBJKIND,
                                  SDICMUNTS               => SDICMUNTS,
                                  SUSERPROCS_DATA         => SUSERPROCS_DATA,
                                  SEXSSERVICE_UPLOAD      => SEXSSERVICE_UPLOAD,
                                  SEXSSERVICEFN_UPLOAD    => SEXSSERVICEFN_UPLOAD,
                                  SEXSSERVICE_SEND_MD     => SEXSSERVICE_SEND_MD,
                                  SEXSSERVICEFN_SEND_MD   => SEXSSERVICEFN_SEND_MD,
                                  SEXSSERVICE_SEND_MDCB   => SEXSSERVICE_SEND_MDCB,
                                  SEXSSERVICEFN_SEND_MDCB => SEXSSERVICEFN_SEND_MDCB,
                                  SEXSSERVICE_SEND_RQ     => SEXSSERVICE_SEND_RQ,
                                  SEXSSERVICEFN_SEND_RQ   => SEXSSERVICEFN_SEND_RQ,
                                  SEXSSERVICE_SEND_RQCB   => SEXSSERVICE_SEND_RQCB,
                                  SEXSSERVICEFN_SEND_RQCB => SEXSSERVICEFN_SEND_RQCB,
                                  SEXSSERVICE_FRCST_MD    => SEXSSERVICE_FRCST_MD,
                                  SEXSSERVICEFN_FRCST_MD  => SEXSSERVICEFN_FRCST_MD,
                                  NEQOBJKIND              => NEQOBJKIND,
                                  NDICMUNTS               => NDICMUNTS,
                                  NUSERPROCS_DATA         => NUSERPROCS_DATA,
                                  NEXSSERVICEFN_UPLOAD    => NEXSSERVICEFN_UPLOAD,
                                  NEXSSERVICEFN_SEND_MD   => NEXSSERVICEFN_SEND_MD,
                                  NEXSSERVICEFN_SEND_MDCB => NEXSSERVICEFN_SEND_MDCB,
                                  NEXSSERVICEFN_SEND_RQ   => NEXSSERVICEFN_SEND_RQ,
                                  NEXSSERVICEFN_SEND_RQCB => NEXSSERVICEFN_SEND_RQCB,
                                  NEXSSERVICEFN_FRCST_MD  => NEXSSERVICEFN_FRCST_MD);
    /* Исправляем запись */
    UDO_PKG_EQUIPDS_BASE.CM_UPD(NRN                     => NRN,
                                NEQOBJKIND              => NEQOBJKIND,
                                NDICMUNTS               => NDICMUNTS,
                                NUSERPROCS_DATA         => NUSERPROCS_DATA,
                                NEXSSERVICEFN_UPLOAD    => NEXSSERVICEFN_UPLOAD,
                                NEXSSERVICEFN_SEND_MD   => NEXSSERVICEFN_SEND_MD,
                                NEXSSERVICEFN_SEND_MDCB => NEXSSERVICEFN_SEND_MDCB,
                                NEXSSERVICEFN_SEND_RQ   => NEXSSERVICEFN_SEND_RQ,
                                NEXSSERVICEFN_SEND_RQCB => NEXSSERVICEFN_SEND_RQCB,
                                NEXSSERVICEFN_FRCST_MD  => NEXSSERVICEFN_FRCST_MD);
  end CM_UPD;

  /* Клиентское удаление "Выборки данных оборудования (классы оборудования)" */
  procedure CM_DEL
  (
    NRN                     in number   -- Регистрационный номер
  )
  is
  begin
    /* Проверим права доступа */
    UDO_PKG_EQUIPDS_BASE.UTL_ACCESS(STABLE => 'UDO_T_EQUIPDSCM', SACTION => 'UDO_EQUIPDSCM_DELETE', NDOCUMENT => NRN);
    /* Удаляем запись */
    UDO_PKG_EQUIPDS_BASE.CM_DEL(NRN => NRN);
  end CM_DEL;
  
  /* Клиентское получение списка доступных выборок данных "Выборки данных оборудования (классы оборудования)" */
  procedure CM_DATASET_LIST
  (
    NRN                     in number,         -- Регистрационный номер
    NSTATUS                 in number := null, -- Статус (null - все, см. константы UDO_PKG_EQUIPDS_BASE.NCMFL_STATUS_*)
    COUT                    out clob           -- Сериализованный список  
  )
  is
    NCUR                    integer;           -- Курсор документа для результата
    XDOC                    PKG_XMAKE.TNODE;   -- Документ для результата
    XDSCM_DATASET           PKG_XMAKE.TNODE;   -- Элемент для выборки данных
  begin
    /* Проверим права доступа */
    UDO_PKG_EQUIPDS_BASE.UTL_ACCESS(STABLE => 'UDO_T_EQUIPDSCM', SACTION => 'UDO_EQUIPDSCM_SELECT');
    /* Открываем документ */
    NCUR := PKG_XMAKE.OPEN_CURSOR();
    /* Обходим выборки, зафиксированные в файлах данных */
    for C in (select distinct T.DATASET_ID NDATASET_ID,
                              T.DATASET_TS DDATASET_TS
                from UDO_T_EQUIPDSCMFL T
               where T.PRN = NRN
                 and ((NSTATUS is null) or ((NSTATUS is not null) and (T.STATUS = NSTATUS)))
               order by T.DATASET_TS)
    loop
      XDSCM_DATASET := PKG_XMAKE.CONCAT(ICURSOR => NCUR,
                                        RNODE00 => XDSCM_DATASET,
                                        RNODE01 => PKG_XMAKE.ELEMENT(ICURSOR     => NCUR,
                                                                     SNAME       => 'XDSCM_DATASET',
                                                                     RATTRIBUTES => PKG_XMAKE.ATTRIBUTES(ICURSOR      => NCUR,
                                                                                                         RATTRIBUTE00 => PKG_XMAKE.ATTRIBUTE(ICURSOR => NCUR,
                                                                                                                                             SNAME   => 'value',
                                                                                                                                             SVALUE  => C.NDATASET_ID),
                                                                                                         RATTRIBUTE01 => PKG_XMAKE.ATTRIBUTE(ICURSOR => NCUR,
                                                                                                                                             SNAME   => 'name',
                                                                                                                                             SVALUE  => UDO_PKG_EQUIPDS_BASE.UTL_DATASET_MAKE_NAME(NDATASET_ID => C.NDATASET_ID,
                                                                                                                                                                                                   DDATASET_TS => C.DDATASET_TS)))));
    end loop;
    /* Формируем XML-представление ответа */
    XDOC := PKG_XMAKE.ELEMENT(ICURSOR => NCUR, SNAME => 'XDATA', RNODE00 => XDSCM_DATASET);
    /* Конвертируем в 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 CM_DATASET_LIST;
  
  /* Список "Выборки данных оборудования (классы оборудования, файлы данных)" */
  procedure CMFL_LIST
  (
    NEQUIPDSCM              in number,                   -- Рег. номер класса оборудования выборки данных
    COUT                    out clob                     -- Сериализованная таблица данных  
  )
  is
    RDG                     PKG_P8PANELS_VISUAL.TDG;     -- Описание таблицы
    RDG_ROW                 PKG_P8PANELS_VISUAL.TDG_ROW; -- Строка таблицы
  begin
    /* Проверим права доступа */
    UDO_PKG_EQUIPDS_BASE.UTL_ACCESS(STABLE => 'UDO_T_EQUIPDSCMFL', SACTION => 'UDO_EQUIPDSCMFL_SELECT');
    /* Инициализируем таблицу данных */
    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      => 'SDATASET',
                                        SCAPTION   => 'Выборка',
                                        SDATA_TYPE => PKG_P8PANELS_VISUAL.SDATA_TYPE_STR);
    PKG_P8PANELS_VISUAL.TDG_ADD_COL_DEF(RDATA_GRID => RDG,
                                        SNAME      => 'SFILE_NAME',
                                        SCAPTION   => 'Имя',
                                        SDATA_TYPE => PKG_P8PANELS_VISUAL.SDATA_TYPE_STR);
    PKG_P8PANELS_VISUAL.TDG_ADD_COL_DEF(RDATA_GRID => RDG,
                                        SNAME      => 'SDESCR',
                                        SCAPTION   => 'Описание',
                                        SDATA_TYPE => PKG_P8PANELS_VISUAL.SDATA_TYPE_STR);
    PKG_P8PANELS_VISUAL.TDG_ADD_COL_DEF(RDATA_GRID => RDG,
                                        SNAME      => 'NSTATUS',
                                        SCAPTION   => 'Состояние',
                                        SDATA_TYPE => PKG_P8PANELS_VISUAL.SDATA_TYPE_NUMB);
    PKG_P8PANELS_VISUAL.TDG_ADD_COL_DEF(RDATA_GRID => RDG,
                                        SNAME      => 'SERR',
                                        SCAPTION   => 'Сообщение об ошибке',
                                        SDATA_TYPE => PKG_P8PANELS_VISUAL.SDATA_TYPE_STR,
                                        BVISIBLE   => false);
    PKG_P8PANELS_VISUAL.TDG_ADD_COL_DEF(RDATA_GRID => RDG,
                                        SNAME      => 'SACTIONS',
                                        SCAPTION   => 'Действия',
                                        SDATA_TYPE => PKG_P8PANELS_VISUAL.SDATA_TYPE_STR);
    /* Обходим данные */
    for C in (select T.RN NRN,
                     T.DATASET_ID NDATASET_ID,
                     T.DATASET_TS DDATASET_TS,
                     T.FILE_NAME SFILE_NAME,
                     replace(replace(T.DESCR, CHR(13) || CHR(10), '<br>'), CHR(10), '<br>') SDESCR,
                     T.STATUS NSTATUS,
                     T.ERR SERR
                from UDO_T_EQUIPDSCMFL T
               where T.PRN = NEQUIPDSCM
               order by T.RN)
    loop
      /* Добавляем колонки с данными */
      PKG_P8PANELS_VISUAL.TDG_ROW_ADD_COL(RROW => RDG_ROW, SNAME => 'NRN', NVALUE => C.NRN, BCLEAR => true);
      PKG_P8PANELS_VISUAL.TDG_ROW_ADD_COL(RROW   => RDG_ROW,
                                          SNAME  => 'SDATASET',
                                          SVALUE => UDO_PKG_EQUIPDS_BASE.UTL_DATASET_MAKE_NAME(NDATASET_ID => C.NDATASET_ID,
                                                                                               DDATASET_TS => C.DDATASET_TS));
      PKG_P8PANELS_VISUAL.TDG_ROW_ADD_COL(RROW => RDG_ROW, SNAME => 'SFILE_NAME', SVALUE => C.SFILE_NAME);
      PKG_P8PANELS_VISUAL.TDG_ROW_ADD_COL(RROW => RDG_ROW, SNAME => 'SDESCR', SVALUE => C.SDESCR);
      PKG_P8PANELS_VISUAL.TDG_ROW_ADD_COL(RROW => RDG_ROW, SNAME => 'NSTATUS', NVALUE => C.NSTATUS);
      PKG_P8PANELS_VISUAL.TDG_ROW_ADD_COL(RROW => RDG_ROW, SNAME => 'SERR', SVALUE => C.SERR);
      PKG_P8PANELS_VISUAL.TDG_ROW_ADD_COL(RROW => RDG_ROW, SNAME => 'SACTIONS');
      /* Добавляем строку в таблицу */
      PKG_P8PANELS_VISUAL.TDG_ADD_ROW(RDATA_GRID => RDG, RROW => RDG_ROW);
    end loop;
    /* Сериализуем описание */
    COUT := PKG_P8PANELS_VISUAL.TDG_TO_XML(RDATA_GRID => RDG, NINCLUDE_DEF => 1);
  end CMFL_LIST;
  
  /* Удаление "Выборки данных оборудования (классы оборудования, файлы данных)" */
  procedure CMFL_DEL
  (
    NRN                     in number   -- Регистрационный номер
  )
  is
  begin
    /* Проверим права доступа */
    UDO_PKG_EQUIPDS_BASE.UTL_ACCESS(STABLE => 'UDO_T_EQUIPDSCMFL', SACTION => 'UDO_EQUIPDSCMFL_DELETE', NDOCUMENT => NRN);
    /* Выполним базовое удаление */
    UDO_PKG_EQUIPDS_BASE.CMFL_DEL(NRN => NRN);
  end CMFL_DEL;
  
  /* Формирование "Выборки данных оборудования (классы оборудования, файлы данных)" */
  procedure CMFL_MAKE
  (
    NEQUIPDSCM              in number,            -- Рег. номер класса оборудования выборки данных
    NDATASET_IDENT          in number,            -- Идентификатор буфера данных
    NDATASET_CONFIG_IDENT   in number,            -- Идентификатор буфера описания данных
    NCLEAR                  in number := 0        -- Флаг очистки имеющихся файлов данных (0 - не очищать, 1 - очистить)
  )
  is
    NCMFL                   PKG_STD.TREF;         -- Рег. номер добавленного файла данных
    NFILES_CNT              PKG_STD.TNUMBER := 0; -- Количество найденных файлов выборки
    NCONFIG_CNT             PKG_STD.TNUMBER := 0; -- Количество найденных описаний выборки
    DDATASET_TS             PKG_STD.TLDATE;       -- Буфер для времени формирования данных выборки
  begin
    /* Проверим параметры */
    if (NDATASET_IDENT is null) then
      P_EXCEPTION(0,
                  'Пользовательская процедура формирования данных не вернула идентификатор буфера выборки.');
    end if;
    if (NDATASET_CONFIG_IDENT is null) then
      P_EXCEPTION(0,
                  'Пользовательская процедура формирования данных не вернула идентификатор буфера описания выборки.');
    end if;
    /* Зачистим старые файлы */
    if (NCLEAR = 1) then
      for C in (select T.RN from UDO_T_EQUIPDSCMFL T where T.PRN = NEQUIPDSCM)
      loop
        UDO_PKG_EQUIPDS_BASE.CMFL_DEL(NRN => C.RN);
      end loop;
    end if;
    /* Зафиксируем время формирования */
    DDATASET_TS := sysdate;
    /* Добавим новые файлы выборки */
    for C in (select F.*
                from FILE_BUFFER F
               where F.IDENT = NDATASET_IDENT
                 and F.DATA is not null
                 and F.BDATA is not null
                 and F.FILENAME is not null)
    loop
      NFILES_CNT := NFILES_CNT + 1;
      UDO_PKG_EQUIPDS_BASE.CMFL_INS(NPRN        => NEQUIPDSCM,
                                    SFILE_NAME  => C.FILENAME,
                                    SDESCR      => C.DATA,
                                    BDATASET    => C.BDATA,
                                    NDATASET_ID => NDATASET_IDENT,
                                    DDATASET_TS => DDATASET_TS,
                                    NRN         => NCMFL);
    end loop;
    /* Добавим описание выборки */
    for C in (select F.*
                from FILE_BUFFER F
               where F.IDENT = NDATASET_CONFIG_IDENT
                 and F.DATA is not null)
    loop
      NCONFIG_CNT := NCONFIG_CNT + 1;
      UDO_PKG_EQUIPDS_BASE.CM_SET_DATA_CONFIG(NRN => NEQUIPDSCM, BDATA_CONFIG => C.DATA);
    end loop;
    /* Проверим, что сформировали данные */
    if (NFILES_CNT = 0) then
      P_EXCEPTION(0,
                  'Пользовательская процедура формирования данных не вернула выборку.');
    end if;
    if (NCONFIG_CNT = 0) then
      P_EXCEPTION(0,
                  'Пользовательская процедура формирования данных не вернула описание выборки.');
    end if;
    /* Зачистим буфер */
    P_FILE_BUFFER_CLEAR(NIDENT => NDATASET_IDENT);
    P_FILE_BUFFER_CLEAR(NIDENT => NDATASET_CONFIG_IDENT);
  end CMFL_MAKE;
  
  /* Загрузка на сервер "Выборки данных оборудования (классы оборудования, файлы данных)" */
  procedure CMFL_UPLOAD
  (
    NEQUIPDSCM              in number                              -- Рег. номер класса оборудования выборки данных
  )
  is
    NCOMPANY                PKG_STD.TREF := GET_SESSION_COMPANY(); -- Рег. номер организации
    NIDENT                  PKG_STD.TREF;                          -- Идентификатор выбранных файлов
    NTMP                    PKG_STD.TREF;                          -- Рег. номер записи буфера
  begin
    /* Проверим права доступа */
    UDO_PKG_EQUIPDS_BASE.UTL_ACCESS(STABLE => 'UDO_T_EQUIPDSCMFL', SACTION => 'UDO_EQUIPDSCMFL_UPLOAD');
    /* Обходим файлы данных для загрузки */
    for C in (select T.RN NRN
                from UDO_T_EQUIPDSCMFL T
               where T.PRN = NEQUIPDSCM
                 and T.STATUS in
                     (UDO_PKG_EQUIPDS_BASE.NCMFL_STATUS_REGISTERED, UDO_PKG_EQUIPDS_BASE.NCMFL_STATUS_UPLOAD_ERR))
    loop
      /* Сформируем идентификатор выборки, если ещё не делали этого */
      if (NIDENT is null) then
        NIDENT := GEN_IDENT();
      end if;
      /* Добавляем файл в выборку */
      P_SELECTLIST_INSERT(NIDENT => NIDENT, NDOCUMENT => C.NRN, SUNITCODE => 'UDO_T_EQUIPDSCMFL', NRN => NTMP);
    end loop;
    /* Проверим, что в выборку попали данные */
    if (NIDENT is null) then
      P_EXCEPTION(0,
                  'Нет данных для загрузки на сервер. Сначала необходимо выполнить формирование обучающей выборки.');
    end if;
    /* Устанавливаем статус - загружается на сервер */
    for C in (select SL.DOCUMENT NRN
                from SELECTLIST SL
               where SL.IDENT = NIDENT
                 and SL.UNITCODE = 'UDO_T_EQUIPDSCMFL')
    loop
      UDO_PKG_EQUIPDS_BASE.CMFL_SET_STATUS(NRN => C.NRN, NSTATUS => UDO_PKG_EQUIPDS_BASE.NCMFL_STATUS_UPLOADING);
    end loop;
    /* Ставим задачу на зугрузку в очередь */
    UDO_PKG_EQUIPDS_DATAPROCESS.UPLOAD(NCOMPANY => NCOMPANY, NIDENT => NIDENT, NEQUIPDSCM => NEQUIPDSCM);
    /* Очищаем выборку */
    P_SELECTLIST_CLEAR(NIDENT => NIDENT);
  end CMFL_UPLOAD;
  
  /* Передача внешней системе "Выборки данных оборудования (классы оборудования, файлы данных)" */
  procedure CMFL_SEND_MD
  (
    NEQUIPDSCM              in number,                             -- Рег. номер класса оборудования выборки данных
    NDATASET_ID             in number                              -- Идентификатор выборки
  )
  is
    NCOMPANY                PKG_STD.TREF := GET_SESSION_COMPANY(); -- Рег. номер организации
    NIDENT                  PKG_STD.TREF;                          -- Идентификатор выбранных файлов
    NTMP                    PKG_STD.TREF;                          -- Рег. номер записи буфера
  begin
    /* Проверим параметры */
    if (NDATASET_ID is null) then
      P_EXCEPTION(0, 'Не указана выборка.');
    end if;
    /* Проверим права доступа */
    UDO_PKG_EQUIPDS_BASE.UTL_ACCESS(STABLE => 'UDO_T_EQUIPDSCMFL', SACTION => 'UDO_EQUIPDSCMFL_SEND_MD');
    /* Обходим файлы данных для передаче внешней системе */
    for C in (select T.RN NRN
                from UDO_T_EQUIPDSCMFL T
               where T.PRN = NEQUIPDSCM
                 and T.DATASET_ID = NDATASET_ID
                 and T.STATUS = UDO_PKG_EQUIPDS_BASE.NCMFL_STATUS_UPLOADED)
    loop
      /* Сформируем идентификатор выборки, если ещё не делали этого */
      if (NIDENT is null) then
        NIDENT := GEN_IDENT();
      end if;
      /* Добавляем файл в выборку */
      P_SELECTLIST_INSERT(NIDENT => NIDENT, NDOCUMENT => C.NRN, SUNITCODE => 'UDO_T_EQUIPDSCMFL', NRN => NTMP);
    end loop;
    /* Проверим, что в выборку попали данные */
    if (NIDENT is null) then
      P_EXCEPTION(0,
                  'Нет данных для передачи внешней системе. Сначала необходимо выполнить передачу данных на сервер.');
    end if;
    /* Ставим задачу на передачу внешней системе */
    UDO_PKG_EQUIPDS_DATAPROCESS.SEND_MD(NCOMPANY => NCOMPANY, NIDENT => NIDENT, NEQUIPDSCM => NEQUIPDSCM);
    /* Очищаем выборку */
    P_SELECTLIST_CLEAR(NIDENT => NIDENT);
  end CMFL_SEND_MD;
  
  /* Список "Выборки данных оборудования (классы оборудования, модели)" */
  procedure CMML_LIST
  (
    NEQUIPDSCM              in number,                   -- Рег. номер класса оборудования выборки данных
    COUT                    out clob                     -- Сериализованная таблица данных  
  )
  is
    RDG                     PKG_P8PANELS_VISUAL.TDG;     -- Описание таблицы
    RDG_ROW                 PKG_P8PANELS_VISUAL.TDG_ROW; -- Строка таблицы
  begin
    /* Проверим права доступа */
    UDO_PKG_EQUIPDS_BASE.UTL_ACCESS(STABLE => 'UDO_T_EQUIPDSCMML', SACTION => 'UDO_EQUIPDSCMML_SELECT');
    /* Инициализируем таблицу данных */
    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      => 'STASK',
                                        SCAPTION   => 'Задача',
                                        SDATA_TYPE => PKG_P8PANELS_VISUAL.SDATA_TYPE_STR,
                                        SHINT      => 'Алгоритм прогонозирования модели:<br>' ||
                                                      UDO_PKG_EQUIPDS_BASE.CMML_TASK_HINT());
    PKG_P8PANELS_VISUAL.TDG_ADD_COL_DEF(RDATA_GRID => RDG,
                                        SNAME      => 'NPRECISION',
                                        SCAPTION   => 'Точность',
                                        SDATA_TYPE => PKG_P8PANELS_VISUAL.SDATA_TYPE_NUMB);
    PKG_P8PANELS_VISUAL.TDG_ADD_COL_DEF(RDATA_GRID => RDG,
                                        SNAME      => 'SDICMUNTS',
                                        SCAPTION   => 'Единица измерения',
                                        SDATA_TYPE => PKG_P8PANELS_VISUAL.SDATA_TYPE_STR,
                                        BVISIBLE   => false);
    PKG_P8PANELS_VISUAL.TDG_ADD_COL_DEF(RDATA_GRID => RDG,
                                        SNAME      => 'SDATASET',
                                        SCAPTION   => 'Выборка',
                                        SDATA_TYPE => PKG_P8PANELS_VISUAL.SDATA_TYPE_STR);
    PKG_P8PANELS_VISUAL.TDG_ADD_COL_DEF(RDATA_GRID => RDG,
                                        SNAME      => 'SUSERPROCS_FRCST_DATA',
                                        SCAPTION   => 'Процедура формирования',
                                        SDATA_TYPE => PKG_P8PANELS_VISUAL.SDATA_TYPE_STR,
                                        SHINT      => UDO_PKG_EQUIPDS_BASE.CMML_USERPROCS_FRCST_DATA_HINT());
    PKG_P8PANELS_VISUAL.TDG_ADD_COL_DEF(RDATA_GRID => RDG,
                                        SNAME      => 'NSTATUS',
                                        SCAPTION   => 'Состояние',
                                        SDATA_TYPE => PKG_P8PANELS_VISUAL.SDATA_TYPE_NUMB);
    PKG_P8PANELS_VISUAL.TDG_ADD_COL_DEF(RDATA_GRID => RDG,
                                        SNAME      => 'SERR',
                                        SCAPTION   => 'Сообщение об ошибке',
                                        SDATA_TYPE => PKG_P8PANELS_VISUAL.SDATA_TYPE_STR,
                                        BVISIBLE   => false);
    PKG_P8PANELS_VISUAL.TDG_ADD_COL_DEF(RDATA_GRID => RDG,
                                        SNAME      => 'SACTIONS',
                                        SCAPTION   => 'Действия',
                                        SDATA_TYPE => PKG_P8PANELS_VISUAL.SDATA_TYPE_STR);
    /* Обходим данные */
    for C in (select T.RN NRN,
                     T.TASK STASK,
                     T.PRECISION NPRECISION,
                     DM.MEAS_MNEMO SDICMUNTS,
                     T.DATASET_ID NDATASET_ID,
                     (select F.DATASET_TS
                        from UDO_T_EQUIPDSCMFL F
                       where F.DATASET_ID = T.DATASET_ID
                         and ROWNUM <= 1) DDATASET_TS,
                     UP.CODE SUSERPROCS_FRCST_DATA,
                     T.STATUS NSTATUS,
                     T.ERR SERR
                from UDO_T_EQUIPDSCMML T,
                     UDO_T_EQUIPDSCM   CM,
                     DICMUNTS          DM,
                     USERPROCS         UP
               where CM.RN = NEQUIPDSCM
                 and T.PRN = CM.RN
                 and CM.DICMUNTS = DM.RN
                 and T.USERPROCS_FRCST_DATA = UP.RN
               order by T.RN)
    loop
      /* Добавляем колонки с данными */
      PKG_P8PANELS_VISUAL.TDG_ROW_ADD_COL(RROW => RDG_ROW, SNAME => 'NRN', NVALUE => C.NRN, BCLEAR => true);
      PKG_P8PANELS_VISUAL.TDG_ROW_ADD_COL(RROW => RDG_ROW, SNAME => 'STASK', SVALUE => C.STASK);
      PKG_P8PANELS_VISUAL.TDG_ROW_ADD_COL(RROW => RDG_ROW, SNAME => 'NPRECISION', NVALUE => C.NPRECISION);
      PKG_P8PANELS_VISUAL.TDG_ROW_ADD_COL(RROW => RDG_ROW, SNAME => 'SDICMUNTS', SVALUE => C.SDICMUNTS);
      PKG_P8PANELS_VISUAL.TDG_ROW_ADD_COL(RROW   => RDG_ROW,
                                          SNAME  => 'SDATASET',
                                          SVALUE => UDO_PKG_EQUIPDS_BASE.UTL_DATASET_MAKE_NAME(NDATASET_ID => C.NDATASET_ID,
                                                                                               DDATASET_TS => C.DDATASET_TS));
      PKG_P8PANELS_VISUAL.TDG_ROW_ADD_COL(RROW   => RDG_ROW,
                                          SNAME  => 'SUSERPROCS_FRCST_DATA',
                                          SVALUE => C.SUSERPROCS_FRCST_DATA);
      PKG_P8PANELS_VISUAL.TDG_ROW_ADD_COL(RROW => RDG_ROW, SNAME => 'NSTATUS', NVALUE => C.NSTATUS);
      PKG_P8PANELS_VISUAL.TDG_ROW_ADD_COL(RROW => RDG_ROW, SNAME => 'SERR', SVALUE => C.SERR);
      PKG_P8PANELS_VISUAL.TDG_ROW_ADD_COL(RROW => RDG_ROW, SNAME => 'SACTIONS');
      /* Добавляем строку в таблицу */
      PKG_P8PANELS_VISUAL.TDG_ADD_ROW(RDATA_GRID => RDG, RROW => RDG_ROW);
    end loop;
    /* Сериализуем описание */
    COUT := PKG_P8PANELS_VISUAL.TDG_TO_XML(RDATA_GRID => RDG, NINCLUDE_DEF => 1);
  end CMML_LIST;
  
  /* Клиентское добавление "Выборки данных оборудования (классы оборудования, модели)" */
  procedure CMML_INS
  (
    NPRN                    in number,    -- Родитель
    STASK                   in varchar2,  -- Задача (см. константы UDO_PKG_EQUIPDS_BASE.SCMML_TASK_*)
    NDATASET_ID             in number,    -- Идентификатор выборки
    SUSERPROCS_FRCST_DATA   in varchar2,  -- Пользовательская процедура формирования данных для прогноза
    NRN                     out number    -- Регистрационный номер
  )
  is
    NUSERPROCS_FRCST_DATA   PKG_STD.TREF; -- Рег. номер пользовательской процедуры формирования данных для прогноза
  begin
    /* Проверим параметры */
    if (STASK is null) then
      P_EXCEPTION(0, 'Не указана задача.');
    end if;
    if (NDATASET_ID is null) then
      P_EXCEPTION(0, 'Не указана выборка.');
    end if;
    if (SUSERPROCS_FRCST_DATA is null) then
      P_EXCEPTION(0,
                  'Не указана процедура формирования данных для прогноза.');
    end if;
    /* Проверим права доступа */
    UDO_PKG_EQUIPDS_BASE.UTL_ACCESS(STABLE => 'UDO_T_EQUIPDSCMML', SACTION => 'UDO_EQUIPDSCMML_INSERT');
    /* Разыменуем ссылки */
    UDO_PKG_EQUIPDS_BASE.CMML_JOINS(SUSERPROCS_FRCST_DATA => SUSERPROCS_FRCST_DATA,
                                    NUSERPROCS_FRCST_DATA => NUSERPROCS_FRCST_DATA);
    /* Добавляем запись */
    UDO_PKG_EQUIPDS_BASE.CMML_INS(NPRN                  => NPRN,
                                  STASK                 => STASK,
                                  NDATASET_ID           => NDATASET_ID,
                                  NUSERPROCS_FRCST_DATA => NUSERPROCS_FRCST_DATA,
                                  NRN                   => NRN);
  end CMML_INS;

  /* Клиентское удаление "Выборки данных оборудования (классы оборудования, модели)" */
  procedure CMML_DEL
  (
    NRN                     in number   -- Регистрационный номер
  )
  is
  begin
    /* Проверим права доступа */
    UDO_PKG_EQUIPDS_BASE.UTL_ACCESS(STABLE => 'UDO_T_EQUIPDSCMML', SACTION => 'UDO_EQUIPDSCMML_DELETE', NDOCUMENT => NRN);
    /* Удаляем запись */
    UDO_PKG_EQUIPDS_BASE.CMML_DEL(NRN => NRN);
  end CMML_DEL;  
  
  /* Обработка внешней системой "Выборки данных оборудования (классы оборудования, модели)" */
  procedure CMML_SEND_RQ
  (
    NEQUIPDSCMML            in number                              -- Рег. номер модели класса оборудования выборки данных
  )
  is
    NCOMPANY                PKG_STD.TREF := GET_SESSION_COMPANY(); -- Рег. номер организации
    RCMML                   UDO_T_EQUIPDSCMML%rowtype;             -- Запись модели
    NCOUNT                  PKG_STD.TNUMBER;                       -- Количество файлов данных модели, переданных внешней системе
  begin
    /* Считаем модель */
    RCMML := UDO_PKG_EQUIPDS_BASE.CMML_GET(NFLAG_SMART => 0, NRN => NEQUIPDSCMML);
    /* Проверим права доступа */
    UDO_PKG_EQUIPDS_BASE.UTL_ACCESS(STABLE    => 'UDO_T_EQUIPDSCMML',
                                    SACTION   => 'UDO_EQUIPDSCMML_SEND_RQ',
                                    NDOCUMENT => RCMML.RN);
    /* Проверим, что у класса оборудования есть файлы данных, переданные внешней системе */
    begin
      select count(T.RN)
        into NCOUNT
        from UDO_T_EQUIPDSCMFL T
       where T.PRN = RCMML.PRN
         and T.DATASET_ID = RCMML.DATASET_ID
         and T.STATUS = UDO_PKG_EQUIPDS_BASE.NCMFL_STATUS_SENT;
    exception
      when others then
        P_EXCEPTION(0,
                    'Не удалось проверить состояние файлов данных выборки.');
    end;
    if (NCOUNT = 0) then
      P_EXCEPTION(0,
                  'У выборки класса оборудования нет файлов данных, переданных фреймворку - обучение невозможно.');
    end if;
    /* Отправим запрос на обучение */
    UDO_PKG_EQUIPDS_DATAPROCESS.SEND_RQ(NCOMPANY => NCOMPANY, NEQUIPDSCMML => RCMML.RN);
  end CMML_SEND_RQ;
  
  /* Состояние "Выборки данных оборудования (классы оборудования, модели)" по единице оборудования */
  function CMML_STATUS_BY_EQCONFIG
  (
    NEQCONFIG               in number        -- Рег. номер позиции состава оборудования
  ) return                  number           -- Код действия с моделью (0 - нет моделей, 1 - есть модели в процессе обучения, 2 - есть обученные модели)
  is
    NRES                    PKG_STD.TNUMBER; -- Буфер для результата
  begin
    /* По умолчанию - моделей нет */
    NRES := 0;
    /* Обходим модели */
    for C in (select ML.STATUS
                from UDO_T_EQUIPDSCM   CM,
                     UDO_T_EQUIPDSCMML ML
               where CM.EQOBJKIND = (select CF.OBJ_KIND from EQCONFIG CF where CF.RN = NEQCONFIG)
                 and CM.RN = ML.PRN)
    loop
      /* Модель есть, но пока не видели обученных */
      if (NRES < 2) then
        NRES := 1;
      end if;
      /* Если она уже обучена */
      if (C.STATUS = UDO_PKG_EQUIPDS_BASE.NCMML_STATUS_PROCESSED) then
        NRES := 2;
      end if;
    end loop;
    /* Возвращаем результат */
    return NRES;
  end CMML_STATUS_BY_EQCONFIG;
  
  /* Список "Выборки данных оборудования (классы оборудования, модели)" по единице оборудования */
  procedure CMML_LIST_BY_EQCONFIG
  (
    NEQCONFIG               in number,                   -- Рег. номер позиции состава оборудования
    COUT                    out clob                     -- Сериализованная таблица данных
  )
  is
    RDG                     PKG_P8PANELS_VISUAL.TDG;     -- Описание таблицы
    RDG_ROW                 PKG_P8PANELS_VISUAL.TDG_ROW; -- Строка таблицы
  begin
    /* Инициализируем таблицу данных */
    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      => 'NEQUIPDS',
                                        SCAPTION   => 'Рег. номер выборки',
                                        SDATA_TYPE => PKG_P8PANELS_VISUAL.SDATA_TYPE_NUMB,
                                        BVISIBLE   => false);
    PKG_P8PANELS_VISUAL.TDG_ADD_COL_DEF(RDATA_GRID => RDG,
                                        SNAME      => 'NEQUIPDSCM',
                                        SCAPTION   => 'Рег. номер класса оборудования выборки',
                                        SDATA_TYPE => PKG_P8PANELS_VISUAL.SDATA_TYPE_NUMB,
                                        BVISIBLE   => false);
    PKG_P8PANELS_VISUAL.TDG_ADD_COL_DEF(RDATA_GRID => RDG,
                                        SNAME      => 'SNEQUIPDS',
                                        SCAPTION   => 'Выборка',
                                        SDATA_TYPE => PKG_P8PANELS_VISUAL.SDATA_TYPE_STR);
    PKG_P8PANELS_VISUAL.TDG_ADD_COL_DEF(RDATA_GRID => RDG,
                                        SNAME      => 'STASK',
                                        SCAPTION   => 'Задача',
                                        SDATA_TYPE => PKG_P8PANELS_VISUAL.SDATA_TYPE_STR,
                                        SHINT      => 'Алгоритм прогонозирования модели:<br>' ||
                                                      UDO_PKG_EQUIPDS_BASE.CMML_TASK_HINT());
    PKG_P8PANELS_VISUAL.TDG_ADD_COL_DEF(RDATA_GRID => RDG,
                                        SNAME      => 'NPRECISION',
                                        SCAPTION   => 'Точность',
                                        SDATA_TYPE => PKG_P8PANELS_VISUAL.SDATA_TYPE_NUMB);
    PKG_P8PANELS_VISUAL.TDG_ADD_COL_DEF(RDATA_GRID => RDG,
                                        SNAME      => 'SDICMUNTS',
                                        SCAPTION   => 'Единица измерения',
                                        SDATA_TYPE => PKG_P8PANELS_VISUAL.SDATA_TYPE_STR,
                                        BVISIBLE   => false);
        PKG_P8PANELS_VISUAL.TDG_ADD_COL_DEF(RDATA_GRID => RDG,
                                        SNAME      => 'SUSERPROCS_FRCST_DATA',
                                        SCAPTION   => 'Процедура формирования',
                                        SDATA_TYPE => PKG_P8PANELS_VISUAL.SDATA_TYPE_STR,
                                        SHINT      => UDO_PKG_EQUIPDS_BASE.CMML_USERPROCS_FRCST_DATA_HINT());
    PKG_P8PANELS_VISUAL.TDG_ADD_COL_DEF(RDATA_GRID => RDG,
                                        SNAME      => 'NSTATUS',
                                        SCAPTION   => 'Состояние',
                                        SDATA_TYPE => PKG_P8PANELS_VISUAL.SDATA_TYPE_NUMB);
    PKG_P8PANELS_VISUAL.TDG_ADD_COL_DEF(RDATA_GRID => RDG,
                                        SNAME      => 'SERR',
                                        SCAPTION   => 'Сообщение об ошибке',
                                        SDATA_TYPE => PKG_P8PANELS_VISUAL.SDATA_TYPE_STR,
                                        BVISIBLE   => false);
    PKG_P8PANELS_VISUAL.TDG_ADD_COL_DEF(RDATA_GRID => RDG,
                                        SNAME      => 'SACTIONS',
                                        SCAPTION   => 'Действия',
                                        SDATA_TYPE => PKG_P8PANELS_VISUAL.SDATA_TYPE_STR);
    /* Обходим данные */
    for C in (select T.RN          NRN,
                     CM.PRN        NEQUIPDS,
                     T.PRN         NEQUIPDSCM,
                     DS.NAME       SNEQUIPDS,
                     T.TASK        STASK,
                     UP.CODE       SUSERPROCS_FRCST_DATA,
                     T.PRECISION   NPRECISION,
                     DM.MEAS_MNEMO SDICMUNTS,
                     T.STATUS      NSTATUS,
                     T.ERR         SERR
                from UDO_T_EQUIPDSCMML T,
                     UDO_T_EQUIPDSCM   CM,
                     UDO_T_EQUIPDS     DS,
                     DICMUNTS          DM,
                     USERPROCS         UP
               where T.PRN = CM.RN
                 and CM.PRN = DS.RN
                 and CM.DICMUNTS = DM.RN
                 and CM.EQOBJKIND = (select CF.OBJ_KIND from EQCONFIG CF where CF.RN = NEQCONFIG)
                 and T.USERPROCS_FRCST_DATA = UP.RN
               order by T.RN)
    loop
      /* Добавляем колонки с данными */
      PKG_P8PANELS_VISUAL.TDG_ROW_ADD_COL(RROW => RDG_ROW, SNAME => 'NRN', NVALUE => C.NRN, BCLEAR => true);
      PKG_P8PANELS_VISUAL.TDG_ROW_ADD_COL(RROW => RDG_ROW, SNAME => 'NEQUIPDS', NVALUE => C.NEQUIPDS);
      PKG_P8PANELS_VISUAL.TDG_ROW_ADD_COL(RROW => RDG_ROW, SNAME => 'NEQUIPDSCM', NVALUE => C.NEQUIPDSCM);
      PKG_P8PANELS_VISUAL.TDG_ROW_ADD_COL(RROW => RDG_ROW, SNAME => 'SNEQUIPDS', SVALUE => C.SNEQUIPDS);
      PKG_P8PANELS_VISUAL.TDG_ROW_ADD_COL(RROW => RDG_ROW, SNAME => 'STASK', SVALUE => C.STASK);
      PKG_P8PANELS_VISUAL.TDG_ROW_ADD_COL(RROW => RDG_ROW, SNAME => 'NPRECISION', NVALUE => C.NPRECISION);
      PKG_P8PANELS_VISUAL.TDG_ROW_ADD_COL(RROW => RDG_ROW, SNAME => 'SDICMUNTS', SVALUE => C.SDICMUNTS);
      PKG_P8PANELS_VISUAL.TDG_ROW_ADD_COL(RROW => RDG_ROW, SNAME => 'SUSERPROCS_FRCST_DATA', SVALUE => C.SUSERPROCS_FRCST_DATA);
      PKG_P8PANELS_VISUAL.TDG_ROW_ADD_COL(RROW => RDG_ROW, SNAME => 'NSTATUS', NVALUE => C.NSTATUS);
      PKG_P8PANELS_VISUAL.TDG_ROW_ADD_COL(RROW => RDG_ROW, SNAME => 'SERR', SVALUE => C.SERR);
      PKG_P8PANELS_VISUAL.TDG_ROW_ADD_COL(RROW => RDG_ROW, SNAME => 'SACTIONS');
      /* Добавляем строку в таблицу */
      PKG_P8PANELS_VISUAL.TDG_ADD_ROW(RDATA_GRID => RDG, RROW => RDG_ROW);
    end loop;
    /* Сериализуем описание */
    COUT := PKG_P8PANELS_VISUAL.TDG_TO_XML(RDATA_GRID => RDG, NINCLUDE_DEF => 1);
  end CMML_LIST_BY_EQCONFIG; 
  
  /* Цвет прогноза "Выборки данных оборудования (классы оборудования, модели, история запросов)" */
  function CMMLH_FORECAST_COLOR
  (
    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 CMMLH_FORECAST_COLOR;  
  
  /* Карточка прогноза "Выборки данных оборудования (классы оборудования, модели, история запросов)" */
  procedure CMMLH_FORECAST_CARD
  (
    NEQUIPDSCMMLH           in number,                          -- Рег. номер записи истории запросов модели
    DFORECAST_DATE          in date,                            -- Дата получения прогноза
    NFORECAST_DAYS          in number,                          -- Прогнозное количество дней до выхода из строя (на дату прогноза)
    STASK                   in varchar2,                        -- Задача (см. константы UDO_PKG_EQUIPDS_BASE.CMML_TASK_*)
    SFORECAST               out varchar2,                       -- Прогноз
    SFORECAST_DESC          out varchar2,                       -- Интерпретация прогноза
    SFORECAST_DESC_COLOR    out varchar2,                       -- Цвет заливки интерпретации прогноза
    CFORECAST_CARD          out clob                            -- Данные детальной карточки прогноза
  )
  is
    RCMMLH                  UDO_T_EQUIPDSCMMLH%rowtype;         -- Запись истории запросов модели
    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;                     -- Дата ближайшего ТО и ремонта по графику/рем. ведомости
    NFORECAST_DAYS_NOW      PKG_STD.TNUMBER;                    -- Количество дней до выхода из строя согласно прогнозу, но от текущей даты
    STASK_NAME              PKG_STD.TSTRING;                    -- Текстовая расшифровка задачи
    SFORECAST_DATE_CALC     PKG_STD.TSTRING;                    -- Текстовое представление плановой даты перехода в предельное состояние
  begin
    /* Считаем запись истории запросов к модели */
    RCMMLH := UDO_PKG_EQUIPDS_BASE.CMMLH_GET(NFLAG_SMART => 0, NRN => NEQUIPDSCMMLH);
    /* Проноз есть */
    if ((DFORECAST_DATE is not null) and (NFORECAST_DAYS is not null)) then
      /* Получим текстовую расшифровку задачи */
      STASK_NAME          := UDO_PKG_EQUIPDS_BASE.CMML_TASK_NAME(STASK => STASK);
      SFORECAST_DATE_CALC := TO_CHAR(DFORECAST_DATE + NFORECAST_DAYS, 'dd.mm.yyyy');
      /* Вычислим сколько осталось до выхода из строя от текущей даты */
      NFORECAST_DAYS_NOW := UDO_PKG_EQUIPDS_BASE.CMMLH_FORECAST_DAYS_NOW(DFORECAST_DATE => DFORECAST_DATE,
                                                                         NFORECAST_DAYS => NFORECAST_DAYS);
      /* Вычислим вероятность выхода из строя до даты ближайшего ТО/ремонта по графику или рем. ведомости с учётом прогноза */
      DNEXT_REPAIR    := UDO_PKG_EQUIPTCF.EQCONFIG_THOBJ_GEN_NXTRPR(NEQCONFIG => RCMMLH.EQCONFIG);
      NBREAKDOWN_PROB := UDO_PKG_EQUIPDS_BASE.CMMLH_RUL_BREAKDOWN_PROB(DFORECAST_DATE => DFORECAST_DATE,
                                                                       NFORECAST_DAYS => NFORECAST_DAYS,
                                                                       DDATE          => DNEXT_REPAIR);
      /* Открываем документ */
      NCUR := PKG_XMAKE.OPEN_CURSOR();
      /* Заполним дату прогноза */
      XROOT := PKG_XMAKE.CONCAT(ICURSOR => NCUR,
                                RNODE00 => XROOT,
                                RNODE01 => PKG_XMAKE.ELEMENT(ICURSOR  => NCUR,
                                                             SNAME    => 'SFORECAST_DATE',
                                                             RVALUE00 => PKG_XMAKE.VALUE(ICURSOR => NCUR,
                                                                                         SVALUE  => TO_CHAR(DFORECAST_DATE,
                                                                                                            'dd.mm.yyyy'))));
      /* Заполним прогнозное количество дней до выхода из стороя на эту дату */
      XROOT := PKG_XMAKE.CONCAT(ICURSOR => NCUR,
                                RNODE00 => XROOT,
                                RNODE01 => PKG_XMAKE.ELEMENT(ICURSOR  => NCUR,
                                                             SNAME    => 'NFORECAST_DAYS',
                                                             RVALUE00 => PKG_XMAKE.VALUE(ICURSOR => NCUR,
                                                                                         NVALUE  => NFORECAST_DAYS)));
      /* Заполним прогнозную дату выхода из стороя */
      XROOT := PKG_XMAKE.CONCAT(ICURSOR => NCUR,
                                RNODE00 => XROOT,
                                RNODE01 => PKG_XMAKE.ELEMENT(ICURSOR  => NCUR,
                                                             SNAME    => 'SFORECAST_DATE_CALC',
                                                             RVALUE00 => PKG_XMAKE.VALUE(ICURSOR => NCUR,
                                                                                         SVALUE  => SFORECAST_DATE_CALC)));
      /* Заполним текущую дату */
      XROOT := PKG_XMAKE.CONCAT(ICURSOR => NCUR,
                                RNODE00 => XROOT,
                                RNODE01 => PKG_XMAKE.ELEMENT(ICURSOR  => NCUR,
                                                             SNAME    => 'SFORECAST_DATE_NOW',
                                                             RVALUE00 => PKG_XMAKE.VALUE(ICURSOR => NCUR,
                                                                                         SVALUE  => TO_CHAR(sysdate,
                                                                                                            'dd.mm.yyyy'))));
      /* Заполним прогнозное количество дней до выхода из стороя на текущую дату */
      XROOT := PKG_XMAKE.CONCAT(ICURSOR => NCUR,
                                RNODE00 => XROOT,
                                RNODE01 => PKG_XMAKE.ELEMENT(ICURSOR  => NCUR,
                                                             SNAME    => 'NFORECAST_DAYS_NOW',
                                                             RVALUE00 => PKG_XMAKE.VALUE(ICURSOR => NCUR,
                                                                                         NVALUE  => NFORECAST_DAYS_NOW)));
      /* Заполним код задачи прогнозирования */
      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  => STASK_NAME)));
      /* Заполним дату следующего ТО и ремонта */
      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 = RCMMLH.EQCONFIG
                                     and P.DATEPRD_BEG >= sysdate
                                  union
                                  select R.DATEPLAN_BEG DDATEPRD_BEG
                                    from EQRPSHEETS R
                                   where R.EQCONFIG = RCMMLH.EQCONFIG
                                     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.CMMLH_RUL_BREAKDOWN_PROB(DFORECAST_DATE => DFORECAST_DATE,
                                                                               NFORECAST_DAYS => NFORECAST_DAYS,
                                                                               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);
      else
        /* Запланированных ремонтов или ТО нет, но прогноз есть - значит точно выйдет из строя */
        NBREAKDOWN_PROB := 100;
      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  => CMMLH_FORECAST_COLOR(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);
      /* Возвращаем полученные данные карточки - конвертируем XML-представление ответа в CLOB */
      CFORECAST_CARD := 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);
      /* Возвращаем текстовое описание прогноза */
      SFORECAST := STASK_NAME || ' на дату выборки (' || TO_CHAR(DFORECAST_DATE, 'dd.mm.yyyy') || '): ' ||
                   TO_CHAR(NFORECAST_DAYS) || 'д (до ' || SFORECAST_DATE_CALC || ')';
      /* Возвращаем интерпретацию прогноза */
      SFORECAST_DESC := TO_CHAR(NFORECAST_DAYS_NOW) || 'Д / ' || TO_CHAR(ROUND(NBREAKDOWN_PROB)) || '%';
      /* Возвращаем цвета заливки интерпретации прогноза */
      SFORECAST_DESC_COLOR := CMMLH_FORECAST_COLOR(NMODE => 1, NVALUE => NBREAKDOWN_PROB);
    else
      SFORECAST := 'Не удалось разобрать ответ модели';
    end if;
  end CMMLH_FORECAST_CARD;
  
  /* Список "Выборки данных оборудования (классы оборудования, модели, история запросов)" по единице оборудования */
  procedure CMMLH_LIST_BY_EQCONFIG
  (
    NEQCONFIG               in number,                   -- Рег. номер позиции состава оборудования
    COUT                    out clob                     -- Сериализованная таблица данных
  )
  is
    RDG                     PKG_P8PANELS_VISUAL.TDG;     -- Описание таблицы
    RDG_ROW                 PKG_P8PANELS_VISUAL.TDG_ROW; -- Строка таблицы
  begin
    /* Инициализируем таблицу данных */
    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      => 'SRQ_AUTHID',
                                        SCAPTION   => 'Пользователь',
                                        SDATA_TYPE => PKG_P8PANELS_VISUAL.SDATA_TYPE_STR);
    PKG_P8PANELS_VISUAL.TDG_ADD_COL_DEF(RDATA_GRID => RDG,
                                        SNAME      => 'SRQ_DATE',
                                        SCAPTION   => 'Дата/время запроса',
                                        SDATA_TYPE => PKG_P8PANELS_VISUAL.SDATA_TYPE_STR);
    PKG_P8PANELS_VISUAL.TDG_ADD_COL_DEF(RDATA_GRID => RDG,
                                        SNAME      => 'SEQUIPDS_CODE',
                                        SCAPTION   => 'Выборка',
                                        SDATA_TYPE => PKG_P8PANELS_VISUAL.SDATA_TYPE_STR,
                                        BVISIBLE   => false);
    PKG_P8PANELS_VISUAL.TDG_ADD_COL_DEF(RDATA_GRID => RDG,
                                        SNAME      => 'SEQUIPDSCMML_TASK',
                                        SCAPTION   => 'Задача',
                                        SDATA_TYPE => PKG_P8PANELS_VISUAL.SDATA_TYPE_STR,
                                        SHINT      => UDO_PKG_EQUIPDS_BASE.CMML_TASK_HINT());
    PKG_P8PANELS_VISUAL.TDG_ADD_COL_DEF(RDATA_GRID => RDG,
                                        SNAME      => 'NEQUIPDSCMML_PRECISION',
                                        SCAPTION   => 'Точность',
                                        SDATA_TYPE => PKG_P8PANELS_VISUAL.SDATA_TYPE_NUMB,
                                        BVISIBLE   => false);
    PKG_P8PANELS_VISUAL.TDG_ADD_COL_DEF(RDATA_GRID => RDG,
                                        SNAME      => 'STO_FORECAST',
                                        SCAPTION   => 'Ответ модели',
                                        SDATA_TYPE => PKG_P8PANELS_VISUAL.SDATA_TYPE_STR);
    PKG_P8PANELS_VISUAL.TDG_ADD_COL_DEF(RDATA_GRID => RDG,
                                        SNAME      => 'STO_FORECAST_DESC',
                                        SCAPTION   => 'Интерпретация',
                                        SDATA_TYPE => PKG_P8PANELS_VISUAL.SDATA_TYPE_STR,
                                        SHINT      => '<b>Формат:</b> "XXД / YY%", где<br>' ||
                                                      '<b>XXД</b> - время (в днях, от текущей даты) до перехода в критическое состояние<br>' ||
                                                      '<b>YY%</b> - вероятность перехода в критическое состояние до следующего ТО и ремонта<br><br>' ||
                                                      '<b>Цвет:</b><br>' || CMMLH_FORECAST_COLOR(NMODE => 0));
    PKG_P8PANELS_VISUAL.TDG_ADD_COL_DEF(RDATA_GRID => RDG,
                                        SNAME      => 'STO_FORECAST_DESC_COLOR',
                                        SCAPTION   => 'Цвет интерпретации',
                                        SDATA_TYPE => PKG_P8PANELS_VISUAL.SDATA_TYPE_STR,
                                        BVISIBLE   => false);
    PKG_P8PANELS_VISUAL.TDG_ADD_COL_DEF(RDATA_GRID => RDG,
                                        SNAME      => 'STO_FORECAST_CARD',
                                        SCAPTION   => 'Данные карточки прогноза для конкретного технического объекта',
                                        SDATA_TYPE => PKG_P8PANELS_VISUAL.SDATA_TYPE_STR,
                                        BVISIBLE   => false);
    PKG_P8PANELS_VISUAL.TDG_ADD_COL_DEF(RDATA_GRID => RDG,
                                        SNAME      => 'SDICMUNTS',
                                        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 NEQUIPDSCMML_PRECISION,
                     DM.MEAS_MNEMO SDICMUNTS,
                     T.FORECAST BFORECAST,
                     T.FORECAST_DATE DFORECAST_DATE,
                     T.FORECAST_DAYS NFORECAST_DAYS,
                     null STO_FORECAST,
                     null STO_FORECAST_DESC,
                     null STO_FORECAST_DESC_COLOR,
                     null STO_FORECAST_CARD
                from UDO_T_EQUIPDSCMMLH T,
                     UDO_T_EQUIPDSCMML  ML,
                     UDO_T_EQUIPDSCM    CM,
                     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
      /* Формируем данные карточки прогноза для конкретного тех. объекта */
      CMMLH_FORECAST_CARD(NEQUIPDSCMMLH        => C.NRN,
                          DFORECAST_DATE       => C.DFORECAST_DATE,
                          NFORECAST_DAYS       => C.NFORECAST_DAYS,
                          STASK                => C.SEQUIPDSCMML_TASK,
                          SFORECAST            => C.STO_FORECAST,
                          SFORECAST_DESC       => C.STO_FORECAST_DESC,
                          SFORECAST_DESC_COLOR => C.STO_FORECAST_DESC_COLOR,
                          CFORECAST_CARD       => C.STO_FORECAST_CARD);
      /* Добавляем колонки с данными */
      PKG_P8PANELS_VISUAL.TDG_ROW_ADD_COL(RROW => RDG_ROW, SNAME => 'NRN', NVALUE => C.NRN, BCLEAR => true);
      PKG_P8PANELS_VISUAL.TDG_ROW_ADD_COL(RROW => RDG_ROW, SNAME => 'SRQ_AUTHID', SVALUE => C.SRQ_AUTHID);
      PKG_P8PANELS_VISUAL.TDG_ROW_ADD_COL(RROW => RDG_ROW, SNAME => 'SRQ_DATE', SVALUE => C.SRQ_DATE);
      PKG_P8PANELS_VISUAL.TDG_ROW_ADD_COL(RROW => RDG_ROW, SNAME => 'SEQUIPDS_CODE', SVALUE => C.SEQUIPDS_CODE);
      PKG_P8PANELS_VISUAL.TDG_ROW_ADD_COL(RROW => RDG_ROW, SNAME => 'SEQUIPDSCMML_TASK', SVALUE => C.SEQUIPDSCMML_TASK);
      PKG_P8PANELS_VISUAL.TDG_ROW_ADD_COL(RROW   => RDG_ROW,
                                          SNAME  => 'NEQUIPDSCMML_PRECISION',
                                          NVALUE => C.NEQUIPDSCMML_PRECISION);
      PKG_P8PANELS_VISUAL.TDG_ROW_ADD_COL(RROW => RDG_ROW, SNAME => 'STO_FORECAST', SVALUE => C.STO_FORECAST);
      PKG_P8PANELS_VISUAL.TDG_ROW_ADD_COL(RROW => RDG_ROW, SNAME => 'STO_FORECAST_DESC', SVALUE => C.STO_FORECAST_DESC);
      PKG_P8PANELS_VISUAL.TDG_ROW_ADD_COL(RROW   => RDG_ROW,
                                          SNAME  => 'STO_FORECAST_DESC_COLOR',
                                          SVALUE => C.STO_FORECAST_DESC_COLOR);
      PKG_P8PANELS_VISUAL.TDG_ROW_ADD_COL(RROW => RDG_ROW, SNAME => 'STO_FORECAST_CARD', SVALUE => C.STO_FORECAST_CARD);
      PKG_P8PANELS_VISUAL.TDG_ROW_ADD_COL(RROW => RDG_ROW, SNAME => 'SDICMUNTS', SVALUE => C.SDICMUNTS);
      /* Добавляем строку в таблицу */
      PKG_P8PANELS_VISUAL.TDG_ADD_ROW(RDATA_GRID => RDG, RROW => RDG_ROW);
    end loop;
    /* Сериализуем описание */
    COUT := PKG_P8PANELS_VISUAL.TDG_TO_XML(RDATA_GRID => RDG, NINCLUDE_DEF => 1);
  end CMMLH_LIST_BY_EQCONFIG;
  
end UDO_PKG_EQUIPDS;
/
