From 8962defb1d4468216fa7edbd660102d27a676439 Mon Sep 17 00:00:00 2001 From: Mikhail Chechnev Date: Wed, 26 Dec 2018 14:59:51 +0300 Subject: [PATCH] =?UTF-8?q?=D0=9C=D0=BE=D0=B4=D1=83=D0=BB=D1=8C=20=D0=BE?= =?UTF-8?q?=D0=B1=D0=BC=D0=B5=D0=BD=D0=B0=20=D1=81=20=D0=90=D0=A2=D0=9E?= =?UTF-8?q?=D0=9B-=D0=BE=D0=BD=D0=BB=D0=B0=D0=B9=D0=BD=20-=20API=20v4,=20?= =?UTF-8?q?=D0=A4=D0=A4=D0=94=201.05=20(=D0=BD=D0=B0=D1=87=D0=B0=D0=BB?= =?UTF-8?q?=D0=BE)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- modules/parus_atol_v4_ffd1.05.js | 253 ++++++++++++++++++++++++++++--- 1 file changed, 230 insertions(+), 23 deletions(-) diff --git a/modules/parus_atol_v4_ffd1.05.js b/modules/parus_atol_v4_ffd1.05.js index 5b1b626..65bf559 100644 --- a/modules/parus_atol_v4_ffd1.05.js +++ b/modules/parus_atol_v4_ffd1.05.js @@ -3,38 +3,245 @@ Дополнительный модуль: Взаимодействие с "АТОЛ-Онлайн" (v4) в формате ФФД 1.05 */ +//---------------------- +// Подключение библиотек +//---------------------- + +const util = require("util"); //Встроенные вспомогательные утилиты +const parseString = require("xml2js").parseString; //Конвертация XML в JSON +const _ = require("lodash"); //Работа с массивами и коллекциями + +//--------------------- +// Глобальные константы +//--------------------- + +//Словарь - Признак способа расчёта +const paymentMethod = { + sName: "Признак способа расчёта", + vals: { + "1": "full_prepayment", + "2": "prepayment", + "3": "advance", + "4": "full_payment", + "5": "partial_payment", + "6": "credit", + "7": "credit_payment" + } +}; + +//Словарь - Признак предмета расчёта +const paymentObject = { + sName: "Признак предмета расчёта", + vals: { + "1": "commodity", + "2": "excise", + "3": "job", + "4": "service", + "5": "gambling_bet", + "6": "gambling_prize", + "7": "lottery", + "8": "lottery_prize", + "9": "intellectual_activity", + "10": "payment", + "11": "agent_commission", + "12": "composite", + "13": "another", + "14": "property_right", + "15": "non-operating_gain", + "16": "insurance_premium", + "17": "sales_tax", + "18": "resort_fee" + } +}; + //------------ // Тело модуля //------------ -//Обработчик "До" отправки чека серверу "АТОЛ-Онлайн" -const beforeRegBillSIR = async prms => { - console.log(`Начал обработку отправки чека ДО - ${prms.queue.nId}`); - //throw Error("AAAAAAAAAAAAA"); - let res = { - blMsg: new Buffer("NEW SOME DATA") - }; - if (!prms.service.context.token) { - console.log("NO TOKEN!!!"); - res.context = { token: `NEW TOKEN FOR${prms.queue.nId}` }; - } else { - console.log(prms.service.context); - } - console.log(prms.queue.blMsg.toString()); - await promiceTimer(2500); - console.log(`Закончил обработку отправки чека ДО - ${prms.queue.nId}`); +//Разбор XML +const parseXML = xmlDoc => { + return new Promise((resolve, reject) => { + parseString(xmlDoc, { explicitArray: false, mergeAttrs: true }, function(err, result) { + if (err) reject(err); + else resolve(result); + }); + }); +}; + +//Конвертация значений в ожидаемые систеой АТОЛ-онлайн +const mapDictionary = (dict, sValue) => { + if (!dict) throw Error(`Словарь не определен`); + if (!dict.sName || !dict.vals || !(dict.vals instanceof Object)) throw Error(`Словарь имеет некорректный формат`); + if (typeof sValue === "undefined" || sValue === null || sValue === "") + throw Error(`Не указано значение для привязки к словарю "${dict.sName}"`); + const res = dict.vals[sValue]; + if (typeof res === "undefined") throw Error(`Значение "${sValue}" отсутствует в словаре "${dict.sName}"`); return res; }; -//Обработчик "После" отправки чека серверу "АТОЛ-Онлайн" -const afterRegBillSIR = async prms => { - console.log(`Начал обработку отправки чека ПОСЛЕ - ${prms.queue.nId}`); - console.log(prms.service.context); - console.log(prms.queue.blMsg.toString()); - //await promiceTimer(2500); - console.log(`Закончил обработку отправки чека ПОСЛЕ - ${prms.queue.nId}`); +//Поиск значения в составе свойств фискального документа по коду свойства +const getPropValueByCode = (props, sCode, sValType = "STR", sValField = "VALUE") => { + if (!["STR", "NUM", "DATE"].includes(sValType)) throw Error(`Тип данных "${sValType}" не поддерживается`); + let res = null; + let prop = _.find(props, { SCODE: sCode }); + if (typeof prop !== "undefined") { + res = prop[sValField]; + if (typeof res === "undefined") res = null; + else if (res === "") res = null; + if (res !== null) { + switch (sValType) { + case "STR": { + try { + res = res.toString(); + } catch (e) { + throw Error(`Ошибка конвертации значения "${res}" в строку: ${e.message}`); + } + break; + } + case "NUM": { + if (isNaN(res)) throw Error(`Значение "${res}" не является числом`); + try { + res = Number(res); + } catch (e) { + throw Error(`Ошибка конвертации значения "${res}" в число: ${e.message}`); + } + break; + } + case "DATE": { + const resTmp = res; + try { + res = new Date(res); + } catch (e) { + throw Error(`Ошибка конвертации значения "${resTmp}" в дату: ${e.message}`); + } + if (res instanceof Date && isNaN(res)) + throw Error(`Значение "${resTmp}" не является корректной датой`); + break; + } + default: + throw Error(`Тип данных "${sValType}" не поддерживается`); + } + } + } + return res; }; +//Обработчик "До" отправки запроса на регистрацию чека (приход, расход, возврат) серверу "АТОЛ-Онлайн" +const beforeRegBillSIR = async prms => { + try { + const parseRes = await parseXML(prms.queue.blMsg.toString()); + const doc = parseRes.FISCDOC; + const docProps = parseRes.FISCDOC.FISCDOC_PROPS.FISCDOC_PROP; + let reqBody = { + timestamp: doc.SDDOC_DATE, + external_id: doc.NRN, + /* + service: { + callback_url: "" + }, + */ + receipt: { + client: { + email: getPropValueByCode(docProps, "1008"), + phone: "" + }, + company: { + email: getPropValueByCode(docProps, "1117"), + sno: getPropValueByCode(docProps, "1117"), + inn: getPropValueByCode(docProps, "1018"), + payment_address: getPropValueByCode(docProps, "1187") + }, + /* + agent_info: { + type: "", + paying_agent: { + operation: "", + phones: [""] + }, + receive_payments_operator: { + phones: [""] + }, + money_transfer_operator: { + phones: [""], + name: "", + address: "", + inn: "" + } + }, + supplier_info: { + phones: [""] + }, + */ + 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: "none", + sum: getPropValueByCode(docProps, "1200", "NUM") + } /*, + agent_info: { + type: "", + paying_agent: { + operation: "", + phones: [""] + }, + receive_payments_operator: { + phones: [""] + }, + money_transfer_operator: { + phones: [""], + name: "", + address: "", + inn: "" + } + }, + supplier_info: { + phones: [""], + name: "", + address: "", + inn: "" + }, + user_data: "" + */ + } + ], + payments: [ + { + type: 0, + sum: 0 + } + ], + vats: [ + { + type: "", + sum: 0 + } + ], + total: 0 /*, + additional_check_props: "", + cashier: "", + additional_user_props: { + name: "", + value: "" + } + */ + } + }; + console.log(util.inspect(reqBody, false, null)); + } catch (e) { + throw Error(e); + } +}; + +//Обработчик "После" отправки запроса на регистрацию чека (приход, расход, возврат) серверу "АТОЛ-Онлайн" +const afterRegBillSIR = async prms => {}; + //----------------- // Интерфейс модуля //-----------------