diff --git a/db/UDO_PKG_EXS_ATOL.pck b/db/UDO_PKG_EXS_ATOL.pck index fb1a59f..b094193 100644 --- a/db/UDO_PKG_EXS_ATOL.pck +++ b/db/UDO_PKG_EXS_ATOL.pck @@ -1,17 +1,36 @@ create or replace package UDO_PKG_EXS_ATOL as + /* Константы - тестовое окружение сервера АТОЛ-Онлайн */ + STEST_SRV_ROOT_PATTERN constant varchar2(80) := '%testonline.atol.ru%'; -- Шаблон адреса тестового сервера + STEST_INN constant varchar2(80) := '5544332219'; -- Тестовый ИНН + STEST_ADDR constant varchar2(80) := 'https://v4.online.atol.ru'; -- Тестовый адрес расчётов + /* Константы - типы функций обработки */ SFN_TYPE_REG_BILL constant varchar2(20) := 'REG_BILL'; -- Типовая функция регистрации чека SFN_TYPE_GET_BILL_INF constant varchar2(20) := 'GET_BILL_INF'; -- Типовая функция получения иформации о регистрации чека + + /* Константы - версии ФФД (строковые представления) */ + SFFD105 constant varchar2(20) := '1.05'; -- Версия ФФД 1.05 + SFFD110 constant varchar2(20) := '1.10'; -- Версия ФФД 1.10 + /* Константы - значения тэга "Номер версии ФФД" (1209) для версий формата */ + NTAG1209_FFD105 constant number(2) := 2; -- Значение тэга 1209 для версии ФФД 1.05 + NTAG1209_FFD110 constant number(2) := 3; -- Значение тэга 1209 для версии ФФД 1.10 + + /* Проверка сервиса на то, что он является тестовым */ + function UTL_EXSSERVICE_IS_TEST + ( + NEXSSERVICE in number -- Регистрационный номер сервиса обмена + ) return boolean; -- Признак тестового сервиса (true - тестовый, false - не тестовый) + /* Получение рег. номера функции сервиса обмена для регистрации чека по рег. номеру фискального документа */ - function UTL_FISCDOC_GET_REG_EXSFN + function UTL_FISCDOC_GET_EXSFN_REG ( NFISCDOC in number -- Рег. номер фискального документа ) return number; -- Рег. номер функции регистрации чека в сервисе АТОЛ-Онлайн /* Получение рег. номера функции сервиса обмена для запроса информации о регистрации чека по рег. номеру фискального документа */ - function UTL_FISCDOC_GET_INF_EXSFN + function UTL_FISCDOC_GET_EXSFN_INF ( NFISCDOC in number -- Рег. номер фискального документа ) return number; -- Рег. номер функции запроса информации о регистрации чека в сервисе АТОЛ-Онлайн @@ -72,13 +91,13 @@ create or replace package body UDO_PKG_EXS_ATOL as /* Считывание записи фискального документа */ function UTL_FISCDOC_GET ( - NFISCDOC in number -- Рег. номер фискального документа - ) return UDO_V_FISCDOCS%rowtype -- Найденная запись фискального документа + NFISCDOC in number -- Рег. номер фискального документа + ) return UDO_FISCDOCS%rowtype -- Найденная запись фискального документа is - RRES UDO_V_FISCDOCS%rowtype; -- Буфер для результата + RRES UDO_FISCDOCS%rowtype; -- Буфер для результата begin /* Считаем запись */ - select T.* into RRES from UDO_V_FISCDOCS T where T.NRN = NFISCDOC; + select T.* into RRES from UDO_FISCDOCS T where T.RN = NFISCDOC; /* Вернём результат */ return RRES; exception @@ -87,137 +106,115 @@ create or replace package body UDO_PKG_EXS_ATOL as end UTL_FISCDOC_GET; /* Получение мнемокода сервиса обмена и мнемокода его функции по типу функции обработки и версии ФФД */ - procedure UTL_FISCDOC_GET_EXSFN_BY_FFD + procedure UTL_FISCDOC_GET_EXSFN ( + NFISCDOC in number, -- Рег. номер фискального документа SFN_TYPE in varchar2, -- Тип функции обработки (см. константы SFN_TYPE_*) - SFFD_VERSION in varchar2, -- Версия ФФД - SEXSSERVICE out varchar2, -- Код сервиса-обработчика - SEXSSERVICEFN out varchar2 -- Код функции-обработчика + NEXSSERVICEFN out number -- Рег. номер функции-обработчика ) 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; + begin + select DECODE(SFN_TYPE, SFN_TYPE_REG_BILL, SFNREG.RN, SFN_TYPE_GET_BILL_INF, SFNINF.RN) + into NEXSSERVICEFN + from UDO_FISCDOCS FD, + UDO_FDKNDVERS TV, + EXSSERVICEFN SFNREG, + EXSSERVICEFN SFNINF + where FD.RN = NFISCDOC + and FD.TYPE_VERSION = TV.RN + and TV.FUNCTION_SEND = SFNREG.RN(+) + and TV.FUNCTION_RESP = SFNINF.RN(+); + exception + when others then + NEXSSERVICEFN := null; + end; + /* Проверим, что хоть что-то нашлось */ + if (NEXSSERVICEFN is null) then + P_EXCEPTION(0, + 'Для фискального документа (RN: %s) не определеная типовая функция "%s".', + TO_CHAR(NFISCDOC), + SFN_TYPE); + end if; + end UTL_FISCDOC_GET_EXSFN; /* Получение рег. номера функции сервиса обмена для регистрации чека по рег. номеру фискального документа */ - function UTL_FISCDOC_GET_REG_EXSFN + function UTL_FISCDOC_GET_EXSFN_REG ( - NFISCDOC in number -- Рег. номер фискального документа - ) return number -- Рег. номер функции регистрации чека в сервисе АТОЛ-Онлайн + 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; -- Код функции-обработчика + NRES PKG_STD.TREF; -- Буфер для результата 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); + UTL_FISCDOC_GET_EXSFN(NFISCDOC => NFISCDOC, SFN_TYPE => SFN_TYPE_REG_BILL, NEXSSERVICEFN => NRES); /* Вернём результат */ return NRES; - end UTL_FISCDOC_GET_REG_EXSFN; + end UTL_FISCDOC_GET_EXSFN_REG; /* Получение рег. номера функции сервиса обмена для запроса информации о регистрации чека по рег. номеру фискального документа */ - function UTL_FISCDOC_GET_INF_EXSFN + function UTL_FISCDOC_GET_EXSFN_INF ( - NFISCDOC in number -- Рег. номер фискального документа - ) return number -- Рег. номер функции запроса информации о регистрации чека в сервисе АТОЛ-Онлайн + 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; -- Код функции-обработчика + NRES PKG_STD.TREF; -- Буфер для результата 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); + UTL_FISCDOC_GET_EXSFN(NFISCDOC => NFISCDOC, SFN_TYPE => SFN_TYPE_GET_BILL_INF, NEXSSERVICEFN => NRES); /* Вернём результат */ return NRES; - end UTL_FISCDOC_GET_INF_EXSFN; + end UTL_FISCDOC_GET_EXSFN_INF; + + /* Контроль версии ФФД */ + procedure UTL_FISCDOC_CHECK_FFD_VERS + ( + NCOMPANY in number, -- Рег. номер организации + NFISCDOC in number, -- Рег. номер фискального документа + NEXPECTED_VERS in number, -- Ожидаемая версия ФФД (по значению тэга 1209, см. констнаты NTAG1209_FFD*) + SEXPECTED_VERS in varchar2 -- Ожидаемая версия ФФД (строковое представление) + ) + is + begin + /* Считаем тэг 1209 (в нем хранится номер версии ФФД) и сверим значения, фактическое и ожидаемое процедурой */ + if (UDO_F_FISCDOCS_GET_NUMB(NRN => NFISCDOC, NCOMPANY => NCOMPANY, SATTRIBUTE => '1209') != NEXPECTED_VERS) then + P_EXCEPTION(0, + 'Версия формата фискального документа (значение тэга 1209 - %s) не поддерживается. Ожидаемая версия - %s (значение тэга 1209 - %s).', + NVL(TO_CHAR(UDO_F_FISCDOCS_GET_NUMB(NRN => NFISCDOC, NCOMPANY => NCOMPANY, SATTRIBUTE => '1209')), + '<НЕ УКАЗАНО>'), + NVL(SEXPECTED_VERS, '<НЕ УКАЗАНА>'), + NVL(TO_CHAR(NEXPECTED_VERS), '<НЕ УКАЗАНО>')); + end if; + end UTL_FISCDOC_CHECK_FFD_VERS; + + /* Проверка сервиса на то, что он является тестовым */ + function UTL_EXSSERVICE_IS_TEST + ( + NEXSSERVICE in number -- Регистрационный номер сервиса обмена + ) return boolean -- Признак тестового сервиса (true - тестовый, false - не тестовый) + is + REXSSERVICE EXSSERVICE%rowtype; -- Запись сервиса обмена + begin + /* Считаем запись сервиса обмена */ + REXSSERVICE := GET_EXSSERVICE_ID(NFLAG_SMART => 0, NRN => NEXSSERVICE); + /* Проверим его по адресу */ + if (REXSSERVICE.SRV_ROOT like STEST_SRV_ROOT_PATTERN) then + return true; + else + return false; + end if; + end; /* Отработка ответов АТОЛ (v4) на регистрацию чека на приход, расход, возврат (ФФД 1.05) */ procedure V4_FFD105_PROCESS_REG_BILL_SIR ( - NIDENT in number, -- Идентификатор процесса - NEXSQUEUE in number -- Регистрационный номер обрабатываемой позиции очереди обмена + NIDENT in number, -- Идентификатор процесса + NEXSQUEUE in number -- Регистрационный номер обрабатываемой позиции очереди обмена ) is - REXSQUEUE EXSQUEUE%rowtype; -- Запись позиции очереди - RFISCDOC UDO_V_FISCDOCS%rowtype; -- Запись фискального документа - CTMP clob; -- Буфер для хранения данных ответа сервера + REXSQUEUE EXSQUEUE%rowtype; -- Запись позиции очереди + RFISCDOC UDO_FISCDOCS%rowtype; -- Запись фискального документа + CTMP clob; -- Буфер для хранения данных ответа сервера begin /* Считаем запись очереди */ REXSQUEUE := GET_EXSQUEUE_ID(NFLAG_SMART => 0, NRN => NEXSQUEUE); @@ -226,11 +223,10 @@ create or replace package body UDO_PKG_EXS_ATOL as /* Считаем запись фискального документа */ 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; + UTL_FISCDOC_CHECK_FFD_VERS(NCOMPANY => RFISCDOC.COMPANY, + NFISCDOC => RFISCDOC.RN, + NEXPECTED_VERS => NTAG1209_FFD105, + SEXPECTED_VERS => SFFD105); /* Разбираем ответ */ CTMP := BLOB2CLOB(LBDATA => REXSQUEUE.RESP, SCHARSET => 'UTF8'); if (CTMP is null) then @@ -249,23 +245,25 @@ create or replace package body UDO_PKG_EXS_ATOL as /* Отработка ответов АТОЛ (v4) на запрос сведений о зарегистрированном документе (ФФД 1.05) */ procedure V4_FFD105_PROCESS_GET_BILL_INF ( - NIDENT in number, -- Идентификатор процесса - NEXSQUEUE in number -- Регистрационный номер обрабатываемой позиции очереди обмена + NIDENT in number, -- Идентификатор процесса + NEXSQUEUE in number -- Регистрационный номер обрабатываемой позиции очереди обмена ) is - REXSQUEUE EXSQUEUE%rowtype; -- Запись позиции очереди - 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; -- Буфер для значения "Текст ошибки" + REXSQUEUE EXSQUEUE%rowtype; -- Запись позиции очереди + RFISCDOC UDO_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) + STAG1038 PKG_STD.TSTRING; -- Буфер для значения "Номер смены" (тэг 1038) + STAG1040 PKG_STD.TSTRING; -- Буфер для значения "Фискальный номер документа" (тэг 1040) + STAG1041 PKG_STD.TSTRING; -- Буфер для значения "Номер ФН" (тэг 1041) + STAG1042 PKG_STD.TSTRING; -- Буфер для значения "Номер чека в смене" (тэг 1042) + STAG1077 PKG_STD.TSTRING; -- Буфер для значения "Фискальный признак документа" (тэг 1077) + SERR_CODE PKG_STD.TSTRING; -- Буфер для значения "Код ошибки" + SERR_TEXT PKG_STD.TSTRING; -- Буфер для значения "Текст ошибки" begin /* Считаем запись очереди */ REXSQUEUE := GET_EXSQUEUE_ID(NFLAG_SMART => 0, NRN => NEXSQUEUE); @@ -274,11 +272,10 @@ create or replace package body UDO_PKG_EXS_ATOL as /* Считаем запись фискального документа */ 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; + UTL_FISCDOC_CHECK_FFD_VERS(NCOMPANY => RFISCDOC.COMPANY, + NFISCDOC => RFISCDOC.RN, + NEXPECTED_VERS => NTAG1209_FFD105, + SEXPECTED_VERS => SFFD105); /* Разбираем ответ */ begin RDOC := PKG_XPATH.PARSE_FROM_BLOB(LBXML => REXSQUEUE.RESP, SCHARSET => 'UTF8'); @@ -290,12 +287,14 @@ create or replace package body UDO_PKG_EXS_ATOL as 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')); + STAG1038 := PKG_XPATH.VALUE(RNODE => PKG_XPATH.SINGLE_NODE(RPARENT_NODE => RROOT_NODE, SPATTERN => '/RESP/TAG1038')); 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')); + STAG1042 := PKG_XPATH.VALUE(RNODE => PKG_XPATH.SINGLE_NODE(RPARENT_NODE => RROOT_NODE, SPATTERN => '/RESP/TAG1042')); STAG1077 := PKG_XPATH.VALUE(RNODE => PKG_XPATH.SINGLE_NODE(RPARENT_NODE => RROOT_NODE, SPATTERN => '/RESP/TAG1077')); + STIMESTAMP := PKG_XPATH.VALUE(RNODE => PKG_XPATH.SINGLE_NODE(RPARENT_NODE => RROOT_NODE, + SPATTERN => '/RESP/TIMESTAMP')); 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, @@ -323,6 +322,16 @@ create or replace package body UDO_PKG_EXS_ATOL as 'Документ в статусе "%s", но не указано значение "Дата и время документа внешней системы".', SSTATUS); end if; + if (STAG1012 is null) then + P_EXCEPTION(0, + 'Документ в статусе "%s", но не указано значение "Дата и время документа из ФН" (тэг 1012).', + SSTATUS); + end if; + if (STAG1038 is null) then + P_EXCEPTION(0, + 'Документ в статусе "%s", но не указано значение "Номер смены" (тэг 1038).', + SSTATUS); + end if; if (STAG1040 is null) then P_EXCEPTION(0, 'Документ в статусе "%s", но не указано значение "Фискальный номер документа" (тэг 1040).', @@ -333,6 +342,11 @@ create or replace package body UDO_PKG_EXS_ATOL as 'Документ в статусе "%s", но не указано значение "Номер ФН" (тэг 1041).', SSTATUS); end if; + if (STAG1042 is null) then + P_EXCEPTION(0, + 'Документ в статусе "%s", но не указано значение "Номер чека в смене" (тэг 1042).', + SSTATUS); + end if; if (STAG1077 is null) then P_EXCEPTION(0, 'Документ в статусе "%s", но не указано значение "Фискальный признак документа" (тэг 1077).', @@ -353,19 +367,31 @@ create or replace package body UDO_PKG_EXS_ATOL as T.DOC_URL = replace(replace(replace(SBILL_OFD_UTL, '<1040>', STAG1040), '<1041>', STAG1041), '<1077>', STAG1077) - where T.RN = RFISCDOC.NRN; + where T.RN = RFISCDOC.RN; /* Устанавливаем значения тэгов */ begin - UDO_P_FISCDOCSPROP_SET_VAL(NPRN => RFISCDOC.NRN, - NCOMPANY => RFISCDOC.NCOMPANY, + UDO_P_FISCDOCSPROP_SET_VAL(NPRN => RFISCDOC.RN, + NCOMPANY => RFISCDOC.COMPANY, + SATTRIBUTE => '1012', + DVAL_DATETIME => TO_DATE(STAG1012, 'dd.mm.yyyy hh24:mi:ss')); + UDO_P_FISCDOCSPROP_SET_VAL(NPRN => RFISCDOC.RN, + NCOMPANY => RFISCDOC.COMPANY, + SATTRIBUTE => '1038', + NVAL_NUMB => TO_NUMBER(STAG1038)); + UDO_P_FISCDOCSPROP_SET_VAL(NPRN => RFISCDOC.RN, + NCOMPANY => RFISCDOC.COMPANY, SATTRIBUTE => '1040', NVAL_NUMB => TO_NUMBER(STAG1040)); - UDO_P_FISCDOCSPROP_SET_VAL(NPRN => RFISCDOC.NRN, - NCOMPANY => RFISCDOC.NCOMPANY, + UDO_P_FISCDOCSPROP_SET_VAL(NPRN => RFISCDOC.RN, + NCOMPANY => RFISCDOC.COMPANY, SATTRIBUTE => '1041', SVAL_STR => STAG1041); - UDO_P_FISCDOCSPROP_SET_VAL(NPRN => RFISCDOC.NRN, - NCOMPANY => RFISCDOC.NCOMPANY, + UDO_P_FISCDOCSPROP_SET_VAL(NPRN => RFISCDOC.RN, + NCOMPANY => RFISCDOC.COMPANY, + SATTRIBUTE => '1042', + NVAL_NUMB => TO_NUMBER(STAG1042)); + UDO_P_FISCDOCSPROP_SET_VAL(NPRN => RFISCDOC.RN, + NCOMPANY => RFISCDOC.COMPANY, SATTRIBUTE => '1077', SVAL_STR => STAG1077); exception @@ -390,7 +416,7 @@ create or replace package body UDO_PKG_EXS_ATOL as REGEXP_REPLACE(replace(SERR_TEXT, CHR(10), ''), '[[:space:]]+', ' '), 1, 4000) - where T.RN = RFISCDOC.NRN; + where T.RN = RFISCDOC.RN; end; /* Неизвестный статус */ else diff --git a/db/UDO_P_FISCDOCS_GET_STATE_ATOL.prc b/db/UDO_P_FISCDOCS_GET_STATE_ATOL.prc index 9143a9d..bfa0fb2 100644 --- a/db/UDO_P_FISCDOCS_GET_STATE_ATOL.prc +++ b/db/UDO_P_FISCDOCS_GET_STATE_ATOL.prc @@ -13,10 +13,10 @@ begin 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)) + and Q.EXSSERVICEFN = UDO_PKG_EXS_ATOL.UTL_FISCDOC_GET_EXSFN_REG(T.RN)) loop /* Ставим запрос на получение статуса документа в очередь */ - PKG_EXS.QUEUE_PUT(NEXSSERVICEFN => UDO_PKG_EXS_ATOL.UTL_FISCDOC_GET_INF_EXSFN(NFISCDOC => C.RN), + PKG_EXS.QUEUE_PUT(NEXSSERVICEFN => UDO_PKG_EXS_ATOL.UTL_FISCDOC_GET_EXSFN_INF(NFISCDOC => C.RN), BMSG => C.BUUID, NLNK_COMPANY => C.COMPANY, NLNK_DOCUMENT => C.RN, diff --git a/db/UDO_P_FISCDOCS_MAKE_MSG_ATOL.prc b/db/UDO_P_FISCDOCS_MAKE_MSG_ATOL.prc index 45ffcff..70f5c7b 100644 --- a/db/UDO_P_FISCDOCS_MAKE_MSG_ATOL.prc +++ b/db/UDO_P_FISCDOCS_MAKE_MSG_ATOL.prc @@ -1,18 +1,20 @@ create or replace procedure UDO_P_FISCDOCS_MAKE_MSG_ATOL ( - NCOMPANY in number, -- Организация - NFISCDOC in number, -- Регистрационный номер фискального документа - NEXSQUEUE out number -- Регистрационный номер добавленной позиции очереди обмена + NCOMPANY in number, -- Организация + NFISCDOC in number, -- Регистрационный номер фискального документа + NEXSQUEUE out number -- Регистрационный номер добавленной позиции очереди обмена ) as /* Локальные переменные */ - CDATA clob; -- Буфер для XML-посылки - NTMP_RN PKG_STD.TREF; -- Буфер для вычислений + CDATA clob; -- Буфер для XML-посылки + NTMP_RN PKG_STD.TREF; -- Буфер для вычислений + REXSSERVICEFN EXSSERVICEFN%rowtype; -- Запись функции сервиса интеграции + BTEST_SRV boolean := false; -- Признак тестового сервиса /* Добавление пустой открытой ветки */ procedure NODE ( - SNAME varchar2 -- Имя ветки + SNAME varchar2 -- Имя ветки ) as begin @@ -25,8 +27,8 @@ as /* Добавление ветки со значением (строка) */ procedure NODE ( - SNAME varchar2, -- Имя ветки - SVALUE varchar2 -- Значение ветки (строка) + SNAME varchar2, -- Имя ветки + SVALUE varchar2 -- Значение ветки (строка) ) as begin @@ -43,8 +45,8 @@ as /* Добавление ветки со значением (число) */ procedure NODE ( - SNAME varchar2, -- Имя ветки - NVALUE number -- Значение ветки (число) + SNAME varchar2, -- Имя ветки + NVALUE number -- Значение ветки (число) ) as begin @@ -61,8 +63,8 @@ as /* Добавление ветки со значением (дата) */ procedure NODE ( - SNAME varchar2, -- Имя ветки - DVALUE date -- Значение ветки (дата) + SNAME varchar2, -- Имя ветки + DVALUE date -- Значение ветки (дата) ) as begin @@ -79,6 +81,11 @@ as begin /* Проверим наличие документа */ UDO_P_FISCDOCS_EXISTS(NRN => NFISCDOC, NCOMPANY => NCOMPANY, NCRN => NTMP_RN, NJUR_PERS => NTMP_RN); + /* Определим сервис интеграции и его функцию, через которые будем отправлять сообщение */ + REXSSERVICEFN := GET_EXSSERVICEFN_ID(NFLAG_SMART => 0, + NRN => UDO_PKG_EXS_ATOL.UTL_FISCDOC_GET_EXSFN_REG(NFISCDOC => NFISCDOC)); + /* Выставим флаг тестового сервиса */ + BTEST_SRV := UDO_PKG_EXS_ATOL.UTL_EXSSERVICE_IS_TEST(NEXSSERVICE => REXSSERVICEFN.PRN); /* Инициализируем сборку документа для отправки */ PKG_XMLFAST.PROLOGUE(NENCODING => PKG_XMLFAST.ENCODING_UTF8_, NSTANDALONE => PKG_XMLFAST.STANDALONE_YES_, @@ -87,77 +94,53 @@ begin NODE(SNAME => 'FISCDOC'); /* Курсорный цикл для доступа к данным фискального документа */ for D in (select T.* - from UDO_V_FISCDOCS T - where T.NRN = UDO_P_FISCDOCS_MAKE_MSG_ATOL.NFISCDOC - and T.NCOMPANY = UDO_P_FISCDOCS_MAKE_MSG_ATOL.NCOMPANY) - loop + from UDO_FISCDOCS T + where T.RN = NFISCDOC + and T.COMPANY = NCOMPANY) + loop /* Данные заголовка фискального документа */ - NODE(SNAME => 'NRN', NVALUE => D.NRN); - NODE(SNAME => 'NCOMPANY', NVALUE => D.NCOMPANY); - NODE(SNAME => 'NCRN', NVALUE => D.NCRN); - NODE(SNAME => 'NJUR_PERS', NVALUE => D.NJUR_PERS); - NODE(SNAME => 'SJUR_PERS', SVALUE => D.SJUR_PERS); - NODE(SNAME => 'SDOC_PREF', SVALUE => trim(D.SDOC_PREF)); - NODE(SNAME => 'SDOC_NUMB', SVALUE => trim(D.SDOC_NUMB)); - NODE(SNAME => 'NDOC_TYPE', NVALUE => D.NDOC_TYPE); - NODE(SNAME => 'NDOC_TYPE_CODE', NVALUE => D.NDOC_TYPE_CODE); - NODE(SNAME => 'NTYPE_VERSION', NVALUE => D.NTYPE_VERSION); - NODE(SNAME => 'STYPE_VERSION', SVALUE => D.STYPE_VERSION); - NODE(SNAME => 'DDOC_DATE', DVALUE => D.DDOC_DATE); - NODE(SNAME => 'SDDOC_DATE', SVALUE => TO_CHAR(D.DDOC_DATE, 'dd.mm.yyyy hh24:mi:ss')); - NODE(SNAME => 'NAGENT', NVALUE => D.NAGENT); - NODE(SNAME => 'SAGENT', SVALUE => D.SAGENT); - NODE(SNAME => 'NCALC_KIND', NVALUE => D.NCALC_KIND); - NODE(SNAME => 'NBASE_SUM', NVALUE => D.NBASE_SUM); - NODE(SNAME => 'SAUTHID', SVALUE => D.SAUTHID); - NODE(SNAME => 'DEDIT_TIME', DVALUE => D.DEDIT_TIME); - NODE(SNAME => 'SDEDIT_TIME', SVALUE => TO_CHAR(D.DEDIT_TIME, 'dd.mm.yyyy hh24:mi:ss')); - NODE(SNAME => 'SNOTE', SVALUE => D.SNOTE); - NODE(SNAME => 'NSTATUS', NVALUE => D.NSTATUS); - NODE(SNAME => 'DSEND_TIME', DVALUE => D.DSEND_TIME); - NODE(SNAME => 'SDSEND_TIME', SVALUE => TO_CHAR(D.DSEND_TIME, 'dd.mm.yyyy hh24:mi:ss')); - NODE(SNAME => 'DCONFIRM_DATE', DVALUE => D.DCONFIRM_DATE); - NODE(SNAME => 'SDCONFIRM_DATE', SVALUE => TO_CHAR(D.DCONFIRM_DATE, 'dd.mm.yyyy hh24:mi:ss')); - NODE(SNAME => 'SNUMB_FD', SVALUE => D.SNUMB_FD); - NODE(SNAME => 'NFACEACC', NVALUE => D.NFACEACC); - NODE(SNAME => 'SFACEACC', SVALUE => D.SFACEACC); - NODE(SNAME => 'SADD_PROP', SVALUE => D.SADD_PROP); - NODE(SNAME => 'SSRC_UNITCODE', SVALUE => D.SSRC_UNITCODE); - NODE(SNAME => 'SSRC_UNITNAME', SVALUE => D.SSRC_UNITNAME); - NODE(SNAME => 'NSRC_TYPE', NVALUE => D.NSRC_TYPE); - NODE(SNAME => 'SSRC_TYPE', SVALUE => D.SSRC_TYPE); - NODE(SNAME => 'SSRC_NUMB', SVALUE => D.SSRC_NUMB); - NODE(SNAME => 'DSRC_DATE', DVALUE => D.DSRC_DATE); - NODE(SNAME => 'SDSRC_DATE', SVALUE => TO_CHAR(D.DSRC_DATE, 'dd.mm.yyyy hh24:mi:ss')); - NODE(SNAME => 'NVALID_TYPE', NVALUE => D.NVALID_TYPE); - NODE(SNAME => 'SVALID_TYPE', SVALUE => D.SVALID_TYPE); - NODE(SNAME => 'SVALID_NUMB', SVALUE => D.SVALID_NUMB); - NODE(SNAME => 'DVALID_DATE', DVALUE => D.DVALID_DATE); - NODE(SNAME => 'SDVALID_DATE', SVALUE => TO_CHAR(D.DVALID_DATE, 'dd.mm.yyyy hh24:mi:ss')); - NODE(SNAME => 'SDOC_URL', SVALUE => D.SDOC_URL); - NODE(SNAME => 'NCORRECT_TYPE', NVALUE => D.NCORRECT_TYPE); + NODE(SNAME => 'NRN', NVALUE => D.RN); + NODE(SNAME => 'DDOC_DATE', DVALUE => D.DOC_DATE); + NODE(SNAME => 'SDDOC_DATE', SVALUE => TO_CHAR(D.DOC_DATE, 'dd.mm.yyyy hh24:mi:ss')); /* Список свойств фискального документа */ NODE('FISCDOC_PROPS'); - for SP in (select T.*, - A.CODE SCODE, - A.NAME SNAME + for SP in (select A.CODE SCODE, + A.NAME SNAME, + UDO_GET_FISCDOCSPROP_VALUE(T.RN) SVALUE, + T.VAL_STR SVAL_STR, + T.VAL_NUMB NVAL_NUMB, + T.VAL_DATE DVAL_DATE, + T.VAL_DATETIME DVAL_DATETIME from UDO_FISCDOCSPROP T, UDO_FDKNDATT P, UDO_FISCDOCATT A - where T.PRN = D.NRN + where T.PRN = D.RN and T.PROP = P.RN and P.ATTRIBUTE = A.RN) loop /* Свойство фискального документа */ NODE(SNAME => 'FISCDOC_PROP'); + /* Для некоторых тэгов необходим тестовый набор данных, если это тестовый сервис */ + if (BTEST_SRV) then + /* Подставим тестовый ИНН */ + if (SP.SCODE = '1018') then + SP.SVALUE := UDO_PKG_EXS_ATOL.STEST_INN; + SP.SVAL_STR := UDO_PKG_EXS_ATOL.STEST_INN; + end if; + /* Подставим тестовый адрес расчётов */ + if (SP.SCODE = '1187') then + SP.SVALUE := UDO_PKG_EXS_ATOL.STEST_ADDR; + SP.SVAL_STR := UDO_PKG_EXS_ATOL.STEST_ADDR; + end if; + end if; /* Данные свойства фискального документа */ NODE(SNAME => 'SCODE', SVALUE => SP.SCODE); NODE(SNAME => 'SNAME', SVALUE => SP.SNAME); - NODE(SNAME => 'VALUE', SVALUE => UDO_GET_FISCDOCSPROP_VALUE(SP.RN)); - NODE(SNAME => 'SVALUE', SVALUE => SP.VAL_STR); - NODE(SNAME => 'NVALUE', NVALUE => SP.VAL_NUMB); - NODE(SNAME => 'DVALUE', DVALUE => SP.VAL_DATE); - NODE(SNAME => 'DTVALUE', DVALUE => SP.VAL_DATETIME); + NODE(SNAME => 'VALUE', SVALUE => SP.SVALUE); + NODE(SNAME => 'SVALUE', SVALUE => SP.SVAL_STR); + NODE(SNAME => 'NVALUE', NVALUE => SP.NVAL_NUMB); + NODE(SNAME => 'DVALUE', DVALUE => SP.DVAL_DATE); + NODE(SNAME => 'DTVALUE', DVALUE => SP.DVAL_DATETIME); /* Закрываем свойство фискального документа */ PKG_XMLFAST.UP; end loop; @@ -169,11 +152,11 @@ begin /* Финализируем сборку XML-документа */ PKG_XMLFAST.EPILOGUE(LDATA => CDATA); /* Отправляем сформированный документ */ - PKG_EXS.QUEUE_PUT(NEXSSERVICEFN => UDO_PKG_EXS_ATOL.UTL_FISCDOC_GET_REG_EXSFN(NFISCDOC => NFISCDOC), + PKG_EXS.QUEUE_PUT(NEXSSERVICEFN => REXSSERVICEFN.RN, BMSG => CLOB2BLOB(LCDATA => CDATA, SCHARSET => 'UTF8'), NLNK_COMPANY => NCOMPANY, NLNK_DOCUMENT => NFISCDOC, - SLNK_UNITCODE => 'UDO_FiscalDocuments', + SLNK_UNITCODE => 'UDO_FiscalDocuments', NNEW_EXSQUEUE => NEXSQUEUE); end; / diff --git a/modules/parus_atol_v4_ffd1.05.js b/modules/parus_atol_v4_ffd1.05.js index 003543f..a654428 100644 --- a/modules/parus_atol_v4_ffd1.05.js +++ b/modules/parus_atol_v4_ffd1.05.js @@ -2,7 +2,7 @@ Сервис интеграции РџРџ Парус 8 СЃ WEB API Дополнительный модуль: Взаимодействие СЃ "РђРўРћР›-Онлайн" (v4) РІ формате ФФД 1.05 - Полный формат формируемой посылки: + Полный формат формируемой посылки для чека: reqBody = { timestamp: "", external_id: 0, @@ -98,6 +98,39 @@ } } }; + + Полный формат формируемой посылки для чека коррекции: + reqBody = { + timestamp: "", + external_id: 0, + correction: { + company: { + sno: "", + inn: "", + payment_address: "" + }, + correction_info: { + type: "", + base_date: "", + base_number: "", + base_name: "" + }, + payments: [ + { + type: "", + sum: 0 + } + ], + vats: [ + { + type: "", + sum: 0 + } + ], + cashier: "" + } + }; + */ //---------------------- @@ -113,9 +146,13 @@ const { buildURL } = require("@core/utils"); //Вспомогательные С„ // Глобальные константы //--------------------- -//РљРѕРґ РєСЂСѓРїРїС‹ РљРљРў +//РљРѕРґ РєСЂСѓРїРїС‹ РљРљРў (тестовой, для боевой - прописать его РІ настройках сервиса) const SGROUP_CODE = "v4-online-atol-ru_4179"; +//РўРёРїС‹ документов РїРѕ значению "Наименование документа" (тэг 1000) +const SDOCTYPE_TAG100_CHECK = "3"; //Чек +const SDOCTYPE_TAG100_CHECK_CORR = "31"; //Чек коррекции + //Статусы документов РђРўРћР›-онлайн const SSTATUS_DONE = "done"; //Готово const SSTATUS_FAIL = "fail"; //Ошибка @@ -164,14 +201,16 @@ const paymentObject = { const paymensOperation = { sName: "РўРёРї операции", vals: { - "1": "sell", - "2": "sell_refund", - "3": "buy", - "4": "buy_refund" + "3_1": "sell", //РўСЌРі 1000 = 3 (чек), тэг 1054 = 1 (РїСЂРёС…РѕРґ) + "31_2": "sell_refund", //РўСЌРі 1000 = 31 (коррекция), тэг 1054 = 2 (возврат РїСЂРёС…РѕРґР°) + "31_1": "sell_correction", //РўСЌРі 1000 = 31 (коррекция), тэг 1054 = 1 (РїСЂРёС…РѕРґ) + "3_3": "buy", //РўСЌРі 1000 = 3 (чек), тэг 1054 = 3 (расход) + "31_4": "buy_refund", //РўСЌРі 1000 = 31 (коррекция), тэг 1054 = 4 (возврат расхода) + "31_3": "buy_correction" //РўСЌРі 1000 = 31 (коррекция), тэг 1054 = 3 (расход) } }; -//Словарь - ставка НДС позиции чека +//Словарь - Ставка НДС позиции чека const receiptItemVat = { sName: "Ставка НДС позиции чека", vals: { @@ -184,6 +223,15 @@ const receiptItemVat = { } }; +//Словарь - РўРёРї коррекции +const correctionInfoType = { + sName: "РўРёРї коррекции", + vals: { + "0": "self", + "1": "instruction" + } +}; + //------------ // Тело модуля //------------ @@ -281,6 +329,92 @@ const strDDMMYYYYHHMISStoDate = sDate => { return res; }; +//Получение СЃРїРёСЃРєР° оплат РїРѕ чеку +const getPayments = props => { + //РЎРїРёСЃРѕРє платежей + let payments = []; + //РЎСѓРјРјР° РїРѕ чеку электронными + if (getPropValueByCode(props, "1081", "NUM") !== null) { + payments.push({ + type: 1, + sum: getPropValueByCode(props, "1081", "NUM") + }); + } + //РЎСѓРјРјР° РїРѕ чеку предоплатой (зачет аванса Рё (или) предыдущих платежей) + if (getPropValueByCode(props, "1215", "NUM") !== null) { + payments.push({ + type: 2, + sum: getPropValueByCode(props, "1215", "NUM") + }); + } + //РЎСѓРјРјР° РїРѕ чеку постоплатой (кредит) + if (getPropValueByCode(props, "1216", "NUM") !== null) { + payments.push({ + type: 3, + sum: getPropValueByCode(props, "1216", "NUM") + }); + } + //РЎСѓРјРјР° РїРѕ чеку встречным представлением + if (getPropValueByCode(props, "1217", "NUM") !== null) { + payments.push({ + type: 4, + sum: getPropValueByCode(props, "1217", "NUM") + }); + } + //Возвращаем результат + return payments; +}; + +//Получение СЃРїРёСЃРєР° налогов РїРѕ чеку +const getVats = props => { + //РЎРїРёСЃРѕРє налогов + let vats = []; + //РЎСѓРјРјР° расчета РїРѕ чеку без НДС; + if (getPropValueByCode(props, "1105", "NUM") !== null) { + vats.push({ + type: "none", + sum: getPropValueByCode(props, "1105", "NUM") + }); + } + //РЎСѓРјРјР° расчета РїРѕ чеку СЃ НДС РїРѕ ставке 0%; + if (getPropValueByCode(props, "1104", "NUM") !== null) { + vats.push({ + type: "vat0", + sum: getPropValueByCode(props, "1104", "NUM") + }); + } + //РЎСѓРјРјР° НДС чека РїРѕ ставке 10%; + if (getPropValueByCode(props, "1103", "NUM") !== null) { + vats.push({ + type: "vat10", + sum: getPropValueByCode(props, "1103", "NUM") + }); + } + //РЎСѓРјРјР° НДС чека РїРѕ ставке 20%; + if (getPropValueByCode(props, "1102", "NUM") !== null) { + vats.push({ + type: "vat20", + sum: getPropValueByCode(props, "1102", "NUM") + }); + } + //РЎСѓРјРјР° НДС чека РїРѕ расч. ставке 10/110; + if (getPropValueByCode(props, "1107", "NUM") !== null) { + vats.push({ + type: "vat110", + sum: getPropValueByCode(props, "1107", "NUM") + }); + } + //РЎСѓРјРјР° НДС чека РїРѕ расч. ставке 20/120 + if (getPropValueByCode(props, "1106", "NUM") !== null) { + vats.push({ + type: "vat120", + sum: getPropValueByCode(props, "1106", "NUM") + }); + } + //Возвращаем результат + return vats; +}; + //Обработчик "До" подключения Рє сервису const beforeConnect = async prms => { return { @@ -341,119 +475,79 @@ const beforeRegBillSIR = async prms => { //Сохраним короткие ссылки РЅР° документ Рё его свойства const doc = parseRes.FISCDOC; const docProps = parseRes.FISCDOC.FISCDOC_PROPS.FISCDOC_PROP; - //Определим тип операции - const sOperation = mapDictionary(paymensOperation, getPropValueByCode(docProps, "1054")); + //Определим тип операции РїРѕ значению "Наименование документа" (тэг 1000) Рё "Признак расчета" (тэг 1054) + if (!getPropValueByCode(docProps, "1000")) + throw new Error("Р’ фискальном документе РЅРµ указано значение 'Наименование документа' (тэг 1000)"); + if (!getPropValueByCode(docProps, "1054")) + throw new Error("Р’ фискальном документе РЅРµ указано значение 'Признак расчёта' (тэг 1054)"); + const sOperation = mapDictionary( + paymensOperation, + `${getPropValueByCode(docProps, "1000")}_${getPropValueByCode(docProps, "1054")}` + ); //Собираем тело запроса РІ JSON РёР· XML-данных документа - let reqBody = { - timestamp: doc.SDDOC_DATE, - external_id: doc.NRN, - receipt: { - client: { - email: getPropValueByCode(docProps, "1008"), - phone: "" - }, - company: { - email: getPropValueByCode(docProps, "1117"), - sno: getPropValueByCode(docProps, "1055"), - inn: getPropValueByCode(docProps, "1018"), - payment_address: getPropValueByCode(docProps, "1187") - }, - items: [ - { - name: getPropValueByCode(docProps, "1030"), - price: getPropValueByCode(docProps, "1079", "NUM"), - quantity: getPropValueByCode(docProps, "1023", "NUM"), - sum: getPropValueByCode(docProps, "1043", "NUM"), - measurement_unit: getPropValueByCode(docProps, "1197"), - payment_method: mapDictionary(paymentMethod, getPropValueByCode(docProps, "1214")), - payment_object: mapDictionary(paymentObject, getPropValueByCode(docProps, "1212")), - vat: { - type: mapDictionary(receiptItemVat, getPropValueByCode(docProps, "1199", "NUM")), - sum: getPropValueByCode(docProps, "1200", "NUM") + let reqBody = {}; + if (getPropValueByCode(docProps, "1000") === SDOCTYPE_TAG100_CHECK) { + //Собираем чека + reqBody = { + timestamp: doc.SDDOC_DATE, + external_id: doc.NRN, + receipt: { + client: { + email: getPropValueByCode(docProps, "1008"), + phone: "" + }, + company: { + email: getPropValueByCode(docProps, "1117"), + sno: getPropValueByCode(docProps, "1055"), + inn: getPropValueByCode(docProps, "1018"), + payment_address: getPropValueByCode(docProps, "1187") + }, + items: [ + { + name: getPropValueByCode(docProps, "1030"), + price: getPropValueByCode(docProps, "1079", "NUM"), + quantity: getPropValueByCode(docProps, "1023", "NUM"), + sum: getPropValueByCode(docProps, "1043", "NUM"), + measurement_unit: getPropValueByCode(docProps, "1197"), + payment_method: mapDictionary(paymentMethod, getPropValueByCode(docProps, "1214")), + payment_object: mapDictionary(paymentObject, getPropValueByCode(docProps, "1212")), + vat: { + type: mapDictionary(receiptItemVat, getPropValueByCode(docProps, "1199", "NUM")), + sum: getPropValueByCode(docProps, "1200", "NUM") + } } - } - ], - total: getPropValueByCode(docProps, "1020", "NUM") - } - }; - //Добавим общие платежи - let payments = []; - //РЎСѓРјРјР° РїРѕ чеку электронными - if (getPropValueByCode(docProps, "1081", "NUM") !== null) { - payments.push({ - type: 1, - sum: getPropValueByCode(docProps, "1081", "NUM") - }); + ], + total: getPropValueByCode(docProps, "1020", "NUM") + } + }; + //Добавим общие платежи + let payments = getPayments(docProps); + if (payments.length > 0) reqBody.receipt.payments = payments; + //Добавим общие налоги + let vats = getVats(docProps); + if (vats.length > 0) reqBody.receipt.vats = vats; + } else { + //Собираем чек коррекции + reqBody = { + timestamp: doc.SDDOC_DATE, + external_id: doc.NRN, + correction: { + company: { + sno: getPropValueByCode(docProps, "1055"), + inn: getPropValueByCode(docProps, "1018"), + payment_address: getPropValueByCode(docProps, "1187") + }, + correction_info: { + type: mapDictionary(correctionInfoType, getPropValueByCode(docProps, "1173")), + base_date: getPropValueByCode(docProps, "1178"), + base_number: getPropValueByCode(docProps, "1179"), + base_name: getPropValueByCode(docProps, "1177") + }, + payments: getPayments(docProps), + vats: getVats(docProps) + } + }; } - //РЎСѓРјРјР° РїРѕ чеку предоплатой (зачет аванса Рё (или) предыдущих платежей) - if (getPropValueByCode(docProps, "1215", "NUM") !== null) { - payments.push({ - type: 2, - sum: getPropValueByCode(docProps, "1215", "NUM") - }); - } - //РЎСѓРјРјР° РїРѕ чеку постоплатой (кредит) - if (getPropValueByCode(docProps, "1216", "NUM") !== null) { - payments.push({ - type: 3, - sum: getPropValueByCode(docProps, "1216", "NUM") - }); - } - //РЎСѓРјРјР° РїРѕ чеку встречным представлением - if (getPropValueByCode(docProps, "1217", "NUM") !== null) { - payments.push({ - type: 4, - sum: getPropValueByCode(docProps, "1217", "NUM") - }); - } - //Если есть хоть РѕРґРёРЅ платёж - помещаем массив РІ запрос - if (payments.length > 0) reqBody.receipt.payments = payments; - //Добавим общие налоги - let vats = []; - //РЎСѓРјРјР° расчета РїРѕ чеку без НДС; - if (getPropValueByCode(docProps, "1105", "NUM") !== null) { - vats.push({ - type: "none", - sum: getPropValueByCode(docProps, "1105", "NUM") - }); - } - //РЎСѓРјРјР° расчета РїРѕ чеку СЃ НДС РїРѕ ставке 0%; - if (getPropValueByCode(docProps, "1104", "NUM") !== null) { - vats.push({ - type: "vat0", - sum: getPropValueByCode(docProps, "1104", "NUM") - }); - } - //РЎСѓРјРјР° НДС чека РїРѕ ставке 10%; - if (getPropValueByCode(docProps, "1103", "NUM") !== null) { - vats.push({ - type: "vat10", - sum: getPropValueByCode(docProps, "1103", "NUM") - }); - } - //РЎСѓРјРјР° НДС чека РїРѕ ставке 20%; - if (getPropValueByCode(docProps, "1102", "NUM") !== null) { - vats.push({ - type: "vat20", - sum: getPropValueByCode(docProps, "1102", "NUM") - }); - } - //РЎСѓРјРјР° НДС чека РїРѕ расч. ставке 10/110; - if (getPropValueByCode(docProps, "1107", "NUM") !== null) { - vats.push({ - type: "vat110", - sum: getPropValueByCode(docProps, "1107", "NUM") - }); - } - //РЎСѓРјРјР° НДС чека РїРѕ расч. ставке 20/120 - if (getPropValueByCode(docProps, "1106", "NUM") !== null) { - vats.push({ - type: "vat120", - sum: getPropValueByCode(docProps, "1106", "NUM") - }); - } - //Если есть хоть РѕРґРёРЅ налог - помещаем массив РІ запрос - if (vats.length > 0) reqBody.receipt.vats = vats; //Собираем общий результат работы let res = { options: { @@ -581,10 +675,14 @@ const afterGetBillInfo = async prms => { TIMESTAMP: resp.timestamp, //Дата Рё время документа РёР· ФН TAG1012: resp.payload.receipt_datetime, + //Номер смены + TAG1038: resp.payload.shift_number, //Фискальный номер документа TAG1040: resp.payload.fiscal_document_number, //Номер ФН TAG1041: resp.payload.fn_number, + //Номер чека РІ смене + TAG1042: resp.payload.fiscal_receipt_number, //Фискальный признак документа TAG1077: resp.payload.fiscal_document_attribute };