diff --git a/db/UDO_PKG_EXS_ALICE.pck b/db/UDO_PKG_EXS_ALICE.pck new file mode 100644 index 0000000..0b7464d --- /dev/null +++ b/db/UDO_PKG_EXS_ALICE.pck @@ -0,0 +1,426 @@ +create or replace package UDO_PKG_EXS_ALICE as + + /* Обработка запроса на поиск контрагента */ + procedure FIND_AGENT + ( + NIDENT in number, -- Идентификатор процесса + NSRV_TYPE in number, -- Тип сервиса (см. константы PKG_EXS.NSRV_TYPE*) + NEXSQUEUE in number -- Регистрационный номер обрабатываемой позиции очереди обмена + ); + + /* Обработка запроса на поиск договора */ + procedure FIND_CONTRACT + ( + NIDENT in number, -- Идентификатор процесса + NSRV_TYPE in number, -- Тип сервиса (см. константы PKG_EXS.NSRV_TYPE*) + NEXSQUEUE in number -- Регистрационный номер обрабатываемой позиции очереди обмена + ); + + /* Обработка запроса на поиск заказа потребителя */ + procedure FIND_CONSUMERORD + ( + NIDENT in number, -- Идентификатор процесса + NSRV_TYPE in number, -- Тип сервиса (см. константы PKG_EXS.NSRV_TYPE*) + NEXSQUEUE in number -- Регистрационный номер обрабатываемой позиции очереди обмена + ); + +end; +/ +create or replace package body UDO_PKG_EXS_ALICE as + + /* Константы - каталог для поиска данных */ + SSEARCH_CATALOG_NAME constant ACATALOG.NAME%type := 'Семинар 20_12_2018'; + + /* Тип данных для коллекции шаблонов вспомогательных слов поиска */ + type THELPER_PATTERNS is table of varchar2(4000); + + /* Проверка на присутствие слова в списке вспомогательных */ + function UTL_HELPER_CHECK + ( + SWORD in varchar2, -- Проверяемое слово + HELPER_PATTERNS in THELPER_PATTERNS -- Коллекция шаблонов вспомогательных слов + ) + return boolean -- Резульата проверки + is + BRES boolean; -- Буфер для результата + begin + /* Инициализируем буфер */ + BRES := false; + /* Если коллекция не пуста */ + if ((HELPER_PATTERNS is not null) and (HELPER_PATTERNS.COUNT > 0)) then + /* Обходим её */ + for I in HELPER_PATTERNS.FIRST .. HELPER_PATTERNS.LAST + loop + /* Если слово есть в коллекции */ + if (LOWER(SWORD) like LOWER(HELPER_PATTERNS(I))) then + /* Выставим флаг присутствия и завершим поиск */ + BRES := true; + exit; + end if; + end loop; + end if; + /* Возвращаем ответ */ + return BRES; + end UTL_HELPER_CHECK; + + /* Инициализация общих вспомогательных поисковых фраз */ + procedure UTL_HELPER_INIT_COMMON + ( + HELPER_PATTERNS in out THELPER_PATTERNS -- Коллекция шаблонов вспомогательных слов + ) + is + begin + /* Создадим пустую коллекцию если надо */ + if (HELPER_PATTERNS is null) then + HELPER_PATTERNS := THELPER_PATTERNS(); + end if; + /* Наполним её общими поисковыми вспомогательными фразами */ + HELPER_PATTERNS.EXTEND(); + HELPER_PATTERNS(HELPER_PATTERNS.LAST) := 'расскажи'; + HELPER_PATTERNS.EXTEND(); + HELPER_PATTERNS(HELPER_PATTERNS.LAST) := 'про'; + HELPER_PATTERNS.EXTEND(); + HELPER_PATTERNS(HELPER_PATTERNS.LAST) := 'о'; + HELPER_PATTERNS.EXTEND(); + HELPER_PATTERNS(HELPER_PATTERNS.LAST) := 'об'; + HELPER_PATTERNS.EXTEND(); + HELPER_PATTERNS(HELPER_PATTERNS.LAST) := 'по'; + HELPER_PATTERNS.EXTEND(); + HELPER_PATTERNS(HELPER_PATTERNS.LAST) := 'сведения'; + HELPER_PATTERNS.EXTEND(); + HELPER_PATTERNS(HELPER_PATTERNS.LAST) := 'информацию'; + HELPER_PATTERNS.EXTEND(); + HELPER_PATTERNS(HELPER_PATTERNS.LAST) := 'информация'; + HELPER_PATTERNS.EXTEND(); + HELPER_PATTERNS(HELPER_PATTERNS.LAST) := 'информации'; + HELPER_PATTERNS.EXTEND(); + HELPER_PATTERNS(HELPER_PATTERNS.LAST) := 'инфы'; + HELPER_PATTERNS.EXTEND(); + HELPER_PATTERNS(HELPER_PATTERNS.LAST) := 'инфу'; + HELPER_PATTERNS.EXTEND(); + HELPER_PATTERNS(HELPER_PATTERNS.LAST) := 'дай'; + HELPER_PATTERNS.EXTEND(); + HELPER_PATTERNS(HELPER_PATTERNS.LAST) := 'нарой'; + HELPER_PATTERNS.EXTEND(); + HELPER_PATTERNS(HELPER_PATTERNS.LAST) := 'запроси'; + HELPER_PATTERNS.EXTEND(); + HELPER_PATTERNS(HELPER_PATTERNS.LAST) := 'найди'; + HELPER_PATTERNS.EXTEND(); + HELPER_PATTERNS(HELPER_PATTERNS.LAST) := 'сообщи'; + HELPER_PATTERNS.EXTEND(); + HELPER_PATTERNS(HELPER_PATTERNS.LAST) := 'поведай'; + HELPER_PATTERNS.EXTEND(); + HELPER_PATTERNS(HELPER_PATTERNS.LAST) := 'мне'; + HELPER_PATTERNS.EXTEND(); + HELPER_PATTERNS(HELPER_PATTERNS.LAST) := 'состояни%'; + HELPER_PATTERNS.EXTEND(); + HELPER_PATTERNS(HELPER_PATTERNS.LAST) := 'статус%'; + HELPER_PATTERNS.EXTEND(); + HELPER_PATTERNS(HELPER_PATTERNS.LAST) := 'как'; + HELPER_PATTERNS.EXTEND(); + HELPER_PATTERNS(HELPER_PATTERNS.LAST) := 'там'; + HELPER_PATTERNS.EXTEND(); + HELPER_PATTERNS(HELPER_PATTERNS.LAST) := 'мой'; + HELPER_PATTERNS.EXTEND(); + HELPER_PATTERNS(HELPER_PATTERNS.LAST) := 'номер%'; + HELPER_PATTERNS.EXTEND(); + HELPER_PATTERNS(HELPER_PATTERNS.LAST) := 'за'; + end UTL_HELPER_INIT_COMMON; + + /* Подготовка поисковой фразы к участию в выборке */ + function UTL_SEARCH_STR_PREPARE + ( + SSEARCH_STR in varchar2, -- Поисковая фраза + SDELIM in varchar2, -- Разделитель слов в поисковой фразе + HELPER_PATTERNS in THELPER_PATTERNS -- Коллекция шаблонов вспомогательных слов + ) + return varchar2 -- Подготовленная поисковая фраза + is + SRES varchar2(32000); -- Результат работы + begin + /* Обходим слова поисковой фразы */ + for W in (select REGEXP_SUBSTR(T.STR, '[^' || SDELIM || ']+', 1, level) SWRD + from (select replace(replace(SSEARCH_STR, ',', ''), '.', '') STR from DUAL) T + connect by INSTR(T.STR, SDELIM, 1, level - 1) > 0) + loop + /* Если слово не в списке вспомогательных */ + if (not UTL_HELPER_CHECK(SWORD => W.SWRD, HELPER_PATTERNS => HELPER_PATTERNS)) then + /* Оставляем его в итоговой выборке */ + SRES := SRES || '%' || W.SWRD; + end if; + end loop; + /* Уберем лишние пробелы и готовим для поиска */ + SRES := '%' || trim(SRES) || '%'; + /* Вернем ответ */ + return SRES; + end UTL_SEARCH_STR_PREPARE; + + /* Обработка запроса на поиск контрагента */ + procedure FIND_AGENT + ( + NIDENT in number, -- Идентификатор процесса + NSRV_TYPE in number, -- Тип сервиса (см. константы PKG_EXS.NSRV_TYPE*) + NEXSQUEUE in number -- Регистрационный номер обрабатываемой позиции очереди обмена + ) + is + HELPER_PATTERNS THELPER_PATTERNS; -- Коллекция шаблонов вспомогательных слов поиска + REXSQUEUE EXSQUEUE%rowtype; -- Запись позиции очереди + CTMP clob; -- Буфер для конвертации + CRESP clob; -- Данные для ответа + RCTMP sys_refcursor; -- Буфер для измененной позиции очереди + begin + /* Считаем запись очереди */ + REXSQUEUE := GET_EXSQUEUE_ID(NFLAG_SMART => 0, NRN => NEXSQUEUE); + /* Инициализируем коллекцию слов-помошников */ + UTL_HELPER_INIT_COMMON(HELPER_PATTERNS => HELPER_PATTERNS); + /* Наполняем её значениями индивидуальными для данного запроса */ + HELPER_PATTERNS.EXTEND(); + HELPER_PATTERNS(HELPER_PATTERNS.LAST) := 'контрагент%'; + /* Забираем данные сообщения и конвертируем в кодировку БД */ + CTMP := BLOB2CLOB(LBDATA => REXSQUEUE.MSG, SCHARSET => 'UTF8'); + /* Кладём конвертированное обратно (просто для удобства мониторинга) */ + PKG_EXS.QUEUE_MSG_SET(NEXSQUEUE => REXSQUEUE.RN, BMSG => CLOB2BLOB(LCDATA => CTMP), RCQUEUE => RCTMP); + /* Если есть что искать */ + if (CTMP is not null) then + /* Подготовим поисковую фразу */ + CTMP := UTL_SEARCH_STR_PREPARE(SSEARCH_STR => CTMP, SDELIM => ' ', HELPER_PATTERNS => HELPER_PATTERNS); + /* Инициализируем ответ */ + CRESP := 'Контрагент не найден'; + /* Ищем запрошенного контрагента */ + for C in (select T.AGNNAME || + DECODE(T.AGNTYPE, 1, ', физическое лицо', ', юридическое лицо') SAGENT, + T.AGNTYPE NAGNTYPE, + (select count(CN.RN) from CONTRACTS CN where CN.AGENT = T.RN) NCNT_CONTRACTS, + (select sum(CN.DOC_SUM) from CONTRACTS CN where CN.AGENT = T.RN) NSUM_CONTRACTS, + T.PHONE SPHONE, + T.MAIL SMAIL, + T.AGN_COMMENT SCONTACT_PERSON, + NVL((select 1 from DUAL where LOWER(T.AGN_COMMENT) like LOWER(CTMP)), 0) NLINKED_SIGN + from AGNLIST T, + ACATALOG CAT + where ((LOWER(T.AGNABBR) like LOWER(CTMP)) or (LOWER(T.AGNNAME) like LOWER(CTMP)) or + (LOWER(T.AGN_COMMENT) like LOWER(CTMP))) + and T.CRN = CAT.RN + and CAT.NAME = SSEARCH_CATALOG_NAME + and ROWNUM <= 1) + loop + /* Основная информация */ + if (C.NLINKED_SIGN = 1) then + CRESP := 'Не является самостоятельным, найден по совпадению в дополнительной информации к контрагенту:' || + CHR(10) || CHR(10) || C.SAGENT; + else + CRESP := C.SAGENT; + end if; + /* Далее - в зависимости от типа, для ЮЛ - сведения о договорах и контактном лице */ + if (C.NAGNTYPE = 0) then + if (C.NCNT_CONTRACTS = 0) then + CRESP := CRESP || ', не имеет зарегистрированных в системе договоров'; + else + CRESP := CRESP || ', зарегистрировано договоров: ' || TO_CHAR(C.NCNT_CONTRACTS); + if (C.NSUM_CONTRACTS <> 0) then + CRESP := CRESP || ', на общую сумму: ' || TO_CHAR(C.NSUM_CONTRACTS) || ' руб.'; + end if; + end if; + if (C.SCONTACT_PERSON is not null) then + CRESP := CRESP || ', контактное лицо: ' || C.SCONTACT_PERSON; + end if; + end if; + /* Контакты контрагента - телефон */ + if (C.SPHONE is not null) then + CRESP := CRESP || ', телефон: ' || C.SPHONE; + end if; + /* Контакты контрагента - e-mail */ + if (C.SMAIL is not null) then + CRESP := CRESP || ', e-mail: ' || C.SMAIL; + end if; + end loop; + else + CRESP := 'Не указан поисковый запрос'; + end if; + /* Возвращаем ответ */ + PKG_EXS.PRC_RESP_ARG_BLOB_SET(NIDENT => NIDENT, + SARG => PKG_EXS.SCONT_FLD_BRESP, + BVALUE => CLOB2BLOB(LCDATA => CRESP, SCHARSET => 'UTF8')); + end FIND_AGENT; + + /* Обработка запроса на поиск договора */ + procedure FIND_CONTRACT + ( + NIDENT in number, -- Идентификатор процесса + NSRV_TYPE in number, -- Тип сервиса (см. константы PKG_EXS.NSRV_TYPE*) + NEXSQUEUE in number -- Регистрационный номер обрабатываемой позиции очереди обмена + ) + is + HELPER_PATTERNS THELPER_PATTERNS; -- Коллекция шаблонов вспомогательных слов поиска + REXSQUEUE EXSQUEUE%rowtype; -- Запись позиции очереди + CTMP clob; -- Буфер для конвертации + CRESP clob; -- Данные для ответа + RCTMP sys_refcursor; -- Буфер для измененной позиции очереди + begin + /* Считаем запись очереди */ + REXSQUEUE := GET_EXSQUEUE_ID(NFLAG_SMART => 0, NRN => NEXSQUEUE); + /* Инициализируем коллекцию слов-помошников */ + UTL_HELPER_INIT_COMMON(HELPER_PATTERNS => HELPER_PATTERNS); + /* Наполняем её значениями индивидуальными для данного запроса */ + HELPER_PATTERNS.EXTEND(); + HELPER_PATTERNS(HELPER_PATTERNS.LAST) := 'договор%'; + /* Забираем данные сообщения и конвертируем в кодировку БД */ + CTMP := BLOB2CLOB(LBDATA => REXSQUEUE.MSG, SCHARSET => 'UTF8'); + /* Кладём конвертированное обратно (просто для удобства мониторинга) */ + PKG_EXS.QUEUE_MSG_SET(NEXSQUEUE => REXSQUEUE.RN, BMSG => CLOB2BLOB(LCDATA => CTMP), RCQUEUE => RCTMP); + /* Если есть что искать */ + if (CTMP is not null) then + /* Подготовим поисковую фразу */ + CTMP := UTL_SEARCH_STR_PREPARE(SSEARCH_STR => CTMP, SDELIM => ' ', HELPER_PATTERNS => HELPER_PATTERNS); + /* Инициализируем ответ */ + CRESP := 'Договор не найден'; + /* Ищем запрошенный договор */ + for C in (select DECODE(T.INOUT_SIGN, 0, 'Входящий', 'Исходящий') || ' договор №' || + NVL(T.EXT_NUMBER, trim(T.DOC_NUMB)) || ' от ' || TO_CHAR(T.DOC_DATE, 'dd.mm.yyyy') || + ' с контрагентом ' || AG.AGNNAME SDOC, + T.SUBJECT SSUBJECT, + T.DOC_SUM NDOC_SUM, + T.DOC_INPAY_SUM NDOC_INPAY_SUM, + T.DOC_OUTPAY_SUM NDOC_OUTPAY_SUM, + T.END_DATE DEND_DATE, + CN.ALTNAME10 SCUR + from CONTRACTS T, + AGNLIST AG, + CURNAMES CN, + ACATALOG CAT + where ((LOWER(T.EXT_NUMBER) like LOWER(CTMP)) or + (LOWER(trim(T.DOC_NUMB)) like LOWER(CTMP))) + and T.AGENT = AG.RN + and T.CURRENCY = CN.RN + and T.CRN = CAT.RN + and CAT.NAME = SSEARCH_CATALOG_NAME + and ROWNUM <= 1) + loop + /* Основные сведения */ + CRESP := C.SDOC; + /* Предмет договора */ + if (C.SSUBJECT is not null) then + CRESP := CRESP || ', предмет договора: ' || C.SSUBJECT; + end if; + /* Сумма договора */ + if (C.NDOC_SUM <> 0) then + CRESP := CRESP || CHR(10) || 'Сумма договора: ' || TO_CHAR(C.NDOC_SUM) || ' ' || C.SCUR; + /* Состояние оплаты для поступления ДС */ + if (C.NDOC_INPAY_SUM <> 0) then + if (C.NDOC_INPAY_SUM = C.NDOC_SUM) then + CRESP := CRESP || ', оплачен закзчиком полностью'; + else + CRESP := CRESP || ', получено от заказчика: ' || TO_CHAR(C.NDOC_INPAY_SUM) || ' ' || C.SCUR; + if (C.NDOC_SUM - C.NDOC_INPAY_SUM > 0) then + CRESP := CRESP || ', остаток к получению: ' || TO_CHAR(C.NDOC_SUM - C.NDOC_INPAY_SUM) || ' ' || C.SCUR; + if (C.DEND_DATE is not null) then + CRESP := CRESP || ', договор истекает ' || TO_CHAR(C.DEND_DATE, 'dd.mm.yyyy'); + end if; + end if; + end if; + end if; + /* Состояние оплаты для выбытия ДС */ + if (C.NDOC_OUTPAY_SUM <> 0) then + if (C.NDOC_OUTPAY_SUM = C.NDOC_SUM) then + CRESP := CRESP || ', полностью оплачен закзчику'; + else + CRESP := CRESP || ', оплачено заказчику ' || TO_CHAR(C.NDOC_OUTPAY_SUM) || ' ' || C.SCUR; + if (C.NDOC_SUM - C.NDOC_OUTPAY_SUM > 0) then + CRESP := CRESP || ', остаток к оплате ' || TO_CHAR(C.NDOC_SUM - C.NDOC_OUTPAY_SUM) || ' ' || C.SCUR; + if (C.DEND_DATE is not null) then + CRESP := CRESP || ', договор истекает ' || TO_CHAR(C.DEND_DATE, 'dd.mm.yyyy'); + end if; + end if; + end if; + end if; + end if; + end loop; + else + CRESP := 'Не указан поисковый запрос'; + end if; + /* Возвращаем ответ */ + PKG_EXS.PRC_RESP_ARG_BLOB_SET(NIDENT => NIDENT, + SARG => PKG_EXS.SCONT_FLD_BRESP, + BVALUE => CLOB2BLOB(LCDATA => CRESP, SCHARSET => 'UTF8')); + end FIND_CONTRACT; + + /* Обработка запроса на поиск заказа потребителя */ + procedure FIND_CONSUMERORD + ( + NIDENT in number, -- Идентификатор процесса + NSRV_TYPE in number, -- Тип сервиса (см. константы PKG_EXS.NSRV_TYPE*) + NEXSQUEUE in number -- Регистрационный номер обрабатываемой позиции очереди обмена + ) + is + HELPER_PATTERNS THELPER_PATTERNS; -- Коллекция шаблонов вспомогательных слов поиска + REXSQUEUE EXSQUEUE%rowtype; -- Запись позиции очереди + NSTATE_PROP PKG_STD.TREF; -- Рег. номер ДС для хранения состояния заказа + CTMP clob; -- Буфер для конвертации + CRESP clob; -- Данные для ответа + RCTMP sys_refcursor; -- Буфер для измененной позиции очереди + begin + /* Считаем запись очереди */ + REXSQUEUE := GET_EXSQUEUE_ID(NFLAG_SMART => 0, NRN => NEXSQUEUE); + /* Инициализируем коллекцию слов-помошников */ + UTL_HELPER_INIT_COMMON(HELPER_PATTERNS => HELPER_PATTERNS); + /* Наполняем её значениями индивидуальными для данного запроса */ + HELPER_PATTERNS.EXTEND(); + HELPER_PATTERNS(HELPER_PATTERNS.LAST) := 'заказ%'; + /* Забираем данные сообщения и конвертируем в кодировку БД */ + CTMP := BLOB2CLOB(LBDATA => REXSQUEUE.MSG, SCHARSET => 'UTF8'); + /* Кладём конвертированное обратно (просто для удобства мониторинга) */ + PKG_EXS.QUEUE_MSG_SET(NEXSQUEUE => REXSQUEUE.RN, BMSG => CLOB2BLOB(LCDATA => CTMP), RCQUEUE => RCTMP); + /* Если есть что искать */ + if (CTMP is not null) then + /* Подготовим поисковую фразу */ + CTMP := UTL_SEARCH_STR_PREPARE(SSEARCH_STR => CTMP, SDELIM => ' ', HELPER_PATTERNS => HELPER_PATTERNS); + /* Инициализируем ответ */ + CRESP := 'Заказ не найден'; + /* Ищем запрошенный заказ */ + for C in (select 'Заказ №' || trim(T.ORD_NUMB) || ' от ' || TO_CHAR(T.ORD_DATE, 'dd.mm.yyyy') SDOC, + T.PSUMWTAX NSUM, + T.RELEASE_DATE DRELEASE_DATE, + (select V.STR_VALUE + from DOCS_PROPS_VALS V, + DOCS_PROPS DP + where V.UNIT_RN = T.RN + and V.DOCS_PROP_RN = DP.RN + and DP.CODE = 'СостояниеЗаказаПотр') SSTATE, + CN.ALTNAME10 SCUR + from CONSUMERORD T, + AGNLIST AG, + CURNAMES CN, + ACATALOG CAT + where (LOWER(trim(T.ORD_NUMB)) like LOWER(CTMP)) + and T.AGENT = AG.RN + and T.CURRENCY = CN.RN + and T.CRN = CAT.RN + and CAT.NAME = SSEARCH_CATALOG_NAME + and ROWNUM <= 1) + loop + /* Основные сведения */ + CRESP := C.SDOC; + /* Состояние */ + if (C.SSTATE is not null) then + CRESP := CRESP || ', находится в состоянии "' || C.SSTATE || '"'; + else + CRESP := CRESP || ', к сожалению не удалось определить состояние заказа, но мы можно сказать что'; + end if; + /* Сумма зазаза */ + if (C.NSUM <> 0) then + CRESP := CRESP || ', сумма заказа составляет ' || TO_CHAR(C.NSUM) || ' ' || C.SCUR; + end if; + /* Плановый срок исполнения */ + CRESP := CRESP || ', плановая дата исполнения заказа ' || TO_CHAR(C.DRELEASE_DATE, 'dd.mm.yyyy'); + end loop; + else + CRESP := 'Не указан поисковый запрос'; + end if; + /* Возвращаем ответ */ + PKG_EXS.PRC_RESP_ARG_BLOB_SET(NIDENT => NIDENT, + SARG => PKG_EXS.SCONT_FLD_BRESP, + BVALUE => CLOB2BLOB(LCDATA => CRESP, SCHARSET => 'UTF8')); + end FIND_CONSUMERORD; + +end; +/ diff --git a/db/UDO_PKG_EXS_INV.pck b/db/UDO_PKG_EXS_INV.pck new file mode 100644 index 0000000..b7cf4d1 --- /dev/null +++ b/db/UDO_PKG_EXS_INV.pck @@ -0,0 +1,293 @@ +create or replace package UDO_PKG_EXS_INV as + + /* Электронная инвентаризация - аутентификация */ + procedure CHECKAUTH + ( + NIDENT in number, -- Идентификатор процесса + NSRV_TYPE in number, -- Тип сервиса (см. константы PKG_EXS.NSRV_TYPE*) + NEXSQUEUE in number -- Регистрационный номер обрабатываемой позиции очереди обмена + ); + + /* Электронная инвентаризация - считывание пользователей */ + procedure GETUSERS + ( + NIDENT in number, -- Идентификатор процесса + NSRV_TYPE in number, -- Тип сервиса (см. константы PKG_EXS.NSRV_TYPE*) + NEXSQUEUE in number -- Регистрационный номер обрабатываемой позиции очереди обмена + ); + +end; +/ +create or replace package body UDO_PKG_EXS_INV as + + /* Константы - тэги */ + STSD constant varchar2(20) := 'tsd'; + SCHECKAUTHRESPONSE constant varchar2(20) := 'CheckAuthResponse'; + SGETUSERSRESPONSE constant varchar2(20) := 'GetUsersResponse'; + SDEVICEID constant varchar2(20) := 'DeviceID'; + SRESULT constant varchar2(20) := 'Result'; + SSOAPENV constant varchar2(20) := 'soapenv'; + SENVELOPE constant varchar2(20) := 'Envelope'; + SHEADER constant varchar2(20) := 'Header'; + SBODY constant varchar2(20) := 'Body'; + SITEM constant varchar2(20) := 'Item'; + SCODE constant varchar2(20) := 'Code'; + SNAME constant varchar2(20) := 'Name'; + + /* Создание ветки XML */ + function UTL_CREATENODE + ( + XDOC in DBMS_XMLDOM.DOMDOCUMENT, -- Документ + STAG in varchar2, -- Наименование тэга + SNS in varchar2 default null, -- Пространство имён + SVAL in varchar2 default null -- Значение тэга + ) + return DBMS_XMLDOM.DOMNODE -- Ссылка на сформированный тэг документа + is + XEL DBMS_XMLDOM.DOMELEMENT; -- Элемент пространства имён + XNODE DBMS_XMLDOM.DOMNODE; -- Формируемая ветка + XTEXT DBMS_XMLDOM.DOMNODE; -- Текст (значение) формируемой ветки + begin + /* Если задано пространство имён */ + if (SNS is not null) then + /* Создаём элемент с его использованием */ + XEL := DBMS_XMLDOM.CREATEELEMENT(DOC => XDOC, TAGNAME => STAG, NS => SNS); + XNODE := DBMS_XMLDOM.MAKENODE(ELEM => XEL); + DBMS_XMLDOM.SETPREFIX(N => XNODE, PREFIX => SNS); + else + /* Или без него */ + XEL := DBMS_XMLDOM.CREATEELEMENT(DOC => XDOC, TAGNAME => STAG); + XNODE := DBMS_XMLDOM.MAKENODE(ELEM => XEL); + end if; + /* Значение размещаем в текстовой части ветки */ + if (SVAL is not null) then + XTEXT := DBMS_XMLDOM.APPENDCHILD(N => XNODE, + NEWCHILD => DBMS_XMLDOM.MAKENODE(T => DBMS_XMLDOM.CREATETEXTNODE(DOC => XDOC, + DATA => SVAL))); + end if; + /* Вернем результат */ + return XNODE; + end UTL_CREATENODE; + + /* Считывание значения ветки XML */ + function UTL_GETNODEVAL + ( + XROOTNODE in DBMS_XMLDOM.DOMNODE, -- Корневая ветка для считывания значения + SPATTERN in varchar2 -- Шаблон для считывания данных + ) + return varchar2 -- Считанное значение + is + XNODE DBMS_XMLDOM.DOMNODE; -- Искомая ветка со значением (подходящая под шаблон) + SVAL PKG_STD.TSTRING; -- Результат работы + begin + /* Найдем нужную ветку по шаблону */ + XNODE := DBMS_XSLPROCESSOR.SELECTSINGLENODE(N => XROOTNODE, PATTERN => SPATTERN); + /* Если там нет ничего */ + if (DBMS_XMLDOM.ISNULL(N => XNODE)) then + /* Его и вернём */ + return null; + end if; + /* Что-то есть - читаем данные */ + SVAL := DBMS_XMLDOM.GETNODEVALUE(DBMS_XMLDOM.GETFIRSTCHILD(N => XNODE)); + /* Отдаём результат */ + return SVAL; + end UTL_GETNODEVAL; + + /* Создание документа для ответа */ + procedure UTL_CREATERESPONSEDOC + ( + XDOC out DBMS_XMLDOM.DOMDOCUMENT -- Буфер для документа + ) + is + begin + /* Создаём новый документ */ + XDOC := DBMS_XMLDOM.NEWDOMDOCUMENT(); + /* Выставляем параметры заголовка */ + DBMS_XMLDOM.SETVERSION(DOC => XDOC, VERSION => '1.0" encoding="UTF-8'); + /* Выставляем кодировку */ + DBMS_XMLDOM.SETCHARSET(DOC => XDOC, CHARSET => 'UTF-8'); + end UTL_CREATERESPONSEDOC; + + /* Формировние ответа на запрос из XML-документа (обёртывание в конверт подготовленных данных) */ + function UTL_CREATERESPONSE + ( + XDOC in DBMS_XMLDOM.DOMDOCUMENT, -- Документ + XCONTENT in DBMS_XMLDOM.DOMNODE -- Наименование тэга с отправляемым контентом + ) return clob -- Результат работы + is + XMAIN_NODE DBMS_XMLDOM.DOMNODE; + XENVELOPE_EL DBMS_XMLDOM.DOMELEMENT; + XENVELOPE DBMS_XMLDOM.DOMNODE; + XHEADER DBMS_XMLDOM.DOMNODE; + XBODY DBMS_XMLDOM.DOMNODE; + XNODE DBMS_XMLDOM.DOMNODE; + CDATA clob; -- Буфер для результата + begin + /* Подготовим документ */ + XMAIN_NODE := DBMS_XMLDOM.MAKENODE(DOC => XDOC); + /* Обернём его в конверт */ + XENVELOPE_EL := DBMS_XMLDOM.CREATEELEMENT(DOC => XDOC, TAGNAME => SENVELOPE, NS => SSOAPENV); + DBMS_XMLDOM.SETATTRIBUTE(ELEM => XENVELOPE_EL, + name => 'xmlns:soapenv', + NEWVALUE => 'http://schemas.xmlsoap.org/soap/envelope/'); + DBMS_XMLDOM.SETATTRIBUTE(ELEM => XENVELOPE_EL, + name => 'xmlns:tsd', + NEWVALUE => 'http://www.example.org/TSDService/'); + XENVELOPE := DBMS_XMLDOM.MAKENODE(ELEM => XENVELOPE_EL); + DBMS_XMLDOM.SETPREFIX(N => XENVELOPE, PREFIX => SSOAPENV); + XENVELOPE := DBMS_XMLDOM.APPENDCHILD(N => XMAIN_NODE, NEWCHILD => XENVELOPE); + /* Сформируем заголовок */ + XHEADER := UTL_CREATENODE(XDOC => XDOC, STAG => SHEADER, SNS => SSOAPENV); + XHEADER := DBMS_XMLDOM.APPENDCHILD(N => XENVELOPE, NEWCHILD => XHEADER); + /* Сформируем тело */ + XBODY := UTL_CREATENODE(XDOC => XDOC, STAG => SBODY, SNS => SSOAPENV); + XBODY := DBMS_XMLDOM.APPENDCHILD(N => XENVELOPE, NEWCHILD => XBODY); + XNODE := DBMS_XMLDOM.APPENDCHILD(N => XBODY, NEWCHILD => XCONTENT); + /* Конвертируем в CLOB */ + DBMS_LOB.CREATETEMPORARY(LOB_LOC => CDATA, CACHE => true, DUR => DBMS_LOB.SESSION); + DBMS_XMLDOM.WRITETOCLOB(DOC => XDOC, CL => CDATA, CHARSET => 'UTF-8'); + DBMS_XMLDOM.FREEDOCUMENT(DOC => XDOC); + /* Вернем результат */ + return CDATA; + end UTL_CREATERESPONSE; + + /* Электронная инвентаризация - аутентификация */ + procedure CHECKAUTH + ( + NIDENT in number, -- Идентификатор процесса + NSRV_TYPE in number, -- Тип сервиса (см. константы PKG_EXS.NSRV_TYPE*) + NEXSQUEUE in number -- Регистрационный номер обрабатываемой позиции очереди обмена + ) + is + REXSQUEUE EXSQUEUE%rowtype; -- Запись позиции очереди + XCHECKAUTHRESPONSE DBMS_XMLDOM.DOMNODE; -- Корневой элемент ответа + XRESULT DBMS_XMLDOM.DOMNODE; -- Результат аутентификации + XNODE DBMS_XMLDOM.DOMNODE; -- Буфер для ветки ответа + XDOC DBMS_XMLDOM.DOMDOCUMENT; -- Документ + XMLPARCER DBMS_XMLPARSER.PARSER; -- Парсер + XENVELOPE DBMS_XMLDOM.DOMNODE; -- Конверт + XBODY DBMS_XMLDOM.DOMNODE; -- Тело документа + XNODELIST DBMS_XMLDOM.DOMNODELIST; -- Ветки тела документа + XNODE_ROOT DBMS_XMLDOM.DOMNODE; -- Корневой элемент первой ветки тела документа + CRESPONSE clob; -- Буфер для ответа + CREQ clob; -- Буфер для запроса + SREQDEVICEID varchar2(30); -- Идентификатор устройства из запроса + begin + /* Считаем запись очереди */ + REXSQUEUE := GET_EXSQUEUE_ID(NFLAG_SMART => 0, NRN => NEXSQUEUE); + /* Возьмем текст запроса */ + CREQ := BLOB2CLOB(LBDATA => REXSQUEUE.MSG); + /* Создаем инстанс XML парсера */ + XMLPARCER := DBMS_XMLPARSER.NEWPARSER; + /* Разбираем XML из запроса */ + DBMS_XMLPARSER.PARSECLOB(P => XMLPARCER, DOC => CREQ); + /* Берем XML документ из разобранного */ + XDOC := DBMS_XMLPARSER.GETDOCUMENT(P => XMLPARCER); + /* Считываем корневой элемент */ + XENVELOPE := DBMS_XMLDOM.MAKENODE(ELEM => DBMS_XMLDOM.GETDOCUMENTELEMENT(DOC => XDOC)); + /* Считываем элемент тело */ + XBODY := DBMS_XSLPROCESSOR.SELECTSINGLENODE(N => XENVELOPE, PATTERN => SBODY); + /* Считываем дочерние элементы тела */ + XNODELIST := DBMS_XMLDOM.GETCHILDNODES(N => XBODY); + /* Берем первый дочерний элемент */ + XNODE_ROOT := DBMS_XMLDOM.ITEM(NL => XNODELIST, IDX => 0); + /* Считываем идентификатор устройства */ + SREQDEVICEID := UTL_GETNODEVAL(XROOTNODE => XNODE_ROOT, SPATTERN => SDEVICEID); + /* Контроль индетификатора устройства по лицензии */ + /* UTL_CHECK_DEVICEID(SDEVICEID => SREQDEVICEID); */ + /* Подготавливаем документ для ответа */ + UTL_CREATERESPONSEDOC(XDOC => XDOC); + /* Вместо проверки по лицензии - пока просто проверка на то, что идентификатор устройства был передан */ + if (SREQDEVICEID is not null) then + /* Т.к. пока проверок нет никаких - всегда возвращаем положительный ответ */ + XCHECKAUTHRESPONSE := UTL_CREATENODE(XDOC => XDOC, STAG => SCHECKAUTHRESPONSE, SNS => STSD); + XRESULT := UTL_CREATENODE(XDOC => XDOC, STAG => SRESULT, SNS => STSD, SVAL => 'true'); + XNODE := DBMS_XMLDOM.APPENDCHILD(N => XCHECKAUTHRESPONSE, NEWCHILD => XRESULT); + /* Оборачиваем его в конверт */ + CRESPONSE := UTL_CREATERESPONSE(XDOC => XDOC, XCONTENT => XCHECKAUTHRESPONSE); + end if; + /* Возвращаем ответ */ + PKG_EXS.PRC_RESP_ARG_BLOB_SET(NIDENT => NIDENT, + SARG => PKG_EXS.SCONT_FLD_BRESP, + BVALUE => CLOB2BLOB(LCDATA => CRESPONSE)); + end CHECKAUTH; + + /* Электронная инвентаризация - считывание пользователей */ + procedure GETUSERS + ( + NIDENT in number, -- Идентификатор процесса + NSRV_TYPE in number, -- Тип сервиса (см. константы PKG_EXS.NSRV_TYPE*) + NEXSQUEUE in number -- Регистрационный номер обрабатываемой позиции очереди обмена + ) + is + REXSQUEUE EXSQUEUE%rowtype; -- Запись позиции очереди + XGETUSERSRESPONSE DBMS_XMLDOM.DOMNODE; -- Корневой элемент ответа + XNODE DBMS_XMLDOM.DOMNODE; -- Буфер для ветки ответа + XITEM DBMS_XMLDOM.DOMNODE; -- Элемент ответного списка + XCODE DBMS_XMLDOM.DOMNODE; -- Код элемента ответного списка + XNAME DBMS_XMLDOM.DOMNODE; -- Нименование элемента ответного списка + XDOC DBMS_XMLDOM.DOMDOCUMENT; -- Документ + XMLPARCER DBMS_XMLPARSER.PARSER; -- Парсер + XENVELOPE DBMS_XMLDOM.DOMNODE; -- Конверт + XBODY DBMS_XMLDOM.DOMNODE; -- Тело документа + XNODELIST DBMS_XMLDOM.DOMNODELIST; -- Ветки тела документа + XNODE_ROOT DBMS_XMLDOM.DOMNODE; -- Корневой элемент первой ветки тела документа + CRESPONSE clob; -- Буфер для ответа + CREQ clob; -- Буфер для запроса + SREQDEVICEID varchar2(30); -- Идентификатор устройства из запроса + begin + /* Считаем запись очереди */ + REXSQUEUE := GET_EXSQUEUE_ID(NFLAG_SMART => 0, NRN => NEXSQUEUE); + /* Возьмем текст запроса */ + CREQ := BLOB2CLOB(LBDATA => REXSQUEUE.MSG); + /* Создаем инстанс XML парсера */ + XMLPARCER := DBMS_XMLPARSER.NEWPARSER; + /* Разбираем XML из запроса */ + DBMS_XMLPARSER.PARSECLOB(P => XMLPARCER, DOC => CREQ); + /* Берем XML документ из разобранного */ + XDOC := DBMS_XMLPARSER.GETDOCUMENT(P => XMLPARCER); + /* Считываем корневой элемент */ + XENVELOPE := DBMS_XMLDOM.MAKENODE(ELEM => DBMS_XMLDOM.GETDOCUMENTELEMENT(DOC => XDOC)); + /* Считываем элемент тело */ + XBODY := DBMS_XSLPROCESSOR.SELECTSINGLENODE(N => XENVELOPE, PATTERN => SBODY); + /* Считываем дочерние элементы тела */ + XNODELIST := DBMS_XMLDOM.GETCHILDNODES(N => XBODY); + /* Берем первый дочерний элемент */ + XNODE_ROOT := DBMS_XMLDOM.ITEM(NL => XNODELIST, IDX => 0); + /* Считываем идентификатор устройства */ + SREQDEVICEID := UTL_GETNODEVAL(XROOTNODE => XNODE_ROOT, SPATTERN => SDEVICEID); + /* Контроль индетификатора устройства по лицензии */ + /* UTL_CHECK_DEVICEID(SDEVICEID => SREQDEVICEID); */ + /* Подготавливаем документ для ответа */ + UTL_CREATERESPONSEDOC(XDOC => XDOC); + /* Вместо проверки по лицензии - пока просто проверка на то, что идентификатор устройства был передан */ + if (SREQDEVICEID is not null) then + /* Создаём пространство имён для ответа */ + XGETUSERSRESPONSE := UTL_CREATENODE(XDOC => XDOC, STAG => SGETUSERSRESPONSE, SNS => STSD); + /* Обходим сотрудников-инвентаризаторов */ + for REC in (select T.RN, + A.AGNABBR + from INVPERSONS T, + AGNLIST A + where T.COMPANY = 136018 + and T.AGNLIST = A.RN) + loop + /* Собираем информацию по сотруднику в ответ */ + XITEM := UTL_CREATENODE(XDOC => XDOC, STAG => SITEM, SNS => STSD); + XCODE := UTL_CREATENODE(XDOC => XDOC, STAG => SCODE, SNS => STSD, SVAL => REC.RN); + XNAME := UTL_CREATENODE(XDOC => XDOC, STAG => SNAME, SNS => STSD, SVAL => REC.AGNABBR); + XNODE := DBMS_XMLDOM.APPENDCHILD(N => XITEM, NEWCHILD => XCODE); + XNODE := DBMS_XMLDOM.APPENDCHILD(N => XITEM, NEWCHILD => XNAME); + XNODE := DBMS_XMLDOM.APPENDCHILD(N => XGETUSERSRESPONSE, NEWCHILD => XITEM); + end loop; + /* Оборачиваем ответ в конверт */ + CRESPONSE := UTL_CREATERESPONSE(XDOC => XDOC, XCONTENT => XGETUSERSRESPONSE); + end if; + /* Возвращаем ответ */ + PKG_EXS.PRC_RESP_ARG_BLOB_SET(NIDENT => NIDENT, + SARG => PKG_EXS.SCONT_FLD_BRESP, + BVALUE => CLOB2BLOB(LCDATA => CRESPONSE, SCHARSET => 'UTF8')); + end GETUSERS; + +end; +/ diff --git a/db/UDO_PKG_EXS_TEST.pck b/db/UDO_PKG_EXS_TEST.pck index 8993bb4..931084a 100644 --- a/db/UDO_PKG_EXS_TEST.pck +++ b/db/UDO_PKG_EXS_TEST.pck @@ -1,249 +1,34 @@ create or replace package UDO_PKG_EXS_TEST as - /* Запросить контрагента */ - procedure RECIVE_AGENT + /* Обработка запроса на создание сессии */ + procedure UTL_LOGIN ( + NIDENT in number, -- Идентификатор процесса + NSRV_TYPE in number, -- Тип сервиса (см. константы PKG_EXS.NSRV_TYPE*) + NEXSQUEUE in number -- Регистрационный номер обрабатываемой позиции очереди обмена + ); + + /* Запросить контрагента */ + procedure AGENT_GET_INFO + ( + NCOMPANY in number, -- Рег. номер организации NREMOTE_AGENT in number -- Рег. номер контрагента в удалённой БД ); /* Обработка ответа с информацией о контрагенте от тестового стенда */ - procedure PROCESS_AGN_INFO_RESP + procedure AGENT_PROCESS_INFO ( NIDENT in number, -- Идентификатор процесса NSRV_TYPE in number, -- Тип сервиса (см. константы PKG_EXS.NSRV_TYPE*) NEXSQUEUE in number -- Регистрационный номер обрабатываемой позиции очереди обмена ); - /* Обработка запроса на создание сессии */ - procedure RESP_LOGIN - ( - NIDENT in number, -- Идентификатор процесса - NSRV_TYPE in number, -- Тип сервиса (см. константы PKG_EXS.NSRV_TYPE*) - NEXSQUEUE in number -- Регистрационный номер обрабатываемой позиции очереди обмена - ); - - /* Обработка запроса на поиск контрагента */ - procedure RESP_FIND_AGENT - ( - NIDENT in number, -- Идентификатор процесса - NSRV_TYPE in number, -- Тип сервиса (см. константы PKG_EXS.NSRV_TYPE*) - NEXSQUEUE in number -- Регистрационный номер обрабатываемой позиции очереди обмена - ); - - /* Обработка запроса на поиск договора */ - procedure RESP_FIND_CONTRACT - ( - NIDENT in number, -- Идентификатор процесса - NSRV_TYPE in number, -- Тип сервиса (см. константы PKG_EXS.NSRV_TYPE*) - NEXSQUEUE in number -- Регистрационный номер обрабатываемой позиции очереди обмена - ); - - /* Электронная инвентаризация - аутентификация */ - procedure INV_CHECKAUTH_XML - ( - NIDENT in number, -- Идентификатор процесса - NSRV_TYPE in number, -- Тип сервиса (см. константы PKG_EXS.NSRV_TYPE*) - NEXSQUEUE in number -- Регистрационный номер обрабатываемой позиции очереди обмена - ); - - /* Электронная инвентаризация - считывание пользователей */ - procedure INV_GETUSERS_XML - ( - NIDENT in number, -- Идентификатор процесса - NSRV_TYPE in number, -- Тип сервиса (см. константы PKG_EXS.NSRV_TYPE*) - NEXSQUEUE in number -- Регистрационный номер обрабатываемой позиции очереди обмена - ); - end; / create or replace package body UDO_PKG_EXS_TEST as - /* Тип данных для коллекции шаблонов вспомогательных слов поиска */ - type THELPER_PATTERNS is table of varchar2(4000); - - /* Проверка на присутствие слова в списке вспомогательных */ - function UTL_HELPER_CHECK - ( - SWORD in varchar2, -- Проверяемое слово - HELPER_PATTERNS in THELPER_PATTERNS -- Коллекция шаблонов вспомогательных слов - ) - return boolean -- Резульата проверки - is - BRES boolean; -- Буфер для результата - begin - /* Инициализируем буфер */ - BRES := false; - /* Если коллекция не пуста */ - if ((HELPER_PATTERNS is not null) and (HELPER_PATTERNS.COUNT > 0)) then - /* Обходим её */ - for I in HELPER_PATTERNS.FIRST .. HELPER_PATTERNS.LAST - loop - /* Если слово есть в коллекции */ - if (LOWER(SWORD) like LOWER(HELPER_PATTERNS(I))) then - /* Выставим флаг присутствия и завершим поиск */ - BRES := true; - exit; - end if; - end loop; - end if; - /* Возвращаем ответ */ - return BRES; - end UTL_HELPER_CHECK; - - /* Инициализация общих вспомогательных поисковых фраз */ - procedure UTL_HELPER_INIT_COMMON - ( - HELPER_PATTERNS in out THELPER_PATTERNS -- Коллекция шаблонов вспомогательных слов - ) - is - begin - /* Создадим пустую коллекцию если надо */ - if (HELPER_PATTERNS is null) then - HELPER_PATTERNS := THELPER_PATTERNS(); - end if; - /* Наполним её общими поисковыми вспомогательными фразами */ - HELPER_PATTERNS.EXTEND(); - HELPER_PATTERNS(HELPER_PATTERNS.LAST) := 'расскажи'; - HELPER_PATTERNS.EXTEND(); - HELPER_PATTERNS(HELPER_PATTERNS.LAST) := 'про'; - HELPER_PATTERNS.EXTEND(); - HELPER_PATTERNS(HELPER_PATTERNS.LAST) := 'о'; - HELPER_PATTERNS.EXTEND(); - HELPER_PATTERNS(HELPER_PATTERNS.LAST) := 'об'; - HELPER_PATTERNS.EXTEND(); - HELPER_PATTERNS(HELPER_PATTERNS.LAST) := 'по'; - HELPER_PATTERNS.EXTEND(); - HELPER_PATTERNS(HELPER_PATTERNS.LAST) := 'сведения'; - HELPER_PATTERNS.EXTEND(); - HELPER_PATTERNS(HELPER_PATTERNS.LAST) := 'информацию'; - HELPER_PATTERNS.EXTEND(); - HELPER_PATTERNS(HELPER_PATTERNS.LAST) := 'информация'; - HELPER_PATTERNS.EXTEND(); - HELPER_PATTERNS(HELPER_PATTERNS.LAST) := 'информации'; - HELPER_PATTERNS.EXTEND(); - HELPER_PATTERNS(HELPER_PATTERNS.LAST) := 'инфы'; - HELPER_PATTERNS.EXTEND(); - HELPER_PATTERNS(HELPER_PATTERNS.LAST) := 'инфу'; - HELPER_PATTERNS.EXTEND(); - HELPER_PATTERNS(HELPER_PATTERNS.LAST) := 'дай'; - HELPER_PATTERNS.EXTEND(); - HELPER_PATTERNS(HELPER_PATTERNS.LAST) := 'нарой'; - HELPER_PATTERNS.EXTEND(); - HELPER_PATTERNS(HELPER_PATTERNS.LAST) := 'запроси'; - HELPER_PATTERNS.EXTEND(); - HELPER_PATTERNS(HELPER_PATTERNS.LAST) := 'найди'; - end UTL_HELPER_INIT_COMMON; - - /* Подготовка поисковой фразы к участию в выборке */ - function UTL_SEARCH_STR_PREPARE - ( - SSEARCH_STR in varchar2, -- Поисковая фраза - SDELIM in varchar2, -- Разделитель слов в поисковой фразе - HELPER_PATTERNS in THELPER_PATTERNS -- Коллекция шаблонов вспомогательных слов - ) - return varchar2 -- Подготовленная поисковая фраза - is - SRES varchar2(32000); -- Результат работы - begin - /* Обходим слова поисковой фразы */ - for W in (select REGEXP_SUBSTR(T.STR, '[^' || SDELIM || ']+', 1, level) SWRD - from (select replace(replace(SSEARCH_STR, ',', ''), '.', '') STR from DUAL) T - connect by INSTR(T.STR, SDELIM, 1, level - 1) > 0) - loop - /* Если слово не в списке вспомогательных */ - if (not UTL_HELPER_CHECK(SWORD => W.SWRD, HELPER_PATTERNS => HELPER_PATTERNS)) then - /* Оставляем его в итоговой выборке */ - SRES := SRES || '%' || W.SWRD; - end if; - end loop; - /* Уберем лишние пробелы и готовим для поиска */ - SRES := '%' || trim(SRES) || '%'; - /* Вернем ответ */ - return SRES; - end UTL_SEARCH_STR_PREPARE; - - /* Запросить контрагента */ - procedure RECIVE_AGENT - ( - NREMOTE_AGENT in number -- Рег. номер контрагента в удалённой БД - ) - is - SEXSSERVICEFN EXSSERVICEFN.CODE%type; -- Мнемокод функции сервиса - NEXSSERVICEFN EXSSERVICEFN.RN%type; -- Рег. номер функции сервиса - RCTMP sys_refcursor; -- Буфер для измененной позиции очереди - begin - /* Инициализируем мнемокод функции сервиса */ - SEXSSERVICEFN := 'ПолучениеКонтрагента'; - /* Найдем рег. номер функции сервиса */ - FIND_EXSSERVICEFN_CODE(NFLAG_SMART => 0, NFLAG_OPTION => 0, SCODE => SEXSSERVICEFN, NRN => NEXSSERVICEFN); - /* Поместим задание в очередь */ - PKG_EXS.QUEUE_PUT(NEXSSERVICEFN => NEXSSERVICEFN, - BMSG => CLOB2BLOB(LCDATA => 'CPRMS={SACTION:"GET_AGENT",NAGENT:' || TO_CHAR(NREMOTE_AGENT) || '}'), - RCQUEUE => RCTMP); - end RECIVE_AGENT; - - /* Обработка ответа с информацией о контрагенте от тестового стенда */ - procedure PROCESS_AGN_INFO_RESP - ( - NIDENT in number, -- Идентификатор процесса - NSRV_TYPE in number, -- Тип сервиса (см. константы PKG_EXS.NSRV_TYPE*) - NEXSQUEUE in number -- Регистрационный номер обрабатываемой позиции очереди обмена - ) - is - REXSQUEUE EXSQUEUE%rowtype; -- Запись позиции очереди - CTMP clob; -- Буфер для конвертации - RCTMP sys_refcursor; -- Буфер для измененной позиции очереди - NCOMPANY PKG_STD.TREF; -- Рег. номер организации - NCRN PKG_STD.TREF; -- Рег. номер каталога - SAGNABBR AGNLIST.AGNABBR%type; -- Мнемокод контрагента - SAGNNAME AGNLIST.AGNNAME%type; -- Наименование контрагента - NAGENT AGNLIST.RN%type; -- Рег. номер добавленного контрагента - begin - /* Инициализируем организацию */ - NCOMPANY := 136018; - /* Считаем запись очереди */ - REXSQUEUE := GET_EXSQUEUE_ID(NFLAG_SMART => 0, NRN => NEXSQUEUE); - /* Конвертируем в кодировку БД */ - CTMP := BLOB2CLOB(LBDATA => REXSQUEUE.RESP, SCHARSET => 'UTF8'); - /* Кладём конвертированное обратно (просто для удобства мониторинга) */ - PKG_EXS.QUEUE_MSG_SET(NEXSQUEUE => REXSQUEUE.RN, BMSG => CLOB2BLOB(LCDATA => CTMP), RCQUEUE => RCTMP); - /* Разбираем ответ сервера */ - if (CTMP is not null) then - select EXTRACTVALUE(XMLTYPE(CTMP), '/AGENT/SAGNABBR') SAGNABBR, - EXTRACTVALUE(XMLTYPE(CTMP), '/AGENT/SAGNNAME') SAGNNAME - into SAGNABBR, - SAGNNAME - from DUAL; - else - P_EXCEPTION(0, 'Не указаны данные для добавления контрагента.'); - end if; - if (SAGNABBR is null) then - P_EXCEPTION(0, 'В ответе сервера не указан мнемокод контрагента.'); - end if; - if (SAGNNAME is null) then - P_EXCEPTION(0, - 'В ответе сервера не указано наименование контрагента.'); - end if; - /* Найдём каталог */ - FIND_ACATALOG_NAME(NFLAG_SMART => 0, - NCOMPANY => NCOMPANY, - NVERSION => null, - SUNITCODE => 'AGNLIST', - SNAME => 'ExchangeService', - NRN => NCRN); - /* Регистрируем контрагента */ - P_AGNLIST_BASE_INSERT(NCOMPANY => NCOMPANY, - NCRN => NCRN, - SAGNABBR => SUBSTR(NIDENT || SAGNABBR, 1, 20), - SAGNNAME => SAGNNAME || ' ' || NIDENT, - NRN => NAGENT); - exception - when others then - PKG_EXS.PRC_RESP_ARG_STR_SET(NIDENT => NIDENT, SARG => PKG_EXS.SCONT_FLD_SERR, SVALUE => sqlerrm); - end PROCESS_AGN_INFO_RESP; - /* Обработка запроса на создание сессии */ - procedure RESP_LOGIN + procedure UTL_LOGIN ( NIDENT in number, -- Идентификатор процесса NSRV_TYPE in number, -- Тип сервиса (см. константы PKG_EXS.NSRV_TYPE*) @@ -298,472 +83,100 @@ create or replace package body UDO_PKG_EXS_TEST as exception when others then PKG_EXS.PRC_RESP_ARG_STR_SET(NIDENT => NIDENT, SARG => PKG_EXS.SCONT_FLD_SERR, SVALUE => sqlerrm); - end RESP_LOGIN; + end UTL_LOGIN; - /* Обработка запроса на поиск контрагента */ - procedure RESP_FIND_AGENT + /* Запросить контрагента на удалённом сервере */ + procedure AGENT_GET_INFO ( - NIDENT in number, -- Идентификатор процесса - NSRV_TYPE in number, -- Тип сервиса (см. константы PKG_EXS.NSRV_TYPE*) - NEXSQUEUE in number -- Регистрационный номер обрабатываемой позиции очереди обмена + NCOMPANY in number, -- Рег. номер организации + NREMOTE_AGENT in number -- Рег. номер контрагента в удалённой БД ) is - HELPER_PATTERNS THELPER_PATTERNS; -- Коллекция шаблонов вспомогательных слов поиска - REXSQUEUE EXSQUEUE%rowtype; -- Запись позиции очереди - CTMP clob; -- Буфер для конвертации - CRESP clob; -- Данные для ответа - RCTMP sys_refcursor; -- Буфер для измененной позиции очереди - begin - /* Считаем запись очереди */ - REXSQUEUE := GET_EXSQUEUE_ID(NFLAG_SMART => 0, NRN => NEXSQUEUE); - /* Инициализируем коллекцию слов-помошников */ - UTL_HELPER_INIT_COMMON(HELPER_PATTERNS => HELPER_PATTERNS); - /* Наполняем её значениями индивидуальными для данного запроса */ - HELPER_PATTERNS.EXTEND(); - HELPER_PATTERNS(HELPER_PATTERNS.LAST) := 'контрагент%'; - /* Забираем данные сообщения и конвертируем в кодировку БД */ - CTMP := BLOB2CLOB(LBDATA => REXSQUEUE.MSG, SCHARSET => 'UTF8'); - /* Кладём конвертированное обратно (просто для удобства мониторинга) */ - PKG_EXS.QUEUE_MSG_SET(NEXSQUEUE => REXSQUEUE.RN, BMSG => CLOB2BLOB(LCDATA => CTMP), RCQUEUE => RCTMP); - /* Если есть что искать */ - if (CTMP is not null) then - /* Подготовим поисковую фразу */ - CTMP := UTL_SEARCH_STR_PREPARE(SSEARCH_STR => CTMP, SDELIM => ' ', HELPER_PATTERNS => HELPER_PATTERNS); - /* Инициализируем ответ */ - CRESP := 'Контрагент не найден'; - /* Ищем запрошенного контрагента */ - for C in (select T.AGNNAME || - DECODE(T.AGNTYPE, 1, ', физическое лицо', ', юридическое лицо') SAGENT, - (select count(CN.RN) from CONTRACTS CN where CN.AGENT = T.RN) NCNT_CONTRACTS, - (select sum(CN.DOC_SUM) from CONTRACTS CN where CN.AGENT = T.RN) NSUM_CONTRACTS - from AGNLIST T - where ((LOWER(T.AGNABBR) like LOWER(CTMP)) or (LOWER(T.AGNNAME) like LOWER(CTMP))) - and ROWNUM <= 1) - loop - CRESP := C.SAGENT; - if (C.NCNT_CONTRACTS = 0) then - CRESP := CRESP || ', не имеет зарегистрированных в системе договоров'; - else - CRESP := CRESP || ', зарегистрировано договоров: ' || TO_CHAR(C.NCNT_CONTRACTS); - if (C.NSUM_CONTRACTS <> 0) then - CRESP := CRESP || ', на общую сумму: ' || TO_CHAR(C.NSUM_CONTRACTS) || ' руб.'; - end if; - end if; - end loop; - else - CRESP := 'Не указан поисковый запрос'; - end if; - /* Возвращаем ответ */ - PKG_EXS.PRC_RESP_ARG_BLOB_SET(NIDENT => NIDENT, - SARG => PKG_EXS.SCONT_FLD_BRESP, - BVALUE => CLOB2BLOB(LCDATA => CRESP, SCHARSET => 'UTF8')); - end RESP_FIND_AGENT; - - /* Обработка запроса на поиск договора */ - procedure RESP_FIND_CONTRACT + RCTMP sys_refcursor; -- Буфер для измененной позиции очереди + begin + /* Поместим задание в очередь */ + PKG_EXS.QUEUE_PUT(SEXSSERVICE => 'ТестовыйСтенд', + SEXSSERVICEFN => 'ПолучениеКонтрагента', + BMSG => CLOB2BLOB(LCDATA => '{"SACTION":"GET_AGENT","NAGENT":' || TO_CHAR(NREMOTE_AGENT) || + ',"NCOMPANY":' || TO_CHAR(NCOMPANY) || '}'), + RCQUEUE => RCTMP); + end AGENT_GET_INFO; + + /* Обработка ответа с информацией о контрагенте от тестового стенда */ + procedure AGENT_PROCESS_INFO ( - NIDENT in number, -- Идентификатор процесса - NSRV_TYPE in number, -- Тип сервиса (см. константы PKG_EXS.NSRV_TYPE*) - NEXSQUEUE in number -- Регистрационный номер обрабатываемой позиции очереди обмена + NIDENT in number, -- Идентификатор процесса + NSRV_TYPE in number, -- Тип сервиса (см. константы PKG_EXS.NSRV_TYPE*) + NEXSQUEUE in number -- Регистрационный номер обрабатываемой позиции очереди обмена ) is - HELPER_PATTERNS THELPER_PATTERNS; -- Коллекция шаблонов вспомогательных слов поиска - REXSQUEUE EXSQUEUE%rowtype; -- Запись позиции очереди - CTMP clob; -- Буфер для конвертации - CRESP clob; -- Данные для ответа - RCTMP sys_refcursor; -- Буфер для измененной позиции очереди + REXSQUEUE EXSQUEUE%rowtype; -- Запись позиции очереди + CMSG clob; -- Буфер для запроса + CRESP clob; -- Буфер для ответа + RCTMP sys_refcursor; -- Буфер для измененной позиции очереди + NCOMPANY PKG_STD.TREF; -- Рег. номер организации + NCRN PKG_STD.TREF; -- Рег. номер каталога + SAGNABBR AGNLIST.AGNABBR%type; -- Мнемокод контрагента + SAGNNAME AGNLIST.AGNNAME%type; -- Наименование контрагента + NAGENT AGNLIST.RN%type; -- Рег. номер добавленного контрагента begin /* Считаем запись очереди */ REXSQUEUE := GET_EXSQUEUE_ID(NFLAG_SMART => 0, NRN => NEXSQUEUE); - /* Инициализируем коллекцию слов-помошников */ - UTL_HELPER_INIT_COMMON(HELPER_PATTERNS => HELPER_PATTERNS); - /* Наполняем её значениями индивидуальными для данного запроса */ - HELPER_PATTERNS.EXTEND(); - HELPER_PATTERNS(HELPER_PATTERNS.LAST) := 'договор%'; - /* Забираем данные сообщения и конвертируем в кодировку БД */ - CTMP := BLOB2CLOB(LBDATA => REXSQUEUE.MSG, SCHARSET => 'UTF8'); + /* Считаем запрос серверу */ + CMSG := BLOB2CLOB(LBDATA => REXSQUEUE.MSG); + /* Считаем ответ сервера и конвертируем в кодировку БД */ + CRESP := BLOB2CLOB(LBDATA => REXSQUEUE.RESP, SCHARSET => 'UTF8'); /* Кладём конвертированное обратно (просто для удобства мониторинга) */ - PKG_EXS.QUEUE_MSG_SET(NEXSQUEUE => REXSQUEUE.RN, BMSG => CLOB2BLOB(LCDATA => CTMP), RCQUEUE => RCTMP); - /* Если есть что искать */ - if (CTMP is not null) then - /* Подготовим поисковую фразу */ - CTMP := UTL_SEARCH_STR_PREPARE(SSEARCH_STR => CTMP, SDELIM => ' ', HELPER_PATTERNS => HELPER_PATTERNS); - /* Ищем запрошенный договор */ + PKG_EXS.QUEUE_RESP_SET(NEXSQUEUE => REXSQUEUE.RN, BRESP => CLOB2BLOB(LCDATA => CRESP), RCQUEUE => RCTMP); + /* Заберем организацию из исходящего сообщения */ + begin + select EXTRACTVALUE(XMLTYPE(CMSG), '/MSG/NCOMPANY') NCOMPANY into NCOMPANY from DUAL; + exception + when others then + P_EXCEPTION(0, 'Не удалось определить организацию'); + end; + if (NCOMPANY is null) then + P_EXCEPTION(0, 'В исходящем сообщении не указана организация'); + end if; + /* Разбираем ответ сервера */ + if (CRESP is not null) then begin - select DECODE(T.INOUT_SIGN, 0, 'Входящий', 'Исходящий') || ' договор №' || - NVL(T.EXT_NUMBER, trim(T.DOC_PREF) || '-' || trim(T.DOC_NUMB)) || ' от ' || - TO_CHAR(T.DOC_DATE, 'dd.mm.yyyy') || ' с контрагентом ' || AG.AGNNAME || ' на сумму ' || - TO_CHAR(T.DOC_SUM) || ' ' || CN.INTCODE || ', оплачено ' || TO_CHAR(T.FACT_OUTPAY_SUM) || ' ' || - CN.INTCODE SDOC - into CRESP - from CONTRACTS T, - AGNLIST AG, - CURNAMES CN - where ((LOWER(T.EXT_NUMBER) like LOWER(CTMP)) or - (LOWER(trim(T.DOC_PREF) || trim(T.DOC_NUMB)) like LOWER(CTMP))) - and T.AGENT = AG.RN - and T.CURRENCY = CN.RN - and ROWNUM <= 1; + select EXTRACTVALUE(XMLTYPE(CRESP), '/AGENT/SAGNABBR') SAGNABBR, + EXTRACTVALUE(XMLTYPE(CRESP), '/AGENT/SAGNNAME') SAGNNAME + into SAGNABBR, + SAGNNAME + from DUAL; exception - when NO_DATA_FOUND then - CRESP := 'Договор не найден'; + when others then + P_EXCEPTION(0, 'Неожиданный ответ сервера.'); end; else - CRESP := 'Не указан поисковый запрос'; + P_EXCEPTION(0, 'Не указаны данные для добавления контрагента.'); end if; - /* Возвращаем ответ */ - PKG_EXS.PRC_RESP_ARG_BLOB_SET(NIDENT => NIDENT, - SARG => PKG_EXS.SCONT_FLD_BRESP, - BVALUE => CLOB2BLOB(LCDATA => CRESP, SCHARSET => 'UTF8')); - end RESP_FIND_CONTRACT; - - /* Электронная инвентаризация - аутентификация */ - procedure INV_CHECKAUTH_XML - ( - NIDENT in number, -- Идентификатор процесса - NSRV_TYPE in number, -- Тип сервиса (см. константы PKG_EXS.NSRV_TYPE*) - NEXSQUEUE in number -- Регистрационный номер обрабатываемой позиции очереди обмена - ) - is - REXSQUEUE EXSQUEUE%rowtype; -- Запись позиции очереди - /**/ - SREQDEVICEID varchar2(30); - XCHECKAUTHRESPONSE DBMS_XMLDOM.DOMNODE; - XRESULT DBMS_XMLDOM.DOMNODE; - XNODE DBMS_XMLDOM.DOMNODE; - CRESPONSE clob; - XDOC DBMS_XMLDOM.DOMDOCUMENT; - /**/ - XMLPARCER DBMS_XMLPARSER.PARSER; - XENVELOPE DBMS_XMLDOM.DOMNODE; - XBODY DBMS_XMLDOM.DOMNODE; - XNODELIST DBMS_XMLDOM.DOMNODELIST; - XNODE_ROOT DBMS_XMLDOM.DOMNODE; - SNODE varchar2(100); - CREQ clob; - /**/ - STSD constant varchar2(20) := 'tsd'; - SCHECKAUTHRESPONSE constant varchar2(20) := 'CheckAuthResponse'; - SDEVICEID constant varchar2(20) := 'DeviceID'; - SRESULT constant varchar2(20) := 'Result'; - SSOAPENV constant varchar2(20) := 'soapenv'; - SENVELOPE constant varchar2(20) := 'Envelope'; - SHEADER constant varchar2(20) := 'Header'; - SBODY constant varchar2(20) := 'Body'; - /* Создание ветки XML */ - function CREATENODE - ( - STAG in varchar2, - SNS in varchar2 default null, - SVAL in varchar2 default null - ) return DBMS_XMLDOM.DOMNODE is - XEL DBMS_XMLDOM.DOMELEMENT; - XNODE DBMS_XMLDOM.DOMNODE; - XTEXT DBMS_XMLDOM.DOMNODE; - begin - if SNS is not null then - XEL := DBMS_XMLDOM.CREATEELEMENT(DOC => XDOC, TAGNAME => STAG, NS => SNS); - XNODE := DBMS_XMLDOM.MAKENODE(XEL); - DBMS_XMLDOM.SETPREFIX(N => XNODE, PREFIX => SNS); - else - XEL := DBMS_XMLDOM.CREATEELEMENT(DOC => XDOC, TAGNAME => STAG); - XNODE := DBMS_XMLDOM.MAKENODE(XEL); - end if; - if SVAL is not null then - XTEXT := DBMS_XMLDOM.APPENDCHILD(XNODE, DBMS_XMLDOM.MAKENODE(DBMS_XMLDOM.CREATETEXTNODE(XDOC, SVAL))); - end if; - return XNODE; - end; - /* Считывание значения ветки XML */ - function GETNODEVAL - ( - XROOTNODE in DBMS_XMLDOM.DOMNODE, - SPATTERN in varchar2 - ) return varchar2 is - XNODE DBMS_XMLDOM.DOMNODE; - SVAL varchar2(100); - begin - XNODE := DBMS_XSLPROCESSOR.SELECTSINGLENODE(N => XROOTNODE, PATTERN => SPATTERN); - if DBMS_XMLDOM.ISNULL(XNODE) then - return null; - end if; - SVAL := DBMS_XMLDOM.GETNODEVALUE(DBMS_XMLDOM.GETFIRSTCHILD(N => XNODE)); - return SVAL; - end GETNODEVAL; - /* Создание документа для ответа */ - procedure CREATERESPONSEDOC is - begin - XDOC := DBMS_XMLDOM.NEWDOMDOCUMENT; - DBMS_XMLDOM.SETVERSION(XDOC - ,'1.0" encoding="UTF-8'); - DBMS_XMLDOM.SETCHARSET(XDOC - ,'UTF-8'); - end; - /* Создание ответа */ - function CREATERESPONSE(XCONTENT in DBMS_XMLDOM.DOMNODE) return clob is - XMAIN_NODE DBMS_XMLDOM.DOMNODE; - XENVELOPE_EL DBMS_XMLDOM.DOMELEMENT; - XENVELOPE DBMS_XMLDOM.DOMNODE; - XHEADER DBMS_XMLDOM.DOMNODE; - XBODY DBMS_XMLDOM.DOMNODE; - XNODE DBMS_XMLDOM.DOMNODE; - CDATA clob; - begin - -- Document - XMAIN_NODE := DBMS_XMLDOM.MAKENODE(XDOC); - -- Envelope - XENVELOPE_EL := DBMS_XMLDOM.CREATEELEMENT(DOC => XDOC, TAGNAME => SENVELOPE, NS => SSOAPENV); - DBMS_XMLDOM.SETATTRIBUTE(ELEM => XENVELOPE_EL, - name => 'xmlns:soapenv', - NEWVALUE => 'http://schemas.xmlsoap.org/soap/envelope/'); - DBMS_XMLDOM.SETATTRIBUTE(ELEM => XENVELOPE_EL, name => 'xmlns:tsd', NEWVALUE => 'http://www.example.org/TSDService/'); - XENVELOPE := DBMS_XMLDOM.MAKENODE(XENVELOPE_EL); - DBMS_XMLDOM.SETPREFIX(N => XENVELOPE, PREFIX => SSOAPENV); - XENVELOPE := DBMS_XMLDOM.APPENDCHILD(N => XMAIN_NODE, NEWCHILD => XENVELOPE); - -- Header - XHEADER := CREATENODE(SHEADER, SSOAPENV); - XHEADER := DBMS_XMLDOM.APPENDCHILD(N => XENVELOPE, NEWCHILD => XHEADER); - -- Body - XBODY := CREATENODE(SBODY, SSOAPENV); - XBODY := DBMS_XMLDOM.APPENDCHILD(N => XENVELOPE, NEWCHILD => XBODY); - XNODE := DBMS_XMLDOM.APPENDCHILD(N => XBODY, NEWCHILD => XCONTENT); - -- Создаем CLOB - DBMS_LOB.CREATETEMPORARY(LOB_LOC => CDATA, CACHE => true, DUR => DBMS_LOB.SESSION); - DBMS_XMLDOM.WRITETOCLOB(XDOC, CDATA, 'UTF-8'); - DBMS_XMLDOM.FREEDOCUMENT(DOC => XDOC); - return CDATA; - end; - begin - /* Считаем запись очереди */ - REXSQUEUE := GET_EXSQUEUE_ID(NFLAG_SMART => 0, NRN => NEXSQUEUE); - /* Конвертируем в кодировку БД */ - CREQ := BLOB2CLOB(LBDATA => REXSQUEUE.MSG); - -- Создаем инстанс XML парсера - XMLPARCER := DBMS_XMLPARSER.NEWPARSER; - -- Считываем XML из запроса - DBMS_XMLPARSER.PARSECLOB(XMLPARCER - ,CREQ); - -- Берем XML документ - XDOC := DBMS_XMLPARSER.GETDOCUMENT(XMLPARCER); - -- Считываем Корневой элемент - XENVELOPE := DBMS_XMLDOM.MAKENODE(DBMS_XMLDOM.GETDOCUMENTELEMENT(XDOC)); - -- Считываем элемент Body - XBODY := DBMS_XSLPROCESSOR.SELECTSINGLENODE(XENVELOPE - ,SBODY); - -- Считываем дочерние элементы к Body - XNODELIST := DBMS_XMLDOM.GETCHILDNODES(XBODY); - -- Берем первый дочерний элемент - XNODE_ROOT := DBMS_XMLDOM.ITEM(XNODELIST - ,0); - -- Считаем имя элемента - DBMS_XMLDOM.GETLOCALNAME(XNODE_ROOT - ,SNODE); - -- Считываем DeviceID - SREQDEVICEID := GETNODEVAL(XNODE_ROOT - ,SDEVICEID); - --CHECK_ID(SREQDEVICEID); - CREATERESPONSEDOC(); - if SREQDEVICEID is not null - then - XCHECKAUTHRESPONSE := CREATENODE(SCHECKAUTHRESPONSE - ,STSD); - XRESULT := CREATENODE(SRESULT - ,STSD - ,'true'); - XNODE := DBMS_XMLDOM.APPENDCHILD(N => XCHECKAUTHRESPONSE - ,NEWCHILD => XRESULT); - CRESPONSE := CREATERESPONSE(XCHECKAUTHRESPONSE); + if (SAGNABBR is null) then + P_EXCEPTION(0, 'В ответе сервера не указан мнемокод контрагента.'); end if; - /* Возвращаем ответ */ - PKG_EXS.PRC_RESP_ARG_BLOB_SET(NIDENT => NIDENT, - SARG => PKG_EXS.SCONT_FLD_BRESP, - BVALUE => CLOB2BLOB(LCDATA => CRESPONSE)); - end; - - /* Электронная инвентаризация - считывание пользователей */ - procedure INV_GETUSERS_XML - ( - NIDENT in number, -- Идентификатор процесса - NSRV_TYPE in number, -- Тип сервиса (см. константы PKG_EXS.NSRV_TYPE*) - NEXSQUEUE in number -- Регистрационный номер обрабатываемой позиции очереди обмена - ) - is - REXSQUEUE EXSQUEUE%rowtype; -- Запись позиции очереди - /**/ - SREQDEVICEID varchar2(30); - XGETUSERSRESPONSE DBMS_XMLDOM.DOMNODE; - XITEM DBMS_XMLDOM.DOMNODE; - XCODE DBMS_XMLDOM.DOMNODE; - XNAME DBMS_XMLDOM.DOMNODE; - XNODE DBMS_XMLDOM.DOMNODE; - CRESPONSE clob; - XDOC DBMS_XMLDOM.DOMDOCUMENT; - /**/ - XMLPARCER DBMS_XMLPARSER.PARSER; - XENVELOPE DBMS_XMLDOM.DOMNODE; - XBODY DBMS_XMLDOM.DOMNODE; - XNODELIST DBMS_XMLDOM.DOMNODELIST; - XNODE_ROOT DBMS_XMLDOM.DOMNODE; - SNODE varchar2(100); - CREQ clob; - /**/ - STSD constant varchar2(20) := 'tsd'; - SGETUSERSRESPONSE constant varchar2(20) := 'GetUsersResponse'; - SDEVICEID constant varchar2(20) := 'DeviceID'; - SRESULT constant varchar2(20) := 'Result'; - SSOAPENV constant varchar2(20) := 'soapenv'; - SENVELOPE constant varchar2(20) := 'Envelope'; - SHEADER constant varchar2(20) := 'Header'; - SBODY constant varchar2(20) := 'Body'; - SITEM constant varchar2(20) := 'Item'; - SCODE constant varchar2(20) := 'Code'; - SNAME constant varchar2(20) := 'Name'; - /* Создание ветки XML */ - function CREATENODE - ( - STAG in varchar2, - SNS in varchar2 default null, - SVAL in varchar2 default null - ) return DBMS_XMLDOM.DOMNODE is - XEL DBMS_XMLDOM.DOMELEMENT; - XNODE DBMS_XMLDOM.DOMNODE; - XTEXT DBMS_XMLDOM.DOMNODE; - begin - if SNS is not null then - XEL := DBMS_XMLDOM.CREATEELEMENT(DOC => XDOC, TAGNAME => STAG, NS => SNS); - XNODE := DBMS_XMLDOM.MAKENODE(XEL); - DBMS_XMLDOM.SETPREFIX(N => XNODE, PREFIX => SNS); - else - XEL := DBMS_XMLDOM.CREATEELEMENT(DOC => XDOC, TAGNAME => STAG); - XNODE := DBMS_XMLDOM.MAKENODE(XEL); - end if; - if SVAL is not null then - XTEXT := DBMS_XMLDOM.APPENDCHILD(XNODE, DBMS_XMLDOM.MAKENODE(DBMS_XMLDOM.CREATETEXTNODE(XDOC, SVAL))); - end if; - return XNODE; - end; - /* Считывание значения ветки XML */ - function GETNODEVAL - ( - XROOTNODE in DBMS_XMLDOM.DOMNODE, - SPATTERN in varchar2 - ) return varchar2 is - XNODE DBMS_XMLDOM.DOMNODE; - SVAL varchar2(100); - begin - XNODE := DBMS_XSLPROCESSOR.SELECTSINGLENODE(N => XROOTNODE, PATTERN => SPATTERN); - if DBMS_XMLDOM.ISNULL(XNODE) then - return null; - end if; - SVAL := DBMS_XMLDOM.GETNODEVALUE(DBMS_XMLDOM.GETFIRSTCHILD(N => XNODE)); - return SVAL; - end GETNODEVAL; - /* Создание документа для ответа */ - procedure CREATERESPONSEDOC is - begin - XDOC := DBMS_XMLDOM.NEWDOMDOCUMENT; - DBMS_XMLDOM.SETVERSION(XDOC - ,'1.0" encoding="UTF-8'); - DBMS_XMLDOM.SETCHARSET(XDOC - ,'UTF-8'); - end; - /* Создание ответа */ - function CREATERESPONSE(XCONTENT in DBMS_XMLDOM.DOMNODE) return clob is - XMAIN_NODE DBMS_XMLDOM.DOMNODE; - XENVELOPE_EL DBMS_XMLDOM.DOMELEMENT; - XENVELOPE DBMS_XMLDOM.DOMNODE; - XHEADER DBMS_XMLDOM.DOMNODE; - XBODY DBMS_XMLDOM.DOMNODE; - XNODE DBMS_XMLDOM.DOMNODE; - CDATA clob; - begin - -- Document - XMAIN_NODE := DBMS_XMLDOM.MAKENODE(XDOC); - -- Envelope - XENVELOPE_EL := DBMS_XMLDOM.CREATEELEMENT(DOC => XDOC, TAGNAME => SENVELOPE, NS => SSOAPENV); - DBMS_XMLDOM.SETATTRIBUTE(ELEM => XENVELOPE_EL, - name => 'xmlns:soapenv', - NEWVALUE => 'http://schemas.xmlsoap.org/soap/envelope/'); - DBMS_XMLDOM.SETATTRIBUTE(ELEM => XENVELOPE_EL, name => 'xmlns:tsd', NEWVALUE => 'http://www.example.org/TSDService/'); - XENVELOPE := DBMS_XMLDOM.MAKENODE(XENVELOPE_EL); - DBMS_XMLDOM.SETPREFIX(N => XENVELOPE, PREFIX => SSOAPENV); - XENVELOPE := DBMS_XMLDOM.APPENDCHILD(N => XMAIN_NODE, NEWCHILD => XENVELOPE); - -- Header - XHEADER := CREATENODE(SHEADER, SSOAPENV); - XHEADER := DBMS_XMLDOM.APPENDCHILD(N => XENVELOPE, NEWCHILD => XHEADER); - -- Body - XBODY := CREATENODE(SBODY, SSOAPENV); - XBODY := DBMS_XMLDOM.APPENDCHILD(N => XENVELOPE, NEWCHILD => XBODY); - XNODE := DBMS_XMLDOM.APPENDCHILD(N => XBODY, NEWCHILD => XCONTENT); - -- Создаем CLOB - DBMS_LOB.CREATETEMPORARY(LOB_LOC => CDATA, CACHE => true, DUR => DBMS_LOB.SESSION); - DBMS_XMLDOM.WRITETOCLOB(XDOC, CDATA, 'UTF-8'); - DBMS_XMLDOM.FREEDOCUMENT(DOC => XDOC); - return CDATA; - end; - begin - /* Считаем запись очереди */ - REXSQUEUE := GET_EXSQUEUE_ID(NFLAG_SMART => 0, NRN => NEXSQUEUE); - /* Конвертируем в кодировку БД */ - CREQ := BLOB2CLOB(LBDATA => REXSQUEUE.MSG); - -- Создаем инстанс XML парсера - XMLPARCER := DBMS_XMLPARSER.NEWPARSER; - -- Считываем XML из запроса - DBMS_XMLPARSER.PARSECLOB(XMLPARCER - ,CREQ); - -- Берем XML документ - XDOC := DBMS_XMLPARSER.GETDOCUMENT(XMLPARCER); - -- Считываем Корневой элемент - XENVELOPE := DBMS_XMLDOM.MAKENODE(DBMS_XMLDOM.GETDOCUMENTELEMENT(XDOC)); - -- Считываем элемент Body - XBODY := DBMS_XSLPROCESSOR.SELECTSINGLENODE(XENVELOPE - ,SBODY); - -- Считываем дочерние элементы к Body - XNODELIST := DBMS_XMLDOM.GETCHILDNODES(XBODY); - -- Берем первый дочерний элемент - XNODE_ROOT := DBMS_XMLDOM.ITEM(XNODELIST - ,0); - -- Считаем имя элемента - DBMS_XMLDOM.GETLOCALNAME(XNODE_ROOT - ,SNODE); - -- Считываем DeviceID - SREQDEVICEID := GETNODEVAL(XNODE_ROOT - ,SDEVICEID); - --CHECK_ID(SREQDEVICEID); - CREATERESPONSEDOC(); - if SREQDEVICEID is not null - then - XGETUSERSRESPONSE := CREATENODE(SGETUSERSRESPONSE - ,STSD); - for REC in (select T.RN - ,A.AGNABBR - from INVPERSONS T - ,AGNLIST A - where T.COMPANY = 136018 - and T.AGNLIST = A.RN) - loop - XITEM := CREATENODE(SITEM - ,STSD); - XCODE := CREATENODE(SCODE - ,STSD - ,REC.RN); - XNAME := CREATENODE(SNAME - ,STSD - ,REC.AGNABBR); - XNODE := DBMS_XMLDOM.APPENDCHILD(N => XITEM - ,NEWCHILD => XCODE); - XNODE := DBMS_XMLDOM.APPENDCHILD(N => XITEM - ,NEWCHILD => XNAME); - XNODE := DBMS_XMLDOM.APPENDCHILD(N => XGETUSERSRESPONSE - ,NEWCHILD => XITEM); - end loop; - CRESPONSE := CREATERESPONSE(XGETUSERSRESPONSE); - end if; - /* Возвращаем ответ */ - PKG_EXS.PRC_RESP_ARG_BLOB_SET(NIDENT => NIDENT, - SARG => PKG_EXS.SCONT_FLD_BRESP, - BVALUE => CLOB2BLOB(LCDATA => CRESPONSE, sCHARSET => 'UTF8')); - end; + if (SAGNNAME is null) then + P_EXCEPTION(0, + 'В ответе сервера не указано наименование контрагента.'); + end if; + /* Найдём каталог */ + FIND_ACATALOG_NAME(NFLAG_SMART => 0, + NCOMPANY => NCOMPANY, + NVERSION => null, + SUNITCODE => 'AGNLIST', + SNAME => 'ExchangeService', + NRN => NCRN); + /* Регистрируем контрагента */ + P_AGNLIST_BASE_INSERT(NCOMPANY => NCOMPANY, + NCRN => NCRN, + SAGNABBR => SUBSTR(NIDENT || SAGNABBR, 1, 20), + SAGNNAME => SAGNNAME || ' ' || NIDENT, + NRN => NAGENT); + exception + when others then + PKG_EXS.PRC_RESP_ARG_STR_SET(NIDENT => NIDENT, SARG => PKG_EXS.SCONT_FLD_SERR, SVALUE => sqlerrm); + end AGENT_PROCESS_INFO; end; /