create or replace package UDO_PKG_EQUIPDS_DATAPROCESS
is
/*
  Описание: Обеспечивает подготовку/обработку данных для отпраки и получения запросов/ответов.
  Проект: Интеграция ПП «Парус 8» и «Фреймворка оценки и прогнозирования состояния оборудования»
  Разработчик: ЦИТК-ПАРУС
  Отественный: Селианов А.Е.
  Дата последнего изменения: 15.02.2025
*/

  /* Константы - Описание возможных событий */
  SDEF_EVENTTYPE_E0            constant PKG_STD.tSTRING := 'E0';       --событие ввода системы в эксплуатацию (начало наблюдения за функционированием системы)
  SDEF_EVENTTYPE_EOS           constant PKG_STD.tSTRING := 'EOS';     -- событие перехода работоспособной системы из нерабочего состояния в рабочее состояние (начало i-го цикла работы системы)
  SDEF_EVENTTYPE_ENOS          constant PKG_STD.tSTRING := 'ENOS';    -- событие перехода работоспособной системы из рабочего состояния в нерабочее состояние (окончание i-го цикла работы системы)
  SDEF_EVENTTYPE_ETMS          constant PKG_STD.tSTRING := 'ETMS';    -- событие перехода в состояние ТОИР
  SDEF_EVENTTYPE_ERMS          constant PKG_STD.tSTRING := 'ERMS';    -- событие выхода из состояния ТОИР
  SDEF_EVENTTYPE_EF            constant PKG_STD.tSTRING := 'EF';      -- событие возникновения i-го отказа работоспособной системы в j-м рабочем состоянии, т.е. переход системы в состояние отказа
  SDEF_EVENTTYPE_EOL           constant PKG_STD.tSTRING := 'EOL';     -- событие возникновения i-го предельного состояния в работоспособной системе в j-м рабочем состоянии (цикле)

  /* Константы - наименование типов колонок - усраревшие НЕ ИСПОЛЬЗОАТЬ!!!*/
  SCOL_TYP_DF                          constant PKG_STD.tSTRING := 'null_0';
  SCOL_TYP_PARAM_HARDWARE              constant PKG_STD.tSTRING := 'диагностический признак';     -- параметры технического состояния
  SCOL_TYP_CONDITIONS                  constant PKG_STD.tSTRING := 'условия эксплуатации';        -- эксплуатационные характеристики
  SCOL_TYP_HLSTATETYPES                constant PKG_STD.tSTRING := 'Типы состояний оборудования'; -- Типы состояний оборудования
  /* Константы - коды типов колонок - устаревшие НЕ ИСПОЛЬЗОВАТЬ!!!!*/
  NCOL_TYP_DF                          constant PKG_STD.tNUMBER := -1;
  NCOL_TYP_PARAM_HARDWARE              constant PKG_STD.tNUMBER := 0;   -- параметры технического состояния
  NCOL_TYP_CONDITIONS                  constant PKG_STD.tNUMBER := 1;   -- эксплуатационные характеристики
  NCOL_TYP_HLSTATETYPES                constant PKG_STD.tNUMBER := 2;   -- Типы состояний оборудования

  /* Константы - наименование типов колонок */
  SCOL_TYP_STRING                      constant PKG_STD.tSTRING := 'string';        -- тип строка
  SCOL_TYP_DATATIME                    constant PKG_STD.tSTRING := 'datetime';      -- тип дата время
  /* Константы - коды типов колонок */
  NCOL_TYP_STRING                      constant PKG_STD.tNUMBER := 3;    -- КОД типа строка
  NCOL_TYP_DATATIME                    constant PKG_STD.tNUMBER := 4;    -- КОД типа дата время



  /* Типы данных колонок - перечень колонок для построения датасета и формирования конфигурации */
  type TCOL_TYP_VAL is record
  (
    SINDEX           PKG_STD.TSTRING,   -- Интекс применения
    SCOL_CODE        PKG_STD.TSTRING,   -- Наименование
    SCOL_NAME        PKG_STD.TSTRING,   -- Наименование
    SCOL_VAL         PKG_STD.TSTRING,   -- Значение
    NCOL_TYP         PKG_STD.tNUMBER,   -- тип 
    SCOL_TYP         PKG_STD.TSTRING    -- наименование типа
  );

  /* Типы данных - коллекция переченя колонок для построения датасета и формирования конфигурации */
  type TCOL_TYP_VALS is table of TCOL_TYP_VAL; --index by PKG_STD.TSTRING;

  /* DataSet - перечень колонок c даннми для построения датасета */
  type TDATASET_VAL is record
  (
    NEQOBJKIND       PKG_STD.tREF,      -- Класс оборудования
    NUNIT            PKG_STD.tREF,      -- Экземпляр оборудования
    DDATATIME        DATE,         -- Дата события
    TCOLTYP_VAL      TCOL_TYP_VALS,     -- коллекция переченя колонок
    SEVENTTYPE       PKG_STD.TSTRING    -- Событие
  );

  /* DataSet  - коллекция переченя колонок c даннми для построения датасета */
  type TDATASET_VALS is table of TDATASET_VAL;
  
  /* Получение имени файла с расширением из полного пути */
  function GET_FILENAME
  (
    SPATH            IN VARCHAR2        -- Полный путь размещения файла
  )RETURN            varchar2;          -- имя файла с разрешением

  /* Получение данных датасета и Описание структуры выборки */
  procedure DATASET_CONF_SET
  (
    NCOMPANY                  in number,              -- регистрационный номер организации
    NEQUIPDSCM                in number default null, -- Рег. номер класса оборудования выборки данных (null - работать по указанной единице оборудования)
    NEQCONFIG                 in number default null, -- Рег. номер единицы оборудования (null - по всем)
    DBEG                      in date,                -- Дата С
    DEND                      in date,                -- Дата По
    NLENGTH_GB                in number default null, -- Ограничение размера файла в Гб 
    NDATASET_IDENT            out number,             -- Идентификатор буфера данных
    NDATASET_CONFIG_IDENT     out number              -- Идентификатор буфера описания данных  )
  );
  
  /* Обеспечивает постановку в очередь обмена сообщения на загрузку данных выборки на FTP, SCP */
  procedure UPLOAD
  (
    NCOMPANY         in number,         -- Организация
    NIDENT           in number,         -- Идентификатор Selectlis 
    NEQUIPDSCM      in number          -- Рег. номер класса оборудования выборки данных
  );
  
  /* Обеспечивает постановку в очередь обмена сообщения на передачу данных выборки внешней системе */
  procedure SEND_MD
  (
    NCOMPANY         in number,         -- Организация
    NIDENT           in number,         -- Идентификатор Selectlis 
    NEQUIPDSCM       in number          -- регистрационный номер записи Выборки данных класса оборудования»
  );  

  /* Обеспечивает постановку в очередь обмена сообщения на передачу запроса на обработку данных выборки внешней системе */
  procedure SEND_RQ
  (
    NCOMPANY         in number,         -- Организация
    NEQUIPDSCMML     in number          --  Рег. номер Модели   
  );


