forked from CITKParus/P8-ExchangeService
Запрос статуса зарегистрированного в АТОЛ-Онлайн чека, канализация алгоритмов подбора функции и сервиса обработчика от версии ФФД
This commit is contained in:
parent
2c6e24f91e
commit
9b42179bde
@ -1,5 +1,21 @@
|
|||||||
create or replace package UDO_PKG_EXS_ATOL as
|
create or replace package UDO_PKG_EXS_ATOL as
|
||||||
|
|
||||||
|
/* Константы - типы функций обработки */
|
||||||
|
SFN_TYPE_REG_BILL constant varchar2(20) := 'REG_BILL'; -- Типовая функция регистрации чека
|
||||||
|
SFN_TYPE_GET_BILL_INF constant varchar2(20) := 'GET_BILL_INF'; -- Типовая функция получения иформации о регистрации чека
|
||||||
|
|
||||||
|
/* Получение рег. номера функции сервиса обмена для регистрации чека по рег. номеру фискального документа */
|
||||||
|
function UTL_FISCDOC_GET_REG_EXSFN
|
||||||
|
(
|
||||||
|
NFISCDOC in number -- Рег. номер фискального документа
|
||||||
|
) return number; -- Рег. номер функции регистрации чека в сервисе АТОЛ-Онлайн
|
||||||
|
|
||||||
|
/* Получение рег. номера функции сервиса обмена для запроса информации о регистрации чека по рег. номеру фискального документа */
|
||||||
|
function UTL_FISCDOC_GET_INF_EXSFN
|
||||||
|
(
|
||||||
|
NFISCDOC in number -- Рег. номер фискального документа
|
||||||
|
) return number; -- Рег. номер функции запроса информации о регистрации чека в сервисе АТОЛ-Онлайн
|
||||||
|
|
||||||
/* Îòðàáîòêà îòâåòîâ ÀÒÎË (v4) íà ðåãèñòðàöèþ ÷åêà íà ïðèõîä, ðàñõîä, âîçâðàò (ÔÔÄ 1.05) */
|
/* Îòðàáîòêà îòâåòîâ ÀÒÎË (v4) íà ðåãèñòðàöèþ ÷åêà íà ïðèõîä, ðàñõîä, âîçâðàò (ÔÔÄ 1.05) */
|
||||||
procedure V4_FFD105_PROCESS_REG_BILL_SIR
|
procedure V4_FFD105_PROCESS_REG_BILL_SIR
|
||||||
(
|
(
|
||||||
@ -10,38 +26,211 @@ create or replace package UDO_PKG_EXS_ATOL as
|
|||||||
/* Îòðàáîòêà îòâåòîâ ÀÒÎË (v4) íà çàïðîñ ñâåäåíèé î çàðåãèñòðèðîâàííîì äîêóìåíòå (ÔÔÄ 1.05) */
|
/* Îòðàáîòêà îòâåòîâ ÀÒÎË (v4) íà çàïðîñ ñâåäåíèé î çàðåãèñòðèðîâàííîì äîêóìåíòå (ÔÔÄ 1.05) */
|
||||||
procedure V4_FFD105_PROCESS_GET_BILL_INF
|
procedure V4_FFD105_PROCESS_GET_BILL_INF
|
||||||
(
|
(
|
||||||
NIDENT in number, -- Идентификатор процесса
|
NIDENT in number, -- Идентификатор процесса
|
||||||
NEXSQUEUE in number -- Регистрационный номер обрабатываемой позиции очереди обмена
|
NEXSQUEUE in number -- Регистрационный номер обрабатываемой позиции очереди обмена
|
||||||
);
|
);
|
||||||
|
|
||||||
end;
|
end;
|
||||||
/
|
/
|
||||||
create or replace package body UDO_PKG_EXS_ATOL as
|
create or replace package body UDO_PKG_EXS_ATOL as
|
||||||
|
|
||||||
/* Отработка ответов АТОЛ (v4) на регистрацию чека на приход, расход, возврат (ФФД 1.05) */
|
/* Константы - состояния документа в АТОЛ */
|
||||||
procedure V4_FFD105_PROCESS_REG_BILL_SIR
|
SSTATUS_DONE constant varchar2(10) := 'done'; -- Готово
|
||||||
|
SSTATUS_FAIL constant varchar2(10) := 'fail'; -- Ошибка
|
||||||
|
SSTATUS_WAIT constant varchar2(10) := 'wait'; -- Ожидание
|
||||||
|
|
||||||
|
/* Шаблон URL для чека ОФД */
|
||||||
|
SBILL_OFD_UTL constant varchar2(80) := 'https://ofd.ru/rec/<1041>/<1040>/<1077>?format=pdf';
|
||||||
|
|
||||||
|
/* Проверка корректности атрибутов позиции очереди */
|
||||||
|
procedure UTL_EXSQUEUE_CHECK_ATTRS
|
||||||
(
|
(
|
||||||
NIDENT in number, -- Идентификатор процесса
|
REXSQUEUE in EXSQUEUE%rowtype -- Проверяемая запись позиции очереди
|
||||||
NEXSQUEUE in number -- Регистрационный номер обрабатываемой позиции очереди обмена
|
|
||||||
)
|
)
|
||||||
is
|
is
|
||||||
REXSQUEUE EXSQUEUE%rowtype; -- Запись позиции очереди
|
|
||||||
CTMP clob; -- Буфер для хранения данных ответа сервера
|
|
||||||
begin
|
begin
|
||||||
/* Считаем запись очереди */
|
/* Должна быть организация */
|
||||||
REXSQUEUE := GET_EXSQUEUE_ID(NFLAG_SMART => 0, NRN => NEXSQUEUE);
|
if (REXSQUEUE.LNK_COMPANY is null) then
|
||||||
/* Проверим что позиция очереди корректна */
|
P_EXCEPTION(0, 'Для позиции очереди не указана связанная организация.');
|
||||||
|
end if;
|
||||||
|
/* Должна быть связь с документом */
|
||||||
if (REXSQUEUE.LNK_DOCUMENT is null) then
|
if (REXSQUEUE.LNK_DOCUMENT is null) then
|
||||||
P_EXCEPTION(0, 'Äëÿ ïîçèöèè î÷åðåäè íå óêàçàí ñâÿçàííûé äîêóìåíò.');
|
P_EXCEPTION(0, 'Äëÿ ïîçèöèè î÷åðåäè íå óêàçàí ñâÿçàííûé äîêóìåíò.');
|
||||||
end if;
|
end if;
|
||||||
|
/* Должна быть связь с разделом */
|
||||||
if (REXSQUEUE.LNK_UNITCODE is null) then
|
if (REXSQUEUE.LNK_UNITCODE is null) then
|
||||||
P_EXCEPTION(0, 'Äëÿ ïîçèöèè î÷åðåäè íå óêàçàí ñâÿçàííûé ðàçäåë.');
|
P_EXCEPTION(0, 'Äëÿ ïîçèöèè î÷åðåäè íå óêàçàí ñâÿçàííûé ðàçäåë.');
|
||||||
end if;
|
end if;
|
||||||
|
/* Должна быть связь именно с разделом "Фискальные документы" */
|
||||||
if (REXSQUEUE.LNK_UNITCODE <> 'UDO_FiscalDocuments') then
|
if (REXSQUEUE.LNK_UNITCODE <> 'UDO_FiscalDocuments') then
|
||||||
P_EXCEPTION(0,
|
P_EXCEPTION(0,
|
||||||
'Ñâÿçàííûé ðàçäåë "%s", óêàçàííûé â ïîçèöèè î÷åðåäè, íå ïîääåðæèâàåòñÿ.',
|
'Ñâÿçàííûé ðàçäåë "%s", óêàçàííûé â ïîçèöèè î÷åðåäè, íå ïîääåðæèâàåòñÿ.',
|
||||||
REXSQUEUE.LNK_UNITCODE);
|
REXSQUEUE.LNK_UNITCODE);
|
||||||
end if;
|
end if;
|
||||||
|
end UTL_EXSQUEUE_CHECK_ATTRS;
|
||||||
|
|
||||||
|
/* Считывание записи фискального документа */
|
||||||
|
function UTL_FISCDOC_GET
|
||||||
|
(
|
||||||
|
NFISCDOC in number -- Рег. номер фискального документа
|
||||||
|
) return UDO_V_FISCDOCS%rowtype -- Найденная запись фискального документа
|
||||||
|
is
|
||||||
|
RRES UDO_V_FISCDOCS%rowtype; -- Буфер для результата
|
||||||
|
begin
|
||||||
|
/* Считаем запись */
|
||||||
|
select T.* into RRES from UDO_V_FISCDOCS T where T.NRN = NFISCDOC;
|
||||||
|
/* Вернём результат */
|
||||||
|
return RRES;
|
||||||
|
exception
|
||||||
|
when NO_DATA_FOUND then
|
||||||
|
PKG_MSG.RECORD_NOT_FOUND(NFLAG_SMART => 0, NDOCUMENT => NFISCDOC, SUNIT_TABLE => 'UDO_FISCDOCS');
|
||||||
|
end UTL_FISCDOC_GET;
|
||||||
|
|
||||||
|
/* Получение мнемокода сервиса обмена и мнемокода его функции по типу функции обработки и версии ФФД */
|
||||||
|
procedure UTL_FISCDOC_GET_EXSFN_BY_FFD
|
||||||
|
(
|
||||||
|
SFN_TYPE in varchar2, -- Тип функции обработки (см. константы SFN_TYPE_*)
|
||||||
|
SFFD_VERSION in varchar2, -- Версия ФФД
|
||||||
|
SEXSSERVICE out varchar2, -- Код сервиса-обработчика
|
||||||
|
SEXSSERVICEFN out varchar2 -- Код функции-обработчика
|
||||||
|
)
|
||||||
|
is
|
||||||
|
begin
|
||||||
|
/* Работаем от типовой функции */
|
||||||
|
case SFN_TYPE
|
||||||
|
/* Регистрация чека */
|
||||||
|
when SFN_TYPE_REG_BILL then
|
||||||
|
begin
|
||||||
|
/* Выбираем API обмена в зависимости от версии фискального документа */
|
||||||
|
case SFFD_VERSION
|
||||||
|
/* ФФД 1.05 */
|
||||||
|
when '1.05' then
|
||||||
|
begin
|
||||||
|
SEXSSERVICE := 'АТОЛ_V4_ИСХ';
|
||||||
|
SEXSSERVICEFN := 'V4_ФФД1.05_РегистрацияЧекаРПВ';
|
||||||
|
end;
|
||||||
|
/* Неизвестная версия ФФД */
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
P_EXCEPTION(0,
|
||||||
|
'Версия фискального документа "%s" не поддерживается!',
|
||||||
|
SFFD_VERSION);
|
||||||
|
end;
|
||||||
|
end case;
|
||||||
|
end;
|
||||||
|
/* Получение иформации о регистрации чека */
|
||||||
|
when SFN_TYPE_GET_BILL_INF then
|
||||||
|
begin
|
||||||
|
/* Выбираем API обмена в зависимости от версии фискального документа */
|
||||||
|
case SFFD_VERSION
|
||||||
|
/* ФФД 1.05 */
|
||||||
|
when '1.05' then
|
||||||
|
begin
|
||||||
|
SEXSSERVICE := 'АТОЛ_V4_ИСХ';
|
||||||
|
SEXSSERVICEFN := 'V4_ФФД1.05_РезОбрабЧека';
|
||||||
|
end;
|
||||||
|
/* Неизвестная версия ФФД */
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
P_EXCEPTION(0,
|
||||||
|
'Версия фискального документа "%s" не поддерживается!',
|
||||||
|
SFFD_VERSION);
|
||||||
|
end;
|
||||||
|
end case;
|
||||||
|
end;
|
||||||
|
/* Неизвестная типовая функция */
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
P_EXCEPTION(0, 'Типовая функция "%s" не поддерживается!', SFN_TYPE);
|
||||||
|
end;
|
||||||
|
end case;
|
||||||
|
end UTL_FISCDOC_GET_EXSFN_BY_FFD;
|
||||||
|
|
||||||
|
/* Получение рег. номера функции сервиса обмена для регистрации чека по рег. номеру фискального документа */
|
||||||
|
function UTL_FISCDOC_GET_REG_EXSFN
|
||||||
|
(
|
||||||
|
NFISCDOC in number -- Рег. номер фискального документа
|
||||||
|
) return number -- Рег. номер функции регистрации чека в сервисе АТОЛ-Онлайн
|
||||||
|
is
|
||||||
|
NRES PKG_STD.TREF; -- Буфер для результата
|
||||||
|
RFISCDOC UDO_V_FISCDOCS%rowtype; -- Запись фискального документа
|
||||||
|
NEXSSERVICE EXSSERVICEFN.RN%type; -- Рег. номер сервиса-обработчика
|
||||||
|
SEXSSERVICE EXSSERVICEFN.CODE%type; -- Код сервиса-обработчика
|
||||||
|
SEXSSERVICEFN EXSSERVICEFN.CODE%type; -- Код функции-обработчика
|
||||||
|
begin
|
||||||
|
/* Считаем запись фискального документа */
|
||||||
|
RFISCDOC := UTL_FISCDOC_GET(NFISCDOC => NFISCDOC);
|
||||||
|
/* Определим мнемокоды сервиса и функции для обработки */
|
||||||
|
UTL_FISCDOC_GET_EXSFN_BY_FFD(SFN_TYPE => SFN_TYPE_REG_BILL,
|
||||||
|
SFFD_VERSION => RFISCDOC.STYPE_VERSION,
|
||||||
|
SEXSSERVICE => SEXSSERVICE,
|
||||||
|
SEXSSERVICEFN => SEXSSERVICEFN);
|
||||||
|
/* Находим рег. номер сервиса */
|
||||||
|
FIND_EXSSERVICE_CODE(NFLAG_SMART => 0, NFLAG_OPTION => 0, SCODE => SEXSSERVICE, NRN => NEXSSERVICE);
|
||||||
|
/* Находим рег. номер функции сервиса */
|
||||||
|
FIND_EXSSERVICEFN_CODE(NFLAG_SMART => 0,
|
||||||
|
NFLAG_OPTION => 0,
|
||||||
|
NEXSSERVICE => NEXSSERVICE,
|
||||||
|
SCODE => SEXSSERVICEFN,
|
||||||
|
NRN => NRES);
|
||||||
|
/* Вернём результат */
|
||||||
|
return NRES;
|
||||||
|
end UTL_FISCDOC_GET_REG_EXSFN;
|
||||||
|
|
||||||
|
/* Получение рег. номера функции сервиса обмена для запроса информации о регистрации чека по рег. номеру фискального документа */
|
||||||
|
function UTL_FISCDOC_GET_INF_EXSFN
|
||||||
|
(
|
||||||
|
NFISCDOC in number -- Рег. номер фискального документа
|
||||||
|
) return number -- Рег. номер функции запроса информации о регистрации чека в сервисе АТОЛ-Онлайн
|
||||||
|
is
|
||||||
|
NRES PKG_STD.TREF; -- Буфер для результата
|
||||||
|
RFISCDOC UDO_V_FISCDOCS%rowtype; -- Запись фискального документа
|
||||||
|
NEXSSERVICE EXSSERVICEFN.RN%type; -- Рег. номер сервиса-обработчика
|
||||||
|
SEXSSERVICE EXSSERVICEFN.CODE%type; -- Код сервиса-обработчика
|
||||||
|
SEXSSERVICEFN EXSSERVICEFN.CODE%type; -- Код функции-обработчика
|
||||||
|
begin
|
||||||
|
/* Считаем запись фискального документа */
|
||||||
|
RFISCDOC := UTL_FISCDOC_GET(NFISCDOC => NFISCDOC);
|
||||||
|
/* Определим мнемокоды сервиса и функции для обработки */
|
||||||
|
UTL_FISCDOC_GET_EXSFN_BY_FFD(SFN_TYPE => SFN_TYPE_GET_BILL_INF,
|
||||||
|
SFFD_VERSION => RFISCDOC.STYPE_VERSION,
|
||||||
|
SEXSSERVICE => SEXSSERVICE,
|
||||||
|
SEXSSERVICEFN => SEXSSERVICEFN);
|
||||||
|
/* Находим рег. номер сервиса */
|
||||||
|
FIND_EXSSERVICE_CODE(NFLAG_SMART => 0, NFLAG_OPTION => 0, SCODE => SEXSSERVICE, NRN => NEXSSERVICE);
|
||||||
|
/* Находим рег. номер функции сервиса */
|
||||||
|
FIND_EXSSERVICEFN_CODE(NFLAG_SMART => 0,
|
||||||
|
NFLAG_OPTION => 0,
|
||||||
|
NEXSSERVICE => NEXSSERVICE,
|
||||||
|
SCODE => SEXSSERVICEFN,
|
||||||
|
NRN => NRES);
|
||||||
|
/* Вернём результат */
|
||||||
|
return NRES;
|
||||||
|
end UTL_FISCDOC_GET_INF_EXSFN;
|
||||||
|
|
||||||
|
/* Отработка ответов АТОЛ (v4) на регистрацию чека на приход, расход, возврат (ФФД 1.05) */
|
||||||
|
procedure V4_FFD105_PROCESS_REG_BILL_SIR
|
||||||
|
(
|
||||||
|
NIDENT in number, -- Идентификатор процесса
|
||||||
|
NEXSQUEUE in number -- Регистрационный номер обрабатываемой позиции очереди обмена
|
||||||
|
)
|
||||||
|
is
|
||||||
|
REXSQUEUE EXSQUEUE%rowtype; -- Запись позиции очереди
|
||||||
|
RFISCDOC UDO_V_FISCDOCS%rowtype; -- Запись фискального документа
|
||||||
|
CTMP clob; -- Буфер для хранения данных ответа сервера
|
||||||
|
begin
|
||||||
|
/* Считаем запись очереди */
|
||||||
|
REXSQUEUE := GET_EXSQUEUE_ID(NFLAG_SMART => 0, NRN => NEXSQUEUE);
|
||||||
|
/* Проверим что позиция очереди корректна */
|
||||||
|
UTL_EXSQUEUE_CHECK_ATTRS(REXSQUEUE => REXSQUEUE);
|
||||||
|
/* Считаем запись фискального документа */
|
||||||
|
RFISCDOC := UTL_FISCDOC_GET(NFISCDOC => REXSQUEUE.LNK_DOCUMENT);
|
||||||
|
/* Проверим, что он верного формата */
|
||||||
|
if (RFISCDOC.STYPE_VERSION <> '1.05') then
|
||||||
|
P_EXCEPTION(0,
|
||||||
|
'Версия формата фискального документа (%s) не поддерживается. Ожидаемая версия - 1.05.',
|
||||||
|
RFISCDOC.STYPE_VERSION);
|
||||||
|
end if;
|
||||||
/* Ðàçáèðàåì îòâåò */
|
/* Ðàçáèðàåì îòâåò */
|
||||||
CTMP := BLOB2CLOB(LBDATA => REXSQUEUE.RESP, SCHARSET => 'UTF8');
|
CTMP := BLOB2CLOB(LBDATA => REXSQUEUE.RESP, SCHARSET => 'UTF8');
|
||||||
if (CTMP is null) then
|
if (CTMP is null) then
|
||||||
@ -60,20 +249,153 @@ create or replace package body UDO_PKG_EXS_ATOL as
|
|||||||
/* Îòðàáîòêà îòâåòîâ ÀÒÎË (v4) íà çàïðîñ ñâåäåíèé î çàðåãèñòðèðîâàííîì äîêóìåíòå (ÔÔÄ 1.05) */
|
/* Îòðàáîòêà îòâåòîâ ÀÒÎË (v4) íà çàïðîñ ñâåäåíèé î çàðåãèñòðèðîâàííîì äîêóìåíòå (ÔÔÄ 1.05) */
|
||||||
procedure V4_FFD105_PROCESS_GET_BILL_INF
|
procedure V4_FFD105_PROCESS_GET_BILL_INF
|
||||||
(
|
(
|
||||||
NIDENT in number, -- Идентификатор процесса
|
NIDENT in number, -- Идентификатор процесса
|
||||||
NEXSQUEUE in number -- Регистрационный номер обрабатываемой позиции очереди обмена
|
NEXSQUEUE in number -- Регистрационный номер обрабатываемой позиции очереди обмена
|
||||||
)
|
)
|
||||||
is
|
is
|
||||||
REXSQUEUE EXSQUEUE%rowtype; -- Запись позиции очереди
|
REXSQUEUE EXSQUEUE%rowtype; -- Запись позиции очереди
|
||||||
CTMP clob; -- Буфер для хранения данных ответа сервера
|
RFISCDOC UDO_V_FISCDOCS%rowtype; -- Запись фискального документа
|
||||||
|
RDOC PKG_XPATH.TDOCUMENT; -- Разобранный XML-документ
|
||||||
|
RROOT_NODE PKG_XPATH.TNODE; -- Корневой тэг XML-документа
|
||||||
|
SSTATUS PKG_STD.TSTRING; -- Буфер для значения "Статус обработки документа"
|
||||||
|
STIMESTAMP PKG_STD.TSTRING; -- Буфер для значения "Дата и время документа внешней системы" (строковое представление)
|
||||||
|
DTIMESTAMP PKG_STD.TLDATE; -- Буфер для значения "Дата и время документа внешней системы"
|
||||||
|
STAG1012 PKG_STD.TSTRING; -- Буфер для значения "Дата и время документа из ФН" (тэг 1012)
|
||||||
|
STAG1040 PKG_STD.TSTRING; -- Буфер для значения "Фискальный номер документа" (тэг 1040)
|
||||||
|
STAG1041 PKG_STD.TSTRING; -- Буфер для значения "Номер ФН" (тэг 1041)
|
||||||
|
STAG1077 PKG_STD.TSTRING; -- Буфер для значения "Фискальный признак документа" (тэг 1077)
|
||||||
|
SERR_CODE PKG_STD.TSTRING; -- Буфер для значения "Код ошибки"
|
||||||
|
SERR_TEXT PKG_STD.TSTRING; -- Буфер для значения "Текст ошибки"
|
||||||
begin
|
begin
|
||||||
/* Ñ÷èòàåì çàïèñü î÷åðåäè */
|
/* Ñ÷èòàåì çàïèñü î÷åðåäè */
|
||||||
REXSQUEUE := GET_EXSQUEUE_ID(NFLAG_SMART => 0, NRN => NEXSQUEUE);
|
REXSQUEUE := GET_EXSQUEUE_ID(NFLAG_SMART => 0, NRN => NEXSQUEUE);
|
||||||
/* Разбираем ответ */
|
/* Проверим что позиция очереди корректна */
|
||||||
CTMP := BLOB2CLOB(LBDATA => REXSQUEUE.RESP, SCHARSET => 'UTF8');
|
UTL_EXSQUEUE_CHECK_ATTRS(REXSQUEUE => REXSQUEUE);
|
||||||
if (CTMP is null) then
|
/* Считаем запись фискального документа */
|
||||||
P_EXCEPTION(0, 'Нет ответа от сервера.');
|
RFISCDOC := UTL_FISCDOC_GET(NFISCDOC => REXSQUEUE.LNK_DOCUMENT);
|
||||||
|
/* Проверим, что он верного формата */
|
||||||
|
if (RFISCDOC.STYPE_VERSION <> '1.05') then
|
||||||
|
P_EXCEPTION(0,
|
||||||
|
'Версия формата фискального документа (%s) не поддерживается. Ожидаемая версия - 1.05.',
|
||||||
|
RFISCDOC.STYPE_VERSION);
|
||||||
end if;
|
end if;
|
||||||
|
/* Разбираем ответ */
|
||||||
|
begin
|
||||||
|
RDOC := PKG_XPATH.PARSE_FROM_BLOB(LBXML => REXSQUEUE.RESP, SCHARSET => 'UTF8');
|
||||||
|
exception
|
||||||
|
when others then
|
||||||
|
P_EXCEPTION(0, 'Ошибка разбора XML - неожиданный ответ сервера.');
|
||||||
|
end;
|
||||||
|
/* Находим корневой элемент */
|
||||||
|
RROOT_NODE := PKG_XPATH.ROOT_NODE(RDOCUMENT => RDOC);
|
||||||
|
/* Забираем значения документа */
|
||||||
|
SSTATUS := PKG_XPATH.VALUE(RNODE => PKG_XPATH.SINGLE_NODE(RPARENT_NODE => RROOT_NODE, SPATTERN => '/RESP/STATUS'));
|
||||||
|
STIMESTAMP := PKG_XPATH.VALUE(RNODE => PKG_XPATH.SINGLE_NODE(RPARENT_NODE => RROOT_NODE,
|
||||||
|
SPATTERN => '/RESP/TIMESTAMP'));
|
||||||
|
STAG1012 := PKG_XPATH.VALUE(RNODE => PKG_XPATH.SINGLE_NODE(RPARENT_NODE => RROOT_NODE, SPATTERN => '/RESP/TAG1012'));
|
||||||
|
STAG1040 := PKG_XPATH.VALUE(RNODE => PKG_XPATH.SINGLE_NODE(RPARENT_NODE => RROOT_NODE, SPATTERN => '/RESP/TAG1040'));
|
||||||
|
STAG1041 := PKG_XPATH.VALUE(RNODE => PKG_XPATH.SINGLE_NODE(RPARENT_NODE => RROOT_NODE, SPATTERN => '/RESP/TAG1041'));
|
||||||
|
STAG1077 := PKG_XPATH.VALUE(RNODE => PKG_XPATH.SINGLE_NODE(RPARENT_NODE => RROOT_NODE, SPATTERN => '/RESP/TAG1077'));
|
||||||
|
SERR_CODE := PKG_XPATH.VALUE(RNODE => PKG_XPATH.SINGLE_NODE(RPARENT_NODE => RROOT_NODE,
|
||||||
|
SPATTERN => '/RESP/ERROR/CODE'));
|
||||||
|
SERR_TEXT := PKG_XPATH.VALUE(RNODE => PKG_XPATH.SINGLE_NODE(RPARENT_NODE => RROOT_NODE,
|
||||||
|
SPATTERN => '/RESP/ERROR/TEXT'));
|
||||||
|
/* Освобождаем память */
|
||||||
|
PKG_XPATH.FREE(RDOCUMENT => RDOC);
|
||||||
|
/* Проверим, что указан статус документа */
|
||||||
|
if (SSTATUS is null) then
|
||||||
|
P_EXCEPTION(0, 'Не указан статус обработки документа.');
|
||||||
|
end if;
|
||||||
|
/* Обрабатываем ответ в зависимости от статуса */
|
||||||
|
case SSTATUS
|
||||||
|
/* Обрабатывается */
|
||||||
|
when SSTATUS_WAIT then
|
||||||
|
begin
|
||||||
|
/* Документ ещё не обработан, ожидаем результатов, поэтому пока ничего не делаем */
|
||||||
|
null;
|
||||||
|
end;
|
||||||
|
/* Готов */
|
||||||
|
when SSTATUS_DONE then
|
||||||
|
begin
|
||||||
|
/* Проверим наличие данных в тэгах и дату ответа АТОЛ */
|
||||||
|
if (STIMESTAMP is null) then
|
||||||
|
P_EXCEPTION(0,
|
||||||
|
'Документ в статусе "%s", но не указано значение "Дата и время документа внешней системы".',
|
||||||
|
SSTATUS);
|
||||||
|
end if;
|
||||||
|
if (STAG1040 is null) then
|
||||||
|
P_EXCEPTION(0,
|
||||||
|
'Документ в статусе "%s", но не указано значение "Фискальный номер документа" (тэг 1040).',
|
||||||
|
SSTATUS);
|
||||||
|
end if;
|
||||||
|
if (STAG1041 is null) then
|
||||||
|
P_EXCEPTION(0,
|
||||||
|
'Документ в статусе "%s", но не указано значение "Номер ФН" (тэг 1041).',
|
||||||
|
SSTATUS);
|
||||||
|
end if;
|
||||||
|
if (STAG1077 is null) then
|
||||||
|
P_EXCEPTION(0,
|
||||||
|
'Документ в статусе "%s", но не указано значение "Фискальный признак документа" (тэг 1077).',
|
||||||
|
SSTATUS);
|
||||||
|
end if;
|
||||||
|
/* Проверяем корректность даты подтверждения */
|
||||||
|
begin
|
||||||
|
DTIMESTAMP := TO_DATE(STIMESTAMP, 'dd.mm.yyyy hh24:mi:ss');
|
||||||
|
exception
|
||||||
|
when others then
|
||||||
|
P_EXCEPTION(0,
|
||||||
|
'Значение поля "Дата и время документа внешней системы" (%s) не является датой в формате "ДД.ММ.ГГГГ ЧЧ:МИ:CC"',
|
||||||
|
STIMESTAMP);
|
||||||
|
end;
|
||||||
|
/* Выставляем значение "Дата подтверждения" и "Ссылка на фискальный документ в ОФД" для фискального документа */
|
||||||
|
update UDO_FISCDOCS T
|
||||||
|
set T.CONFIRM_DATE = DTIMESTAMP,
|
||||||
|
T.DOC_URL = replace(replace(replace(SBILL_OFD_UTL, '<1040>', STAG1040), '<1041>', STAG1041),
|
||||||
|
'<1077>',
|
||||||
|
STAG1077)
|
||||||
|
where T.RN = RFISCDOC.NRN;
|
||||||
|
/* Устанавливаем значения тэгов */
|
||||||
|
begin
|
||||||
|
UDO_P_FISCDOCSPROP_SET_VAL(NPRN => RFISCDOC.NRN,
|
||||||
|
NCOMPANY => RFISCDOC.NCOMPANY,
|
||||||
|
SATTRIBUTE => '1040',
|
||||||
|
NVAL_NUMB => TO_NUMBER(STAG1040));
|
||||||
|
UDO_P_FISCDOCSPROP_SET_VAL(NPRN => RFISCDOC.NRN,
|
||||||
|
NCOMPANY => RFISCDOC.NCOMPANY,
|
||||||
|
SATTRIBUTE => '1041',
|
||||||
|
SVAL_STR => STAG1041);
|
||||||
|
UDO_P_FISCDOCSPROP_SET_VAL(NPRN => RFISCDOC.NRN,
|
||||||
|
NCOMPANY => RFISCDOC.NCOMPANY,
|
||||||
|
SATTRIBUTE => '1077',
|
||||||
|
SVAL_STR => STAG1077);
|
||||||
|
exception
|
||||||
|
when others then
|
||||||
|
P_EXCEPTION(0,
|
||||||
|
'Ошибка установки значения атрибута фискального документа: %s',
|
||||||
|
sqlerrm);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
/* Ошибка обработки */
|
||||||
|
when SSTATUS_FAIL then
|
||||||
|
begin
|
||||||
|
/* Проверим, что пришли код и текст ошибки */
|
||||||
|
if ((SERR_CODE is null) or (SERR_TEXT is null)) then
|
||||||
|
P_EXCEPTION(0,
|
||||||
|
'Документ в статусе "%s", но не указан код или текст ошибки.',
|
||||||
|
SSTATUS);
|
||||||
|
end if;
|
||||||
|
/* Выставим код и текст в фискальном документе */
|
||||||
|
update UDO_FISCDOCS T
|
||||||
|
set T.SEND_ERROR = SUBSTR(SERR_CODE || ': ' ||
|
||||||
|
REGEXP_REPLACE(replace(SERR_TEXT, CHR(10), ''), '[[:space:]]+', ' '),
|
||||||
|
1,
|
||||||
|
4000)
|
||||||
|
where T.RN = RFISCDOC.NRN;
|
||||||
|
end;
|
||||||
|
/* Неизвестный статус */
|
||||||
|
else
|
||||||
|
P_EXCEPTION(0, 'Cтатус докуента "%s" не поддерживается.', SSTATUS);
|
||||||
|
end case;
|
||||||
/* Âñ¸ ïðîøëî óñïåøíî */
|
/* Âñ¸ ïðîøëî óñïåøíî */
|
||||||
PKG_EXS.PRC_RESP_RESULT_SET(NIDENT => NIDENT);
|
PKG_EXS.PRC_RESP_RESULT_SET(NIDENT => NIDENT);
|
||||||
exception
|
exception
|
||||||
@ -81,5 +403,6 @@ create or replace package body UDO_PKG_EXS_ATOL as
|
|||||||
/* Âåðí¸ì îøèáêó */
|
/* Âåðí¸ì îøèáêó */
|
||||||
PKG_EXS.PRC_RESP_RESULT_SET(NIDENT => NIDENT, SRESULT => PKG_EXS.SPRC_RESP_RESULT_ERR, SMSG => sqlerrm);
|
PKG_EXS.PRC_RESP_RESULT_SET(NIDENT => NIDENT, SRESULT => PKG_EXS.SPRC_RESP_RESULT_ERR, SMSG => sqlerrm);
|
||||||
end V4_FFD105_PROCESS_GET_BILL_INF;
|
end V4_FFD105_PROCESS_GET_BILL_INF;
|
||||||
|
|
||||||
end;
|
end;
|
||||||
/
|
/
|
||||||
|
71
db/UDO_P_FISCDOCS_BASE_SEND.prc
Normal file
71
db/UDO_P_FISCDOCS_BASE_SEND.prc
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
create or replace procedure UDO_P_FISCDOCS_BASE_SEND
|
||||||
|
(
|
||||||
|
NRN in number, -- Ðåãèñòðàöèîííûé íîìåð
|
||||||
|
NCOMPANY in number -- Îðãàíèçàöèÿ
|
||||||
|
)
|
||||||
|
as
|
||||||
|
NEXSQUEUE PKG_STD.TREF; -- Ðåãèñòðàöèîííûé íîìåð çàïèñè î÷åðåäè îáìåíà
|
||||||
|
SPRC_NAME varchar2(60); -- Íàèìåíîâàíèå ïðîöåäóðû ïðîâåðêè çíà÷åíèé
|
||||||
|
PRMS PKG_CONTPRMLOC.TCONTAINER; -- Êîíòåéíåð äëÿ ïàðàìåòðîâ ïðîöåäóðû îáðàáîòêè
|
||||||
|
begin
|
||||||
|
/* Ïðîâåðêà çàïîëíåíèÿ îáÿçàòåëüíûõ àòðèáóòîâ */
|
||||||
|
UDO_P_FISCDOCSPROP_CHECK_REQ(NCOMPANY => NCOMPANY, NPRN => NRN);
|
||||||
|
|
||||||
|
/* Îïðåäåëåíèå ïðîöåäóðû ïðîâåðêè çíà÷åíèé */
|
||||||
|
for REC in (select V.PKG_CHECK,
|
||||||
|
V.PRC_CHECK
|
||||||
|
from UDO_FISCDOCS T,
|
||||||
|
UDO_FDKNDVERS V
|
||||||
|
where T.RN = NRN
|
||||||
|
and T.COMPANY = NCOMPANY
|
||||||
|
and T.TYPE_VERSION = V.RN)
|
||||||
|
loop
|
||||||
|
/* Íàèìåíîâàíèå ïðîöåäóðû */
|
||||||
|
SPRC_NAME := NULLIF(REC.PKG_CHECK || '.', '.') || REC.PRC_CHECK;
|
||||||
|
end loop;
|
||||||
|
|
||||||
|
/* Åñëè åñòü çàïîëíåíà ïðîöåäóðà ïðîâåðêè */
|
||||||
|
if (SPRC_NAME is not null) then
|
||||||
|
/* Óñòàíîâêà çíà÷åíèé ôèêñèðîâàííûõ âõîäíûõ ïàðàìåòðîâ */
|
||||||
|
PKG_CONTPRMLOC.APPENDN(RCONTAINER => PRMS, SNAME => 'NRN', NVALUE => NRN, NIN_OUT => PKG_STD.IPARAM_TYPE_IN);
|
||||||
|
PKG_CONTPRMLOC.APPENDN(RCONTAINER => PRMS,
|
||||||
|
SNAME => 'NCOMPANY',
|
||||||
|
NVALUE => NCOMPANY,
|
||||||
|
NIN_OUT => PKG_STD.IPARAM_TYPE_IN);
|
||||||
|
/* Âûïîëíåíèå ïðîöåäóðû */
|
||||||
|
begin
|
||||||
|
PKG_SQL_CALL.EXECUTE_STORED(SSTORED_NAME => SPRC_NAME, RPARAM_CONTAINER => PRMS);
|
||||||
|
exception
|
||||||
|
when others then
|
||||||
|
P_EXCEPTION(0,
|
||||||
|
'Îøèáêà âûïîëíåíèÿ ïðîöåäóðû "%s".' || CR || 'Òåêñò îøèáêè: %s',
|
||||||
|
SPRC_NAME,
|
||||||
|
sqlerrm);
|
||||||
|
end;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
/* Ôîðìèðîâàíèå è îòïðàâêà ñîîáùåíèÿ äëÿ ÀÒÎË-Îíëàéí */
|
||||||
|
UDO_P_FISCDOCS_MAKE_MSG_ATOL(NCOMPANY => NCOMPANY, NFISCDOC => NRN, NEXSQUEUE => NEXSQUEUE);
|
||||||
|
|
||||||
|
/* Ñîçäàíèå ñâÿçè ìåæäó ÷åêîì è î÷åðåäüþ îáìåíà */
|
||||||
|
PKG_DOCLINKS.LINK(NFLAG_SMART => 0,
|
||||||
|
NCOMPANY => NCOMPANY,
|
||||||
|
SIN_UNITCODE => 'UDO_FiscalDocuments',
|
||||||
|
NIN_DOCUMENT => NRN,
|
||||||
|
SOUT_UNITCODE => 'EXSQueue',
|
||||||
|
NOUT_DOCUMENT => NEXSQUEUE);
|
||||||
|
|
||||||
|
/* Èçìåíåíèå ñòàòóñà */
|
||||||
|
UDO_P_FISCDOCS_BASE_SET_STATUS(NRN => NRN, NCOMPANY => NCOMPANY, NSTATUS => 1);
|
||||||
|
|
||||||
|
/* Óñòàíîâêà äàòû è âðåìåíè îòïðàâêè */
|
||||||
|
update UDO_FISCDOCS
|
||||||
|
set SEND_TIME = sysdate
|
||||||
|
where RN = NRN
|
||||||
|
and COMPANY = NCOMPANY;
|
||||||
|
|
||||||
|
if (sql%notfound) then
|
||||||
|
PKG_MSG.RECORD_NOT_FOUND(NDOCUMENT => NRN, SUNIT_TABLE => 'UDO_FiscalDocuments');
|
||||||
|
end if;
|
||||||
|
end;
|
||||||
|
/
|
27
db/UDO_P_FISCDOCS_GET_STATE_ATOL.prc
Normal file
27
db/UDO_P_FISCDOCS_GET_STATE_ATOL.prc
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
create or replace procedure UDO_P_FISCDOCS_GET_STATE_ATOL
|
||||||
|
as
|
||||||
|
NEXSQUEUE PKG_STD.TREF; -- Ðåãèñòðàöèîííûé íîìåð äîáàâëåííîé ïîçèöèè î÷åðåäè îáìåíà
|
||||||
|
begin
|
||||||
|
/* Îáõîäèì ôèñêàëüíûå äîêóìåíòû, óñïåøíî îòïðàâëåííûå â ÀÒÎË, íî ïî êîòîðûì åù¸ íåò ïðîñòàâëåííîãî ñòàòóñà */
|
||||||
|
for C in (select T.COMPANY,
|
||||||
|
T.RN,
|
||||||
|
Q.RESP BUUID
|
||||||
|
from UDO_FISCDOCS T,
|
||||||
|
EXSQUEUE Q
|
||||||
|
where ((T.SEND_ERROR is null) and (T.CONFIRM_DATE is null))
|
||||||
|
and Q.LNK_COMPANY = T.COMPANY
|
||||||
|
and Q.LNK_UNITCODE = 'UDO_FiscalDocuments'
|
||||||
|
and Q.LNK_DOCUMENT = T.RN
|
||||||
|
and Q.EXEC_STATE = PKG_EXS.NQUEUE_EXEC_STATE_OK
|
||||||
|
and Q.EXSSERVICEFN = UDO_PKG_EXS_ATOL.UTL_FISCDOC_GET_REG_EXSFN(T.RN))
|
||||||
|
loop
|
||||||
|
/* Ñòàâèì çàïðîñ íà ïîëó÷åíèå ñòàòóñà äîêóìåíòà â î÷åðåäü */
|
||||||
|
PKG_EXS.QUEUE_PUT(NEXSSERVICEFN => UDO_PKG_EXS_ATOL.UTL_FISCDOC_GET_INF_EXSFN(NFISCDOC => C.RN),
|
||||||
|
BMSG => C.BUUID,
|
||||||
|
NLNK_COMPANY => C.COMPANY,
|
||||||
|
NLNK_DOCUMENT => C.RN,
|
||||||
|
SLNK_UNITCODE => 'UDO_FiscalDocuments',
|
||||||
|
NNEW_EXSQUEUE => NEXSQUEUE);
|
||||||
|
end loop;
|
||||||
|
end;
|
||||||
|
/
|
@ -1,20 +1,18 @@
|
|||||||
create or replace procedure UDO_P_FISCDOCS_MAKE_MSG_ATOL
|
create or replace procedure UDO_P_FISCDOCS_MAKE_MSG_ATOL
|
||||||
(
|
(
|
||||||
NCOMPANY in number, -- Организация
|
NCOMPANY in number, -- Îðãàíèçàöèÿ
|
||||||
NFISCDOC in number, -- Регистрационный номер фискального документа
|
NFISCDOC in number, -- Ðåãèñòðàöèîííûé íîìåð ôèñêàëüíîãî äîêóìåíòà
|
||||||
NEXSQUEUE out number -- Регистрационный номер добавленной позиции очереди обмена
|
NEXSQUEUE out number -- Ðåãèñòðàöèîííûé íîìåð äîáàâëåííîé ïîçèöèè î÷åðåäè îáìåíà
|
||||||
)
|
)
|
||||||
as
|
as
|
||||||
/* Ëîêàëüíûå ïåðåìåííûå */
|
/* Ëîêàëüíûå ïåðåìåííûå */
|
||||||
CDATA clob; -- Буфер для XML-посылки
|
CDATA clob; -- Áóôåð äëÿ XML-ïîñûëêè
|
||||||
SEXSSERVICE EXSSERVICEFN.CODE%type; -- Код сервиса-обработчика
|
NTMP_RN PKG_STD.TREF; -- Áóôåð äëÿ âû÷èñëåíèé
|
||||||
SEXSSERVICEFN EXSSERVICEFN.CODE%type; -- Код функции отправки
|
|
||||||
NTMP_RN PKG_STD.TREF; -- Буфер для вычислений
|
|
||||||
|
|
||||||
/* Äîáàâëåíèå ïóñòîé îòêðûòîé âåòêè */
|
/* Äîáàâëåíèå ïóñòîé îòêðûòîé âåòêè */
|
||||||
procedure NODE
|
procedure NODE
|
||||||
(
|
(
|
||||||
SNAME varchar2 -- Имя ветки
|
SNAME varchar2 -- Èìÿ âåòêè
|
||||||
)
|
)
|
||||||
as
|
as
|
||||||
begin
|
begin
|
||||||
@ -27,8 +25,8 @@ as
|
|||||||
/* Äîáàâëåíèå âåòêè ñî çíà÷åíèåì (ñòðîêà) */
|
/* Äîáàâëåíèå âåòêè ñî çíà÷åíèåì (ñòðîêà) */
|
||||||
procedure NODE
|
procedure NODE
|
||||||
(
|
(
|
||||||
SNAME varchar2, -- Имя ветки
|
SNAME varchar2, -- Èìÿ âåòêè
|
||||||
SVALUE varchar2 -- Значение ветки
|
SVALUE varchar2 -- Çíà÷åíèå âåòêè (ñòðîêà)
|
||||||
)
|
)
|
||||||
as
|
as
|
||||||
begin
|
begin
|
||||||
@ -45,8 +43,8 @@ as
|
|||||||
/* Äîáàâëåíèå âåòêè ñî çíà÷åíèåì (÷èñëî) */
|
/* Äîáàâëåíèå âåòêè ñî çíà÷åíèåì (÷èñëî) */
|
||||||
procedure NODE
|
procedure NODE
|
||||||
(
|
(
|
||||||
SNAME varchar2, -- Имя ветки
|
SNAME varchar2, -- Èìÿ âåòêè
|
||||||
NVALUE number -- Значение ветки
|
NVALUE number -- Çíà÷åíèå âåòêè (÷èñëî)
|
||||||
)
|
)
|
||||||
as
|
as
|
||||||
begin
|
begin
|
||||||
@ -63,8 +61,8 @@ as
|
|||||||
/* Äîáàâëåíèå âåòêè ñî çíà÷åíèåì (äàòà) */
|
/* Äîáàâëåíèå âåòêè ñî çíà÷åíèåì (äàòà) */
|
||||||
procedure NODE
|
procedure NODE
|
||||||
(
|
(
|
||||||
SNAME varchar2, -- Имя ветки
|
SNAME varchar2, -- Èìÿ âåòêè
|
||||||
DVALUE date -- Значение ветки
|
DVALUE date -- Çíà÷åíèå âåòêè (äàòà)
|
||||||
)
|
)
|
||||||
as
|
as
|
||||||
begin
|
begin
|
||||||
@ -92,23 +90,7 @@ begin
|
|||||||
from UDO_V_FISCDOCS T
|
from UDO_V_FISCDOCS T
|
||||||
where T.NRN = UDO_P_FISCDOCS_MAKE_MSG_ATOL.NFISCDOC
|
where T.NRN = UDO_P_FISCDOCS_MAKE_MSG_ATOL.NFISCDOC
|
||||||
and T.NCOMPANY = UDO_P_FISCDOCS_MAKE_MSG_ATOL.NCOMPANY)
|
and T.NCOMPANY = UDO_P_FISCDOCS_MAKE_MSG_ATOL.NCOMPANY)
|
||||||
loop
|
loop
|
||||||
/* Выбираем API обмена в зависимости от версии фискального документа */
|
|
||||||
case D.STYPE_VERSION
|
|
||||||
/* ФФД 1.05 */
|
|
||||||
when '1.05' then
|
|
||||||
begin
|
|
||||||
SEXSSERVICE := 'АТОЛ_V4_ИСХ';
|
|
||||||
SEXSSERVICEFN := 'V4_ФФД1.05_РегистрацияЧекаРПВ';
|
|
||||||
end;
|
|
||||||
/* Неизвестная версия ФФД */
|
|
||||||
else
|
|
||||||
begin
|
|
||||||
P_EXCEPTION(0,
|
|
||||||
'Версия фискального документа "%s" не поддерживается!',
|
|
||||||
D.STYPE_VERSION);
|
|
||||||
end;
|
|
||||||
end case;
|
|
||||||
/* Äàííûå çàãîëîâêà ôèñêàëüíîãî äîêóìåíòà */
|
/* Äàííûå çàãîëîâêà ôèñêàëüíîãî äîêóìåíòà */
|
||||||
NODE(SNAME => 'NRN', NVALUE => D.NRN);
|
NODE(SNAME => 'NRN', NVALUE => D.NRN);
|
||||||
NODE(SNAME => 'NCOMPANY', NVALUE => D.NCOMPANY);
|
NODE(SNAME => 'NCOMPANY', NVALUE => D.NCOMPANY);
|
||||||
@ -187,8 +169,7 @@ begin
|
|||||||
/* Ôèíàëèçèðóåì ñáîðêó XML-äîêóìåíòà */
|
/* Ôèíàëèçèðóåì ñáîðêó XML-äîêóìåíòà */
|
||||||
PKG_XMLFAST.EPILOGUE(LDATA => CDATA);
|
PKG_XMLFAST.EPILOGUE(LDATA => CDATA);
|
||||||
/* Îòïðàâëÿåì ñôîðìèðîâàííûé äîêóìåíò */
|
/* Îòïðàâëÿåì ñôîðìèðîâàííûé äîêóìåíò */
|
||||||
PKG_EXS.QUEUE_PUT(SEXSSERVICE => SEXSSERVICE,
|
PKG_EXS.QUEUE_PUT(NEXSSERVICEFN => UDO_PKG_EXS_ATOL.UTL_FISCDOC_GET_REG_EXSFN(NFISCDOC => NFISCDOC),
|
||||||
SEXSSERVICEFN => SEXSSERVICEFN,
|
|
||||||
BMSG => CLOB2BLOB(LCDATA => CDATA, SCHARSET => 'UTF8'),
|
BMSG => CLOB2BLOB(LCDATA => CDATA, SCHARSET => 'UTF8'),
|
||||||
NLNK_COMPANY => NCOMPANY,
|
NLNK_COMPANY => NCOMPANY,
|
||||||
NLNK_DOCUMENT => NFISCDOC,
|
NLNK_DOCUMENT => NFISCDOC,
|
||||||
|
@ -104,12 +104,10 @@
|
|||||||
// Подключение библиотек
|
// Подключение библиотек
|
||||||
//----------------------
|
//----------------------
|
||||||
|
|
||||||
const util = require("util"); //Встроенные вспомогательные утилиты
|
|
||||||
const parseString = require("xml2js").parseString; //Конвертация XML в JSON
|
const parseString = require("xml2js").parseString; //Конвертация XML в JSON
|
||||||
|
const js2xmlparser = require("js2xmlparser"); //Конвертация JSON в XML
|
||||||
const _ = require("lodash"); //Работа с массивами и коллекциями
|
const _ = require("lodash"); //Работа с массивами и коллекциями
|
||||||
const rqp = require("request-promise"); //Работа с HTTP/HTTPS запросами
|
|
||||||
const { buildURL } = require("@core/utils"); //Вспомогательные функции
|
const { buildURL } = require("@core/utils"); //Вспомогательные функции
|
||||||
const { NFN_TYPE_LOGIN } = require("@models/obj_service_function");
|
|
||||||
|
|
||||||
//---------------------
|
//---------------------
|
||||||
// Глобальные константы
|
// Глобальные константы
|
||||||
@ -118,6 +116,11 @@ const { NFN_TYPE_LOGIN } = require("@models/obj_service_function");
|
|||||||
//Код круппы ККТ
|
//Код круппы ККТ
|
||||||
const SGROUP_CODE = "v4-online-atol-ru_4179";
|
const SGROUP_CODE = "v4-online-atol-ru_4179";
|
||||||
|
|
||||||
|
//Статусы документов АТОЛ-онлайн
|
||||||
|
const SSTATUS_DONE = "done"; //Готово
|
||||||
|
const SSTATUS_FAIL = "fail"; //Ошибка
|
||||||
|
const SSTATUS_WAIT = "wait"; //Ожидание
|
||||||
|
|
||||||
//Словарь - Признак способа расчёта
|
//Словарь - Признак способа расчёта
|
||||||
const paymentMethod = {
|
const paymentMethod = {
|
||||||
sName: "Признак способа расчёта",
|
sName: "Признак способа расчёта",
|
||||||
@ -474,24 +477,34 @@ const beforeRegBillSIR = async prms => {
|
|||||||
|
|
||||||
//Обработчик "После" отправки запроса на регистрацию чека (приход, расход, возврат) серверу "АТОЛ-Онлайн"
|
//Обработчик "После" отправки запроса на регистрацию чека (приход, расход, возврат) серверу "АТОЛ-Онлайн"
|
||||||
const afterRegBillSIR = async prms => {
|
const afterRegBillSIR = async prms => {
|
||||||
|
//Буфер для данных ответа сервера
|
||||||
let resp = null;
|
let resp = null;
|
||||||
|
//Если есть данные от сервера АТОЛ
|
||||||
if (prms.queue.blResp) {
|
if (prms.queue.blResp) {
|
||||||
|
//Пытаемся их разбирать
|
||||||
try {
|
try {
|
||||||
resp = JSON.parse(prms.queue.blResp.toString());
|
resp = JSON.parse(prms.queue.blResp.toString());
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
//Пришел не JSON
|
||||||
throw new Error(`Неожиданный ответ сервера АТОЛ-Онлайн. Ошибка интерпретации: ${e.message}`);
|
throw new Error(`Неожиданный ответ сервера АТОЛ-Онлайн. Ошибка интерпретации: ${e.message}`);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
//Данных от сервера нет
|
||||||
throw new Error(`Сервер АТОЛ-Онлайн не вернул ответ`);
|
throw new Error(`Сервер АТОЛ-Онлайн не вернул ответ`);
|
||||||
}
|
}
|
||||||
|
//Данные есть и нам удалось их разобрать, проверяем на наличие ошибок
|
||||||
if (resp.error === null) {
|
if (resp.error === null) {
|
||||||
|
//Ошибок нет - забираем идентификатор документа в системе АТОЛ и кладём в тело ответа - он это то что нам нужно
|
||||||
return {
|
return {
|
||||||
blResp: new Buffer(resp.uuid)
|
blResp: new Buffer(resp.uuid)
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
|
//Есть ошибки, посмотрим что это, может быть аутентификация (кончился токен)
|
||||||
if (resp.error.code === 10 || resp.error.code === 11) {
|
if (resp.error.code === 10 || resp.error.code === 11) {
|
||||||
|
//да, это была она - сигнализируем серверу приложений - надо переподключаться
|
||||||
return { bUnAuth: true };
|
return { bUnAuth: true };
|
||||||
} else {
|
} else {
|
||||||
|
//прочие ошибки - фиксируем в журнале
|
||||||
throw new Error(`Сервер АТОЛ-Онлайн вернул ошибку: ${resp.error.text}`);
|
throw new Error(`Сервер АТОЛ-Онлайн вернул ошибку: ${resp.error.text}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -529,8 +542,107 @@ const beforeGetBillInfo = async prms => {
|
|||||||
|
|
||||||
//Обработчик "После" отправки запроса на получение информации о чеке серверу "АТОЛ-Онлайн"
|
//Обработчик "После" отправки запроса на получение информации о чеке серверу "АТОЛ-Онлайн"
|
||||||
const afterGetBillInfo = async prms => {
|
const afterGetBillInfo = async prms => {
|
||||||
if (prms.queue.blResp) console.log(prms.queue.blResp.toString());
|
//if (prms.queue.blResp) console.log(prms.queue.blResp.toString());
|
||||||
else console.log("Сервер не вернул ответ");
|
//else console.log("Сервер не вернул ответ");
|
||||||
|
//Буфер для результата работы обработчика
|
||||||
|
let res = null;
|
||||||
|
//Буфер для данных ответа сервера
|
||||||
|
let resp = null;
|
||||||
|
//Если есть данные от сервера АТОЛ
|
||||||
|
if (prms.queue.blResp) {
|
||||||
|
//Пытаемся их разбирать
|
||||||
|
try {
|
||||||
|
resp = JSON.parse(prms.queue.blResp.toString());
|
||||||
|
} catch (e) {
|
||||||
|
//Пришел не JSON
|
||||||
|
throw new Error(`Неожиданный ответ сервера АТОЛ-Онлайн. Ошибка интерпретации: ${e.message}`);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
//Данных от сервера нет
|
||||||
|
throw new Error(`Сервер АТОЛ-Онлайн не вернул ответ`);
|
||||||
|
}
|
||||||
|
//Данные есть и нам удалось их разобрать - проверим, что нет ошибок аутентификации
|
||||||
|
//Есть ошибки, посмотрим что это, может быть аутентификация (кончился токен)
|
||||||
|
if (resp.error !== null && (resp.error.code === 10 || resp.error.code === 11)) {
|
||||||
|
//да, это была она - сигнализируем серверу приложений - надо переподключаться и дальше не работаем
|
||||||
|
return { bUnAuth: true };
|
||||||
|
}
|
||||||
|
//Ошибок атуентификации нет - проверяем состояние документа
|
||||||
|
if (resp.status) {
|
||||||
|
//Проверям, может быть документ зарегистрирован
|
||||||
|
if (resp.status === SSTATUS_DONE) {
|
||||||
|
//Документ обработан, проверим наличие данных фискализации
|
||||||
|
if (resp.payload) {
|
||||||
|
//Ошибок нет - забираем данные фискализации и кладём в тело ответа - это то что нам нужно
|
||||||
|
res = {
|
||||||
|
//Статус обработки документа
|
||||||
|
STATUS: resp.status,
|
||||||
|
//Дата и время документа внешней системы
|
||||||
|
TIMESTAMP: resp.timestamp,
|
||||||
|
//Дата и время документа из ФН
|
||||||
|
TAG1012: resp.payload.receipt_datetime,
|
||||||
|
//Фискальный номер документа
|
||||||
|
TAG1040: resp.payload.fiscal_document_number,
|
||||||
|
//Номер ФН
|
||||||
|
TAG1041: resp.payload.fn_number,
|
||||||
|
//Фискальный признак документа
|
||||||
|
TAG1077: resp.payload.fiscal_document_attribute
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
//В ответе сервера нет ни данных фискализации, при этом документ отработан - это неожиданный ответ
|
||||||
|
throw new Error(
|
||||||
|
`Неожиданный ответ сервера АТОЛ-Онлайн. Ошибка интерпретации: документ в статусе "Готов" но в ответе сервера нет данных фискализации`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
//Документ не зарегистрирован, может быть ещё обрабатывается
|
||||||
|
if (resp.status === SSTATUS_WAIT) {
|
||||||
|
//Скажем и об этом
|
||||||
|
res = {
|
||||||
|
//Статус обработки документа
|
||||||
|
STATUS: resp.status
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
//Документ не готов и не обрабатывается - очевидно ошибка при регистрации
|
||||||
|
if (resp.status === SSTATUS_FAIL) {
|
||||||
|
if (resp.error) {
|
||||||
|
res = {
|
||||||
|
//Статус обработки документа
|
||||||
|
STATUS: resp.status,
|
||||||
|
//Ошибка
|
||||||
|
ERROR: {
|
||||||
|
//Код ошибки
|
||||||
|
CODE: resp.error.code,
|
||||||
|
//Текст ошибки
|
||||||
|
TEXT: resp.error.text
|
||||||
|
}
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
//Статус - ошибка, но ошибки нет, это неожиданный ответ
|
||||||
|
throw new Error(
|
||||||
|
`Неожиданный ответ сервера АТОЛ-Онлайн. Ошибка интерпретации: документ в статусе "Ошибка" но в ответе сервера нет об ошибке`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
//Других статусов быть не должно - это неожиданный ответ
|
||||||
|
throw new Error(
|
||||||
|
`Неожиданный ответ сервера АТОЛ-Онлайн. Ошибка интерпретации: неизвестный статус документа - ${
|
||||||
|
resp.status
|
||||||
|
}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
//Нет данных о статусе документа - это неожиданный ответ
|
||||||
|
throw new Error(
|
||||||
|
`Неожиданный ответ сервера АТОЛ-Онлайн. Ошибка интерпретации: статус документа в ответе не определён`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
//Вернём сформированный ответ
|
||||||
|
return {
|
||||||
|
blResp: new Buffer(js2xmlparser.parse("RESP", res))
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
//-----------------
|
//-----------------
|
||||||
|
Loading…
x
Reference in New Issue
Block a user