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 запросов с результатами обработки внешней системой
    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 запросов с результатами обработки внешней системой
    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 запросов с результатами обработки внешней системой
  );
  
  /* Клиентское удаление "Выборки данных оборудования (классы оборудования)" */
  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    -- Сериализованная таблица данных    
  );

  /* Формирование данных прогноза "Выборки данных оборудования (классы оборудования, модели, история запросов)" */
  procedure CMMLH_BUILD_FORECAST
  (
    COUT                    out clob    -- Данные прогноза
  );
  
  /* Извлечение описания из данных прогноза "Выборки данных оборудования (классы оборудования, модели, история запросов)" */
  procedure CMMLH_PARSE_FORECAST
  (
    CFORECAST               in clob,    -- Данные прогноза
    NFORECAST               out number  -- Значение прогноза
  );
  
  /* Список "Выборки данных оборудования (классы оборудования, модели, история запросов)" по единице оборудования */
  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 запросов с результатами обработки внешней системой
    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;
    /* Проверим права доступа */
    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,
             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
                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,
                     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.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)));
    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 запросов с результатами обработки внешней системой
    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 функции обмена для обработки внешней системой
  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;
    /* Проверим права доступа */
    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,
                                  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);
    /* Добавляем запись */
    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,
                                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 запросов с результатами обработки внешней системой
  )
  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 функции обмена для обработки внешней системой
  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;
    /* Проверим права доступа */
    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,
                                  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);
    /* Исправляем запись */
    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);
  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 < UDO_PKG_EQUIPDS_BASE.NCMML_STATUS_PROCESSED) 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;
  
  /* Формирование данных прогноза "Выборки данных оборудования (классы оборудования, модели, история запросов)" */
  procedure CMMLH_BUILD_FORECAST
  (
    COUT                    out clob         -- Данные прогноза
  )
  is
    NCUR                    integer;         -- Курсор документа для результата
    XDOC                    PKG_XMAKE.TNODE; -- Документ для результата
    XROOT                   PKG_XMAKE.TNODE; -- Содержимое корневого узла документа
    NFORECAST               PKG_STD.TNUMBER; -- Прогноз по заданной задаче
  begin
    /* Вычислим прогноз - количество периодов в указанных ЕИ до достижения предельного состояния */
    NFORECAST := ROUND(DBMS_RANDOM.VALUE(10, 60));
    /* Открываем документ */
    NCUR := PKG_XMAKE.OPEN_CURSOR();
    /* Заполним прогноз */
    XROOT := PKG_XMAKE.CONCAT(ICURSOR => NCUR,
                              RNODE00 => XROOT,
                              RNODE01 => PKG_XMAKE.ELEMENT(ICURSOR  => NCUR,
                                                           SNAME    => 'NFORECAST',
                                                           RVALUE00 => PKG_XMAKE.VALUE(ICURSOR => NCUR, NVALUE => NFORECAST)));
    /* Формируем XML-представление ответа */
    XDOC := PKG_XMAKE.ELEMENT(ICURSOR => NCUR, SNAME => 'XDATA', RNODE00 => XROOT);
    /* Конвертируем в CLOB */
    COUT := PKG_XMAKE.SERIALIZE_TO_CLOB(ICURSOR => NCUR,
                                        ITYPE   => PKG_XMAKE.CONTENT_,
                                        RNODE   => XDOC,
                                        RHEADER => PKG_XHEADER.WRAP_ALL(SVERSION    => PKG_XHEADER.VERSION_1_0_,
                                                                        SENCODING   => PKG_XHEADER.ENCODING_UTF_,
                                                                        SSTANDALONE => PKG_XHEADER.STANDALONE_YES_));
    /* Закрываем документ */
    PKG_XMAKE.CLOSE_CURSOR(ICURSOR => NCUR);
  end CMMLH_BUILD_FORECAST;
  
  /* Извлечение описания из данных прогноза "Выборки данных оборудования (классы оборудования, модели, история запросов)" */
  procedure CMMLH_PARSE_FORECAST
  (
    CFORECAST               in clob,             -- Данные прогноза
    NFORECAST               out number           -- Значение прогноза
  )
  is
    XDOC                    PKG_XPATH.TDOCUMENT; -- Десериализованный демо-прогноз
    XROOT                   PKG_XPATH.TNODE;     -- Корневой элемент данных
  begin
    /* Разбираем демо-даные */
    XDOC := PKG_XPATH.PARSE_FROM_CLOB(LCXML => CFORECAST);
    /* Извлекаем корневой элемент */
    XROOT := PKG_XPATH.ROOT_NODE(RDOCUMENT => XDOC);
    /* Читаем прогноз */
    NFORECAST := PKG_XPATH.VALUE_NUM(RNODE => PKG_XPATH.SINGLE_NODE(RPARENT_NODE => XROOT, SPATTERN => 'XDATA/NFORECAST'));
  exception
    when others then
      null;
  end CMMLH_PARSE_FORECAST;
  
  /* Список "Выборки данных оборудования (классы оборудования, модели, история запросов)" по единице оборудования */
  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);
    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);
    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>' ||
                                                      UDO_PKG_EQUIPTCF.EQCONFIG_THOBJ_FORECAST_CLR(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',
                                        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,
                     null NFORECAST,
                     null STO_FORECAST_DESC,
                     null STO_FORECAST_DESC_COLOR,
                     null STO_FORECAST
                from UDO_T_EQUIPDSCMMLH T,
                     UDO_T_EQUIPDSCMML  ML,
                     UDO_T_EQUIPDSCM    CM,
                     UDO_T_EQUIPDS      DS,
                     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_PARSE_FORECAST(CFORECAST => BLOB2CLOB(LBDATA => C.BFORECAST), NFORECAST => C.NFORECAST);
      /* Формируем данные карточки прогноза для конкретного тех. объекта */
      UDO_PKG_EQUIPTCF.EQCONFIG_THOBJ_FORECAST_CRD(NEQCONFIG      => NEQCONFIG,
                                                   DFORECAST_DATE => C.DRQ_DATE,
                                                   NFORECAST      => C.NFORECAST,
                                                   SDICMUNTS      => C.SDICMUNTS,
                                                   STASK          => C.SEQUIPDSCMML_TASK,
                                                   COUT           => C.STO_FORECAST);
      /* Извлекаем прогноз и цвет для видимой колонки таблицы из карточки прогноза для конкретного тех. объекта */
      UDO_PKG_EQUIPTCF.EQCONFIG_THOBJ_FORECAST_CRDP(CFORECAST            => C.STO_FORECAST,
                                                    SFORECAST_DESC       => C.STO_FORECAST_DESC,
                                                    SFORECAST_DESC_COLOR => C.STO_FORECAST_DESC_COLOR);
      /* Добавляем колонки с данными */
      PKG_P8PANELS_VISUAL.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_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', SVALUE => C.STO_FORECAST);
      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;
/