end UDO_PKG_EQUIPDS_DATAPROCESS;
/
create or replace package body UDO_PKG_EQUIPDS_DATAPROCESS
is

  /* Получение имени файла с расширением из полного пути */
  function GET_FILENAME
  (
    SPATH            IN VARCHAR2        -- Полный путь размещения файла
  )RETURN            varchar2           -- имя файла с разрешением
  IS
    SFILE            PKG_STD.tSTRING;   -- имя файла с разрешением     
  BEGIN

   /* Parse string for UNIX system */
   IF INSTR(SPATH,'/') > 0 THEN
      SFILE := SUBSTR(SPATH,(INSTR(SPATH,'/',-1,1)+1),length(SPATH));

   /* Parse string for Windows system */
   ELSIF INSTR(SPATH,'\') > 0 THEN
      SFILE := SUBSTR(SPATH,(INSTR(SPATH,'\',-1,1)+1),length(SPATH));
  ELSE
      SFILE := SPATH;

   END IF;

   RETURN SFILE;
  END GET_FILENAME;

  /* Формирование типа колонок */
  function TCOL_TYP_VAL_MAKE
  (
    SINDEX           in varchar2,       -- Индекс применения
    SCOL_CODE        in varchar2,       -- Наименование
    SCOL_NAME        in varchar2,       -- Наименование
    SCOL_VAL         in varchar2,       -- Значение
    NCOL_TYP         in number,         -- тип 
    SCOL_TYP         in varchar2        -- наименование типа
  ) return           TCOL_TYP_VAL       -- Результат работы
  is
    RRES             TCOL_TYP_VAL;      -- Буфер для результата
  begin
    /* Формируем объект */
    RRES.SINDEX    := SINDEX;
    RRES.SCOL_CODE := SCOL_CODE;
    RRES.SCOL_NAME := SCOL_NAME;
    RRES.SCOL_VAL  := SCOL_VAL;
    RRES.NCOL_TYP  := NCOL_TYP;
    RRES.SCOL_TYP  := SCOL_TYP;
    /* Возвращаем результат */
    return RRES;
  end TCOL_TYP_VAL_MAKE;

  /* Добавление значения в коллекцию типы колонок */
  procedure TCOL_TYP_VALS_ADD
  (
    RCOL_TYP_VALS    in out nocopy TCOL_TYP_VALS,  -- Коллекция значений
    SINDEX           in varchar2,                  -- Индекс применения
    SCOL_CODE        in varchar2,                  -- Код
    SCOL_NAME        in varchar2,                  -- Наименование
    SCOL_VAL         in varchar2,                  -- Значение
    NCOL_TYP         in number,                    -- тип 
    SCOL_TYP         in varchar2                   -- наименование типа
  )
  is
  begin
    /* Инициализируем коллекцию если необходимо */
    if (RCOL_TYP_VALS is null) then
      RCOL_TYP_VALS := TCOL_TYP_VALS();
    end if;
    /* Добавляем элемент */
    RCOL_TYP_VALS.EXTEND();
    RCOL_TYP_VALS(RCOL_TYP_VALS.LAST) := TCOL_TYP_VAL_MAKE(SINDEX => SINDEX, SCOL_CODE => SCOL_CODE, SCOL_NAME => SCOL_NAME, SCOL_VAL => SCOL_VAL, NCOL_TYP => NCOL_TYP, SCOL_TYP => SCOL_TYP);   
  
  end TCOL_TYP_VALS_ADD;

  /* Поиск действия (краткое описание) */
  function RCOL_TYP_VALS_FIND_CODE
  (
    RCOL_TYP_VALS    in out nocopy TCOL_TYP_VALS,  -- Коллекция значений
    SCOL_NAME        in varchar2                   -- Наименование
  ) return           PKG_STD.tSTRING               -- Найденный Код записи коллекции типы колонок (null - если ничего не найдено)
  is
  begin
    if ((RCOL_TYP_VALS is not null) and (RCOL_TYP_VALS.COUNT > 0)) then
      for I in RCOL_TYP_VALS.FIRST .. RCOL_TYP_VALS.LAST
      loop
        if (RCOL_TYP_VALS(I).SCOL_NAME = SCOL_NAME) then
          return RCOL_TYP_VALS(I).SCOL_CODE;
        end if;
      end loop;
    end if;
    /* Ничего не нашли */
    return null;
  end RCOL_TYP_VALS_FIND_CODE;
 
  /* Формировавние перечня колонок Data_config - XML */
  procedure TCOL_TYP_VALS_TO_XML
  (
    RCOL_TYP_VALS    in out nocopy TCOL_TYP_VALS, -- Коллекция значений
    CDATA_CONFIG     out clob                     -- Описание структуры выборки
  )
  is
    XDOC             integer;                     -- Документ для размещения XML-элемента  
    XITEMATRIBS      PKG_XMAKE.tATTRIBUTES;       -- Коллекция Атрибутов DATA_CONFIG
    XDCONFIG         PKG_XMAKE.TNODE;             -- Класс DATA_CONFIG  
    ST1 pkg_std.tSTRING;
    ST2 pkg_std.tSTRING;
    
  begin
    /* Проверяем наличие элементов коллекции */
    if (/*(RCOL_TYP_VALS is not null)*/ (RCOL_TYP_VALS.COUNT > 0)) then
      /* Создаём документ */
      XDOC := PKG_XMAKE.OPEN_CURSOR();
      /* Обходим элементы коллекции */
      for I in RCOL_TYP_VALS.FIRST .. RCOL_TYP_VALS.LAST loop
       if  RCOL_TYP_VALS(i).SINDEX != 'DATA_CONFIG' then
         continue;
       end if;  
       ST1 := RCOL_TYP_VALS(i).SCOL_NAME;
       ST2 := RCOL_TYP_VALS(i).SCOL_TYP;
        XITEMATRIBS := PKG_XMAKE.ATTRIBUTES(iCURSOR => XDOC,
                                            rATTRIBUTE00 => PKG_XMAKE.ATTRIBUTE(iCURSOR => XDOC,
                                                                                sNAME   => 'col_code', 
                                                                                sVALUE  => RCOL_TYP_VALS(i).SCOL_CODE),
                                            rATTRIBUTE01 => PKG_XMAKE.ATTRIBUTE(iCURSOR => XDOC,
                                                                                sNAME   => 'col_name', 
                                                                                sVALUE  => RCOL_TYP_VALS(i).SCOL_NAME),
                                            rATTRIBUTE02 => PKG_XMAKE.ATTRIBUTE(iCURSOR => XDOC,
                                                                                sNAME   => 'data_type', 
                                                                                sVALUE  => RCOL_TYP_VALS(i).SCOL_TYP));                
                
        XDCONFIG := PKG_XMAKE.CONCAT(ICURSOR => XDOC, 
                                     RNODE00 => XDCONFIG,
                                     rNODE01 => PKG_XMAKE.ELEMENT(ICURSOR   => XDOC,
                                                                  SNAME       => 'item',
                                                                  rATTRIBUTES => XITEMATRIBS)
                                     );             
      end loop;
      CDATA_CONFIG := PKG_XMAKE.SERIALIZE_TO_CLOB(iCURSOR => XDOC,
                                                  iTYPE   => PKG_XMAKE.DOCUMENT_,
                                                  rNODE   => PKG_XMAKE.CONCAT(iCURSOR => XDOC,
                                                                              rNODE00 => PKG_XMAKE.ELEMENT(iCURSOR => XDOC,
                                                                                                           sNAME   => 'data_config',
                                                                                                           rNODE00 => XDCONFIG)),
                                                  rHEADER => PKG_XHEADER.WRAP_ALL(sVERSION    => PKG_XHEADER.VERSION_1_0_,
                                                                                  sENCODING   => PKG_XHEADER.ENCODING_UTF_,
                                                                                  sSTANDALONE => PKG_XHEADER.STANDALONE_NONE_));
    
    PKG_XMAKE.CLOSE_CURSOR(ICURSOR => XDOC);
    end if;
  end TCOL_TYP_VALS_TO_XML;

  /* Формирование датасета */
  function TDATASET_VAL_MAKE
  (
    NEQOBJKIND       in number,          -- Класс оборудования
    NUNIT            in number,          -- Экземпляр оборудования
    DDATATIME        in TIMESTAMP,       -- Дата события
    TCOLTYP_VAL      in out nocopy TCOL_TYP_VALS,       -- коллекция переченя колонок
    SEVENTTYPE       in varchar2         -- Событие
   ) return           TDATASET_VAL       -- Результат работы
  is
    RRES             TDATASET_VAL;      -- Буфер для результата
  begin
    /* Формируем объект */
    RRES.NEQOBJKIND := NEQOBJKIND;
    RRES.NUNIT      := NUNIT;
    RRES.DDATATIME  := DDATATIME;
    RRES.TCOLTYP_VAL := TCOLTYP_VAL;
    RRES.SEVENTTYPE := SEVENTTYPE;
    /* Возвращаем результат */
    return RRES;
  end TDATASET_VAL_MAKE;

  /* Добавление значения в коллекцию датасета */
  procedure TDATASET_VAL_ADD
  (
    RDATASET_VALS    in out nocopy TDATASET_VALS, -- Коллекция значений
    NEQOBJKIND       in number,          -- Класс оборудования
    NUNIT            in number,          -- Экземпляр оборудования
    DDATATIME        TIMESTAMP,          -- Дата события
    TCOLTYP_VAL      in out nocopy TCOL_TYP_VALS,       -- коллекция переченя колонок
    SEVENTTYPE       in varchar2         -- Событие
  )
  is
  begin
    /* Инициализируем коллекцию если необходимо */
    if (RDATASET_VALS is null) then
      RDATASET_VALS := TDATASET_VALS();
    end if;
    /* Добавляем элемент */
    RDATASET_VALS.EXTEND();
    RDATASET_VALS(RDATASET_VALS.LAST) := TDATASET_VAL_MAKE(NEQOBJKIND  => NEQOBJKIND, 
                                                           NUNIT       => NUNIT, 
                                                           DDATATIME   => DDATATIME, 
                                                           TCOLTYP_VAL => TCOLTYP_VAL,
                                                           SEVENTTYPE  => SEVENTTYPE
                                                           );
  end TDATASET_VAL_ADD;

  /* Формирование dataset в формате XML */
  procedure TDATASET_VALS_TO_XML
  (
    RDATASET_VALS    in out nocopy TDATASET_VALS, -- Коллекция значений
    CDATA_SET        out clob                     -- Описание структуры выборки
  )
  is
    XDOC             integer;                     -- Документ для размещения XML-элемента  
    XDCOL            PKG_XMAKE.TNODE;             --
    XDCONFIG         PKG_XMAKE.TNODE;             -- Класс DATA_CONFIG  
    S1               PKG_STD.TSTRING;             -- Индекс элемментов коллекции
    s2               PKG_STD.TSTRING;             --
  begin
    /* Проверяем наличие элементов коллекции */
    if ((RDATASET_VALS is not null) and (RDATASET_VALS.COUNT > 0)) then
      /* Создаём документ */
      XDOC := PKG_XMAKE.OPEN_CURSOR();
      /* Обходим элементы коллекции */
      for I in RDATASET_VALS.FIRST .. RDATASET_VALS.LAST loop
        if ((RDATASET_VALS(i).TCOLTYP_VAL is not null) and (RDATASET_VALS(i).TCOLTYP_VAL.COUNT > 0)) then
          for j in RDATASET_VALS(i).TCOLTYP_VAL.FIRST .. RDATASET_VALS(i).TCOLTYP_VAL.LAST loop
               
             S1 :=  RDATASET_VALS(i).TCOLTYP_VAL(j).SINDEX; 
             S2 :=  RDATASET_VALS(I).NUNIT||'/'||DTS2S(RDATASET_VALS(I).DDATATIME);
               
          
               if  RDATASET_VALS(i).TCOLTYP_VAL(j).SINDEX != RDATASET_VALS(I).NUNIT||'/'||DTS2S(RDATASET_VALS(I).DDATATIME) then
                  continue;
               end if;  
         
         XDCOL := PKG_XMAKE.CONCAT(ICURSOR   => XDOC,
                                  rNODE00   => XDCOL,
                                  rNODE01   => PKG_XMAKE.ELEMENT(iCURSOR => XDOC,
                                                                 sNAME   => REPLACE(RDATASET_VALS(i).TCOLTYP_VAL(j).SCOL_NAME,' ','_'),
                                                                 rVALUE00 => PKG_XMAKE.VALUE(iCURSOR => XDOC,
                                                                                             sVALUE  => RDATASET_VALS(i).TCOLTYP_VAL(j).SCOL_VAL))
                                                      );
        
         end loop;
        end if;
        /* Собираем XML-описание класса в список */                
        XDCONFIG := PKG_XMAKE.CONCAT(ICURSOR => XDOC, 
                                     RNODE00 => XDCONFIG,
                                     RNODE01 => PKG_XMAKE.ELEMENT(ICURSOR => XDOC,
                                                                  SNAME   => 'item',
                                                                  /*rATTRIBUTES => XITEMATRIBS*/
                                                                  rNODE00 =>  PKG_XMAKE.ELEMENT(iCURSOR => XDOC,
                                                                                                sNAME   => 'NEQOBJKIND',
                                                                                                rVALUE00 => PKG_XMAKE.VALUE(iCURSOR => XDOC,
                                                                                                                            sVALUE  => RDATASET_VALS(I).NEQOBJKIND)),
                                                                  rNODE01 =>  PKG_XMAKE.ELEMENT(iCURSOR => XDOC,
                                                                                                sNAME   => 'NUNIT',
                                                                                                rVALUE00 => PKG_XMAKE.VALUE(iCURSOR => XDOC,
                                                                                                                            sVALUE  => RDATASET_VALS(I).NUNIT)),
                                                                  rNODE02 =>  PKG_XMAKE.ELEMENT(iCURSOR => XDOC,
                                                                                                sNAME   => 'DDATATIME',
                                                                                                rVALUE00 => PKG_XMAKE.VALUE_DZ(iCURSOR => XDOC,
                                                                                                                               DVALUE  => RDATASET_VALS(I).DDATATIME,
                                                                                                                               iFORMAT => 2)),
                                                                  rNODE03 => XDCOL,
                                                                  rNODE04 => PKG_XMAKE.ELEMENT(iCURSOR => XDOC,
                                                                                                sNAME   => 'SEVENTTYPE',
                                                                                                rVALUE00 => PKG_XMAKE.VALUE(iCURSOR => XDOC,
                                                                                                                            sVALUE  => RDATASET_VALS(I).SEVENTTYPE))));
                                                                                                                                             
      XDCOL := null;
      end loop;
      
      CDATA_SET := PKG_XMAKE.SERIALIZE_TO_CLOB(iCURSOR => XDOC,
                                                  iTYPE   => PKG_XMAKE.DOCUMENT_,
                                                  rNODE   => PKG_XMAKE.CONCAT(iCURSOR => XDOC,
                                                                              rNODE00 => PKG_XMAKE.ELEMENT(iCURSOR => XDOC,
                                                                                                           sNAME   => 'data_set',
                                                                                                           rNODE00 => XDCONFIG)),
                                                  rHEADER => PKG_XHEADER.WRAP_ALL(sVERSION    => PKG_XHEADER.VERSION_1_0_,
                                                                                  sENCODING   => PKG_XHEADER.ENCODING_UTF_,
                                                                                  sSTANDALONE => PKG_XHEADER.STANDALONE_NONE_));
    
    PKG_XMAKE.CLOSE_CURSOR(ICURSOR => XDOC);
    end if;
  end TDATASET_VALS_TO_XML;
  
  /* Формирование dataset в формате CSV */ 
  procedure DATASET_SCV_MAKE
  (
    RDATACONF        in out nocopy TCOL_TYP_VALS, -- Коллекция колокон шапки dataset 
    RDATASET_VALS    in out nocopy TDATASET_VALS, -- Коллекция значений
    SDESCR           in varchar2,                 -- Описание выборки данных  
    NLENGTH_GB       in number,                   -- Ограничение размера файла в Гб 
    NEQCONFIG_CNT    in number,                   -- Количесто экземпляров оборудования 
    NDATASET_IDENT   out number                   -- Идентификатор буфера данных
  )
  is
    SLINE            PKG_STD.tSTRING /*:= 'unit;time;'*/;  -- Линия шапки
    SDATA            PKG_STD.tSTRING;                      -- Линия данных
    N                PKG_STD.tNUMBER:= 0;                  -- Всего колонок
    NLENGTH          PKG_STD.tNUMBER;
    NLENGTH_DEF      PKG_STD.tNUMBER;-- := 1073741824; -- 1 гига байт !!! 
    NLENGTH_KOEFF    PKG_STD.tNUMBER := 1024;
    BDATA_SET        blob;                                 -- Описание структуры выборки  
    SFILENAME        PKG_STD.tSTRING :='DataSet_<ID>.csv';                      -- Имя файла
    NF               PKG_STD.tNUMBER := 0;
    SDATA_VAL        PKG_STD.tSTRING;
    nREC             PKG_STD.tNUMBER := 0;
  begin
    /* Переводим Гб в байты */
    if NVL(NLENGTH_GB, 0) != 0 then
      NLENGTH_DEF := ((((NLENGTH_GB * NLENGTH_KOEFF) * NLENGTH_KOEFF) *
                     NLENGTH_KOEFF));
    else
      NLENGTH_DEF := null;
    end if;
    /* Генерация Идентификатора буфера данных */
    NDATASET_IDENT := gen_ident;
    /* Формируем Шапку */
    for I in RDATACONF.FIRST .. RDATACONF.LAST loop
      if RDATACONF(i).SINDEX != 'DATA_CONFIG' then
        continue;
      end if;
      SLINE := SLINE || RDATACONF(i).SCOL_CODE || ';';
      N     := I;
    end loop;
  
    SLINE := RTRIM(SLINE,';') /*|| 'EventType'*/ || CR();
    PKG_LOB_BUFFER.APPEND_BLOB(CLOB2BLOB(SLINE, PKG_CHARSET.CHARSET_UTF_));
    if RDATASET_VALS is not EMPTY then
      /* Обходим элементы коллекции */
      nREC := Round(30632 /NEQCONFIG_CNT,0);
      for J in RDATASET_VALS.FIRST .. RDATASET_VALS.LAST loop
        for r in 1 .. nREC loop
        --exit when r = nREC;

        SDATA := RDATASET_VALS(j)
                 .NUNIT || ';' ||r|| ';'; 
                 --DTS2S(RDATASET_VALS(j).DDATATIME) || ';';
        --if RDATASET_VALS(j).TCOLTYP_VAL is NOT EMPTY then
        
        --end if;
        /*Контроль наличия колонок */
        if RDATACONF is not EMPTY then
          /* Проходим по колонкам */
          for I1 in RDATACONF.FIRST .. RDATACONF.LAST loop
            /* Исключаем выборку данных для DATA_CONFIG */
            if RDATACONF(i1).SINDEX != 'DATA_CONFIG' then
              continue;
            end if;
            /* Обнуление параметра */
            SDATA_VAL := null;
            /* Обходим коллекцию с данными */
            for l in RDATASET_VALS(j).TCOLTYP_VAL.FIRST .. RDATASET_VALS(j)
                                                           .TCOLTYP_VAL.LAST loop
              if RDATACONF(i1).SCOL_CODE is not null and RDATACONF(i1).SCOL_CODE not in ('unit','time')  then
                SDATA_VAL := replace(round(dbms_random.value(-100,100),2),',','.');
                exit;
              end if;
              /* Проверка наличия колонки в коллекции */
              /*if RDATACONF(i1)
               .SCOL_CODE = RDATASET_VALS(j).TCOLTYP_VAL(l).SCOL_CODE and RDATACONF(i1)
                 .NCOL_TYP = RDATASET_VALS(j).TCOLTYP_VAL(l).NCOL_TYP then
                \* Фиксируем данные и выходим из цыкла *\
                --SDATA_VAL := RDATASET_VALS(j).TCOLTYP_VAL(l).SCOL_VAL;
                SDATA_VAL := replace(round(dbms_random.value(-100,100),2),',','.');
                exit;
              else
                \*Если нет колонки переходим к следующей записи коллекции с данными *\
                continue;
                 --SDATA_VAL := replace(round(dbms_random.value(-100,100),2),',','.');
              end if;*/
            end loop;
          if SDATA_VAL is not null then
            SDATA := SDATA||SDATA_VAL || ';';
          end if;  
          end loop;
        end if;
      
        SDATA := RTRIM(SDATA,';') /*|| RDATASET_VALS(j).SEVENTTYPE || ';'*/ || CR();
      
        BDATA_SET := PKG_LOB_BUFFER.GET_BLOB(lCLEAR => false);
        NLENGTH   := dbms_lob.getlength(BDATA_SET);
        if (NLENGTH_DEF is not null and NLENGTH >= NLENGTH_DEF) then
          BDATA_SET := PKG_LOB_BUFFER.GET_BLOB(lCLEAR => true);
          NF        := NF + 1;
          P_FILE_BUFFER_INSERT(nIDENT    => NDATASET_IDENT,
                               cFILENAME => NF || '_' ||
                                            REPLACE(SFILENAME,
                                                    '<ID>',
                                                    gen_ident),
                               cDATA     => SDESCR,
                               bLOBDATA  => BDATA_SET);
        end if;
        PKG_LOB_BUFFER.APPEND_BLOB(CLOB2BLOB(SDATA,
                                             PKG_CHARSET.CHARSET_UTF_));
      end loop;
      end loop;
      BDATA_SET := PKG_LOB_BUFFER.GET_BLOB(lCLEAR => true);
      P_FILE_BUFFER_INSERT(nIDENT    => NDATASET_IDENT,
                           cFILENAME => NF || '_' ||
                                        REPLACE(SFILENAME, '<ID>', gen_ident),
                           cDATA     => SDESCR,
                           bLOBDATA  => BDATA_SET);
    end if;
  end DATASET_SCV_MAKE;
  
  /* Формирование данных датасета и Описание структуры выборки */
  procedure DATASET_CONF_MAKE
  (
    NCOMPANY         in number,                   -- регистрационный номер организации
    NEQUIPDSCM       in number default null,      -- Рег. номер класса оборудования выборки данных (null - работать по указанной единице оборудования)
    NEQCONFIG        in number default null,      -- Рег. номер единицы оборудования (null - по всем)
    DBEG             in date,                     -- Дата С
    DEND             in date,                     -- Дата По
    SDESCR           out varchar2,                -- Описание выборки данных  
    NEQCONFIGCNT     out number,                  -- Количесто экземпляров оборудования
    RDATA_CONFIG     in out nocopy TCOL_TYP_VALS, -- Коллекция значений
    RDATASET_VALS    in out nocopy TDATASET_VALS  -- Коллекция данных датасета
  )
  is 
    NUNIT            PKG_STD.tREF;         -- Экземпляр оборудования
    --NEQOBJKIND       PKG_STD.tREF;       -- Класс оборудования
    RCOLTYPVALS      TCOL_TYP_VALS;        -- Коллекция значений
    DDATATIME        date;                 -- Дата события
    SEVENTTYPE       PKG_STD.TSTRING;      -- Событие
    SUNIT            PKG_STD.tSTRING;
    NEQCONFIG_CNT    PKG_STD.tNUMBER := 0; -- Количесто экземпляров оборудования 
    nPP_TC           PKG_STD.tNUMBER:= 0;  -- Порядкоый номер столца технического состояния 
    nPP_OC           PKG_STD.tNUMBER:= 0;  -- Порядкоый номер столца условий эксплуатации 
    SCOL_CODE        PKG_STD.TSTRING;
    NEQOBJKIND_      PKG_STD.TREF;         -- Класс оборудования    
 begin
  -- NEQOBJKIND := NEQUIPDSCMN; --8358772;
   /* Определим класс технического объекта - сначала по классу оборудования выборки данных, если нам его передали */
   if (NEQUIPDSCM is not null) then
     begin
       select T.EQOBJKIND into NEQOBJKIND_ from UDO_T_EQUIPDSCM T where T.RN = NEQUIPDSCM;
     exception
       when NO_DATA_FOUND then
         P_EXCEPTION(0, 'Запись класса оборудования выборки данных (RN: %s) не определена.', TO_CHAR(NEQUIPDSCM));
     end;
   end if;
   /* Определим класс технического объекта - теперь по единице оборудования, если передали её */
   if (NEQCONFIG is not null) then
     begin
       select T.OBJ_KIND into NEQOBJKIND_ from EQCONFIG T where T.RN = NEQCONFIG;
     exception
       when NO_DATA_FOUND then
         P_EXCEPTION(0, 'Запись единицы оборудования (RN: %s) не определена.', TO_CHAR(NEQCONFIG));
     end;
     if (NEQOBJKIND_ is null) then
       P_EXCEPTION(0, 'Для единицы оборудования (RN: %s) не определён класс технического объекта.', TO_CHAR(NEQCONFIG));
     end if;
   end if;
   /* Проверим, что нашли хоть каким-то способом */
   if (NEQOBJKIND_ is null) then
     P_EXCEPTION(0, 'Не удалось определить класс технического объекта.');
   end if;
     /* Добаляем в колекию первые поля "unit" и "time" */
     /* Заполним коллекцию переченя колонок для построения датасета и формирования конфигурации */
     TCOL_TYP_VALS_ADD(RCOL_TYP_VALS => RDATA_CONFIG,
                       SINDEX        => 'DATA_CONFIG',
                       SCOL_CODE     => 'unit',
                       SCOL_NAME     => 'экземпляр оборудования',
                       SCOL_VAL      => null,
                       NCOL_TYP      => NCOL_TYP_STRING,
                       SCOL_TYP      => SCOL_TYP_STRING);
     /* Заполним коллекцию переченя колонок для построения датасета и формирования конфигурации */
     TCOL_TYP_VALS_ADD(RCOL_TYP_VALS => RDATA_CONFIG,
                       SINDEX        => 'DATA_CONFIG',
                       SCOL_CODE     => 'time',
                       SCOL_NAME     => 'DataTime',
                       SCOL_VAL      => null,
                       NCOL_TYP      => NCOL_TYP_DATATIME,
                       SCOL_TYP      => SCOL_TYP_DATATIME);

 
   /* Заполним данные DATA_CONFIG */
   /*-------------------------------------------------------------------------------*/
   /* Классификатор технических объектов (макет параметров технического состояния) */
   FOR TEQOBJKINDSM in (select T1.CODE, T1.NAME
                          from EQOBJKINDSM t, EQTECHSTPR t1 --, DICMUNTS t2 
                         where T.PRN = NEQOBJKIND_
                           and T.TCHSTPARAM = t1.rn
                           and T1.TYPE_PARAM = 0 --  нормативный0
                           and T.COMPANY = NCOMPANY
                           order by t1.name asc) loop
     nPP_TC := nPP_TC + 1;
     SCOL_CODE := 'p'||nPP_TC;
     /* Заполним коллекцию переченя колонок для построения датасета и формирования конфигурации */
     TCOL_TYP_VALS_ADD(RCOL_TYP_VALS => RDATA_CONFIG,
                       SINDEX        => 'DATA_CONFIG',
                       SCOL_CODE     => SCOL_CODE,
                       SCOL_NAME     => TEQOBJKINDSM.NAME,
                       SCOL_VAL      => null,
                       NCOL_TYP      => NCOL_TYP_STRING,
                       SCOL_TYP      => SCOL_TYP_STRING);
   end loop;
   /* Классификатор технических объектов (макет параметров условий эксплуатации) */
   for TEQOBJKINDEXTPRM in (select T1.CODE, T1.NAME
                              from EQOBJKINDEXTPRM t, EQEXTENVPRM t1
                             where t.PRN = NEQOBJKIND_
                               and T.EQEXTENVPRM = T1.RN
                               and T.COMPANY = NCOMPANY
                               order by t1.name asc ) loop
     nPP_OC := nPP_OC + 1;
     SCOL_CODE := 's'||nPP_OC;
     /* Заполним коллекцию переченя колонок для построения датасета и формирования конфигурации */
     TCOL_TYP_VALS_ADD(RCOL_TYP_VALS => RDATA_CONFIG,
                       SINDEX        => 'DATA_CONFIG',
                       SCOL_CODE     => SCOL_CODE,
                       SCOL_NAME     => TEQOBJKINDEXTPRM.NAME,
                       SCOL_VAL      => null,
                       NCOL_TYP      => NCOL_TYP_STRING,
                       SCOL_TYP      => SCOL_TYP_STRING);
   end loop;
   /* Типы состояний оборудования  */
   for THLSTATETYPES in (select t.code, T.READY_USE
                           from HLSTATETYPES T
                          where t.version =
                                f_company_to_version(nFLAG_SMART => 0,
                                                     nCOMPANY    => NCOMPANY,
                                                     sUNITCODE   => 'HaulierUnitsStateTypes')
                            and T.READY_USE != 0) loop
     
     nPP_OC := nPP_OC + 1;
     SCOL_CODE := 's'||nPP_OC;
     /* Заполним коллекцию переченя колонок для построения датасета и формирования конфигурации */
     TCOL_TYP_VALS_ADD(RCOL_TYP_VALS => RDATA_CONFIG,
                       SINDEX        => 'DATA_CONFIG',
                       SCOL_CODE     => SCOL_CODE,
                       SCOL_NAME     => THLSTATETYPES.CODE,
                       SCOL_VAL      => null,
                       NCOL_TYP      => NCOL_TYP_STRING,
                       SCOL_TYP      => SCOL_TYP_STRING);
   end loop;   
   /* Проверим количесто сформированных колонок, если менее 22, до добавим до минимального необходимого значения 
   - ВРЕМЕННО, для обеспечения требоания по формироанию модели ОБУСЧЕНИЯ */
   If nPP_OC < 22 then
     loop
       exit when nPP_OC = 22;
     nPP_OC := nPP_OC + 1;
     SCOL_CODE := 's'||nPP_OC;
     /* Добаление колонки без наименования "-" */
     TCOL_TYP_VALS_ADD(RCOL_TYP_VALS => RDATA_CONFIG,
                       SINDEX        => 'DATA_CONFIG',
                       SCOL_CODE     => SCOL_CODE,
                       SCOL_NAME     => '-',
                       SCOL_VAL      => null,
                       NCOL_TYP      => NCOL_TYP_STRING,
                       SCOL_TYP      => SCOL_TYP_STRING);
      end loop;
   end if;
   /* Считаем запись оборудования */
   for TEQCONFIG in (select T.RN NUNIT, T.OPER_DATE
                       from EQCONFIG t
                      where T.OBJ_KIND = NEQOBJKIND_
                        and ((NEQCONFIG is null) or ((NEQCONFIG is not null) and (T.RN = NEQCONFIG)))
                        and T.OPER_DATE between DBEG and DEND
                        and T.COMPANY = NCOMPANY
                        order by t.OPER_DATE asc) loop
      NEQCONFIG_CNT := NEQCONFIG_CNT + 1;                   
     SUNIT := to_char(TEQCONFIG.NUNIT || '/' || DTS2S(TEQCONFIG.OPER_DATE));
     -- Соббытие SDEF_EVENTTYPE_E0 Event 0   
     /* Параметры технического состояния */
     FOR TPARAM_HARDWARE in (select T1.CODE,
                                    T1.NAME,
                                    T2.MEAS_MNEMO,
                                    T2.MEAS_NAME,
                                    T.NOM_VALUE,
                                    T.MIN_VALUE,
                                    T.MAX_VALUE
                               from EQCONFIGSP t, EQTECHSTPR t1, DICMUNTS t2
                              where T.PRN = TEQCONFIG.NUNIT
                                and T.TCHSTPARAM = t1.rn
                                and T1.TYPE_PARAM = 0 --  нормативный
                                and T.UMEAS = t2.rn(+)
                              order by t1.name asc) loop

     SCOL_CODE := RCOL_TYP_VALS_FIND_CODE(RCOL_TYP_VALS => RDATA_CONFIG, SCOL_NAME => TPARAM_HARDWARE.NAME); 

       /* Заполним коллекцию переченя колонок для построения датасета и формирования конфигурации */
       TCOL_TYP_VALS_ADD(RCOL_TYP_VALS => RCOLTYPVALS,
                         SINDEX        => SUNIT,
                         SCOL_CODE     => NVL(SCOL_CODE,'S0'),
                         SCOL_NAME     => TPARAM_HARDWARE.NAME,
                         SCOL_VAL      => TPARAM_HARDWARE.NOM_VALUE,
                         NCOL_TYP      => NCOL_TYP_STRING,
                         SCOL_TYP      => SCOL_TYP_STRING);
     
     end loop; -- TPARAM_HARDWARE   
     /* параметры окружения и эксплуатационные характеристики */
     for TCONDITIONS in (select t1.code code_PRM,
                                t1.name name_PRM,
                                t2.code code_tp
                           from EQCONFEXTPRM     t,
                                EQEXTENVPRM      t1,
                                EQUIPWORKACTTYPE t2
                          where t.PRN = TEQCONFIG.NUNIT
                            and t.eqextenvprm = t1.rn
                            and t1.workacttype = t2.rn
                          order by t1.name asc) loop

     SCOL_CODE := RCOL_TYP_VALS_FIND_CODE(RCOL_TYP_VALS => RDATA_CONFIG, SCOL_NAME => TCONDITIONS.NAME_PRM); 

       /* Заполним коллекцию переченя колонок для построения датасета и формирования конфигурации */
       TCOL_TYP_VALS_ADD(RCOL_TYP_VALS => RCOLTYPVALS,
                         SINDEX        => SUNIT,
                         SCOL_CODE     => NVL(SCOL_CODE,'S0'),
                         SCOL_NAME     => TCONDITIONS.NAME_PRM,
                         SCOL_VAL      => TCONDITIONS.code_tp,
                         NCOL_TYP      => NCOL_TYP_STRING,
                         SCOL_TYP      => SCOL_TYP_STRING);
     
     end loop; -- TCONDITIONS
     DDATATIME :=  /* S2ZSTAMP(PKG_XCONVERT.DZ_TO_XML(*/
      TEQCONFIG.OPER_DATE /*,2))*/
       ;
     /**/
     TDATASET_VAL_ADD(RDATASET_VALS => RDATASET_VALS,
                      NEQOBJKIND    => NEQOBJKIND_,
                      NUNIT         => TEQCONFIG.NUNIT,
                      DDATATIME     => DDATATIME,
                      TCOLTYP_VAL   => RCOLTYPVALS,
                      SEVENTTYPE    => SDEF_EVENTTYPE_E0);
     /* Очистим коллекцию переченя колонок */
     if RCOLTYPVALS IS NOT EMPTY then
     RCOLTYPVALS.delete;
     end if;
   
     -- Соббытие SDEF_EVENTTYPE_E0, Event 0   
   
     -- Соббытие SDEF_EVENTTYPE_EF Event of Failure  
     /* Учёт повреждений оборудования - Состояние "Зафиксировано" */
     for TEQDAMCTRL in (select T.RN, T.CHNG_FIX_DATE
                          from EQDAMCTRL t
                         where T.EQCONFIG = TEQCONFIG.NUNIT
                           AND T.COMPANY = NCOMPANY
                           and T.EQ_FIX = 1) loop
       SUNIT := to_char(TEQCONFIG.NUNIT || '/' ||
                        DTS2S(TEQDAMCTRL.CHNG_FIX_DATE));
     
       /* Учёт повреждений оборудования (параметры технического состояния) */
       for TEQDAMCTRLPRM in (select t2.code, t2.name, t.cur_val, t.max_val
                               from EQDAMCTRLPRM t,
                                    EQCONFIGSP   t1,
                                    EQTECHSTPR   t2
                              where t.PRN = TEQDAMCTRL.RN
                                and t.eqconfigsp = t1.rn
                                and t1.tchstparam = t2.rn
                                order by t2.code asc) loop

     SCOL_CODE := RCOL_TYP_VALS_FIND_CODE(RCOL_TYP_VALS => RDATA_CONFIG, SCOL_NAME => TEQDAMCTRLPRM.code); 

         /* Заполним коллекцию переченя колонок для построения датасета и формирования конфигурации */
         TCOL_TYP_VALS_ADD(RCOL_TYP_VALS => RCOLTYPVALS,
                           SINDEX        => SUNIT,
                           SCOL_CODE     => NVL(SCOL_CODE,'S0'),
                           SCOL_NAME     => TEQDAMCTRLPRM.code,
                           SCOL_VAL      => TEQDAMCTRLPRM.max_val,
                           NCOL_TYP      => NCOL_TYP_STRING,
                           SCOL_TYP      => SCOL_TYP_STRING);
       end loop; -- TEQDAMCTRLPRM
     
       /* Учёт повреждений оборудования (параметры условий эксплуатации) */
       for TEQDAMCTRLEXTPRM in (select t2.code, t.value
                                  from EQDAMCTRLEXTPRM t,
                                       EQCONFEXTPRM    t1,
                                       EQEXTENVPRM     t2
                                 where t.PRN = TEQDAMCTRL.RN
                                   and T.EQCONFEXTPRM = t1.rn
                                   and T1.EQEXTENVPRM = t2.rn
                                   order by t2.code asc) loop

     SCOL_CODE := RCOL_TYP_VALS_FIND_CODE(RCOL_TYP_VALS => RDATA_CONFIG, SCOL_NAME => TEQDAMCTRLEXTPRM.code); 

         /* Заполним коллекцию переченя колонок для построения датасета и формирования конфигурации */
         TCOL_TYP_VALS_ADD(RCOL_TYP_VALS => RCOLTYPVALS,
                           SINDEX        => SUNIT,
                           SCOL_CODE     => NVL(SCOL_CODE,'S0'),
                           SCOL_NAME     => TEQDAMCTRLEXTPRM.code,
                           SCOL_VAL      => TEQDAMCTRLEXTPRM.value,
                           NCOL_TYP      => NCOL_TYP_STRING,
                           SCOL_TYP      => SCOL_TYP_STRING);
       end loop;
       /**/
       DDATATIME :=  /*S2ZSTAMP(PKG_XCONVERT.DZ_TO_XML(*/
        TEQDAMCTRL.CHNG_FIX_DATE; /*,2)),*/
       TDATASET_VAL_ADD(RDATASET_VALS => RDATASET_VALS,
                        NEQOBJKIND    => NEQOBJKIND_,
                        NUNIT         => TEQCONFIG.NUNIT,
                        DDATATIME     => DDATATIME,
                        TCOLTYP_VAL   => RCOLTYPVALS,
                        SEVENTTYPE    => SDEF_EVENTTYPE_EF);
     
     end loop;
     /* Очистим коллекцию переченя колонок */
     if RCOLTYPVALS is not EMPTY then
     RCOLTYPVALS.delete;
     end if;
     -- Соббытие SDEF_EVENTTYPE_EF Event of Failure  
   
     -- Соббытие SDEF_EVENTTYPE_ENOS Event of Non-Operation of System i
     -- Соббытие SDEF_EVENTTYPE_ETMS Event of Transition to Maintenance State
   
     /* Ремонтные ведомости - Вход и Выход для состояния ТОИР */
     for TEQRPSHEETS in (select T.STATE, t.datefact_beg, t.datefact_end
                           from EQRPSHEETS t
                          where t.EQCONFIG = TEQCONFIG.NUNIT) loop
       /* Определим параметры */
       case TEQRPSHEETS.STATE
       /* Статус - "Закрыт" выход из состояния ТОИР */
         when 3 then
           DDATATIME  :=  /*S2ZSTAMP(PKG_XCONVERT.DZ_TO_XML(*/
            TEQRPSHEETS.DATEFACT_END /*,2))*/
             ;
           SEVENTTYPE := SDEF_EVENTTYPE_ERMS;
           /* Статус - "Утвержден" вход в состояние ТОИР */
         when 2 then
           DDATATIME  :=  /*S2ZSTAMP(PKG_XCONVERT.DZ_TO_XML(*/
            TEQRPSHEETS.DATEFACT_BEG /*,2))*/
             ;
           SEVENTTYPE := SDEF_EVENTTYPE_ETMS;
         else
           DDATATIME  := null;
           SEVENTTYPE := null;
       end case;
       SUNIT := TO_CHAR(TEQCONFIG.NUNIT || '/' || DTS2S(DDATATIME));
       /*  */
       if DDATATIME is not null and SEVENTTYPE is not null then
        /* TCOL_TYP_VALS_ADD(RCOL_TYP_VALS => RCOLTYPVALS,
                           SINDEX        => SUNIT,
                           SCOL_NAME     => 'null_0',
                           SCOL_VAL      => '-',
                           NCOL_TYP      => NCOL_TYP_DF,
                           SCOL_TYP      => SCOL_TYP_DF);*/
         TDATASET_VAL_ADD(RDATASET_VALS => RDATASET_VALS,
                          NEQOBJKIND    => NEQOBJKIND_,
                          NUNIT         => TEQCONFIG.NUNIT,
                          DDATATIME     => DDATATIME,
                          TCOLTYP_VAL   => RCOLTYPVALS,
                          --SCOL_NAME     => null, -- Вопрос для обсуждения чем заполнять
                          --SCOL_VAL      => null, -- Вопрос для обсуждения чем заполнять                       
                          SEVENTTYPE => SEVENTTYPE);
         /* Очистим коллекцию переченя колонок */
         if RCOLTYPVALS is not EMPTY then
         RCOLTYPVALS.delete;
         end if;
       end if;
     end loop;
   
     -- Соббытие SDEF_EVENTTYPE_ENOS Event of Non-Operation of System i 
     -- Соббытие SDEF_EVENTTYPE_ETMS Event of Transition to Maintenance State
   
     -- Соббытие SDEF_EVENTTYPE_ERMS Event of Return from Maintenance State
     -- Соббытие SDEF_EVENTTYPE_EOS Event of System i
     /* Состав оборудования (история смены состояний) */
     for TEQCONFIGSH in (select t1.code, t1.ready_use, t.change_date
                           from EQCONFIGSH t, HLSTATETYPES t1
                          where t.PRN = TEQCONFIG.NUNIT
                            and t.hlstatetypes = t1.rn
                            order by t1.code asc) loop
       case TEQCONFIGSH.READY_USE
       /* Готово к эксплуатации */
         when 2 then
           SEVENTTYPE := SDEF_EVENTTYPE_EOS;
           /* Не готово к эксплуатации */
         when 1 then
           SEVENTTYPE := SDEF_EVENTTYPE_ENOS;
         else
           SEVENTTYPE := null;
       end case;
       /**/
     
       if SEVENTTYPE is not null then
         DDATATIME :=  /*PKG_XCONVERT.DZ_TO_XML(*/
          TEQCONFIGSH.CHANGE_DATE; /*,2)*/
         SUNIT     := TO_CHAR(TEQCONFIG.NUNIT || '/' || DTS2S(DDATATIME));
     SCOL_CODE := RCOL_TYP_VALS_FIND_CODE(RCOL_TYP_VALS => RDATA_CONFIG, SCOL_NAME => TEQCONFIGSH.CODE); 

         TCOL_TYP_VALS_ADD(RCOL_TYP_VALS => RCOLTYPVALS,
                           SINDEX        => SUNIT,
                           SCOL_CODE     => NVL(SCOL_CODE,'S0'),
                           SCOL_NAME     => TEQCONFIGSH.CODE,
                           SCOL_VAL      => TEQCONFIGSH.READY_USE,
                           NCOL_TYP      => NCOL_TYP_STRING,
                           SCOL_TYP      => SCOL_TYP_STRING);
       
         TDATASET_VAL_ADD(RDATASET_VALS => RDATASET_VALS,
                          NEQOBJKIND    => NEQOBJKIND_,
                          NUNIT         => TEQCONFIG.NUNIT,
                          DDATATIME     => DDATATIME,
                          TCOLTYP_VAL   => RCOLTYPVALS,
                          --SCOL_NAME     => TEQCONFIGSH.CODE,        -- Вопрос для обсуждения чем заполнять
                          --SCOL_VAL      => TEQCONFIGSH.READY_USE,   -- Вопрос для обсуждения чем заполнять                           
                          SEVENTTYPE => SEVENTTYPE);
         /* Очистим коллекцию переченя колонок */
         if RCOLTYPVALS is not EMPTY then
         RCOLTYPVALS.delete;
         end if;
       end if;
     
     end loop;
   
   -- Соббытие SDEF_EVENTTYPE_ERMS Event of Return from Maintenance State
   -- Соббытие SDEF_EVENTTYPE_EOS Event of System i
   
   -- Соббытие SDEF_EVENTTYPE_EOL Event of Limit State i   
   -- Вопрос для обсуждения чем заполнять - Есть предложение - требуется регистраия  Параметры технического состояния с типом "Критический - отслеживается не аварийные ситуаии, но с близкими значениями к аварийным " по типу "Нормативый отслеживаем аварии и ремонты"
   -- Соббытие SDEF_EVENTTYPE_EOL Event of Limit State i  
   
   end loop; -- TEQCONFIG
   /* Описание */
   SDESCR := 'дата с - '|| D2S(DBEG)||CR()
          ||'дата по - '||D2S(DEND)||CR()
          ||'Количество единиц оборудования  выборке - '||NEQCONFIG_CNT||CR()
          ||'ID Класса оборудования - '||NEQOBJKIND_;
   NEQCONFIGCNT := NEQCONFIG_CNT;
 end DATASET_CONF_MAKE;
 
  /* Получение данных датасета и Описание структуры выборки */
  procedure DATASET_CONF_SET
  (
    NCOMPANY                in number,              -- регистрационный номер организации
    NEQUIPDSCM              in number default null, -- Рег. номер класса оборудования выборки данных (null - работать по указанной единице оборудования)
    NEQCONFIG               in number default null, -- Рег. номер единицы оборудования (null - по всем)
    DBEG                    in date,                -- Дата С
    DEND                    in date,                -- Дата По
    NLENGTH_GB              in number default null, -- Ограничение размера файла в Гб 
    NDATASET_IDENT          out number,             -- Идентификатор буфера данных
    NDATASET_CONFIG_IDENT   out number              -- Идентификатор буфера описания данных  )
  ) 
  is
    RDATA_CONFIG            TCOL_TYP_VALS;          -- Коллекция значений
    RDATASET_VALS           TDATASET_VALS;          -- Коллекция данных датасета
    SDESCR                  PKG_STD.TSTRING;        -- Описание выборки данных  
    CDATA_CONFIG            clob;                   -- Данные описания структуры выборки
    NEQCONFIGCNT            PKG_STD.TNUMBER;        -- Количество единиц оборудования, попавших в выборку
  begin
    /* Проверим, что нам указали либо класс оборудования выборки данных, либо рег. номер единицы оборудования */
    if (((NEQUIPDSCM is null) and (NEQCONFIG is null)) or ((NEQUIPDSCM is not null) and (NEQCONFIG is not null))) then
      P_EXCEPTION(0,
                  'Должен быть указан либо класс оборудования выборки данных, либо единица оборудения.');
    end if;
    /* Формирование данных датасета и описания структуры выборки */
    DATASET_CONF_MAKE(NCOMPANY      => NCOMPANY,
                      NEQUIPDSCM    => NEQUIPDSCM,
                      NEQCONFIG     => NEQCONFIG,
                      DBEG          => DBEG,
                      DEND          => DEND,
                      SDESCR        => SDESCR,
                      NEQCONFIGCNT  => NEQCONFIGCNT,
                      RDATA_CONFIG  => RDATA_CONFIG,
                      RDATASET_VALS => RDATASET_VALS);
    /* Формировавние перечня колонок Data_config - XML */
    TCOL_TYP_VALS_TO_XML(RCOL_TYP_VALS => RDATA_CONFIG, CDATA_CONFIG => CDATA_CONFIG);
    /* Генерация идентификатора файлового буфера для настроек структуры данных */
    NDATASET_CONFIG_IDENT := GEN_IDENT();
    /* Сохраним настройку структуры данных */
    P_FILE_BUFFER_INSERT(NIDENT    => NDATASET_CONFIG_IDENT,
                         CFILENAME => 'CDATA_CONFIG',
                         CDATA     => CDATA_CONFIG,
                         BLOBDATA  => null);
    /* Формирование dataset в формате CSV */
    DATASET_SCV_MAKE(RDATACONF      => RDATA_CONFIG,
                     RDATASET_VALS  => RDATASET_VALS,
                     SDESCR         => SDESCR,
                     NLENGTH_GB     => NLENGTH_GB,
                     NEQCONFIG_CNT  => NEQCONFIGCNT,
                     NDATASET_IDENT => NDATASET_IDENT);
  end DATASET_CONF_SET;

  /* Обеспечивает постановку в очередь обмена сообщения на загрузку данных выборки на FTP, SCP */
  procedure UPLOAD
  (
    NCOMPANY         in number,         -- Организация
    NIDENT           in number,         -- Идентификатор Selectlis 
    NEQUIPDSCM       in number          -- Рег. номер класса оборудования выборки данных
  )  
  is
    NEXSSERVICEFN    PKG_STD.tREF;      -- Функция обмена для загрузки на нешний ресурс
    SHOST            PKG_STD.tSTRING;   -- host
    SPORT            PKG_STD.tSTRING;   -- port
    SUSER            PKG_STD.tSTRING;   -- username
    SPASS            PKG_STD.tSTRING;   -- password
    SPATCH_FSERV     PKG_STD.tSTRING;   -- Путь размещения файла на сервере CSP
  begin
   /* Определим класс оборудования - Спецификации первого уровня «Классы оборудования» */
   begin
     select T.EXSSERVICEFN_UPLOAD
       into NEXSSERVICEFN
       from UDO_T_EQUIPDSCM T
      where T.RN = NEQUIPDSCM;
   exception
     when NO_DATA_FOUND then
       p_exception(0,
                   ' Запись Спецификации первого уровня «Классы оборудования» с RN "s%", не определена.',
                   NEQUIPDSCM);
     when TOO_MANY_ROWS then
       p_exception(0,
                   ' Найдено более одной записи Спецификации первого уровня «Классы оборудования» с RN "s%".',
                   NEQUIPDSCM);
   end;
   UDO_PKG_EQUIPDS_SEND.SCP_DATA_MAKE(NEXSSERVICEFN => NEXSSERVICEFN, 
                                      SHOST         => SHOST, 
                                      SPORT         => SPORT, 
                                      SUSER         => SUSER,
                                      SPASS         => SPASS, 
                                      SPATCH_FSERV  => SPATCH_FSERV);
                                      
   for TEQUIPDSCMFL in(select E.* from UDO_T_EQUIPDSCMFL E, SELECTLIST SL where E.RN = SL.DOCUMENT and SL.IDENT = NIDENT)loop
       /* отправка запроса */
       UDO_PKG_EQUIPDS_SEND.SEND_PACKGE(NEXSSERVICEFN  => NEXSSERVICEFN, 
                                        NLNK_NEXSQUEUE => null, 
                                        NCOMPANY       => NCOMPANY, 
                                        NDOCUMENT      => TEQUIPDSCMFL.RN, 
                                        SUNITCODE      => null, 
                                        SHOST          => SHOST, 
                                        SPORT          => SPORT, 
                                        SUSER          => SUSER, 
                                        SPASS          => SPASS, 
                                        --bAUTH          => true,
                                        SPATCH_LOKAL   => TEQUIPDSCMFL.FILE_NAME, 
                                        NEQUIPDSCMN    => NEQUIPDSCM,
                                        SPATCH_FSERV   => '/'||SPATCH_FSERV||'/'||TEQUIPDSCMFL.FILE_NAME, 
                                        NPRIORITY      => 0, 
                                        BMSG           => TEQUIPDSCMFL.DATASET);
   end loop;
  end UPLOAD;
  
  /* Обеспечивает постановку в очередь обмена сообщения на передачу данных выборки внешней системе */
  procedure SEND_MD
  (
    NCOMPANY         in number,         -- Организация
    NIDENT           in number,         -- Идентификатор Selectlis 
    NEQUIPDSCM       in number          -- регистрационный номер записи Выборки данных класса оборудования»
  )  
  is
    NEXSSERVICEFN    PKG_STD.tREF;      -- Рег. номер функции обработки
    BXML             blob;              -- Тело запроса 
    NDATASET_ID      PKG_STD.tREF;      -- DATASET_ID
  begin
   /* Определим класс оборудования - Спецификации первого уровня «Классы оборудования» */
   begin
     select T.EXSSERVICEFN_SEND_MD
       into NEXSSERVICEFN
       from UDO_T_EQUIPDSCM T
      where T.RN = NEQUIPDSCM;
   exception
     when NO_DATA_FOUND then
       p_exception(0,
                   ' Запись Спецификации первого уровня «Классы оборудования» с RN "s%", не определена.',
                   NEQUIPDSCM);
     when TOO_MANY_ROWS then
       p_exception(0,
                   ' Найдено более одной записи Спецификации первого уровня «Классы оборудования» с RN "s%".',
                   NEQUIPDSCM);
   end;

      /* Формируем тело запроса */
      UDO_PKG_EQUIPDS_SEND.METADATA_MAKE(NIDENT => NIDENT, NEQUIPDSCM => NEQUIPDSCM, NDATASET_ID => NDATASET_ID, BXML => BXML );
  
      /* отправка запроса */
      UDO_PKG_EQUIPDS_SEND.SEND_PACKGE(NEXSSERVICEFN  => NEXSSERVICEFN, 
                                       NLNK_NEXSQUEUE => null, 
                                       NCOMPANY       => NCOMPANY, 
                                       NDOCUMENT      => NDATASET_ID, 
                                       SUNITCODE      => null,
                                       bAUTH          => true, 
                                       NPRIORITY      => 0, 
                                       BMSG           => BXML
                                       );
       
  end SEND_MD;
  
  /* Обеспечивает постановку в очередь обмена сообщения на передачу запроса на обработку данных выборки внешней системе */
  procedure SEND_RQ
  (
    NCOMPANY         in number,         -- Организация
    NEQUIPDSCMML     in number          --  Рег. номер Модели     
  )  
  is
    NEXSSERVICEFN    PKG_STD.tREF;      -- Рег. номер функции обработки
    BXML             blob;              -- Тело запроса 
  begin
   /* Определим класс оборудования - Спецификации первого уровня «Классы оборудования» */
   begin
     select m.EXSSERVICEFN_SEND_RQ
       into NEXSSERVICEFN
       from UDO_T_EQUIPDSCM m, UDO_T_EQUIPDSCMML ml 
      where ml.rn = NEQUIPDSCMML
        and M.RN = ML.PRN;
   exception
     when NO_DATA_FOUND then
       p_exception(0,
                   ' Запись Спецификация второго уровня «Модели» с RN "s%", не определена.',
                   NEQUIPDSCMML);
     when TOO_MANY_ROWS then
       p_exception(0,
                   ' Найдено более одной записи Спецификация второго уровня «Модели» с RN "s%".',
                   NEQUIPDSCMML);
   end;

      /* Формируем тело запроса */
      UDO_PKG_EQUIPDS_SEND.REQUIREMENTS_MAKE(NEQUIPDSCMML => NEQUIPDSCMML, BXML => BXML );
  
      /* отправка запроса */
      UDO_PKG_EQUIPDS_SEND.SEND_PACKGE(NEXSSERVICEFN  => NEXSSERVICEFN, 
                                       NLNK_NEXSQUEUE => null, 
                                       NCOMPANY       => NCOMPANY, 
                                       NDOCUMENT      => NEQUIPDSCMML, 
                                       SUNITCODE      => null, 
                                       bAUTH          => true,
                                       NPRIORITY      => 0, 
                                       BMSG           => BXML
                                       );
       
  end SEND_RQ;


end UDO_PKG_EQUIPDS_DATAPROCESS;
/
