create or replace package UDO_PKG_EQUIPDS_SEND
is
/*
  Описание: Обеспечивает формироание и отправку тела запроса.
  Проект: Интеграция ПП «Парус 8» и «Фреймворка оценки и прогнозирования состояния оборудования»
  Разработчик: ЦИТК-ПАРУС
  Отественный: Селианов А.Е.
  Дата последнего изменения: 24.03.2025
*/
  /* Константы */
  SDEF_SEND_POINT_PRM                     constant PKG_STD.tSTRING := 'EXSService_AppServer';       -- Адрес сервера приложений (сервисы обмена)
  
  /* отправка запроса */
  procedure SEND_PACKGE
  (
    NEXSSERVICEFN    in number,                             -- Рег. номер функции обработки
    NLNK_NEXSQUEUE   in number   default null,              -- Рег.номер сязанной очереди    
    NCOMPANY         in number   := null,                   -- Рег. номер связанной организации
    NDOCUMENT        in number   := null,                   -- Рег. номер связанной записи документа
    SUNITCODE        in varchar2 := null,                   -- Код связанного раздела
    SHOST            in varchar2 := null,                   -- host
    SPORT            in varchar2 := null,                   -- port
    SUSER            in varchar2 := null,                   -- username
    SPASS            in varchar2 := null,                   -- password
    bAUTH            in boolean  := false,                  -- Требуется авторизация
    SPATCH_LOKAL     in varchar2 := null,                   -- Путь размещения файла на локальном сервере 
    NEQUIPDSCMN      in number   := null,                   -- Рег. номер класса оборудования выборки данных
    SPATCH_FSERV     in varchar2 := null,                   -- Путь размещения файла на сервере CSP
    SDESCR           in varchar2 := null,                   -- Описание выборки данных 
    NPRIORITY        in number default 0,                   -- Приоритет (0- поумолчанию; 100- наиысший приоритет)
    BMSG             in blob                                -- Загружаемый XML с данными запроса в СКУД;
  );

  /* Подготока данных для Загрузки файла на SCP */
  procedure SCP_DATA_MAKE
  ( 
    NEXSSERVICEFN    in number,         -- Рег. номер функции обработки
    SHOST            out varchar2,      -- host
    SPORT            out varchar2,      -- port
    SUSER            out varchar2,      -- username
    SPASS            out varchar2,      -- password
    --SPATCH_LOKAL     out varchar2,    -- Путь размещения файла на локальном сервере 
    SPATCH_FSERV     out varchar2       -- Путь размещения файла на сервере CSP
  );

  /* Подготока данных для Загрузки файла на Фреймворк */
  procedure AUTH_DATA_MAKE
  ( 
    NEXSSERVICEFN    in number,         -- Рег. номер функции обработки
    sAUTH            out varchar2       -- Данные авторизции ("Authorization Basic base64(login:pass))
   );

  /* Подготока данных для для передачи внешней системе */
  procedure METADATA_MAKE
  ( 
    NIDENT           in number,         -- Идентификатор Selectlis 
    NEQUIPDSCM       in number,         -- регистрационный номер записи Выборки данных класса оборудования»
    NDATASET_ID      out number,        -- DATASET_ID
    BXML             out blob           -- Тело файла 
  );
  
  /* Подготока данных для передачи Фреймворку запроса на обучение модели */
  procedure REQUIREMENTS_MAKE
  ( 
    NEQUIPDSCMML     in number,         -- регистрационный номер записи Выборки Модели»
    BXML             out blob           -- Тело файла 
  );

end UDO_PKG_EQUIPDS_SEND;
/
create or replace package body UDO_PKG_EQUIPDS_SEND
is
  
  /* Получение  URL для обработки результата */
  function GET_URL_END_POINT
  (
    NEXSSERVICEFN    in varchar2        -- Мнемокод функции сервиса обмена
  )return            varchar2           --  URL для обработки результата
  is
    REXSSERVICEFN    EXSSERVICEFN%rowtype;        -- 
    REXSSERVICE      EXSSERVICE%rowtype;          -- Запись сервиса обмена
    SURL             PKG_STD.tSTRING;             -- Адрес сервера приложений (сервисы обмена)
  begin
      /* Считывание записи функции сервиса обмена */    
      REXSSERVICEFN := GET_EXSSERVICEFN_ID(NFLAG_SMART => 0, NRN => NEXSSERVICEFN);
      /* Считывание записи сервиса обмена */
      REXSSERVICE := GET_EXSSERVICE_ID(NFLAG_SMART => 0, NRN => REXSSERVICEFN.PRN);
      /*Считывание параметра - Адрес сервера приложений (сервисы обмена)*/
      SURL := get_options_str(sCODE => SDEF_SEND_POINT_PRM, nCOMP_VERS => null );
      /* Формирование полного URL END_POINT */
      SURL := SURL||REXSSERVICE.SRV_ROOT||'/'||REXSSERVICEFN.FN_URL;
    return SURL;
  end GET_URL_END_POINT;  
  

  /* отправка запроса */
  procedure SEND_PACKGE
  (
    NEXSSERVICEFN    in number,                             -- Рег. номер функции обработки
    NLNK_NEXSQUEUE   in number   default null,              -- Рег.номер сязанной очереди    
    NCOMPANY         in number   := null,                   -- Рег. номер связанной организации
    NDOCUMENT        in number   := null,                   -- Рег. номер связанной записи документа
    SUNITCODE        in varchar2 := null,                   -- Код связанного раздела
    SHOST            in varchar2 := null,                   -- host
    SPORT            in varchar2 := null,                   -- port
    SUSER            in varchar2 := null,                   -- username
    SPASS            in varchar2 := null,                   -- password
    bAUTH            in boolean  := false,                  -- Требуется авторизация
    SPATCH_LOKAL     in varchar2 := null,                   -- Путь размещения файла на локальном сервере 
    NEQUIPDSCMN      in number   := null,                   -- Рег. номер класса оборудования выборки данных
    SPATCH_FSERV     in varchar2 := null,                   -- Путь размещения файла на сервере CSP
    SDESCR           in varchar2 := null,                   -- Описание выборки данных 
    NPRIORITY        in number default 0,                   -- Приоритет (0- поумолчанию; 100- наиысший приоритет)
    BMSG             in blob                                -- Загружаемый XML с данными запроса в СКУД;
  )
  is
    NQ               PKG_STD.TREF;                         -- Рег. номер очереди обмена
    OPTS             PKG_EXS.TOPTIONS;                     -- Параметры запроса
    HDR_HEADERS      PKG_EXS.TOPTIONS;                     -- Заголоок запроса
    sAUTH            PKG_STD.tLSTRING;                     -- Строка аторизации
  begin  
    
    PKG_EXS.OPTIONS_SET(OPTIONS => OPTS,
                        SCODE   => 'NEXSSERVICEFN',
                        SVALUE  => NEXSSERVICEFN);
  
    if SHOST is not null then
      PKG_EXS.OPTIONS_SET(OPTIONS => OPTS,
                          SCODE   => 'SHOST_SCP',
                          SVALUE  => SHOST);
    end if;
    if SPORT is not null then
      PKG_EXS.OPTIONS_SET(OPTIONS => OPTS,
                          SCODE   => 'SPORT_SCP',
                          SVALUE  => SPORT);
    end if;    
    if SUSER is not null then
      PKG_EXS.OPTIONS_SET(OPTIONS => OPTS,
                          SCODE   => 'SUSER_SCP',
                          SVALUE  => SUSER);
    end if;
    if SPASS is not null then
      PKG_EXS.OPTIONS_SET(OPTIONS => OPTS,
                          SCODE   => 'SPASS_SCP',
                          SVALUE  => SPASS);
    end if;
    if (bAUTH) then
    AUTH_DATA_MAKE(NEXSSERVICEFN => NEXSSERVICEFN, sAUTH => sAUTH);
    if sAUTH is not null then
    /* authorization */
    PKG_EXS.OPTIONS_SET(OPTIONS => HDR_HEADERS,
                        SCODE   => pkg_exs.SHTP_HDR_AUTHORIZATION,
                        SVALUE  => sAUTH);
    
    PKG_EXS.OPTIONS_SET(OPTIONS => HDR_HEADERS,
                        SCODE   => pkg_exs.SHTP_HDR_CNT_TP,
                        SVALUE  => pkg_exs.SHTP_HDR_CNT_TP_JSON);
    end if;
    end if;   
    if SPATCH_LOKAL is not null then
      PKG_EXS.OPTIONS_SET(OPTIONS => OPTS,
                          SCODE   => 'SPATCH_LOCAL',
                          SVALUE  => SPATCH_LOKAL);
    end if;
    if NEQUIPDSCMN is not null then
      PKG_EXS.OPTIONS_SET(OPTIONS => OPTS,
                          SCODE   => 'NEQUIPDSCMN',
                          SVALUE  => NEQUIPDSCMN);      
    end if;
    if SPATCH_FSERV is not null then
      PKG_EXS.OPTIONS_SET(OPTIONS => OPTS,
                          SCODE   => 'SPATCH_FSERV',
                          SVALUE  => SPATCH_FSERV);
    end if;
    if SDESCR is not null then
      PKG_EXS.OPTIONS_SET(OPTIONS => OPTS,
                          SCODE   => 'SDESCR',
                          SVALUE  => SDESCR);     
    end if;
        PKG_EXS.OPTIONS_SET(OPTIONS => OPTS,
                          SCODE   => PKG_EXS.SMSG_OPTION_CODE_SIMPLE,
                          SVALUE  => PKG_EXS.SMSG_OPTION_SIMPLE_FALSE);
    
    /* Формируем параметры запроса */
    PKG_EXS.OPTIONS_SET(OPTIONS => OPTS,
                        SCODE   => pkg_exs.SMSG_OPTION_CODE_HEADERS,
                        SVALUE  => PKG_EXS.OPTIONS_SERIALIZE(OPTIONS => HDR_HEADERS,
                                                             BROOT   => false));
    /* Постанока запроса в очередь */
    PKG_EXS.QUEUE_PUT(NEXSSERVICEFN => NEXSSERVICEFN,
                      BMSG          => BMSG,
                      NEXSQUEUE     => NLNK_NEXSQUEUE,                    
                      NLNK_COMPANY  => nCOMPANY,
                      NLNK_DOCUMENT => NDOCUMENT,
                      SLNK_UNITCODE => SUNITCODE,
                      SOPTIONS      => PKG_EXS.OPTIONS_SERIALIZE(OPTIONS => OPTS),
                      NPRIORITY     => NPRIORITY,
                      NNEW_EXSQUEUE => NQ);
  end SEND_PACKGE;
 
  /* Подготока данных для Загрузки файла на SCP */
  procedure SCP_DATA_MAKE
  ( 
    NEXSSERVICEFN    in number,         -- Рег. номер функции обработки
    SHOST            out varchar2,      -- host
    SPORT            out varchar2,      -- port
    SUSER            out varchar2,      -- username
    SPASS            out varchar2,      -- password
    SPATCH_FSERV     out varchar2       -- Путь размещения файла на сервере CSP
  )
  is
    REXSSERVICEFN    EXSSERVICEFN%rowtype;                  -- 
    REXSSERVICE      EXSSERVICE%rowtype;                    -- Запись сервиса обмена
  begin
    /* Считывание записи функции сервиса обмена */    
    REXSSERVICEFN := GET_EXSSERVICEFN_ID(NFLAG_SMART => 0, NRN => NEXSSERVICEFN);
    /* Считывание записи сервиса обмена */
    REXSSERVICE := GET_EXSSERVICE_ID(NFLAG_SMART => 0, NRN => REXSSERVICEFN.PRN);
    /**/
    SHOST := REGEXP_SUBSTR(REGEXP_SUBSTR(REXSSERVICE.SRV_ROOT,'(.*?)(//|$)', 1,2,NULL,1),'(.*?)(:|$)', 1,1,NULL,1); 
    SPORT := REGEXP_SUBSTR(REGEXP_SUBSTR(REXSSERVICE.SRV_ROOT,'(.*?)(//|$)', 1,2,NULL,1),'(.*?)(:|$)', 1,2,NULL,1);
    /* Считаем параметры пользователя логин и пароль */
    SUSER := REXSSERVICE.SRV_USER;
    SPASS := BLOB2CLOB(lbDATA => BASE64_DECODE(REXSSERVICE.SRV_PASS),sCHARSET => PKG_CHARSET.CHARSET_UTF_);
    /**/
    SPATCH_FSERV := REXSSERVICEFN.FN_URL;
  end SCP_DATA_MAKE; 

  /* Подготока данных для Загрузки файла на Фреймворк */
  procedure AUTH_DATA_MAKE
  ( 
    NEXSSERVICEFN    in number,         -- Рег. номер функции обработки
    sAUTH            out varchar2       -- Данные авторизции ("Authorization Basic base64(login:pass))
   )
  is
    REXSSERVICEFN    EXSSERVICEFN%rowtype;        -- Запись функции сервиса обмена
    REXSSERVICE      EXSSERVICE%rowtype;          -- Запись сервиса обмена
    SUSER            PKG_STD.tSTRING;             -- username
    SPASS            PKG_STD.tSTRING;             -- password
  begin
    /* Считывание записи функции сервиса обмена */    
    REXSSERVICEFN := GET_EXSSERVICEFN_ID(NFLAG_SMART => 0, NRN => NEXSSERVICEFN);
    /* Считывание записи сервиса обмена */
    REXSSERVICE := GET_EXSSERVICE_ID(NFLAG_SMART => 0, NRN => REXSSERVICEFN.PRN);
    /* Считаем параметры пользователя логин и пароль */
    SUSER := REXSSERVICE.SRV_USER;
    SPASS := BLOB2CLOB(lbDATA => BASE64_DECODE(REXSSERVICE.SRV_PASS),sCHARSET => PKG_CHARSET.CHARSET_UTF_);
    /**/
    sAUTH := 'Basic'||' '||BASE64_ENCODE(lbSRCE => CLOB2BLOB(lcDATA => SUSER||':'||SPASS,sCHARSET => PKG_CHARSET.CHARSET_UTF_));
  end AUTH_DATA_MAKE; 
  
  /* Подготока данных для для передачи внешней системе */
  procedure METADATA_MAKE
  ( 
    NIDENT           in number,         -- Идентификатор Selectlis 
    NEQUIPDSCM       in number,         -- регистрационный номер записи Выборки данных класса оборудования»
    NDATASET_ID      out number,        -- DATASET_ID
    BXML             out blob           -- Тело файла 
  )
  is
    SEND_POINT       PKG_STD.tSTRING;             -- URL для обработки результата
    xNODE            PKG_XMAKE.tNODE;             -- Подчиненный узел
    xNODE_FL         PKG_XMAKE.tNODE;             -- Подчиненный узел Имён файлов
    XDOC             integer;                     -- Документ для размещения XML-элемента  
    DATACONFIG       PKG_XMAKE.tNODE;             -- DATACONFIG 
    ATRIBS           PKG_XMAKE.tATTRIBUTES;       -- Атрибуты
    RDOCUMENT        PKG_XPATH.TDOCUMENT;         -- XML документ
    RROOT            PKG_XPATH.TNODE;             -- Корневой узел XML документа
    FIRSTNODE        PKG_XPATH.TNODE;             -- Корневой узел XML документа
    RNODE            PKG_XPATH.TNODE;             --
    RNODES           PKG_XPATH.TNODES;            -- Узлы XML документа
    NCURS_COUNT      PKG_STD.tNUMBER;             -- Количество узлов
    BONLYONE         boolean := true;
  begin
    XDOC := PKG_XMAKE.OPEN_CURSOR();
    for REQUIPDSCM in (select E.CODE SEQOBJKIND, t.* from UDO_T_EQUIPDSCM T, EQOBJKIND E where T.RN = NEQUIPDSCM and T.EQOBJKIND = E.RN)loop
      
      RDOCUMENT   := PKG_XPATH.PARSE_FROM_CLOB(REQUIPDSCM.DATA_CONFIG);
      RROOT       := PKG_XPATH.ROOT_NODE(RDOCUMENT);
      FIRSTNODE   := PKG_XPATH.FIRST_NODE(RROOT);
      RNODES      := PKG_XPATH.LIST_NODES(FIRSTNODE, 'item');
      NCURS_COUNT := PKG_XPATH.COUNT_NODES(RNODES);
      for I in 1 .. NCURS_COUNT loop
        RNODE := PKG_XPATH.ITEM_NODE(RNODES, I);
        ATRIBS := PKG_XMAKE.ATTRIBUTES(iCURSOR => XDOC,
                                       rATTRIBUTE00 => PKG_XMAKE.ATTRIBUTE(iCURSOR => XDOC,sNAME => 'col_name',sVALUE => PKG_XPATH.ATTRIBUTE(RNODE, 'col_code')),
                                       rATTRIBUTE01 => PKG_XMAKE.ATTRIBUTE(iCURSOR => XDOC,sNAME => 'data_type',sVALUE => PKG_XPATH.ATTRIBUTE(RNODE, 'data_type'))
                                      );  
        DATACONFIG := PKG_XMAKE.CONCAT(iCURSOR => XDOC,  
                                       rNODE00 => DATACONFIG,                                       
                                       rNODE01 => PKG_XMAKE.ELEMENT(iCURSOR => XDOC,sNAME => 'data_config',rATTRIBUTES => ATRIBS)
                                       );               
      end loop;  
      PKG_XPATH.FREE(rDOCUMENT => RDOCUMENT); 
      /* Сформируем полный URL */
      SEND_POINT := GET_URL_END_POINT(NEXSSERVICEFN => REQUIPDSCM.EXSSERVICEFN_SEND_MDCB);
      
        /* Перечень файлов */
        for REQUIPDSCMFL in (select FL.* from UDO_T_EQUIPDSCMFL FL, SELECTLIST SL Where FL.RN = SL.DOCUMENT and SL.IDENT = NIDENT)loop
          
          /* Идентификатор dataset */
          if (BONLYONE) then
            xNODE := PKG_XMAKE.ELEMENT(iCURSOR => XDOC,
                                       sNAME   => 'dataset_ID',
                                       rVALUE00 => PKG_XMAKE.VALUE(iCURSOR => XDOC,
                                                                   sVALUE  => REQUIPDSCMFL.DATASET_ID));
            BONLYONE := false;
            NDATASET_ID := REQUIPDSCMFL.DATASET_ID;
          end if;
          xNODE_FL := PKG_XMAKE.CONCAT(iCURSOR => XDOC,
                                       rNODE00 => xNODE_FL,
                                       rNODE01 => PKG_XMAKE.ELEMENT(iCURSOR => XDOC,
                                                                    sNAME   => 'ftp_filepath',
                                                                    rVALUE00 => PKG_XMAKE.VALUE(iCURSOR => XDOC,
                                                                                                sVALUE  => REQUIPDSCMFL.FILE_NAME)));
          
         end loop; 
   
      
      
      
      xNODE := PKG_XMAKE.CONCAT(iCURSOR => XDOC,
                                rNODE00 => xNODE,
                                /* Тип оборудования */
                                rNODE01 => PKG_XMAKE.ELEMENT(iCURSOR => XDOC,
                                                             sNAME   => 'class_machine',
                                                             rVALUE00 => PKG_XMAKE.VALUE(iCURSOR => XDOC,
                                                                                         sVALUE  => TRIM(REQUIPDSCM.SEQOBJKIND))),
                                   
                                rNODE02 => xNODE_FL,
                                /* url для результата отпраки */
                                rNODE03 => PKG_XMAKE.ELEMENT(iCURSOR => XDOC,
                                                             sNAME   => 'end_point',
                                                             rVALUE00 => PKG_XMAKE.VALUE(iCURSOR => XDOC,
                                                                                         sVALUE  => SEND_POINT)),
                                /* Описание полей dataset */
                                rNODE04 => DATACONFIG
                               );

    
    end loop; 
          BXML := PKG_XMAKE.SERIALIZE_TO_BLOB(iCURSOR => XDOC,
                                              iTYPE   => PKG_XMAKE.DOCUMENT_,
                                              rNODE   => PKG_XMAKE.CONCAT(iCURSOR => XDOC,
                                                                          rNODE00 => PKG_XMAKE.ELEMENT(iCURSOR => XDOC,
                                                                                                       sNAME   => 'root',
                                                                                                       rNODE00 => xNODE)),
                                              rHEADER => PKG_XHEADER.WRAP_ALL(PKG_XHEADER.VERSION_1_0_,
                                                                              PKG_XHEADER.ENCODING_UTF_,
                                                                              PKG_XHEADER.STANDALONE_NONE_)
                                              );
    PKG_XMAKE.CLOSE_CURSOR(iCURSOR => XDOC);   
  end METADATA_MAKE;

  /* Подготока данных для передачи Фреймворку запроса на обучение модели */
  procedure REQUIREMENTS_MAKE
  ( 
    NEQUIPDSCMML     in number,         -- регистрационный номер записи Выборки Модели»
    BXML             out blob           -- Тело файла 
  )
  is
    SEND_POINT       PKG_STD.tSTRING;             -- URL для обработки результата
    xNODE            PKG_XMAKE.tNODE;             -- Подчиненный узел
    xNODE_ML         PKG_XMAKE.tNODE;             -- Подчиненный узел обучение модели
    XDOC             integer;                     -- Документ для размещения XML-элемента  
    BONLYONE         boolean := true;
  begin
    /*Старт сборки XML*/
    XDOC := PKG_XMAKE.OPEN_CURSOR();
    /* Перечень файлов */
    for REQUIPDSCMML in (select M.EQOBJKIND,
                                M.EXSSERVICEFN_SEND_RQCB,                                 
                                TRIM(E.CODE) SEQOBJKIND,
                                ML.*
                           from UDO_T_EQUIPDSCMML ML,
                                UDO_T_EQUIPDSCM   M,
                                EQOBJKIND         E
                          Where ML.RN = NEQUIPDSCMML
                            and ML.PRN = M.RN
                            and M.EQOBJKIND = E.RN) loop
      /* Сформируем полный URL */
      if (BONLYONE) then
        SEND_POINT := GET_URL_END_POINT(NEXSSERVICEFN => REQUIPDSCMML.EXSSERVICEFN_SEND_RQCB);
        BONLYONE := false;
      end if;  
    
      /* Ссобирем узел запроса */
      xNODE_ML := PKG_XMAKE.CONCAT(iCURSOR => XDOC,
                                   rNODE00 => PKG_XMAKE.ELEMENT(iCURSOR  => XDOC,
                                                                sNAME    => 'dataset_ID',
                                                                rVALUE00 => PKG_XMAKE.VALUE(iCURSOR => XDOC,
                                                                sVALUE  => REQUIPDSCMML.DATASET_ID)),
                                   rNODE01 => PKG_XMAKE.ELEMENT(iCURSOR  => XDOC,
                                                                sNAME    => 'task',
                                                                rVALUE00 => PKG_XMAKE.VALUE(iCURSOR => XDOC,
                                                                                            sVALUE  => REQUIPDSCMML.TASK)),
                                   rNODE02 => PKG_XMAKE.ELEMENT(iCURSOR  => XDOC,
                                                                sNAME    => 'precision',
                                                                rVALUE00 => PKG_XMAKE.VALUE(iCURSOR => XDOC,
                                                                                            sVALUE  => 100)));

  
    /* Ссобирем узел запроса */
    xNODE := PKG_XMAKE.CONCAT(iCURSOR => XDOC,                            
                              rNODE00 => xNODE_ML,
                              /* Тип оборудования */
                              rNODE01 => PKG_XMAKE.ELEMENT(iCURSOR  => XDOC,
                                                           sNAME    => 'class_machine',
                                                           rVALUE00 => PKG_XMAKE.VALUE(iCURSOR => XDOC,
                                                                                       sVALUE  => REQUIPDSCMML.SEQOBJKIND)),
                              /* url для результата отпраки */
                              rNODE02 => PKG_XMAKE.ELEMENT(iCURSOR  => XDOC,
                                                           sNAME    => 'end_point',
                                                           rVALUE00 => PKG_XMAKE.VALUE(iCURSOR => XDOC,
                                                                                       sVALUE  => SEND_POINT)));
  
  end loop;
  /* Формируем тело запроса */
  BXML := PKG_XMAKE.SERIALIZE_TO_BLOB(iCURSOR => XDOC,
                                      iTYPE   => PKG_XMAKE.DOCUMENT_,
                                      rNODE   => PKG_XMAKE.CONCAT(iCURSOR => XDOC,
                                                                  rNODE00 => PKG_XMAKE.ELEMENT(iCURSOR => XDOC,
                                                                                               sNAME   => 'root',
                                                                                               rNODE00 => xNODE)),
                                      rHEADER => PKG_XHEADER.WRAP_ALL(PKG_XHEADER.VERSION_1_0_,
                                                                      PKG_XHEADER.ENCODING_UTF_,
                                                                      PKG_XHEADER.STANDALONE_NONE_));
  
  PKG_XMAKE.CLOSE_CURSOR(iCURSOR => XDOC);
  end REQUIREMENTS_MAKE;


end UDO_PKG_EQUIPDS_SEND;
/
