UNPKG

poster-prro-kit

Version:

Цей Kit призначений для роботи з PRRO, а саме для генерації XML документів для податкової, генерації фіскальних чеків для термопринтерів, генерації документів для PRRO в офлайн режимі, розрахунку податків та генераціі посилання на фіскальний чек в кабін

443 lines (437 loc) 19.7 kB
import xml2js from "xml2js"; import { XML_ENCODING } from "./const/xml.js"; import { getDateTimeFields } from "./generators/commonXMLTagGenerator.js"; import getReceiptDocument from "./generators/receiptXMLGenerator.js"; import getShiftOpenDocument from "./generators/shiftOpenXMLGenerator.js"; import getZReportDocument from "./generators/zReportXMLGenerator.js"; import { getTaxesData, getTaxPrograms } from "../taxes/index.js"; import { receiptRequestData, receiptRequestDatInCentsAndGrams, zReportData, } from "./mock/data.js"; import { mockCustomTaxes } from "../taxes/mock/taxes.js"; describe("XMLDocuments", () => { describe("receiptXMLGenerator", () => { describe("getDateTime", () => { it("should return date and time if data has ISO format", () => { expect(getDateTimeFields("2024-04-11T12:33:11")).toEqual({ ORDERDATE: "11042024", ORDERTIME: "123311", }); }); it("should return empty data if uses incorrect format", () => { expect(getDateTimeFields("2024-04-11-12-33-11")).toEqual({ ORDERDATE: "", ORDERTIME: "", }); }); }); describe("xml2js builder", () => { const builder = new xml2js.Builder({ xmldec: { encoding: XML_ENCODING }, }); it("should generate valid receipt XML, with a correct tag's order", () => { const taxesConfig = getTaxPrograms(mockCustomTaxes); const taxes = getTaxesData(taxesConfig)(receiptRequestData.products); const data = getReceiptDocument({ ...receiptRequestData, taxes, }); expect(builder.buildObject(data)).toBe( '<?xml version="1.0" encoding="windows-1251"?>\n' + "<CHECK>\n" + " <CHECKHEAD>\n" + " <DOCTYPE>0</DOCTYPE>\n" + " <DOCSUBTYPE>0</DOCSUBTYPE>\n" + " <UID>11111111-1111-1111-1111-111111111111</UID>\n" + " <TIN>44657555</TIN>\n" + " <ORGNM>ТОВ ТЕСТ ПРРО</ORGNM>\n" + " <POINTNM>кафе Ромашка</POINTNM>\n" + " <POINTADDR>Дніпропетровська область, м. Дніпро, вул. Шевченка, 1</POINTADDR>\n" + " <ORDERDATE>18042024</ORDERDATE>\n" + " <ORDERTIME>151617</ORDERTIME>\n" + " <ORDERNUM>2834</ORDERNUM>\n" + " <CASHDESKNUM>123</CASHDESKNUM>\n" + " <CASHREGISTERNUM>4000438533</CASHREGISTERNUM>\n" + " <CASHIER>Шевченко Т.Г.</CASHIER>\n" + " <VER>1</VER>\n" + " <ORDERTAXNUM>23649865.4.1077</ORDERTAXNUM>\n" + " <OFFLINE>true</OFFLINE>\n" + " <PREVDOCHASH>47a08c017274237765f9081d994e76e08742dcef85056d655a8458ec43dff6e4</PREVDOCHASH>\n" + " <TESTING>true</TESTING>\n" + " </CHECKHEAD>\n" + " <CHECKTOTAL>\n" + " <SUM>950.04</SUM>\n" + " <DISCOUNTSUM>50.35</DISCOUNTSUM>\n" + " </CHECKTOTAL>\n" + " <CHECKPAY>\n" + ' <ROW ROWNUM="1">\n' + " <PAYFORMCD>0</PAYFORMCD>\n" + " <PAYFORMNM>ГОТІВКА</PAYFORMNM>\n" + " <SUM>100.00</SUM>\n" + " <PROVIDED>100.00</PROVIDED>\n" + " </ROW>\n" + ' <ROW ROWNUM="2">\n' + " <PAYFORMCD>1</PAYFORMCD>\n" + " <PAYFORMNM>КАРТКА</PAYFORMNM>\n" + " <SUM>850.04</SUM>\n" + " <PROVIDED>850.04</PROVIDED>\n" + " </ROW>\n" + " </CHECKPAY>\n" + " <CHECKTAX>\n" + ' <ROW ROWNUM="1">\n' + " <TYPE>1</TYPE>\n" + " <NAME>Акциз</NAME>\n" + " <LETTER>Д</LETTER>\n" + " <PRC>5.00</PRC>\n" + " <TURNOVER>980.26</TURNOVER>\n" + " <TURNOVERDISCOUNT>930.26</TURNOVERDISCOUNT>\n" + " <SOURCESUM>930.26</SOURCESUM>\n" + " <SUM>44.30</SUM>\n" + " </ROW>\n" + ' <ROW ROWNUM="2">\n' + " <TYPE>0</TYPE>\n" + " <NAME>ПДВ 0%</NAME>\n" + " <LETTER>Г</LETTER>\n" + " <PRC>0.00</PRC>\n" + " <TURNOVER>800.00</TURNOVER>\n" + " <TURNOVERDISCOUNT>770.00</TURNOVERDISCOUNT>\n" + " <SOURCESUM>733.33</SOURCESUM>\n" + " <SUM>0.00</SUM>\n" + " </ROW>\n" + ' <ROW ROWNUM="3">\n' + " <TYPE>0</TYPE>\n" + " <NAME>ПДВ 7%</NAME>\n" + " <LETTER>Б</LETTER>\n" + " <PRC>7.00</PRC>\n" + " <TURNOVER>180.26</TURNOVER>\n" + " <TURNOVERDISCOUNT>160.26</TURNOVERDISCOUNT>\n" + " <SOURCESUM>152.63</SOURCESUM>\n" + " <SUM>9.99</SUM>\n" + " </ROW>\n" + ' <ROW ROWNUM="4">\n' + " <TYPE>0</TYPE>\n" + " <NAME>ПДВ 20%</NAME>\n" + " <LETTER>В</LETTER>\n" + " <PRC>20.00</PRC>\n" + " <TURNOVER>20.13</TURNOVER>\n" + " <TURNOVERDISCOUNT>19.78</TURNOVERDISCOUNT>\n" + " <SOURCESUM>19.78</SOURCESUM>\n" + " <SUM>3.30</SUM>\n" + " </ROW>\n" + " </CHECKTAX>\n" + " <CHECKBODY>\n" + ' <ROW ROWNUM="1">\n' + " <CODE>54</CODE>\n" + " <NAME>Сирна паличка</NAME>\n" + " <UNITNM>шт</UNITNM>\n" + " <AMOUNT>4</AMOUNT>\n" + " <PRICE>200.00</PRICE>\n" + " <LETTERS>ГД</LETTERS>\n" + " <COST>800.00</COST>\n" + " <DISCOUNTTYPE>0</DISCOUNTTYPE>\n" + " <DISCOUNTSUM>30.00</DISCOUNTSUM>\n" + " </ROW>\n" + ' <ROW ROWNUM="2">\n' + " <CODE>55</CODE>\n" + " <NAME>Морозиво</NAME>\n" + " <UNITNM>шт</UNITNM>\n" + " <AMOUNT>2</AMOUNT>\n" + " <PRICE>90.13</PRICE>\n" + " <LETTERS>БД</LETTERS>\n" + " <COST>180.26</COST>\n" + " <DISCOUNTTYPE>0</DISCOUNTTYPE>\n" + " <DISCOUNTSUM>20.00</DISCOUNTSUM>\n" + " </ROW>\n" + ' <ROW ROWNUM="3">\n' + " <CODE>56</CODE>\n" + " <NAME>Кава</NAME>\n" + " <UNITNM>шт</UNITNM>\n" + " <AMOUNT>1</AMOUNT>\n" + " <PRICE>20.13</PRICE>\n" + " <LETTERS>В</LETTERS>\n" + " <COST>20.13</COST>\n" + " <DISCOUNTTYPE>0</DISCOUNTTYPE>\n" + " <DISCOUNTSUM>0.35</DISCOUNTSUM>\n" + " </ROW>\n" + " </CHECKBODY>\n" + "</CHECK>", ); }); it("should generate valid receipt XML, with a correct tag's order if money in cents format", () => { const taxesConfig = getTaxPrograms(mockCustomTaxes); const taxes = getTaxesData(taxesConfig)( receiptRequestDatInCentsAndGrams.products, ); const data = getReceiptDocument({ ...receiptRequestDatInCentsAndGrams, taxes, }); expect(builder.buildObject(data)).toBe( '<?xml version="1.0" encoding="windows-1251"?>\n' + "<CHECK>\n" + " <CHECKHEAD>\n" + " <DOCTYPE>0</DOCTYPE>\n" + " <DOCSUBTYPE>0</DOCSUBTYPE>\n" + " <UID>11111111-1111-1111-1111-111111111111</UID>\n" + " <TIN>44657555</TIN>\n" + " <ORGNM>ТОВ ТЕСТ ПРРО</ORGNM>\n" + " <POINTNM>кафе Ромашка</POINTNM>\n" + " <POINTADDR>Дніпропетровська область, м. Дніпро, вул. Шевченка, 1</POINTADDR>\n" + " <ORDERDATE>18042024</ORDERDATE>\n" + " <ORDERTIME>151617</ORDERTIME>\n" + " <ORDERNUM>2834</ORDERNUM>\n" + " <CASHDESKNUM>123</CASHDESKNUM>\n" + " <CASHREGISTERNUM>4000438533</CASHREGISTERNUM>\n" + " <CASHIER>Шевченко Т.Г.</CASHIER>\n" + " <VER>1</VER>\n" + " <ORDERTAXNUM>23649865.4.1077</ORDERTAXNUM>\n" + " <OFFLINE>true</OFFLINE>\n" + " <PREVDOCHASH>47a08c017274237765f9081d994e76e08742dcef85056d655a8458ec43dff6e4</PREVDOCHASH>\n" + " <TESTING>true</TESTING>\n" + " </CHECKHEAD>\n" + " <CHECKTOTAL>\n" + " <SUM>950.04</SUM>\n" + " <DISCOUNTSUM>50.35</DISCOUNTSUM>\n" + " </CHECKTOTAL>\n" + " <CHECKPAY>\n" + ' <ROW ROWNUM="1">\n' + " <PAYFORMCD>0</PAYFORMCD>\n" + " <PAYFORMNM>ГОТІВКА</PAYFORMNM>\n" + " <SUM>100.00</SUM>\n" + " <PROVIDED>100.00</PROVIDED>\n" + " </ROW>\n" + ' <ROW ROWNUM="2">\n' + " <PAYFORMCD>1</PAYFORMCD>\n" + " <PAYFORMNM>КАРТКА</PAYFORMNM>\n" + " <SUM>850.04</SUM>\n" + " <PROVIDED>850.04</PROVIDED>\n" + " </ROW>\n" + " </CHECKPAY>\n" + " <CHECKTAX>\n" + ' <ROW ROWNUM="1">\n' + " <TYPE>1</TYPE>\n" + " <NAME>Акциз</NAME>\n" + " <LETTER>Д</LETTER>\n" + " <PRC>5.00</PRC>\n" + " <TURNOVER>980.26</TURNOVER>\n" + " <TURNOVERDISCOUNT>930.26</TURNOVERDISCOUNT>\n" + " <SOURCESUM>930.26</SOURCESUM>\n" + " <SUM>44.30</SUM>\n" + " </ROW>\n" + ' <ROW ROWNUM="2">\n' + " <TYPE>0</TYPE>\n" + " <NAME>ПДВ 0%</NAME>\n" + " <LETTER>Г</LETTER>\n" + " <PRC>0.00</PRC>\n" + " <TURNOVER>800.00</TURNOVER>\n" + " <TURNOVERDISCOUNT>770.00</TURNOVERDISCOUNT>\n" + " <SOURCESUM>733.33</SOURCESUM>\n" + " <SUM>0.00</SUM>\n" + " </ROW>\n" + ' <ROW ROWNUM="3">\n' + " <TYPE>0</TYPE>\n" + " <NAME>ПДВ 7%</NAME>\n" + " <LETTER>Б</LETTER>\n" + " <PRC>7.00</PRC>\n" + " <TURNOVER>180.26</TURNOVER>\n" + " <TURNOVERDISCOUNT>160.26</TURNOVERDISCOUNT>\n" + " <SOURCESUM>152.63</SOURCESUM>\n" + " <SUM>9.99</SUM>\n" + " </ROW>\n" + ' <ROW ROWNUM="4">\n' + " <TYPE>0</TYPE>\n" + " <NAME>ПДВ 20%</NAME>\n" + " <LETTER>В</LETTER>\n" + " <PRC>20.00</PRC>\n" + " <TURNOVER>20.13</TURNOVER>\n" + " <TURNOVERDISCOUNT>19.78</TURNOVERDISCOUNT>\n" + " <SOURCESUM>19.78</SOURCESUM>\n" + " <SUM>3.30</SUM>\n" + " </ROW>\n" + " </CHECKTAX>\n" + " <CHECKBODY>\n" + ' <ROW ROWNUM="1">\n' + " <CODE>54</CODE>\n" + " <NAME>Сирна паличка</NAME>\n" + " <UNITNM>шт</UNITNM>\n" + " <AMOUNT>4</AMOUNT>\n" + " <PRICE>200.00</PRICE>\n" + " <LETTERS>ГД</LETTERS>\n" + " <COST>800.00</COST>\n" + " <DISCOUNTTYPE>0</DISCOUNTTYPE>\n" + " <DISCOUNTSUM>30.00</DISCOUNTSUM>\n" + " </ROW>\n" + ' <ROW ROWNUM="2">\n' + " <CODE>55</CODE>\n" + " <NAME>Морозиво</NAME>\n" + " <UNITNM>шт</UNITNM>\n" + " <AMOUNT>2</AMOUNT>\n" + " <PRICE>90.13</PRICE>\n" + " <LETTERS>БД</LETTERS>\n" + " <COST>180.26</COST>\n" + " <DISCOUNTTYPE>0</DISCOUNTTYPE>\n" + " <DISCOUNTSUM>20.00</DISCOUNTSUM>\n" + " </ROW>\n" + ' <ROW ROWNUM="3">\n' + " <CODE>56</CODE>\n" + " <NAME>Кава</NAME>\n" + " <UNITNM>шт</UNITNM>\n" + " <AMOUNT>1</AMOUNT>\n" + " <PRICE>20.13</PRICE>\n" + " <LETTERS>В</LETTERS>\n" + " <COST>20.13</COST>\n" + " <DISCOUNTTYPE>0</DISCOUNTTYPE>\n" + " <DISCOUNTSUM>0.35</DISCOUNTSUM>\n" + " </ROW>\n" + " </CHECKBODY>\n" + "</CHECK>", ); }); }); }); describe("shiftOpenXMLGenerator", () => { describe("xml2js builder", () => { const builder = new xml2js.Builder({ xmldec: { encoding: XML_ENCODING }, }); const data = { type: "shiftOpen", dateTime: "2024-04-18T15:16:17", uid: "11111111-1111-1111-1111-111111111111", cashboxData: { tin: 44657555, name: "ТОВ ТЕСТ ПРРО", pointName: "кафе Ромашка", pointAddress: "Дніпропетровська область, м. Дніпро, вул. Шевченка, 1", cashbox: "4000438533", cashboxLocalNumber: "123", isOffline: true, isTestingMode: true, nextDocumentNumber: 1, offlineSessionData: { id: 23649865, seed: 135969449201653, nextOfflineDocumentNumber: 1, lastDocumentHash: "685df9bd624bde3dfb25c40c1d80583e60fe1d6ec6f4932343d79abb1aecab40", }, }, cashier: "Шевченко Т.Г.", }; it("getShiftOpenDocument should generate shiftOpen valid XML, with a correct tag's order", async () => { const shiftOpenData = await getShiftOpenDocument(data); expect(builder.buildObject(shiftOpenData)).toBe( '<?xml version="1.0" encoding="windows-1251"?>\n' + "<CHECK>\n" + " <CHECKHEAD>\n" + " <DOCTYPE>100</DOCTYPE>\n" + " <UID>11111111-1111-1111-1111-111111111111</UID>\n" + " <TIN>44657555</TIN>\n" + " <ORGNM>ТОВ ТЕСТ ПРРО</ORGNM>\n" + " <POINTNM>кафе Ромашка</POINTNM>\n" + " <POINTADDR>Дніпропетровська область, м. Дніпро, вул. Шевченка, 1</POINTADDR>\n" + " <ORDERDATE>18042024</ORDERDATE>\n" + " <ORDERTIME>151617</ORDERTIME>\n" + " <ORDERNUM>1</ORDERNUM>\n" + " <CASHDESKNUM>123</CASHDESKNUM>\n" + " <CASHREGISTERNUM>4000438533</CASHREGISTERNUM>\n" + " <CASHIER>Шевченко Т.Г.</CASHIER>\n" + " <VER>1</VER>\n" + " <ORDERTAXNUM>23649865.1.3650</ORDERTAXNUM>\n" + " <OFFLINE>true</OFFLINE>\n" + " <PREVDOCHASH>685df9bd624bde3dfb25c40c1d80583e60fe1d6ec6f4932343d79abb1aecab40</PREVDOCHASH>\n" + " <TESTING>true</TESTING>\n" + " </CHECKHEAD>\n" + "</CHECK>", ); }); }); }); describe("zReportXMLGenerator", () => { describe("xml2js builder", () => { const builder = new xml2js.Builder({ xmldec: { encoding: XML_ENCODING }, }); it("should generate valid z-report XML, with a correct tag's order", async () => { const data = await getZReportDocument(zReportData); expect(builder.buildObject(data)).toBe( '<?xml version="1.0" encoding="windows-1251"?>\n' + "<ZREP>\n" + " <ZREPHEAD>\n" + " <UID>11111111-1111-1111-1111-111111111111</UID>\n" + " <TIN>44657555</TIN>\n" + " <ORGNM>ТОВ ТЕСТ ПРРО</ORGNM>\n" + " <POINTNM>кафе Ромашка</POINTNM>\n" + " <POINTADDR>Дніпропетровська область, м. Дніпро, вул. Шевченка, 1</POINTADDR>\n" + " <ORDERDATE>18042024</ORDERDATE>\n" + " <ORDERTIME>151617</ORDERTIME>\n" + " <ORDERNUM>1</ORDERNUM>\n" + " <CASHDESKNUM>123</CASHDESKNUM>\n" + " <CASHREGISTERNUM>4000438533</CASHREGISTERNUM>\n" + " <CASHIER>Шевченко Т.Г.</CASHIER>\n" + " <VER>1</VER>\n" + " <ORDERTAXNUM>23649865.1.3650</ORDERTAXNUM>\n" + " <OFFLINE>true</OFFLINE>\n" + " <PREVDOCHASH>685df9bd624bde3dfb25c40c1d80583e60fe1d6ec6f4932343d79abb1aecab40</PREVDOCHASH>\n" + " <TESTING>true</TESTING>\n" + " </ZREPHEAD>\n" + " <ZREPREALIZ>\n" + " <SUM>27710.69</SUM>\n" + " <ORDERSCNT>87</ORDERSCNT>\n" + " <PAYFORMS>\n" + ' <ROW ROWNUM="1">\n' + " <PAYFORMCD>0</PAYFORMCD>\n" + " <PAYFORMNM>ГОТІВКА</PAYFORMNM>\n" + " <SUM>8700.00</SUM>\n" + " </ROW>\n" + ' <ROW ROWNUM="2">\n' + " <PAYFORMCD>1</PAYFORMCD>\n" + " <PAYFORMNM>КАРТКА</PAYFORMNM>\n" + " <SUM>19010.69</SUM>\n" + " </ROW>\n" + " </PAYFORMS>\n" + " <TAXES>\n" + ' <ROW ROWNUM="1">\n' + " <TYPE>2</TYPE>\n" + " <NAME>ПДВ 20%</NAME>\n" + " <LETTER>Б</LETTER>\n" + " <PRC>20.00</PRC>\n" + " <TURNOVER>4506.50</TURNOVER>\n" + " <TURNOVERDISCOUNT>4506.50</TURNOVERDISCOUNT>\n" + " <SOURCESUM>3755.42</SOURCESUM>\n" + " <SUM>751.08</SUM>\n" + " </ROW>\n" + ' <ROW ROWNUM="2">\n' + " <TYPE>4</TYPE>\n" + " <NAME>ПДВ 20%</NAME>\n" + " <LETTER>Г</LETTER>\n" + " <PRC>20.00</PRC>\n" + " <TURNOVER>2303.25</TURNOVER>\n" + " <TURNOVERDISCOUNT>2303.25</TURNOVERDISCOUNT>\n" + " <SOURCESUM>1919.38</SOURCESUM>\n" + " <SUM>383.88</SUM>\n" + " </ROW>\n" + ' <ROW ROWNUM="3">\n' + " <TYPE>5</TYPE>\n" + " <NAME>Акциз 5%</NAME>\n" + " <LETTER>Д</LETTER>\n" + " <PRC>5.00</PRC>\n" + " <TURNOVER>20900.94</TURNOVER>\n" + " <TURNOVERDISCOUNT>20900.94</TURNOVERDISCOUNT>\n" + " <SOURCESUM>19905.66</SOURCESUM>\n" + " <SUM>995.28</SUM>\n" + " </ROW>\n" + " </TAXES>\n" + " </ZREPREALIZ>\n" + " <ZREPBODY>\n" + " <SERVICEINPUT>10.00</SERVICEINPUT>\n" + " <SERVICEOUTPUT>20.00</SERVICEOUTPUT>\n" + " </ZREPBODY>\n" + "</ZREP>", ); }); }); }); });