@danielrebolledo/cafe-ipdh-lib 1.0.2 → 1.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -1,9 +1,7 @@
1
1
  "use strict";
2
- var __create = Object.create;
3
2
  var __defProp = Object.defineProperty;
4
3
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
4
  var __getOwnPropNames = Object.getOwnPropertyNames;
6
- var __getProtoOf = Object.getPrototypeOf;
7
5
  var __hasOwnProp = Object.prototype.hasOwnProperty;
8
6
  var __export = (target, all) => {
9
7
  for (var name in all)
@@ -17,20 +15,11 @@ var __copyProps = (to, from, except, desc) => {
17
15
  }
18
16
  return to;
19
17
  };
20
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
- // If the importer is in node compatibility mode or this is not an ESM
22
- // file that has been converted to a CommonJS file using a Babel-
23
- // compatible transform (i.e. "__esModule" has not been set), then set
24
- // "default" to the CommonJS "module.exports" for node compatibility.
25
- isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
- mod
27
- ));
28
18
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
19
 
30
20
  // src/index.ts
31
21
  var index_exports = {};
32
22
  __export(index_exports, {
33
- DtpClient: () => DtpClient,
34
23
  PaymentMethodId: () => PaymentMethodId,
35
24
  PrinterTaxValues: () => PrinterTaxValues,
36
25
  TaxValues: () => TaxValues,
@@ -41,107 +30,6 @@ __export(index_exports, {
41
30
  });
42
31
  module.exports = __toCommonJS(index_exports);
43
32
 
44
- // src/printers/dtp/dtp-client.ts
45
- var import_node_net = __toESM(require("net"), 1);
46
- var STX = 2;
47
- var ETX = 3;
48
- var FS = 28;
49
- var DtpClient = class {
50
- constructor(opts) {
51
- this.opts = opts;
52
- }
53
- socket = null;
54
- buffer = Buffer.alloc(0);
55
- pending = null;
56
- async connect() {
57
- if (this.socket) return;
58
- const socket = import_node_net.default.createConnection({
59
- host: this.opts.host,
60
- port: this.opts.port
61
- });
62
- this.socket = socket;
63
- socket.on(
64
- "data",
65
- (chunk) => this.onData(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk, "utf8"))
66
- );
67
- socket.on("error", (e) => this.onError(e));
68
- socket.on("close", () => this.onClose());
69
- const timeoutMs = this.opts.connectTimeoutMs ?? 3e3;
70
- await new Promise((resolve, reject) => {
71
- const t = setTimeout(
72
- () => reject(new Error("Connect timeout")),
73
- timeoutMs
74
- );
75
- socket.once("connect", () => {
76
- clearTimeout(t);
77
- resolve();
78
- });
79
- socket.once("error", (e) => {
80
- clearTimeout(t);
81
- reject(e);
82
- });
83
- });
84
- }
85
- close() {
86
- this.socket?.end();
87
- this.socket = null;
88
- this.buffer = Buffer.alloc(0);
89
- }
90
- async send(parts) {
91
- if (!this.socket) throw new Error("Socket not connected");
92
- if (this.pending) throw new Error("Another command is in-flight");
93
- const frame = this.buildFrame(parts);
94
- const timeoutMs = this.opts.commandTimeoutMs ?? 1e4;
95
- return await new Promise((resolve, reject) => {
96
- const timer = setTimeout(() => {
97
- this.pending = null;
98
- reject(new Error(`Command timeout: ${parts[0]}`));
99
- }, timeoutMs);
100
- this.pending = { resolve, reject, timer };
101
- this.socket?.write(frame);
102
- });
103
- }
104
- buildFrame(parts) {
105
- const payload = Buffer.from(parts.join(String.fromCharCode(FS)), "utf8");
106
- return Buffer.concat([Buffer.from([STX]), payload, Buffer.from([ETX])]);
107
- }
108
- tryParseOneFrame() {
109
- const start = this.buffer.indexOf(STX);
110
- const end = this.buffer.indexOf(ETX, start + 1);
111
- if (start === -1 || end === -1) return null;
112
- const body = this.buffer.subarray(start + 1, end);
113
- this.buffer = this.buffer.subarray(end + 1);
114
- const params = body.toString("utf8").split(String.fromCharCode(FS));
115
- return params;
116
- }
117
- onData(chunk) {
118
- this.buffer = Buffer.concat([this.buffer, chunk]);
119
- const params = this.tryParseOneFrame();
120
- if (!params) return;
121
- if (!this.pending) return;
122
- const { resolve, timer } = this.pending;
123
- clearTimeout(timer);
124
- this.pending = null;
125
- resolve(params);
126
- }
127
- onError(e) {
128
- if (this.pending) {
129
- const { reject, timer } = this.pending;
130
- clearTimeout(timer);
131
- this.pending = null;
132
- reject(e);
133
- }
134
- }
135
- onClose() {
136
- if (this.pending) {
137
- const { reject, timer } = this.pending;
138
- clearTimeout(timer);
139
- this.pending = null;
140
- reject(new Error("Socket closed"));
141
- }
142
- }
143
- };
144
-
145
33
  // src/types/enums.ts
146
34
  var TaxValues = /* @__PURE__ */ ((TaxValues2) => {
147
35
  TaxValues2[TaxValues2["EXENTO_E"] = 0] = "EXENTO_E";
@@ -862,7 +750,6 @@ async function sendAegCommands(args, options) {
862
750
  }
863
751
  // Annotate the CommonJS export names for ESM import in node:
864
752
  0 && (module.exports = {
865
- DtpClient,
866
753
  PaymentMethodId,
867
754
  PrinterTaxValues,
868
755
  TaxValues,
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/printers/dtp/dtp-client.ts","../src/types/enums.ts","../src/printers/aeg/aeg-printer.ts","../src/printers/dtp/dtp-printer.ts","../src/printers/dtp/dtp-printer-driver.ts","../src/runner/send-printer-commands.ts"],"sourcesContent":["/**\n * cafe-ipdh-lib\n * Librería para gestionar impresoras fiscales y de recibos.\n *\n * Soporta:\n * - AEG-R1: impresora fiscal vía HTTP (comandos JSON)\n *\n * Uso:\n * ```ts\n * import { aegPrinter } from \"cafe-ipdh-lib\";\n *\n * const commands = aegPrinter.buildInvoiceCommands(order, {\n * paymentMethodId: \"pos_credit\",\n * storeName: \"Mi Tienda\"\n * });\n * // Enviar commands a la impresora vía tu API/transport\n * ```\n */\n\nexport type { DtpOptions } from \"./printers/dtp/dtp-client.js\";\nexport { DtpClient } from \"./printers/dtp/dtp-client.js\";\nexport type {\n\tBuildInvoiceOptions,\n\tBuildReceiptOptions,\n\tDocumentType,\n\tDtpPrinterCommand,\n\tExecuteDtpCommandsResult,\n\tPrinterCommandResponse,\n\tPrinterDriver,\n} from \"./printers/index.js\";\nexport {\n\taegPrinter,\n\tdtpPrinter,\n\texecuteDtpCommands,\n} from \"./printers/index.js\";\nexport type {\n\tAegModel,\n\tDtpModel,\n\tPrinterBrand,\n\tSendPrinterCommandsAeg,\n\tSendPrinterCommandsArgs,\n\tSendPrinterCommandsDtp,\n} from \"./runner/index.js\";\nexport { sendPrinterCommands } from \"./runner/index.js\";\nexport type {\n\tAegPrinterCommand,\n\tFiscalClient,\n\tItemTax,\n\tOrder,\n\tOrderItem,\n\tOrderPayment,\n} from \"./types/index.js\";\nexport {\n\tPaymentMethodId,\n\tPrinterTaxValues,\n\tTaxValues,\n} from \"./types/index.js\";\n","import net from \"node:net\";\n\nconst STX = 0x02;\nconst ETX = 0x03;\nconst FS = 0x1c;\n\nexport type DtpOptions = {\n\thost: string;\n\tport: number;\n\tconnectTimeoutMs?: number;\n\tcommandTimeoutMs?: number;\n};\n\nexport class DtpClient {\n\tprivate socket: net.Socket | null = null;\n\tprivate buffer = Buffer.alloc(0);\n\tprivate pending: {\n\t\tresolve: (v: string[]) => void;\n\t\treject: (e: Error) => void;\n\t\ttimer: NodeJS.Timeout;\n\t} | null = null;\n\n\tconstructor(private opts: DtpOptions) {}\n\n\tasync connect(): Promise<void> {\n\t\tif (this.socket) return;\n\n\t\tconst socket = net.createConnection({\n\t\t\thost: this.opts.host,\n\t\t\tport: this.opts.port,\n\t\t});\n\n\t\tthis.socket = socket;\n\n\t\tsocket.on(\"data\", (chunk: Buffer | string) =>\n\t\t\tthis.onData(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk, \"utf8\")),\n\t\t);\n\t\tsocket.on(\"error\", (e) => this.onError(e));\n\t\tsocket.on(\"close\", () => this.onClose());\n\n\t\tconst timeoutMs = this.opts.connectTimeoutMs ?? 3000;\n\n\t\tawait new Promise<void>((resolve, reject) => {\n\t\t\tconst t = setTimeout(\n\t\t\t\t() => reject(new Error(\"Connect timeout\")),\n\t\t\t\ttimeoutMs,\n\t\t\t);\n\n\t\t\tsocket.once(\"connect\", () => {\n\t\t\t\tclearTimeout(t);\n\t\t\t\tresolve();\n\t\t\t});\n\n\t\t\tsocket.once(\"error\", (e) => {\n\t\t\t\tclearTimeout(t);\n\t\t\t\treject(e);\n\t\t\t});\n\t\t});\n\t}\n\n\tclose(): void {\n\t\tthis.socket?.end();\n\t\tthis.socket = null;\n\t\tthis.buffer = Buffer.alloc(0);\n\t}\n\n\tasync send(parts: string[]): Promise<string[]> {\n\t\tif (!this.socket) throw new Error(\"Socket not connected\");\n\n\t\tif (this.pending) throw new Error(\"Another command is in-flight\");\n\n\t\tconst frame = this.buildFrame(parts);\n\t\tconst timeoutMs = this.opts.commandTimeoutMs ?? 10_000;\n\n\t\treturn await new Promise<string[]>((resolve, reject) => {\n\t\t\tconst timer = setTimeout(() => {\n\t\t\t\tthis.pending = null;\n\t\t\t\treject(new Error(`Command timeout: ${parts[0]}`));\n\t\t\t}, timeoutMs);\n\n\t\t\tthis.pending = { resolve, reject, timer };\n\n\t\t\tthis.socket?.write(frame);\n\t\t});\n\t}\n\n\tprivate buildFrame(parts: string[]): Buffer {\n\t\tconst payload = Buffer.from(parts.join(String.fromCharCode(FS)), \"utf8\");\n\t\treturn Buffer.concat([Buffer.from([STX]), payload, Buffer.from([ETX])]);\n\t}\n\n\tprivate tryParseOneFrame(): string[] | null {\n\t\tconst start = this.buffer.indexOf(STX);\n\t\tconst end = this.buffer.indexOf(ETX, start + 1);\n\n\t\tif (start === -1 || end === -1) return null;\n\n\t\tconst body = this.buffer.subarray(start + 1, end);\n\n\t\tthis.buffer = this.buffer.subarray(end + 1);\n\n\t\tconst params = body.toString(\"utf8\").split(String.fromCharCode(FS));\n\t\treturn params;\n\t}\n\n\tprivate onData(chunk: Buffer) {\n\t\tthis.buffer = Buffer.concat([this.buffer, chunk]);\n\n\t\tconst params = this.tryParseOneFrame();\n\t\tif (!params) return;\n\n\t\tif (!this.pending) return;\n\n\t\tconst { resolve, timer } = this.pending;\n\t\tclearTimeout(timer);\n\t\tthis.pending = null;\n\n\t\tresolve(params);\n\t}\n\n\tprivate onError(e: Error) {\n\t\tif (this.pending) {\n\t\t\tconst { reject, timer } = this.pending;\n\t\t\tclearTimeout(timer);\n\t\t\tthis.pending = null;\n\t\t\treject(e);\n\t\t}\n\t}\n\n\tprivate onClose() {\n\t\tif (this.pending) {\n\t\t\tconst { reject, timer } = this.pending;\n\t\t\tclearTimeout(timer);\n\t\t\tthis.pending = null;\n\t\t\treject(new Error(\"Socket closed\"));\n\t\t}\n\t}\n}\n","/**\n * Valores de impuestos (porcentajes) según legislación venezolana.\n */\nexport enum TaxValues {\n\tEXENTO_E = 0,\n\tBI_G = 16.0,\n\tIVA_G = 16.0,\n\tBI_R = 8.0,\n\tIVA_R = 8.0,\n\tBI_A = 31.0,\n\tIVA_A = 31.0,\n\tPERCIBIDO = 0,\n\tBI_IGTF = 3.0,\n\tIVA_IGTF = 3.0,\n}\n\n/**\n * Códigos de impuesto para impresora fiscal AEG-R1.\n */\nexport enum PrinterTaxValues {\n\tEXENTO_E = 1,\n\tBI_G = 2,\n\tIVA_G = 2,\n\tBI_R = 3,\n\tIVA_R = 3,\n\tBI_A = 4,\n\tIVA_A = 4,\n\tPERCIBIDO = 5,\n\tBI_IGTF = 5,\n\tIVA_IGTF = 5,\n}\n\n/**\n * IDs de método de pago para impresora fiscal AEG-R1.\n * Efectivo: 1, Débito: 2, Crédito: 3, Pago Móvil: 5,\n * Débito/Crédito int: 11, Efectivo int: 12\n */\nexport enum PaymentMethodId {\n\tCASH = 1,\n\tPOS_DEBIT = 2,\n\tPOS_CREDIT = 3,\n\tPAGO_MOVIL = 5,\n\tPOS_DEBIT_CREDIT_INT = 11,\n\tCASH_INT = 12,\n}\n","import type { AegPrinterCommand } from \"../../types/aeg-commands.js\";\nimport {\n\tPaymentMethodId,\n\tPrinterTaxValues,\n\tTaxValues,\n} from \"../../types/enums.js\";\nimport type { Order } from \"../../types/order.js\";\nimport type {\n\tBuildInvoiceOptions,\n\tBuildReceiptOptions,\n\tPrinterDriver,\n} from \"../printer.types.js\";\n\nfunction truncateString(str: string, maxLength = 64): string {\n\tif (!str) return \"\";\n\treturn str.length > maxLength ? str.substring(0, maxLength) : str;\n}\n\n// biome-ignore lint: avoid control char in literal\nconst ISO_8859_1_REGEX = new RegExp(\"[^\\\\u0000-\\\\u00FF]\", \"g\");\n\nfunction normalizeIso88591(str: string): string {\n\treturn str.replace(ISO_8859_1_REGEX, \"?\");\n}\n\nfunction formatDate(date: Date): string {\n\tconst day = date.getDate().toString().padStart(2, \"0\");\n\tconst month = (date.getMonth() + 1).toString().padStart(2, \"0\");\n\tconst year = date.getFullYear();\n\treturn `${day}/${month}/${year}`;\n}\n\nfunction formatTime(date: Date): string {\n\tconst hours = date.getHours().toString().padStart(2, \"0\");\n\tconst minutes = date.getMinutes().toString().padStart(2, \"0\");\n\treturn `${hours}:${minutes}`;\n}\n\nfunction mapTaxIdToPrinterCode(taxId: string | null | undefined): number {\n\tif (!taxId) {\n\t\treturn PrinterTaxValues.EXENTO_E;\n\t}\n\tconst taxIdUpper = taxId.toUpperCase();\n\tconst printerTaxValue =\n\t\tPrinterTaxValues[taxIdUpper as keyof typeof PrinterTaxValues];\n\tif (printerTaxValue !== undefined) {\n\t\treturn printerTaxValue;\n\t}\n\treturn PrinterTaxValues.EXENTO_E;\n}\n\nfunction mapPaymentMethod(method: string): PaymentMethodId {\n\tif (method === \"pos_debit\") return PaymentMethodId.POS_DEBIT;\n\tif (method === \"pos_credit\") return PaymentMethodId.POS_CREDIT;\n\tif (method === \"pos_debit_credit_int\")\n\t\treturn PaymentMethodId.POS_DEBIT_CREDIT_INT;\n\tif (method === \"cash_int\") return PaymentMethodId.CASH_INT;\n\tif (method === \"cash_nat\") return PaymentMethodId.CASH;\n\tthrow new Error(\n\t\t`Método de pago inválido: ${method}. Debe ser \"pos_debit\", \"pos_credit\", \"pos_debit_credit_int\", \"cash_int\" o \"cash_nat\"`,\n\t);\n}\n\n/**\n * Driver para impresora fiscal AEG-R1.\n * Construye comandos JSON según documentación oficial.\n */\nexport const aegPrinter: PrinterDriver<AegPrinterCommand> = {\n\tmodel: \"aeg-r1\",\n\n\tbuildInvoiceCommands(\n\t\torder: Order,\n\t\toptions: BuildInvoiceOptions,\n\t): AegPrinterCommand[] {\n\t\tconst commands: AegPrinterCommand[] = [];\n\n\t\tif (!order) {\n\t\t\tthrow new Error(\"Order es requerido\");\n\t\t}\n\t\tif (!order.client) {\n\t\t\tthrow new Error(\"Order debe tener un cliente asociado\");\n\t\t}\n\t\tif (!order.items || order.items.length === 0) {\n\t\t\tthrow new Error(\"Order debe tener al menos un item\");\n\t\t}\n\n\t\tconst { paymentMethodId, storeName = \"N/A\" } = options;\n\n\t\t// 1. cliF - Datos del cliente\n\t\tconst clientRifCI = order.client.id || \"\";\n\t\tconst clientName = order.client.name || \"\";\n\t\tconst clientEmail = order.client.email || \"\";\n\t\tconst clientPhone = order.client.phone || \"\";\n\t\tconst clientAddress = order.client.address || \"\";\n\t\tconst razSoc = [clientName, clientEmail, clientPhone]\n\t\t\t.filter(Boolean)\n\t\t\t.map((v) => truncateString(v, 64));\n\t\tconst storeLine = `Tienda: ${storeName}`;\n\t\tconst LineAd = [storeLine, clientAddress]\n\t\t\t.filter(Boolean)\n\t\t\t.map((v) => truncateString(v, 64));\n\n\t\tcommands.push({\n\t\t\tcmd: \"cliF\",\n\t\t\tdata: { rifCI: clientRifCI, razSoc, LineAd },\n\t\t});\n\n\t\t// 2. proF - Productos\n\t\tlet subtotalWithoutTaxes = 0;\n\n\t\tfor (const item of order.items) {\n\t\t\tif (!item.name) continue;\n\n\t\t\tconst taxId =\n\t\t\t\titem.taxes && item.taxes.length > 0 ? item.taxes[0].id : null;\n\t\t\tconst imp = mapTaxIdToPrinterCode(taxId);\n\t\t\tconst price = item.price || 0;\n\t\t\tconst pre = Math.round(Math.max(price, 0) * 100);\n\t\t\tconst quantity = item.selectedQuantity ?? item.quantity ?? 1;\n\t\t\tconst cant = Math.round(Math.max(quantity, 1) * 1000);\n\t\t\tconst des01 = truncateString(item.name, 64);\n\n\t\t\tsubtotalWithoutTaxes += price * Math.max(quantity, 1);\n\n\t\t\tcommands.push({\n\t\t\t\tcmd: \"proF\",\n\t\t\t\tdata: { imp, pre, cant, des01 },\n\t\t\t});\n\t\t}\n\n\t\t// 2.1 IGTF si pago en divisas\n\t\tconst isForeignCurrency =\n\t\t\tpaymentMethodId === \"pos_debit_credit_int\" ||\n\t\t\tpaymentMethodId === \"cash_int\";\n\n\t\tif (isForeignCurrency && subtotalWithoutTaxes > 0) {\n\t\t\tconst roundedSubtotal =\n\t\t\t\tMath.round((subtotalWithoutTaxes + Number.EPSILON) * 100) / 100;\n\t\t\tconst igtfPercentage = TaxValues.BI_IGTF / 100;\n\t\t\tconst igtfAmount =\n\t\t\t\tMath.round((roundedSubtotal * igtfPercentage + Number.EPSILON) * 100) /\n\t\t\t\t100;\n\n\t\t\tcommands.push({\n\t\t\t\tcmd: \"proF\",\n\t\t\t\tdata: {\n\t\t\t\t\timp: PrinterTaxValues.PERCIBIDO,\n\t\t\t\t\tpre: Math.round(igtfAmount * 100),\n\t\t\t\t\tcant: 1000,\n\t\t\t\t\tdes01: \"IGTF 3% pago en divisas\",\n\t\t\t\t},\n\t\t\t});\n\t\t}\n\n\t\t// 3. subToF - Subtotal\n\t\tcommands.push({ cmd: \"subToF\", data: 1, valor: 0 });\n\n\t\t// 4. fpaF - Forma de pago\n\t\tif (!order.payments?.length) {\n\t\t\tthrow new Error(\"Order debe tener al menos un pago exitoso\");\n\t\t}\n\n\t\tfor (const payment of order.payments) {\n\t\t\tconst paymentType = mapPaymentMethod(payment.paymentMethod);\n\t\t\tconst paymentAmount = Math.round(payment.amount * 100);\n\t\t\tcommands.push({\n\t\t\t\tcmd: \"fpaF\",\n\t\t\t\tdata: {\n\t\t\t\t\ttipo: paymentType,\n\t\t\t\t\tmonto: paymentAmount,\n\t\t\t\t\ttasaConv: 0,\n\t\t\t\t},\n\t\t\t});\n\t\t}\n\n\t\t// 5. endFac - Cierre\n\t\tcommands.push({ cmd: \"endFac\", data: 1 });\n\n\t\treturn commands;\n\t},\n\n\tbuildReceiptCommands(options: BuildReceiptOptions): AegPrinterCommand[] {\n\t\tconst {\n\t\t\torderId,\n\t\t\tamountPaid,\n\t\t\tpaymentMethod,\n\t\t\tpaidAt,\n\t\t\tcardLast4,\n\t\t\torganizationName,\n\t\t} = options;\n\n\t\tif (!orderId) {\n\t\t\tthrow new Error(\"OrderId es requerido\");\n\t\t}\n\t\tif (!Number.isFinite(amountPaid) || amountPaid <= 0) {\n\t\t\tthrow new Error(\"Monto pagado inválido\");\n\t\t}\n\n\t\tconst paidDate = paidAt ?? new Date();\n\t\tconst amountLabel = `Bs ${amountPaid}`;\n\t\tconst paymentLabel = `Medio de pago: ${paymentMethod}`;\n\t\tconst dateLabel = `Fecha del pago: ${formatDate(paidDate)}`;\n\t\tconst timeLabel = `Hora del pago: ${formatTime(paidDate)}`;\n\t\tconst cardLabel = `Tarjeta ${cardLast4 ?? \"N/A\"}`;\n\t\tconst orgLabel = organizationName?.trim() || \"N/A\";\n\n\t\treturn [\n\t\t\t{\n\t\t\t\tcmd: \"encDNF\",\n\t\t\t\tdata: [\n\t\t\t\t\tnormalizeIso88591(truncateString(\"RECIBO DE PAGO\")),\n\t\t\t\t\tnormalizeIso88591(truncateString(orderId)),\n\t\t\t\t],\n\t\t\t},\n\t\t\t{\n\t\t\t\tcmd: \"aperDNF\",\n\t\t\t\tdata: normalizeIso88591(truncateString(\"Recibo de pago\")),\n\t\t\t},\n\t\t\t{\n\t\t\t\tcmd: \"efeNorJuIzDNF\",\n\t\t\t\tdata: normalizeIso88591(truncateString(orgLabel)),\n\t\t\t},\n\t\t\t{\n\t\t\t\tcmd: \"efeNorJuIzDNF\",\n\t\t\t\tdata: normalizeIso88591(truncateString(amountLabel)),\n\t\t\t},\n\t\t\t{\n\t\t\t\tcmd: \"efeNorJuIzDNF\",\n\t\t\t\tdata: normalizeIso88591(truncateString(paymentLabel)),\n\t\t\t},\n\t\t\t{\n\t\t\t\tcmd: \"efeNorJuIzDNF\",\n\t\t\t\tdata: normalizeIso88591(truncateString(cardLabel)),\n\t\t\t},\n\t\t\t{\n\t\t\t\tcmd: \"efeNorJuIzDNF\",\n\t\t\t\tdata: normalizeIso88591(truncateString(timeLabel)),\n\t\t\t},\n\t\t\t{\n\t\t\t\tcmd: \"efeNorJuIzDNF\",\n\t\t\t\tdata: normalizeIso88591(truncateString(dateLabel)),\n\t\t\t},\n\t\t\t{\n\t\t\t\tcmd: \"endDNF\",\n\t\t\t\tdata: normalizeIso88591(\"Cierre del Documento No Fiscal\"),\n\t\t\t},\n\t\t];\n\t},\n};\n","import type { DtpClient } from \"./dtp-client\";\nimport type { AbrirCfArgs, ItemCfArgs, PagoCfArgs } from \"./dtp-printer.types\";\n\nconst formatDateDDMMYYYY = (d: Date) => {\n\tconst dd = String(d.getDate()).padStart(2, \"0\");\n\tconst mm = String(d.getMonth() + 1).padStart(2, \"0\");\n\tconst yyyy = String(d.getFullYear());\n\treturn `${dd}${mm}${yyyy}`;\n};\n\nfunction parseCode(r: string[], idx = 0): number {\n\tconst v = r[idx];\n\tconst n = Number(v);\n\treturn v !== undefined && v !== null && !Number.isNaN(n) ? n : 16;\n}\n\n// C0 Get Status (used as \"real ping\")\nexport async function getStatus(client: DtpClient) {\n\tconst r = await client.send([\"C0\"]);\n\tconst code = parseCode(r);\n\treturn {\n\t\tcode,\n\t\tstate: code === 0 && r.length > 2 ? Number(r[2] ?? -1) : -1,\n\t\tblock: code === 0 && r.length > 3 ? Number(r[3] ?? -1) : -1,\n\t\tfiscalStatus: code === 0 && r.length > 4 ? String(r[4] ?? \"\") : \"\",\n\t\tlastCommandResponse:\n\t\t\tcode === 0 && r.length > 5 ? Number(r[5] ?? -1) : -1,\n\t\traw: r,\n\t};\n}\n\nexport async function openFiscalDoc(client: DtpClient, args: AbrirCfArgs) {\n\tconst r = await client.send([\n\t\t\"F0\",\n\t\tString(args.iTipo ?? 0),\n\t\targs.sNombreCliente,\n\t\targs.sRifCliente,\n\t\tString(args.iFacturaReferencia ?? 0),\n\t\tformatDateDDMMYYYY(args.fechaReferencia ?? new Date()),\n\t\targs.sSerialReferencia ?? \"\",\n\t\t(args.bLogo ?? false) ? \"1\" : \"0\",\n\t\targs.sLineaAdicional ?? \"\",\n\t]);\n\treturn {\n\t\tcode: parseCode(r),\n\t\tdocumentNumber: Number(r[1] ?? -1),\n\t\traw: r,\n\t};\n}\n\nexport async function addFiscalItem(client: DtpClient, args: ItemCfArgs) {\n\tconst r = await client.send([\n\t\t\"F1\",\n\t\tString(args.iTipo ?? 0),\n\t\targs.sDescripcion,\n\t\targs.sCodigo,\n\t\tString(args.lCantidad),\n\t\targs.sUnidad,\n\t\tString(args.lPrecio),\n\t\tString(args.iImpuesto),\n\t\tString(args.iDecPrecio),\n\t\tString(args.iDecCantidad),\n\t]);\n\treturn {\n\t\tcode: parseCode(r),\n\t\titemCount: Number(r[1] ?? -1),\n\t\ttotalItem: Number(r[2] ?? -1),\n\t\tprintedLines: Number(r[3] ?? -1),\n\t\traw: r,\n\t};\n}\n\nexport async function subtotalFiscalDoc(\n\tclient: DtpClient,\n\tmode = 0,\n\tforeignCurrencyAmount = 0,\n) {\n\tconst r = await client.send([\n\t\t\"F2\",\n\t\tString(mode),\n\t\tString(foreignCurrencyAmount),\n\t]);\n\treturn { code: parseCode(r), raw: r };\n}\n\nexport async function payFiscalDoc(client: DtpClient, args: PagoCfArgs) {\n\tconst r = await client.send([\n\t\t\"F4\",\n\t\tString(args.iTipoPago ?? 0),\n\t\tString(args.iFormaPago),\n\t\targs.sDescripcion,\n\t\tString(args.lMonto),\n\t]);\n\treturn {\n\t\tcode: parseCode(r),\n\t\tamountDue: Number(r[1] ?? -1),\n\t\tchangeAmount: Number(r[2] ?? -1),\n\t\tprintedLines: Number(r[3] ?? -1),\n\t\traw: r,\n\t};\n}\n\nexport async function addFiscalComment(\n\tclient: DtpClient,\n\tcomment: string,\n\tsize = 0,\n\talign = 0,\n\tstyle = 0,\n) {\n\tconst r = await client.send([\n\t\t\"F7\",\n\t\tcomment,\n\t\tString(size),\n\t\tString(align),\n\t\tString(style),\n\t]);\n\treturn {\n\t\tcode: parseCode(r),\n\t\tprintedLines: Number(r[1] ?? -1),\n\t\traw: r,\n\t};\n}\n\nexport async function closeFiscalDoc(\n\tclient: DtpClient,\n\tadditionalLine = \"\",\n) {\n\tconst r = await client.send([\"F5\", additionalLine]);\n\treturn {\n\t\tcode: parseCode(r),\n\t\tdocumentNumber: Number(r[1] ?? -1),\n\t\ttotalAmount: Number(r[2] ?? -1),\n\t\traw: r,\n\t};\n}\n\nexport async function cancelFiscalDoc(client: DtpClient) {\n\tconst r = await client.send([\"F6\"]);\n\treturn { code: parseCode(r), raw: r };\n}\n\nexport async function getSerializationData(client: DtpClient) {\n\tconst r = await client.send([\"C2\"]);\n\tconst code = parseCode(r);\n\treturn {\n\t\tcode,\n\t\tfiscalSerial: code === 0 && r.length >= 2 ? r[1] : \"\",\n\t\tprinterSerial: code === 0 && r.length >= 3 ? r[2] : \"\",\n\t\tkitSerial: code === 0 && r.length >= 4 ? r[3] : \"\",\n\t\tmfSerial: code === 0 && r.length >= 5 ? r[4] : \"\",\n\t\tmaSerial: code === 0 && r.length >= 6 ? r[5] : \"\",\n\t\traw: r,\n\t};\n}\n\nexport async function getFiscalizationData(client: DtpClient) {\n\tconst r = await client.send([\"C3\"]);\n\tconst code = parseCode(r);\n\treturn {\n\t\tcode,\n\t\ttaxpayerName: code === 0 && r.length >= 2 ? r[1] : \"\",\n\t\tfiscalAddress: code === 0 && r.length >= 3 ? r[2] : \"\",\n\t\ttaxpayerRif: code === 0 && r.length >= 4 ? r[3] : \"\",\n\t\tcommercialName: code === 0 && r.length >= 5 ? r[4] : \"\",\n\t\tdistributorName: code === 0 && r.length >= 6 ? r[5] : \"\",\n\t\tdistributorRif: code === 0 && r.length >= 7 ? r[6] : \"\",\n\t\ttaxRate1: code === 0 && r.length >= 8 ? Number(r[7]) : 0,\n\t\ttaxRate2: code === 0 && r.length >= 9 ? Number(r[8]) : 0,\n\t\ttaxRate3: code === 0 && r.length >= 10 ? Number(r[9]) : 0,\n\t\ttaxRate4: code === 0 && r.length >= 11 ? Number(r[10]) : 0,\n\t\traw: r,\n\t};\n}\n\nexport async function getPaymentMethod(\n\tclient: DtpClient,\n\tpaymentMethodId: number,\n) {\n\tconst r = await client.send([\"C9\", String(paymentMethodId)]);\n\treturn {\n\t\tcode: parseCode(r),\n\t\tname: parseCode(r) === 0 && r.length >= 2 ? r[1] : \"\",\n\t\traw: r,\n\t};\n}\n\nexport async function setPaymentMethod(\n\tclient: DtpClient,\n\tpaymentMethodId: number,\n\tname: string,\n) {\n\tconst r = await client.send([\"C10\", String(paymentMethodId), name]);\n\treturn { code: parseCode(r), raw: r };\n}\n\nexport async function payFiscalDocForeignCurrency(\n\tclient: DtpClient,\n\targs: {\n\t\tiFormaPago: number;\n\t\tsDescripcion: string;\n\t\tlMonto: number;\n\t\tlTasaCambio: number;\n\t\tsSimbolo: string;\n\t},\n) {\n\tconst r = await client.send([\n\t\t\"F11\",\n\t\t\"0\",\n\t\targs.sDescripcion,\n\t\tString(args.lMonto),\n\t\tString(args.lTasaCambio),\n\t\targs.sSimbolo,\n\t\tString(args.iFormaPago),\n\t]);\n\treturn {\n\t\tcode: parseCode(r),\n\t\tamountDue: Number(r[1] ?? -1),\n\t\tchangeAmount: Number(r[2] ?? -1),\n\t\tprintedLines: Number(r[3] ?? -1),\n\t\traw: r,\n\t};\n}\n\nexport async function reportX(\n\tclient: DtpClient,\n\tnoOpenDrawer = false,\n) {\n\tconst parts = [\"R0\", \"0\"];\n\tif (noOpenDrawer) parts.push(\"1\");\n\tconst r = await client.send(parts);\n\tconst code = parseCode(r);\n\treturn {\n\t\tcode,\n\t\tdocumentNumber: code === 0 && r.length >= 2 ? Number(r[1]) : -1,\n\t\traw: r,\n\t};\n}\n\nexport async function reportZ(\n\tclient: DtpClient,\n\tnoOpenDrawer = false,\n) {\n\tconst parts = [\"R0\", \"1\"];\n\tif (noOpenDrawer) parts.push(\"1\");\n\tconst r = await client.send(parts);\n\tconst code = parseCode(r);\n\treturn {\n\t\tcode,\n\t\treportNumber: code === 0 && r.length >= 2 ? Number(r[1]) : -1,\n\t\traw: r,\n\t};\n}\n\nexport async function getFiscalDayInfo(client: DtpClient) {\n\tconst r = await client.send([\"R1\"]);\n\tconst code = parseCode(r);\n\tif (code !== 0 || r.length < 84) {\n\t\treturn { code, raw: r };\n\t}\n\treturn {\n\t\tcode,\n\t\tzNumber: Number(r[1]),\n\t\tzDate: r[2],\n\t\tzTime: r[3],\n\t\tzStartDate: r[4],\n\t\tzStartTime: r[5],\n\t\tlastInvoiceNumber: Number(r[67]),\n\t\tlastInvoiceDate: r[68],\n\t\tlastInvoiceTime: r[69],\n\t\tlastCreditNoteNumber: Number(r[71]),\n\t\tlastDebitNoteNumber: Number(r[75]),\n\t\traw: r,\n\t};\n}\n\nexport async function getCounters(client: DtpClient) {\n\tconst r = await client.send([\"R9\"]);\n\tconst code = parseCode(r);\n\treturn {\n\t\tcode,\n\t\tlastInvoice: code === 0 && r.length >= 2 ? Number(r[1]) : -1,\n\t\tlastVoidedInvoice: code === 0 && r.length >= 3 ? Number(r[2]) : -1,\n\t\tlastCreditNote: code === 0 && r.length >= 4 ? Number(r[3]) : -1,\n\t\tlastDebitNote: code === 0 && r.length >= 5 ? Number(r[4]) : -1,\n\t\tlastNonFiscal: code === 0 && r.length >= 6 ? Number(r[5]) : -1,\n\t\tlastZReport: code === 0 && r.length >= 7 ? Number(r[6]) : -1,\n\t\traw: r,\n\t};\n}\n\nexport async function searchReprint(\n\tclient: DtpClient,\n\tdocumentType: number,\n\tdocumentNumber: number,\n\tprint = true,\n) {\n\tconst r = await client.send([\n\t\t\"R8\",\n\t\tprint ? \"1\" : \"0\",\n\t\tString(documentType),\n\t\tString(documentNumber),\n\t]);\n\treturn { code: parseCode(r), raw: r };\n}\n\nexport async function startFiscalMemoryReportByDateRange(\n\tclient: DtpClient,\n\treportType: number,\n\tstartDate: Date,\n\tendDate: Date,\n) {\n\tconst r = await client.send([\n\t\t\"R2\",\n\t\t\"0\",\n\t\tString(reportType),\n\t\tformatDateDDMMYYYY(startDate),\n\t\tformatDateDDMMYYYY(endDate),\n\t]);\n\treturn {\n\t\tcode: parseCode(r),\n\t\trecordCount: parseCode(r) === 0 && r.length >= 2 ? Number(r[1]) : -1,\n\t\traw: r,\n\t};\n}\n\nexport async function getFiscalMemoryReportData(client: DtpClient) {\n\tconst r = await client.send([\"R3\"]);\n\treturn { code: parseCode(r), raw: r };\n}\n\nexport async function finishFiscalMemoryReport(client: DtpClient) {\n\tconst r = await client.send([\"R4\"]);\n\treturn { code: parseCode(r), raw: r };\n}\n\nexport async function openNonFiscalDoc(client: DtpClient) {\n\tconst r = await client.send([\"N0\"]);\n\treturn { code: parseCode(r), raw: r };\n}\n\nexport async function addNonFiscalLine(\n\tclient: DtpClient,\n\tline: string,\n\tsize = 0,\n\talign = 0,\n\tstyle = 0,\n) {\n\tconst r = await client.send([\n\t\t\"N1\",\n\t\tline,\n\t\tString(size),\n\t\tString(align),\n\t\tString(style),\n\t]);\n\treturn {\n\t\tcode: parseCode(r),\n\t\tprintedLines: parseCode(r) === 0 && r.length >= 2 ? Number(r[1]) : -1,\n\t\traw: r,\n\t};\n}\n\nexport async function closeNonFiscalDoc(client: DtpClient) {\n\tconst r = await client.send([\"N3\"]);\n\treturn {\n\t\tcode: parseCode(r),\n\t\tdocumentNumber: parseCode(r) === 0 && r.length >= 2 ? Number(r[1]) : -1,\n\t\traw: r,\n\t};\n}\n","import {\n\tPaymentMethodId,\n\tPrinterTaxValues,\n\tTaxValues,\n} from \"../../types/enums.js\";\nimport type { Order } from \"../../types/order.js\";\nimport type {\n\tBuildInvoiceOptions,\n\tBuildReceiptOptions,\n\tPrinterDriver,\n} from \"../printer.types.js\";\nimport type { DtpClient } from \"./dtp-client.js\";\nimport type { DtpPrinterCommand } from \"./dtp-commands.js\";\nimport {\n\taddFiscalItem,\n\taddNonFiscalLine,\n\tcloseFiscalDoc,\n\tcloseNonFiscalDoc,\n\topenFiscalDoc,\n\topenNonFiscalDoc,\n\tpayFiscalDoc,\n\tpayFiscalDocForeignCurrency,\n\tsubtotalFiscalDoc,\n} from \"./dtp-printer.js\";\n\nfunction truncateString(str: string, maxLength = 64): string {\n\tif (!str) return \"\";\n\treturn str.length > maxLength ? str.substring(0, maxLength) : str;\n}\n\nfunction formatDate(date: Date): string {\n\tconst day = date.getDate().toString().padStart(2, \"0\");\n\tconst month = (date.getMonth() + 1).toString().padStart(2, \"0\");\n\tconst year = date.getFullYear();\n\treturn `${day}/${month}/${year}`;\n}\n\nfunction formatTime(date: Date): string {\n\tconst hours = date.getHours().toString().padStart(2, \"0\");\n\tconst minutes = date.getMinutes().toString().padStart(2, \"0\");\n\treturn `${hours}:${minutes}`;\n}\n\n/**\n * Mapea taxId (IVA_G, EXENTO_E, etc.) a código DTP iImpuesto (0..4).\n * DTP: 0=exento, 1=16%, 2=8%, 3=31%, 4=percibido/IGTF.\n */\nfunction mapTaxIdToDtpCode(taxId: string | null | undefined): number {\n\tif (!taxId) return 0;\n\tconst taxIdUpper = taxId.toUpperCase();\n\tconst aegCode =\n\t\tPrinterTaxValues[taxIdUpper as keyof typeof PrinterTaxValues];\n\tif (aegCode === undefined) return 0;\n\tconst n = Number(aegCode);\n\t// DTP iImpuesto: 0=exento, 1=16%, 2=8%, 3=31%, 4=percibido\n\tif (n === PrinterTaxValues.EXENTO_E) return 0;\n\tif (n === PrinterTaxValues.BI_G || n === PrinterTaxValues.IVA_G)\n\t\treturn 1;\n\tif (n === PrinterTaxValues.BI_R || n === PrinterTaxValues.IVA_R)\n\t\treturn 2;\n\tif (n === PrinterTaxValues.BI_A || n === PrinterTaxValues.IVA_A)\n\t\treturn 3;\n\tif (\n\t\tn === PrinterTaxValues.PERCIBIDO ||\n\t\tn === PrinterTaxValues.BI_IGTF ||\n\t\tn === PrinterTaxValues.IVA_IGTF\n\t)\n\t\treturn 4;\n\treturn 0;\n}\n\nfunction mapPaymentMethod(method: string): PaymentMethodId {\n\tif (method === \"pos_debit\") return PaymentMethodId.POS_DEBIT;\n\tif (method === \"pos_credit\") return PaymentMethodId.POS_CREDIT;\n\tif (method === \"pos_debit_credit_int\")\n\t\treturn PaymentMethodId.POS_DEBIT_CREDIT_INT;\n\tif (method === \"cash_int\") return PaymentMethodId.CASH_INT;\n\tif (method === \"cash_nat\") return PaymentMethodId.CASH;\n\tthrow new Error(\n\t\t`Método de pago inválido: ${method}. Debe ser \"pos_debit\", \"pos_credit\", \"pos_debit_credit_int\", \"cash_int\" o \"cash_nat\"`,\n\t);\n}\n\nfunction paymentMethodLabel(id: PaymentMethodId): string {\n\tswitch (id) {\n\t\tcase PaymentMethodId.CASH:\n\t\t\treturn \"EFECTIVO\";\n\t\tcase PaymentMethodId.POS_DEBIT:\n\t\t\treturn \"TARJETA DEBITO\";\n\t\tcase PaymentMethodId.POS_CREDIT:\n\t\t\treturn \"TARJETA CREDITO\";\n\t\tcase PaymentMethodId.PAGO_MOVIL:\n\t\t\treturn \"PAGO MOVIL\";\n\t\tcase PaymentMethodId.POS_DEBIT_CREDIT_INT:\n\t\t\treturn \"TARJETA INT\";\n\t\tcase PaymentMethodId.CASH_INT:\n\t\t\treturn \"EFECTIVO USD\";\n\t\tdefault:\n\t\t\treturn \"EFECTIVO\";\n\t}\n}\n\n/**\n * Driver para impresora fiscal DTP-80i.\n * Construye comandos DTP compatibles con el protocolo TCP.\n */\nexport const dtpPrinter: PrinterDriver<DtpPrinterCommand> = {\n\tmodel: \"dtp-80i\",\n\n\tbuildInvoiceCommands(\n\t\torder: Order,\n\t\toptions: BuildInvoiceOptions,\n\t): DtpPrinterCommand[] {\n\t\tconst commands: DtpPrinterCommand[] = [];\n\n\t\tif (!order) {\n\t\t\tthrow new Error(\"Order es requerido\");\n\t\t}\n\t\tif (!order.client) {\n\t\t\tthrow new Error(\"Order debe tener un cliente asociado\");\n\t\t}\n\t\tif (!order.items || order.items.length === 0) {\n\t\t\tthrow new Error(\"Order debe tener al menos un item\");\n\t\t}\n\n\t\tconst { paymentMethodId, storeName = \"N/A\" } = options;\n\n\t\tconst clientName = order.client.name || \"\";\n\t\tconst clientRif = order.client.id || \"\";\n\t\tconst storeLine = `Tienda: ${storeName}`;\n\n\t\tcommands.push({\n\t\t\tcmd: \"F0\",\n\t\t\tdata: {\n\t\t\t\tsNombreCliente: truncateString(clientName, 64),\n\t\t\t\tsRifCliente: truncateString(clientRif, 20),\n\t\t\t\tbLogo: false,\n\t\t\t\tsLineaAdicional: truncateString(storeLine, 64),\n\t\t\t},\n\t\t});\n\n\t\tlet subtotalWithoutTaxes = 0;\n\n\t\tfor (const item of order.items) {\n\t\t\tif (!item.name) continue;\n\n\t\t\tconst taxId =\n\t\t\t\titem.taxes && item.taxes.length > 0 ? item.taxes[0].id : null;\n\t\t\tconst iImpuesto = mapTaxIdToDtpCode(taxId);\n\t\t\tconst price = item.price ?? 0;\n\t\t\tconst lPrecio = Math.round(Math.max(price, 0) * 100);\n\t\t\tconst quantity = item.selectedQuantity ?? item.quantity ?? 1;\n\t\t\tconst lCantidad = Math.round(Math.max(quantity, 1) * 1000);\n\n\t\t\tsubtotalWithoutTaxes += price * Math.max(quantity, 1);\n\n\t\t\tcommands.push({\n\t\t\t\tcmd: \"F1\",\n\t\t\t\tdata: {\n\t\t\t\t\tsDescripcion: truncateString(item.name, 64),\n\t\t\t\t\tsCodigo: truncateString(item.sku ?? \"N/A\", 20),\n\t\t\t\t\tlCantidad,\n\t\t\t\t\tsUnidad: \"UND\",\n\t\t\t\t\tlPrecio,\n\t\t\t\t\tiImpuesto,\n\t\t\t\t\tiDecPrecio: 2,\n\t\t\t\t\tiDecCantidad: 3,\n\t\t\t\t},\n\t\t\t});\n\t\t}\n\n\t\tconst isForeignCurrency =\n\t\t\tpaymentMethodId === \"pos_debit_credit_int\" ||\n\t\t\tpaymentMethodId === \"cash_int\";\n\n\t\tif (isForeignCurrency && subtotalWithoutTaxes > 0) {\n\t\t\tconst roundedSubtotal =\n\t\t\t\tMath.round((subtotalWithoutTaxes + Number.EPSILON) * 100) / 100;\n\t\t\tconst igtfPercentage = TaxValues.BI_IGTF / 100;\n\t\t\tconst igtfAmount =\n\t\t\t\tMath.round((roundedSubtotal * igtfPercentage + Number.EPSILON) * 100) /\n\t\t\t\t100;\n\n\t\t\tcommands.push({\n\t\t\t\tcmd: \"F1\",\n\t\t\t\tdata: {\n\t\t\t\t\tsDescripcion: \"IGTF 3% pago en divisas\",\n\t\t\t\t\tsCodigo: \"IGTF\",\n\t\t\t\t\tlCantidad: 1000,\n\t\t\t\t\tsUnidad: \"UND\",\n\t\t\t\t\tlPrecio: Math.round(igtfAmount * 100),\n\t\t\t\t\tiImpuesto: 4,\n\t\t\t\t\tiDecPrecio: 2,\n\t\t\t\t\tiDecCantidad: 3,\n\t\t\t\t},\n\t\t\t});\n\t\t}\n\n\t\tcommands.push({\n\t\t\tcmd: \"F2\",\n\t\t\tdata: { mode: 1, foreignCurrencyAmount: 0 },\n\t\t});\n\n\t\tif (!order.payments?.length) {\n\t\t\tthrow new Error(\"Order debe tener al menos un pago exitoso\");\n\t\t}\n\n\t\tfor (const payment of order.payments) {\n\t\t\tconst tipo = mapPaymentMethod(payment.paymentMethod);\n\t\t\tconst lMonto = Math.round(payment.amount * 100);\n\t\t\tconst isForeign =\n\t\t\t\tpayment.paymentMethod === \"pos_debit_credit_int\" ||\n\t\t\t\tpayment.paymentMethod === \"cash_int\";\n\n\t\t\tif (isForeign) {\n\t\t\t\tcommands.push({\n\t\t\t\t\tcmd: \"F11\",\n\t\t\t\t\tdata: {\n\t\t\t\t\t\tiFormaPago: tipo,\n\t\t\t\t\t\tsDescripcion: paymentMethodLabel(tipo),\n\t\t\t\t\t\tlMonto,\n\t\t\t\t\t\tlTasaCambio: 1,\n\t\t\t\t\t\tsSimbolo: \"USD\",\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tcommands.push({\n\t\t\t\t\tcmd: \"F4\",\n\t\t\t\t\tdata: {\n\t\t\t\t\t\tiFormaPago: tipo,\n\t\t\t\t\t\tsDescripcion: paymentMethodLabel(tipo),\n\t\t\t\t\t\tlMonto,\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\tcommands.push({ cmd: \"F5\", data: {} });\n\n\t\treturn commands;\n\t},\n\n\tbuildReceiptCommands(options: BuildReceiptOptions): DtpPrinterCommand[] {\n\t\tconst {\n\t\t\torderId,\n\t\t\tamountPaid,\n\t\t\tpaymentMethod,\n\t\t\tpaidAt,\n\t\t\tcardLast4,\n\t\t\torganizationName,\n\t\t} = options;\n\n\t\tif (!orderId) {\n\t\t\tthrow new Error(\"OrderId es requerido\");\n\t\t}\n\t\tif (!Number.isFinite(amountPaid) || amountPaid <= 0) {\n\t\t\tthrow new Error(\"Monto pagado inválido\");\n\t\t}\n\n\t\tconst paidDate = paidAt ?? new Date();\n\t\tconst lines = [\n\t\t\t\"RECIBO DE PAGO\",\n\t\t\torderId,\n\t\t\t\"Recibo de pago\",\n\t\t\torganizationName?.trim() || \"N/A\",\n\t\t\t`Bs ${amountPaid}`,\n\t\t\t`Medio de pago: ${paymentMethod}`,\n\t\t\t`Tarjeta ${cardLast4 ?? \"N/A\"}`,\n\t\t\t`Hora del pago: ${formatTime(paidDate)}`,\n\t\t\t`Fecha del pago: ${formatDate(paidDate)}`,\n\t\t\t\"Cierre del Documento No Fiscal\",\n\t\t];\n\n\t\tconst commands: DtpPrinterCommand[] = [{ cmd: \"N0\" }];\n\n\t\tfor (const line of lines) {\n\t\t\tcommands.push({\n\t\t\t\tcmd: \"N1\",\n\t\t\t\tdata: { line: truncateString(line, 64) },\n\t\t\t});\n\t\t}\n\n\t\tcommands.push({ cmd: \"N3\" });\n\n\t\treturn commands;\n\t},\n};\n\n/**\n * Resultado de ejecutar comandos DTP.\n * Incluye documentNumber y totalAmount cuando el último comando es F5 (cerrar factura).\n */\nexport interface ExecuteDtpCommandsResult {\n\tdocumentNumber?: number;\n\ttotalAmount?: number;\n}\n\n/**\n * Ejecuta una secuencia de comandos DTP contra un cliente conectado.\n * Lanza en el primer error.\n * Retorna documentNumber y totalAmount cuando se ejecuta F5 (cerrar factura).\n */\nexport async function executeDtpCommands(\n\tclient: DtpClient,\n\tcommands: DtpPrinterCommand[],\n): Promise<ExecuteDtpCommandsResult> {\n\tlet documentNumber: number | undefined;\n\tlet totalAmount: number | undefined;\n\tfor (const cmd of commands) {\n\t\tswitch (cmd.cmd) {\n\t\t\tcase \"F0\": {\n\t\t\t\tconst r = await openFiscalDoc(client, cmd.data);\n\t\t\t\tif (r.code !== 0) throw new Error(`F0 falló: código ${r.code}`);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase \"F1\": {\n\t\t\t\tconst r = await addFiscalItem(client, cmd.data);\n\t\t\t\tif (r.code !== 0) throw new Error(`F1 falló: código ${r.code}`);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase \"F2\": {\n\t\t\t\tconst r = await subtotalFiscalDoc(\n\t\t\t\t\tclient,\n\t\t\t\t\tcmd.data?.mode ?? 1,\n\t\t\t\t\tcmd.data?.foreignCurrencyAmount ?? 0,\n\t\t\t\t);\n\t\t\t\tif (r.code !== 0) throw new Error(`F2 falló: código ${r.code}`);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase \"F4\": {\n\t\t\t\tconst r = await payFiscalDoc(client, cmd.data);\n\t\t\t\tif (r.code !== 0) throw new Error(`F4 falló: código ${r.code}`);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase \"F5\": {\n\t\t\t\tconst r = await closeFiscalDoc(client, cmd.data?.additionalLine ?? \"\");\n\t\t\t\tif (r.code !== 0) throw new Error(`F5 falló: código ${r.code}`);\n\t\t\t\tdocumentNumber = r.documentNumber;\n\t\t\t\ttotalAmount = r.totalAmount;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase \"F11\": {\n\t\t\t\tconst r = await payFiscalDocForeignCurrency(client, cmd.data);\n\t\t\t\tif (r.code !== 0)\n\t\t\t\t\tthrow new Error(`F11 falló: código ${r.code}`);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase \"N0\": {\n\t\t\t\tconst r = await openNonFiscalDoc(client);\n\t\t\t\tif (r.code !== 0) throw new Error(`N0 falló: código ${r.code}`);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase \"N1\": {\n\t\t\t\tconst r = await addNonFiscalLine(\n\t\t\t\t\tclient,\n\t\t\t\t\tcmd.data.line,\n\t\t\t\t\tcmd.data.size ?? 0,\n\t\t\t\t\tcmd.data.align ?? 0,\n\t\t\t\t\tcmd.data.style ?? 0,\n\t\t\t\t);\n\t\t\t\tif (r.code !== 0) throw new Error(`N1 falló: código ${r.code}`);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase \"N3\": {\n\t\t\t\tconst r = await closeNonFiscalDoc(client);\n\t\t\t\tif (r.code !== 0) throw new Error(`N3 falló: código ${r.code}`);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tdefault: {\n\t\t\t\tconst _: never = cmd;\n\t\t\t\tthrow new Error(`Comando DTP desconocido: ${String((cmd as { cmd: string }).cmd)}`);\n\t\t\t}\n\t\t}\n\t}\n\treturn { documentNumber, totalAmount };\n}\n","import type {\n\tPrinterCommandResponse,\n\tPrinterResponse,\n\tSendPrinterCommandsAeg,\n\tSendPrinterCommandsArgs,\n} from \"./types.js\";\n\nfunction normalizeBaseUrl(address: string): string {\n\tconst trimmed = address.trim();\n\tif (!trimmed) return trimmed;\n\tconst withProtocol = /^https?:\\/\\//i.test(trimmed)\n\t\t? trimmed\n\t\t: `http://${trimmed}`;\n\treturn withProtocol.replace(/\\/+$/, \"\");\n}\n\n/**\n * Envía comandos a una impresora fiscal.\n *\n * - **AEG-R1**: POST HTTP a {ip}/cmdoJson con body = commands (JSON)\n * - **DTP-80i**: No soportado en esta librería (usa TCP vía módulo nativo).\n * El consumidor debe usar ExpoDtpFiscalPrinter directamente.\n */\nexport async function sendPrinterCommands(\n\targs: SendPrinterCommandsArgs,\n\toptions?: { timeout?: number },\n): Promise<PrinterResponse> {\n\tconst { brand, model, commands } = args;\n\n\tif (!commands || commands.length === 0) {\n\t\tthrow new Error(\"No hay comandos para enviar\");\n\t}\n\n\tswitch (brand) {\n\t\tcase \"AEG\":\n\t\t\tif (model !== \"R1\") {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Modelo inválido para AEG: \"${model}\". Solo se soporta \"R1\".`,\n\t\t\t\t);\n\t\t\t}\n\t\t\treturn sendAegCommands(args as SendPrinterCommandsAeg, options);\n\t\tcase \"DTP\":\n\t\t\tif (model !== \"80i\") {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Modelo inválido para DTP: \"${model}\". Solo se soporta \"80i\".`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tthrow new Error(\n\t\t\t\t\"DTP-80i requiere el módulo nativo ExpoDtpFiscalPrinter. \" +\n\t\t\t\t\t\"Use la conexión TCP directamente desde su aplicación.\",\n\t\t\t);\n\t\tdefault: {\n\t\t\tconst _exhaustive: never = brand;\n\t\t\tthrow new Error(\n\t\t\t\t`Marca de impresora no soportada: ${String(_exhaustive)}`,\n\t\t\t);\n\t\t}\n\t}\n}\n\nasync function sendAegCommands(\n\targs: SendPrinterCommandsAeg,\n\toptions?: { timeout?: number },\n): Promise<PrinterResponse> {\n\tconst { ip, commands } = args;\n\tconst baseUrl = normalizeBaseUrl(ip);\n\tconst url = `${baseUrl}/cmdoJson`;\n\tconst controller = new AbortController();\n\tconst timeoutId =\n\t\toptions?.timeout != null\n\t\t\t? setTimeout(() => controller.abort(), options.timeout)\n\t\t\t: undefined;\n\n\ttry {\n\t\tconst response = await fetch(url, {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: {\n\t\t\t\t\"Content-Type\": \"application/json\",\n\t\t\t},\n\t\t\tbody: JSON.stringify(commands),\n\t\t\tsignal: controller.signal,\n\t\t});\n\n\t\tif (!response.ok) {\n\t\t\tthrow new Error(`Error HTTP ${response.status}: ${response.statusText}`);\n\t\t}\n\n\t\tconst data = (await response.json()) as unknown;\n\n\t\tif (!Array.isArray(data)) {\n\t\t\tthrow new Error(\n\t\t\t\t`Respuesta inválida de la impresora: se esperaba un array, se recibió ${typeof data}`,\n\t\t\t);\n\t\t}\n\n\t\tconst result = data as PrinterCommandResponse[];\n\n\t\tconst failedCommands: PrinterCommandResponse[] = [];\n\t\tfor (const commandResponse of result) {\n\t\t\tconst codeValue =\n\t\t\t\ttypeof commandResponse.code === \"string\"\n\t\t\t\t\t? Number.parseInt(commandResponse.code, 10)\n\t\t\t\t\t: commandResponse.code;\n\n\t\t\tif (Number.isNaN(codeValue) || codeValue !== 0) {\n\t\t\t\tfailedCommands.push(commandResponse);\n\t\t\t}\n\t\t}\n\n\t\tif (failedCommands.length > 0) {\n\t\t\tconst errorMessages = failedCommands\n\t\t\t\t.map(\n\t\t\t\t\t(cmd) =>\n\t\t\t\t\t\t`Comando ${cmd.cmd}: código ${cmd.code}${cmd.message ? ` - ${cmd.message}` : \"\"}`,\n\t\t\t\t)\n\t\t\t\t.join(\"; \");\n\t\t\tthrow new Error(\n\t\t\t\t`Error en la impresora: ${failedCommands.length} comando(s) fallaron. ${errorMessages}`,\n\t\t\t);\n\t\t}\n\n\t\treturn result;\n\t} catch (error) {\n\t\tif (error instanceof Error) {\n\t\t\tif (error.name === \"AbortError\") {\n\t\t\t\tthrow new Error(\"Timeout al enviar comandos a la impresora\");\n\t\t\t}\n\t\t\tthrow error;\n\t\t}\n\t\tthrow new Error(\"Error desconocido al enviar comandos a la impresora\");\n\t} finally {\n\t\tif (timeoutId) clearTimeout(timeoutId);\n\t}\n}\n"],"mappings":"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","names":["net","TaxValues","PrinterTaxValues","PaymentMethodId","truncateString","formatDate","formatTime","mapPaymentMethod"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/types/enums.ts","../src/printers/aeg/aeg-printer.ts","../src/printers/dtp/dtp-printer.ts","../src/printers/dtp/dtp-printer-driver.ts","../src/runner/send-printer-commands.ts"],"sourcesContent":["/**\n * cafe-ipdh-lib\n * Librería para gestionar impresoras fiscales y de recibos.\n *\n * Soporta:\n * - AEG-R1: impresora fiscal vía HTTP (comandos JSON)\n *\n * Uso:\n * ```ts\n * import { aegPrinter } from \"cafe-ipdh-lib\";\n *\n * const commands = aegPrinter.buildInvoiceCommands(order, {\n * paymentMethodId: \"pos_credit\",\n * storeName: \"Mi Tienda\"\n * });\n * // Enviar commands a la impresora vía tu API/transport\n * ```\n */\n\nexport type {\n\tBuildInvoiceOptions,\n\tBuildReceiptOptions,\n\tDocumentType,\n\tDtpPrinterCommand,\n\tExecuteDtpCommandsResult,\n\tPrinterCommandResponse,\n\tPrinterDriver,\n} from \"./printers/index.js\";\nexport {\n\taegPrinter,\n\tdtpPrinter,\n\texecuteDtpCommands,\n} from \"./printers/index.js\";\nexport type {\n\tAegModel,\n\tDtpModel,\n\tPrinterBrand,\n\tSendPrinterCommandsAeg,\n\tSendPrinterCommandsArgs,\n\tSendPrinterCommandsDtp,\n} from \"./runner/index.js\";\nexport { sendPrinterCommands } from \"./runner/index.js\";\nexport type {\n\tAegPrinterCommand,\n\tFiscalClient,\n\tItemTax,\n\tOrder,\n\tOrderItem,\n\tOrderPayment,\n} from \"./types/index.js\";\nexport {\n\tPaymentMethodId,\n\tPrinterTaxValues,\n\tTaxValues,\n} from \"./types/index.js\";\n","/**\n * Valores de impuestos (porcentajes) según legislación venezolana.\n */\nexport enum TaxValues {\n\tEXENTO_E = 0,\n\tBI_G = 16.0,\n\tIVA_G = 16.0,\n\tBI_R = 8.0,\n\tIVA_R = 8.0,\n\tBI_A = 31.0,\n\tIVA_A = 31.0,\n\tPERCIBIDO = 0,\n\tBI_IGTF = 3.0,\n\tIVA_IGTF = 3.0,\n}\n\n/**\n * Códigos de impuesto para impresora fiscal AEG-R1.\n */\nexport enum PrinterTaxValues {\n\tEXENTO_E = 1,\n\tBI_G = 2,\n\tIVA_G = 2,\n\tBI_R = 3,\n\tIVA_R = 3,\n\tBI_A = 4,\n\tIVA_A = 4,\n\tPERCIBIDO = 5,\n\tBI_IGTF = 5,\n\tIVA_IGTF = 5,\n}\n\n/**\n * IDs de método de pago para impresora fiscal AEG-R1.\n * Efectivo: 1, Débito: 2, Crédito: 3, Pago Móvil: 5,\n * Débito/Crédito int: 11, Efectivo int: 12\n */\nexport enum PaymentMethodId {\n\tCASH = 1,\n\tPOS_DEBIT = 2,\n\tPOS_CREDIT = 3,\n\tPAGO_MOVIL = 5,\n\tPOS_DEBIT_CREDIT_INT = 11,\n\tCASH_INT = 12,\n}\n","import type { AegPrinterCommand } from \"../../types/aeg-commands.js\";\nimport {\n\tPaymentMethodId,\n\tPrinterTaxValues,\n\tTaxValues,\n} from \"../../types/enums.js\";\nimport type { Order } from \"../../types/order.js\";\nimport type {\n\tBuildInvoiceOptions,\n\tBuildReceiptOptions,\n\tPrinterDriver,\n} from \"../printer.types.js\";\n\nfunction truncateString(str: string, maxLength = 64): string {\n\tif (!str) return \"\";\n\treturn str.length > maxLength ? str.substring(0, maxLength) : str;\n}\n\n// biome-ignore lint: avoid control char in literal\nconst ISO_8859_1_REGEX = new RegExp(\"[^\\\\u0000-\\\\u00FF]\", \"g\");\n\nfunction normalizeIso88591(str: string): string {\n\treturn str.replace(ISO_8859_1_REGEX, \"?\");\n}\n\nfunction formatDate(date: Date): string {\n\tconst day = date.getDate().toString().padStart(2, \"0\");\n\tconst month = (date.getMonth() + 1).toString().padStart(2, \"0\");\n\tconst year = date.getFullYear();\n\treturn `${day}/${month}/${year}`;\n}\n\nfunction formatTime(date: Date): string {\n\tconst hours = date.getHours().toString().padStart(2, \"0\");\n\tconst minutes = date.getMinutes().toString().padStart(2, \"0\");\n\treturn `${hours}:${minutes}`;\n}\n\nfunction mapTaxIdToPrinterCode(taxId: string | null | undefined): number {\n\tif (!taxId) {\n\t\treturn PrinterTaxValues.EXENTO_E;\n\t}\n\tconst taxIdUpper = taxId.toUpperCase();\n\tconst printerTaxValue =\n\t\tPrinterTaxValues[taxIdUpper as keyof typeof PrinterTaxValues];\n\tif (printerTaxValue !== undefined) {\n\t\treturn printerTaxValue;\n\t}\n\treturn PrinterTaxValues.EXENTO_E;\n}\n\nfunction mapPaymentMethod(method: string): PaymentMethodId {\n\tif (method === \"pos_debit\") return PaymentMethodId.POS_DEBIT;\n\tif (method === \"pos_credit\") return PaymentMethodId.POS_CREDIT;\n\tif (method === \"pos_debit_credit_int\")\n\t\treturn PaymentMethodId.POS_DEBIT_CREDIT_INT;\n\tif (method === \"cash_int\") return PaymentMethodId.CASH_INT;\n\tif (method === \"cash_nat\") return PaymentMethodId.CASH;\n\tthrow new Error(\n\t\t`Método de pago inválido: ${method}. Debe ser \"pos_debit\", \"pos_credit\", \"pos_debit_credit_int\", \"cash_int\" o \"cash_nat\"`,\n\t);\n}\n\n/**\n * Driver para impresora fiscal AEG-R1.\n * Construye comandos JSON según documentación oficial.\n */\nexport const aegPrinter: PrinterDriver<AegPrinterCommand> = {\n\tmodel: \"aeg-r1\",\n\n\tbuildInvoiceCommands(\n\t\torder: Order,\n\t\toptions: BuildInvoiceOptions,\n\t): AegPrinterCommand[] {\n\t\tconst commands: AegPrinterCommand[] = [];\n\n\t\tif (!order) {\n\t\t\tthrow new Error(\"Order es requerido\");\n\t\t}\n\t\tif (!order.client) {\n\t\t\tthrow new Error(\"Order debe tener un cliente asociado\");\n\t\t}\n\t\tif (!order.items || order.items.length === 0) {\n\t\t\tthrow new Error(\"Order debe tener al menos un item\");\n\t\t}\n\n\t\tconst { paymentMethodId, storeName = \"N/A\" } = options;\n\n\t\t// 1. cliF - Datos del cliente\n\t\tconst clientRifCI = order.client.id || \"\";\n\t\tconst clientName = order.client.name || \"\";\n\t\tconst clientEmail = order.client.email || \"\";\n\t\tconst clientPhone = order.client.phone || \"\";\n\t\tconst clientAddress = order.client.address || \"\";\n\t\tconst razSoc = [clientName, clientEmail, clientPhone]\n\t\t\t.filter(Boolean)\n\t\t\t.map((v) => truncateString(v, 64));\n\t\tconst storeLine = `Tienda: ${storeName}`;\n\t\tconst LineAd = [storeLine, clientAddress]\n\t\t\t.filter(Boolean)\n\t\t\t.map((v) => truncateString(v, 64));\n\n\t\tcommands.push({\n\t\t\tcmd: \"cliF\",\n\t\t\tdata: { rifCI: clientRifCI, razSoc, LineAd },\n\t\t});\n\n\t\t// 2. proF - Productos\n\t\tlet subtotalWithoutTaxes = 0;\n\n\t\tfor (const item of order.items) {\n\t\t\tif (!item.name) continue;\n\n\t\t\tconst taxId =\n\t\t\t\titem.taxes && item.taxes.length > 0 ? item.taxes[0].id : null;\n\t\t\tconst imp = mapTaxIdToPrinterCode(taxId);\n\t\t\tconst price = item.price || 0;\n\t\t\tconst pre = Math.round(Math.max(price, 0) * 100);\n\t\t\tconst quantity = item.selectedQuantity ?? item.quantity ?? 1;\n\t\t\tconst cant = Math.round(Math.max(quantity, 1) * 1000);\n\t\t\tconst des01 = truncateString(item.name, 64);\n\n\t\t\tsubtotalWithoutTaxes += price * Math.max(quantity, 1);\n\n\t\t\tcommands.push({\n\t\t\t\tcmd: \"proF\",\n\t\t\t\tdata: { imp, pre, cant, des01 },\n\t\t\t});\n\t\t}\n\n\t\t// 2.1 IGTF si pago en divisas\n\t\tconst isForeignCurrency =\n\t\t\tpaymentMethodId === \"pos_debit_credit_int\" ||\n\t\t\tpaymentMethodId === \"cash_int\";\n\n\t\tif (isForeignCurrency && subtotalWithoutTaxes > 0) {\n\t\t\tconst roundedSubtotal =\n\t\t\t\tMath.round((subtotalWithoutTaxes + Number.EPSILON) * 100) / 100;\n\t\t\tconst igtfPercentage = TaxValues.BI_IGTF / 100;\n\t\t\tconst igtfAmount =\n\t\t\t\tMath.round((roundedSubtotal * igtfPercentage + Number.EPSILON) * 100) /\n\t\t\t\t100;\n\n\t\t\tcommands.push({\n\t\t\t\tcmd: \"proF\",\n\t\t\t\tdata: {\n\t\t\t\t\timp: PrinterTaxValues.PERCIBIDO,\n\t\t\t\t\tpre: Math.round(igtfAmount * 100),\n\t\t\t\t\tcant: 1000,\n\t\t\t\t\tdes01: \"IGTF 3% pago en divisas\",\n\t\t\t\t},\n\t\t\t});\n\t\t}\n\n\t\t// 3. subToF - Subtotal\n\t\tcommands.push({ cmd: \"subToF\", data: 1, valor: 0 });\n\n\t\t// 4. fpaF - Forma de pago\n\t\tif (!order.payments?.length) {\n\t\t\tthrow new Error(\"Order debe tener al menos un pago exitoso\");\n\t\t}\n\n\t\tfor (const payment of order.payments) {\n\t\t\tconst paymentType = mapPaymentMethod(payment.paymentMethod);\n\t\t\tconst paymentAmount = Math.round(payment.amount * 100);\n\t\t\tcommands.push({\n\t\t\t\tcmd: \"fpaF\",\n\t\t\t\tdata: {\n\t\t\t\t\ttipo: paymentType,\n\t\t\t\t\tmonto: paymentAmount,\n\t\t\t\t\ttasaConv: 0,\n\t\t\t\t},\n\t\t\t});\n\t\t}\n\n\t\t// 5. endFac - Cierre\n\t\tcommands.push({ cmd: \"endFac\", data: 1 });\n\n\t\treturn commands;\n\t},\n\n\tbuildReceiptCommands(options: BuildReceiptOptions): AegPrinterCommand[] {\n\t\tconst {\n\t\t\torderId,\n\t\t\tamountPaid,\n\t\t\tpaymentMethod,\n\t\t\tpaidAt,\n\t\t\tcardLast4,\n\t\t\torganizationName,\n\t\t} = options;\n\n\t\tif (!orderId) {\n\t\t\tthrow new Error(\"OrderId es requerido\");\n\t\t}\n\t\tif (!Number.isFinite(amountPaid) || amountPaid <= 0) {\n\t\t\tthrow new Error(\"Monto pagado inválido\");\n\t\t}\n\n\t\tconst paidDate = paidAt ?? new Date();\n\t\tconst amountLabel = `Bs ${amountPaid}`;\n\t\tconst paymentLabel = `Medio de pago: ${paymentMethod}`;\n\t\tconst dateLabel = `Fecha del pago: ${formatDate(paidDate)}`;\n\t\tconst timeLabel = `Hora del pago: ${formatTime(paidDate)}`;\n\t\tconst cardLabel = `Tarjeta ${cardLast4 ?? \"N/A\"}`;\n\t\tconst orgLabel = organizationName?.trim() || \"N/A\";\n\n\t\treturn [\n\t\t\t{\n\t\t\t\tcmd: \"encDNF\",\n\t\t\t\tdata: [\n\t\t\t\t\tnormalizeIso88591(truncateString(\"RECIBO DE PAGO\")),\n\t\t\t\t\tnormalizeIso88591(truncateString(orderId)),\n\t\t\t\t],\n\t\t\t},\n\t\t\t{\n\t\t\t\tcmd: \"aperDNF\",\n\t\t\t\tdata: normalizeIso88591(truncateString(\"Recibo de pago\")),\n\t\t\t},\n\t\t\t{\n\t\t\t\tcmd: \"efeNorJuIzDNF\",\n\t\t\t\tdata: normalizeIso88591(truncateString(orgLabel)),\n\t\t\t},\n\t\t\t{\n\t\t\t\tcmd: \"efeNorJuIzDNF\",\n\t\t\t\tdata: normalizeIso88591(truncateString(amountLabel)),\n\t\t\t},\n\t\t\t{\n\t\t\t\tcmd: \"efeNorJuIzDNF\",\n\t\t\t\tdata: normalizeIso88591(truncateString(paymentLabel)),\n\t\t\t},\n\t\t\t{\n\t\t\t\tcmd: \"efeNorJuIzDNF\",\n\t\t\t\tdata: normalizeIso88591(truncateString(cardLabel)),\n\t\t\t},\n\t\t\t{\n\t\t\t\tcmd: \"efeNorJuIzDNF\",\n\t\t\t\tdata: normalizeIso88591(truncateString(timeLabel)),\n\t\t\t},\n\t\t\t{\n\t\t\t\tcmd: \"efeNorJuIzDNF\",\n\t\t\t\tdata: normalizeIso88591(truncateString(dateLabel)),\n\t\t\t},\n\t\t\t{\n\t\t\t\tcmd: \"endDNF\",\n\t\t\t\tdata: normalizeIso88591(\"Cierre del Documento No Fiscal\"),\n\t\t\t},\n\t\t];\n\t},\n};\n","import type { DtpClient } from \"./dtp-client\";\nimport type { AbrirCfArgs, ItemCfArgs, PagoCfArgs } from \"./dtp-printer.types\";\n\nconst formatDateDDMMYYYY = (d: Date) => {\n\tconst dd = String(d.getDate()).padStart(2, \"0\");\n\tconst mm = String(d.getMonth() + 1).padStart(2, \"0\");\n\tconst yyyy = String(d.getFullYear());\n\treturn `${dd}${mm}${yyyy}`;\n};\n\nfunction parseCode(r: string[], idx = 0): number {\n\tconst v = r[idx];\n\tconst n = Number(v);\n\treturn v !== undefined && v !== null && !Number.isNaN(n) ? n : 16;\n}\n\n// C0 Get Status (used as \"real ping\")\nexport async function getStatus(client: DtpClient) {\n\tconst r = await client.send([\"C0\"]);\n\tconst code = parseCode(r);\n\treturn {\n\t\tcode,\n\t\tstate: code === 0 && r.length > 2 ? Number(r[2] ?? -1) : -1,\n\t\tblock: code === 0 && r.length > 3 ? Number(r[3] ?? -1) : -1,\n\t\tfiscalStatus: code === 0 && r.length > 4 ? String(r[4] ?? \"\") : \"\",\n\t\tlastCommandResponse:\n\t\t\tcode === 0 && r.length > 5 ? Number(r[5] ?? -1) : -1,\n\t\traw: r,\n\t};\n}\n\nexport async function openFiscalDoc(client: DtpClient, args: AbrirCfArgs) {\n\tconst r = await client.send([\n\t\t\"F0\",\n\t\tString(args.iTipo ?? 0),\n\t\targs.sNombreCliente,\n\t\targs.sRifCliente,\n\t\tString(args.iFacturaReferencia ?? 0),\n\t\tformatDateDDMMYYYY(args.fechaReferencia ?? new Date()),\n\t\targs.sSerialReferencia ?? \"\",\n\t\t(args.bLogo ?? false) ? \"1\" : \"0\",\n\t\targs.sLineaAdicional ?? \"\",\n\t]);\n\treturn {\n\t\tcode: parseCode(r),\n\t\tdocumentNumber: Number(r[1] ?? -1),\n\t\traw: r,\n\t};\n}\n\nexport async function addFiscalItem(client: DtpClient, args: ItemCfArgs) {\n\tconst r = await client.send([\n\t\t\"F1\",\n\t\tString(args.iTipo ?? 0),\n\t\targs.sDescripcion,\n\t\targs.sCodigo,\n\t\tString(args.lCantidad),\n\t\targs.sUnidad,\n\t\tString(args.lPrecio),\n\t\tString(args.iImpuesto),\n\t\tString(args.iDecPrecio),\n\t\tString(args.iDecCantidad),\n\t]);\n\treturn {\n\t\tcode: parseCode(r),\n\t\titemCount: Number(r[1] ?? -1),\n\t\ttotalItem: Number(r[2] ?? -1),\n\t\tprintedLines: Number(r[3] ?? -1),\n\t\traw: r,\n\t};\n}\n\nexport async function subtotalFiscalDoc(\n\tclient: DtpClient,\n\tmode = 0,\n\tforeignCurrencyAmount = 0,\n) {\n\tconst r = await client.send([\n\t\t\"F2\",\n\t\tString(mode),\n\t\tString(foreignCurrencyAmount),\n\t]);\n\treturn { code: parseCode(r), raw: r };\n}\n\nexport async function payFiscalDoc(client: DtpClient, args: PagoCfArgs) {\n\tconst r = await client.send([\n\t\t\"F4\",\n\t\tString(args.iTipoPago ?? 0),\n\t\tString(args.iFormaPago),\n\t\targs.sDescripcion,\n\t\tString(args.lMonto),\n\t]);\n\treturn {\n\t\tcode: parseCode(r),\n\t\tamountDue: Number(r[1] ?? -1),\n\t\tchangeAmount: Number(r[2] ?? -1),\n\t\tprintedLines: Number(r[3] ?? -1),\n\t\traw: r,\n\t};\n}\n\nexport async function addFiscalComment(\n\tclient: DtpClient,\n\tcomment: string,\n\tsize = 0,\n\talign = 0,\n\tstyle = 0,\n) {\n\tconst r = await client.send([\n\t\t\"F7\",\n\t\tcomment,\n\t\tString(size),\n\t\tString(align),\n\t\tString(style),\n\t]);\n\treturn {\n\t\tcode: parseCode(r),\n\t\tprintedLines: Number(r[1] ?? -1),\n\t\traw: r,\n\t};\n}\n\nexport async function closeFiscalDoc(\n\tclient: DtpClient,\n\tadditionalLine = \"\",\n) {\n\tconst r = await client.send([\"F5\", additionalLine]);\n\treturn {\n\t\tcode: parseCode(r),\n\t\tdocumentNumber: Number(r[1] ?? -1),\n\t\ttotalAmount: Number(r[2] ?? -1),\n\t\traw: r,\n\t};\n}\n\nexport async function cancelFiscalDoc(client: DtpClient) {\n\tconst r = await client.send([\"F6\"]);\n\treturn { code: parseCode(r), raw: r };\n}\n\nexport async function getSerializationData(client: DtpClient) {\n\tconst r = await client.send([\"C2\"]);\n\tconst code = parseCode(r);\n\treturn {\n\t\tcode,\n\t\tfiscalSerial: code === 0 && r.length >= 2 ? r[1] : \"\",\n\t\tprinterSerial: code === 0 && r.length >= 3 ? r[2] : \"\",\n\t\tkitSerial: code === 0 && r.length >= 4 ? r[3] : \"\",\n\t\tmfSerial: code === 0 && r.length >= 5 ? r[4] : \"\",\n\t\tmaSerial: code === 0 && r.length >= 6 ? r[5] : \"\",\n\t\traw: r,\n\t};\n}\n\nexport async function getFiscalizationData(client: DtpClient) {\n\tconst r = await client.send([\"C3\"]);\n\tconst code = parseCode(r);\n\treturn {\n\t\tcode,\n\t\ttaxpayerName: code === 0 && r.length >= 2 ? r[1] : \"\",\n\t\tfiscalAddress: code === 0 && r.length >= 3 ? r[2] : \"\",\n\t\ttaxpayerRif: code === 0 && r.length >= 4 ? r[3] : \"\",\n\t\tcommercialName: code === 0 && r.length >= 5 ? r[4] : \"\",\n\t\tdistributorName: code === 0 && r.length >= 6 ? r[5] : \"\",\n\t\tdistributorRif: code === 0 && r.length >= 7 ? r[6] : \"\",\n\t\ttaxRate1: code === 0 && r.length >= 8 ? Number(r[7]) : 0,\n\t\ttaxRate2: code === 0 && r.length >= 9 ? Number(r[8]) : 0,\n\t\ttaxRate3: code === 0 && r.length >= 10 ? Number(r[9]) : 0,\n\t\ttaxRate4: code === 0 && r.length >= 11 ? Number(r[10]) : 0,\n\t\traw: r,\n\t};\n}\n\nexport async function getPaymentMethod(\n\tclient: DtpClient,\n\tpaymentMethodId: number,\n) {\n\tconst r = await client.send([\"C9\", String(paymentMethodId)]);\n\treturn {\n\t\tcode: parseCode(r),\n\t\tname: parseCode(r) === 0 && r.length >= 2 ? r[1] : \"\",\n\t\traw: r,\n\t};\n}\n\nexport async function setPaymentMethod(\n\tclient: DtpClient,\n\tpaymentMethodId: number,\n\tname: string,\n) {\n\tconst r = await client.send([\"C10\", String(paymentMethodId), name]);\n\treturn { code: parseCode(r), raw: r };\n}\n\nexport async function payFiscalDocForeignCurrency(\n\tclient: DtpClient,\n\targs: {\n\t\tiFormaPago: number;\n\t\tsDescripcion: string;\n\t\tlMonto: number;\n\t\tlTasaCambio: number;\n\t\tsSimbolo: string;\n\t},\n) {\n\tconst r = await client.send([\n\t\t\"F11\",\n\t\t\"0\",\n\t\targs.sDescripcion,\n\t\tString(args.lMonto),\n\t\tString(args.lTasaCambio),\n\t\targs.sSimbolo,\n\t\tString(args.iFormaPago),\n\t]);\n\treturn {\n\t\tcode: parseCode(r),\n\t\tamountDue: Number(r[1] ?? -1),\n\t\tchangeAmount: Number(r[2] ?? -1),\n\t\tprintedLines: Number(r[3] ?? -1),\n\t\traw: r,\n\t};\n}\n\nexport async function reportX(\n\tclient: DtpClient,\n\tnoOpenDrawer = false,\n) {\n\tconst parts = [\"R0\", \"0\"];\n\tif (noOpenDrawer) parts.push(\"1\");\n\tconst r = await client.send(parts);\n\tconst code = parseCode(r);\n\treturn {\n\t\tcode,\n\t\tdocumentNumber: code === 0 && r.length >= 2 ? Number(r[1]) : -1,\n\t\traw: r,\n\t};\n}\n\nexport async function reportZ(\n\tclient: DtpClient,\n\tnoOpenDrawer = false,\n) {\n\tconst parts = [\"R0\", \"1\"];\n\tif (noOpenDrawer) parts.push(\"1\");\n\tconst r = await client.send(parts);\n\tconst code = parseCode(r);\n\treturn {\n\t\tcode,\n\t\treportNumber: code === 0 && r.length >= 2 ? Number(r[1]) : -1,\n\t\traw: r,\n\t};\n}\n\nexport async function getFiscalDayInfo(client: DtpClient) {\n\tconst r = await client.send([\"R1\"]);\n\tconst code = parseCode(r);\n\tif (code !== 0 || r.length < 84) {\n\t\treturn { code, raw: r };\n\t}\n\treturn {\n\t\tcode,\n\t\tzNumber: Number(r[1]),\n\t\tzDate: r[2],\n\t\tzTime: r[3],\n\t\tzStartDate: r[4],\n\t\tzStartTime: r[5],\n\t\tlastInvoiceNumber: Number(r[67]),\n\t\tlastInvoiceDate: r[68],\n\t\tlastInvoiceTime: r[69],\n\t\tlastCreditNoteNumber: Number(r[71]),\n\t\tlastDebitNoteNumber: Number(r[75]),\n\t\traw: r,\n\t};\n}\n\nexport async function getCounters(client: DtpClient) {\n\tconst r = await client.send([\"R9\"]);\n\tconst code = parseCode(r);\n\treturn {\n\t\tcode,\n\t\tlastInvoice: code === 0 && r.length >= 2 ? Number(r[1]) : -1,\n\t\tlastVoidedInvoice: code === 0 && r.length >= 3 ? Number(r[2]) : -1,\n\t\tlastCreditNote: code === 0 && r.length >= 4 ? Number(r[3]) : -1,\n\t\tlastDebitNote: code === 0 && r.length >= 5 ? Number(r[4]) : -1,\n\t\tlastNonFiscal: code === 0 && r.length >= 6 ? Number(r[5]) : -1,\n\t\tlastZReport: code === 0 && r.length >= 7 ? Number(r[6]) : -1,\n\t\traw: r,\n\t};\n}\n\nexport async function searchReprint(\n\tclient: DtpClient,\n\tdocumentType: number,\n\tdocumentNumber: number,\n\tprint = true,\n) {\n\tconst r = await client.send([\n\t\t\"R8\",\n\t\tprint ? \"1\" : \"0\",\n\t\tString(documentType),\n\t\tString(documentNumber),\n\t]);\n\treturn { code: parseCode(r), raw: r };\n}\n\nexport async function startFiscalMemoryReportByDateRange(\n\tclient: DtpClient,\n\treportType: number,\n\tstartDate: Date,\n\tendDate: Date,\n) {\n\tconst r = await client.send([\n\t\t\"R2\",\n\t\t\"0\",\n\t\tString(reportType),\n\t\tformatDateDDMMYYYY(startDate),\n\t\tformatDateDDMMYYYY(endDate),\n\t]);\n\treturn {\n\t\tcode: parseCode(r),\n\t\trecordCount: parseCode(r) === 0 && r.length >= 2 ? Number(r[1]) : -1,\n\t\traw: r,\n\t};\n}\n\nexport async function getFiscalMemoryReportData(client: DtpClient) {\n\tconst r = await client.send([\"R3\"]);\n\treturn { code: parseCode(r), raw: r };\n}\n\nexport async function finishFiscalMemoryReport(client: DtpClient) {\n\tconst r = await client.send([\"R4\"]);\n\treturn { code: parseCode(r), raw: r };\n}\n\nexport async function openNonFiscalDoc(client: DtpClient) {\n\tconst r = await client.send([\"N0\"]);\n\treturn { code: parseCode(r), raw: r };\n}\n\nexport async function addNonFiscalLine(\n\tclient: DtpClient,\n\tline: string,\n\tsize = 0,\n\talign = 0,\n\tstyle = 0,\n) {\n\tconst r = await client.send([\n\t\t\"N1\",\n\t\tline,\n\t\tString(size),\n\t\tString(align),\n\t\tString(style),\n\t]);\n\treturn {\n\t\tcode: parseCode(r),\n\t\tprintedLines: parseCode(r) === 0 && r.length >= 2 ? Number(r[1]) : -1,\n\t\traw: r,\n\t};\n}\n\nexport async function closeNonFiscalDoc(client: DtpClient) {\n\tconst r = await client.send([\"N3\"]);\n\treturn {\n\t\tcode: parseCode(r),\n\t\tdocumentNumber: parseCode(r) === 0 && r.length >= 2 ? Number(r[1]) : -1,\n\t\traw: r,\n\t};\n}\n","import {\n\tPaymentMethodId,\n\tPrinterTaxValues,\n\tTaxValues,\n} from \"../../types/enums.js\";\nimport type { Order } from \"../../types/order.js\";\nimport type {\n\tBuildInvoiceOptions,\n\tBuildReceiptOptions,\n\tPrinterDriver,\n} from \"../printer.types.js\";\nimport type { DtpClient } from \"./dtp-client.js\";\nimport type { DtpPrinterCommand } from \"./dtp-commands.js\";\nimport {\n\taddFiscalItem,\n\taddNonFiscalLine,\n\tcloseFiscalDoc,\n\tcloseNonFiscalDoc,\n\topenFiscalDoc,\n\topenNonFiscalDoc,\n\tpayFiscalDoc,\n\tpayFiscalDocForeignCurrency,\n\tsubtotalFiscalDoc,\n} from \"./dtp-printer.js\";\n\nfunction truncateString(str: string, maxLength = 64): string {\n\tif (!str) return \"\";\n\treturn str.length > maxLength ? str.substring(0, maxLength) : str;\n}\n\nfunction formatDate(date: Date): string {\n\tconst day = date.getDate().toString().padStart(2, \"0\");\n\tconst month = (date.getMonth() + 1).toString().padStart(2, \"0\");\n\tconst year = date.getFullYear();\n\treturn `${day}/${month}/${year}`;\n}\n\nfunction formatTime(date: Date): string {\n\tconst hours = date.getHours().toString().padStart(2, \"0\");\n\tconst minutes = date.getMinutes().toString().padStart(2, \"0\");\n\treturn `${hours}:${minutes}`;\n}\n\n/**\n * Mapea taxId (IVA_G, EXENTO_E, etc.) a código DTP iImpuesto (0..4).\n * DTP: 0=exento, 1=16%, 2=8%, 3=31%, 4=percibido/IGTF.\n */\nfunction mapTaxIdToDtpCode(taxId: string | null | undefined): number {\n\tif (!taxId) return 0;\n\tconst taxIdUpper = taxId.toUpperCase();\n\tconst aegCode =\n\t\tPrinterTaxValues[taxIdUpper as keyof typeof PrinterTaxValues];\n\tif (aegCode === undefined) return 0;\n\tconst n = Number(aegCode);\n\t// DTP iImpuesto: 0=exento, 1=16%, 2=8%, 3=31%, 4=percibido\n\tif (n === PrinterTaxValues.EXENTO_E) return 0;\n\tif (n === PrinterTaxValues.BI_G || n === PrinterTaxValues.IVA_G)\n\t\treturn 1;\n\tif (n === PrinterTaxValues.BI_R || n === PrinterTaxValues.IVA_R)\n\t\treturn 2;\n\tif (n === PrinterTaxValues.BI_A || n === PrinterTaxValues.IVA_A)\n\t\treturn 3;\n\tif (\n\t\tn === PrinterTaxValues.PERCIBIDO ||\n\t\tn === PrinterTaxValues.BI_IGTF ||\n\t\tn === PrinterTaxValues.IVA_IGTF\n\t)\n\t\treturn 4;\n\treturn 0;\n}\n\nfunction mapPaymentMethod(method: string): PaymentMethodId {\n\tif (method === \"pos_debit\") return PaymentMethodId.POS_DEBIT;\n\tif (method === \"pos_credit\") return PaymentMethodId.POS_CREDIT;\n\tif (method === \"pos_debit_credit_int\")\n\t\treturn PaymentMethodId.POS_DEBIT_CREDIT_INT;\n\tif (method === \"cash_int\") return PaymentMethodId.CASH_INT;\n\tif (method === \"cash_nat\") return PaymentMethodId.CASH;\n\tthrow new Error(\n\t\t`Método de pago inválido: ${method}. Debe ser \"pos_debit\", \"pos_credit\", \"pos_debit_credit_int\", \"cash_int\" o \"cash_nat\"`,\n\t);\n}\n\nfunction paymentMethodLabel(id: PaymentMethodId): string {\n\tswitch (id) {\n\t\tcase PaymentMethodId.CASH:\n\t\t\treturn \"EFECTIVO\";\n\t\tcase PaymentMethodId.POS_DEBIT:\n\t\t\treturn \"TARJETA DEBITO\";\n\t\tcase PaymentMethodId.POS_CREDIT:\n\t\t\treturn \"TARJETA CREDITO\";\n\t\tcase PaymentMethodId.PAGO_MOVIL:\n\t\t\treturn \"PAGO MOVIL\";\n\t\tcase PaymentMethodId.POS_DEBIT_CREDIT_INT:\n\t\t\treturn \"TARJETA INT\";\n\t\tcase PaymentMethodId.CASH_INT:\n\t\t\treturn \"EFECTIVO USD\";\n\t\tdefault:\n\t\t\treturn \"EFECTIVO\";\n\t}\n}\n\n/**\n * Driver para impresora fiscal DTP-80i.\n * Construye comandos DTP compatibles con el protocolo TCP.\n */\nexport const dtpPrinter: PrinterDriver<DtpPrinterCommand> = {\n\tmodel: \"dtp-80i\",\n\n\tbuildInvoiceCommands(\n\t\torder: Order,\n\t\toptions: BuildInvoiceOptions,\n\t): DtpPrinterCommand[] {\n\t\tconst commands: DtpPrinterCommand[] = [];\n\n\t\tif (!order) {\n\t\t\tthrow new Error(\"Order es requerido\");\n\t\t}\n\t\tif (!order.client) {\n\t\t\tthrow new Error(\"Order debe tener un cliente asociado\");\n\t\t}\n\t\tif (!order.items || order.items.length === 0) {\n\t\t\tthrow new Error(\"Order debe tener al menos un item\");\n\t\t}\n\n\t\tconst { paymentMethodId, storeName = \"N/A\" } = options;\n\n\t\tconst clientName = order.client.name || \"\";\n\t\tconst clientRif = order.client.id || \"\";\n\t\tconst storeLine = `Tienda: ${storeName}`;\n\n\t\tcommands.push({\n\t\t\tcmd: \"F0\",\n\t\t\tdata: {\n\t\t\t\tsNombreCliente: truncateString(clientName, 64),\n\t\t\t\tsRifCliente: truncateString(clientRif, 20),\n\t\t\t\tbLogo: false,\n\t\t\t\tsLineaAdicional: truncateString(storeLine, 64),\n\t\t\t},\n\t\t});\n\n\t\tlet subtotalWithoutTaxes = 0;\n\n\t\tfor (const item of order.items) {\n\t\t\tif (!item.name) continue;\n\n\t\t\tconst taxId =\n\t\t\t\titem.taxes && item.taxes.length > 0 ? item.taxes[0].id : null;\n\t\t\tconst iImpuesto = mapTaxIdToDtpCode(taxId);\n\t\t\tconst price = item.price ?? 0;\n\t\t\tconst lPrecio = Math.round(Math.max(price, 0) * 100);\n\t\t\tconst quantity = item.selectedQuantity ?? item.quantity ?? 1;\n\t\t\tconst lCantidad = Math.round(Math.max(quantity, 1) * 1000);\n\n\t\t\tsubtotalWithoutTaxes += price * Math.max(quantity, 1);\n\n\t\t\tcommands.push({\n\t\t\t\tcmd: \"F1\",\n\t\t\t\tdata: {\n\t\t\t\t\tsDescripcion: truncateString(item.name, 64),\n\t\t\t\t\tsCodigo: truncateString(item.sku ?? \"N/A\", 20),\n\t\t\t\t\tlCantidad,\n\t\t\t\t\tsUnidad: \"UND\",\n\t\t\t\t\tlPrecio,\n\t\t\t\t\tiImpuesto,\n\t\t\t\t\tiDecPrecio: 2,\n\t\t\t\t\tiDecCantidad: 3,\n\t\t\t\t},\n\t\t\t});\n\t\t}\n\n\t\tconst isForeignCurrency =\n\t\t\tpaymentMethodId === \"pos_debit_credit_int\" ||\n\t\t\tpaymentMethodId === \"cash_int\";\n\n\t\tif (isForeignCurrency && subtotalWithoutTaxes > 0) {\n\t\t\tconst roundedSubtotal =\n\t\t\t\tMath.round((subtotalWithoutTaxes + Number.EPSILON) * 100) / 100;\n\t\t\tconst igtfPercentage = TaxValues.BI_IGTF / 100;\n\t\t\tconst igtfAmount =\n\t\t\t\tMath.round((roundedSubtotal * igtfPercentage + Number.EPSILON) * 100) /\n\t\t\t\t100;\n\n\t\t\tcommands.push({\n\t\t\t\tcmd: \"F1\",\n\t\t\t\tdata: {\n\t\t\t\t\tsDescripcion: \"IGTF 3% pago en divisas\",\n\t\t\t\t\tsCodigo: \"IGTF\",\n\t\t\t\t\tlCantidad: 1000,\n\t\t\t\t\tsUnidad: \"UND\",\n\t\t\t\t\tlPrecio: Math.round(igtfAmount * 100),\n\t\t\t\t\tiImpuesto: 4,\n\t\t\t\t\tiDecPrecio: 2,\n\t\t\t\t\tiDecCantidad: 3,\n\t\t\t\t},\n\t\t\t});\n\t\t}\n\n\t\tcommands.push({\n\t\t\tcmd: \"F2\",\n\t\t\tdata: { mode: 1, foreignCurrencyAmount: 0 },\n\t\t});\n\n\t\tif (!order.payments?.length) {\n\t\t\tthrow new Error(\"Order debe tener al menos un pago exitoso\");\n\t\t}\n\n\t\tfor (const payment of order.payments) {\n\t\t\tconst tipo = mapPaymentMethod(payment.paymentMethod);\n\t\t\tconst lMonto = Math.round(payment.amount * 100);\n\t\t\tconst isForeign =\n\t\t\t\tpayment.paymentMethod === \"pos_debit_credit_int\" ||\n\t\t\t\tpayment.paymentMethod === \"cash_int\";\n\n\t\t\tif (isForeign) {\n\t\t\t\tcommands.push({\n\t\t\t\t\tcmd: \"F11\",\n\t\t\t\t\tdata: {\n\t\t\t\t\t\tiFormaPago: tipo,\n\t\t\t\t\t\tsDescripcion: paymentMethodLabel(tipo),\n\t\t\t\t\t\tlMonto,\n\t\t\t\t\t\tlTasaCambio: 1,\n\t\t\t\t\t\tsSimbolo: \"USD\",\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tcommands.push({\n\t\t\t\t\tcmd: \"F4\",\n\t\t\t\t\tdata: {\n\t\t\t\t\t\tiFormaPago: tipo,\n\t\t\t\t\t\tsDescripcion: paymentMethodLabel(tipo),\n\t\t\t\t\t\tlMonto,\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\tcommands.push({ cmd: \"F5\", data: {} });\n\n\t\treturn commands;\n\t},\n\n\tbuildReceiptCommands(options: BuildReceiptOptions): DtpPrinterCommand[] {\n\t\tconst {\n\t\t\torderId,\n\t\t\tamountPaid,\n\t\t\tpaymentMethod,\n\t\t\tpaidAt,\n\t\t\tcardLast4,\n\t\t\torganizationName,\n\t\t} = options;\n\n\t\tif (!orderId) {\n\t\t\tthrow new Error(\"OrderId es requerido\");\n\t\t}\n\t\tif (!Number.isFinite(amountPaid) || amountPaid <= 0) {\n\t\t\tthrow new Error(\"Monto pagado inválido\");\n\t\t}\n\n\t\tconst paidDate = paidAt ?? new Date();\n\t\tconst lines = [\n\t\t\t\"RECIBO DE PAGO\",\n\t\t\torderId,\n\t\t\t\"Recibo de pago\",\n\t\t\torganizationName?.trim() || \"N/A\",\n\t\t\t`Bs ${amountPaid}`,\n\t\t\t`Medio de pago: ${paymentMethod}`,\n\t\t\t`Tarjeta ${cardLast4 ?? \"N/A\"}`,\n\t\t\t`Hora del pago: ${formatTime(paidDate)}`,\n\t\t\t`Fecha del pago: ${formatDate(paidDate)}`,\n\t\t\t\"Cierre del Documento No Fiscal\",\n\t\t];\n\n\t\tconst commands: DtpPrinterCommand[] = [{ cmd: \"N0\" }];\n\n\t\tfor (const line of lines) {\n\t\t\tcommands.push({\n\t\t\t\tcmd: \"N1\",\n\t\t\t\tdata: { line: truncateString(line, 64) },\n\t\t\t});\n\t\t}\n\n\t\tcommands.push({ cmd: \"N3\" });\n\n\t\treturn commands;\n\t},\n};\n\n/**\n * Resultado de ejecutar comandos DTP.\n * Incluye documentNumber y totalAmount cuando el último comando es F5 (cerrar factura).\n */\nexport interface ExecuteDtpCommandsResult {\n\tdocumentNumber?: number;\n\ttotalAmount?: number;\n}\n\n/**\n * Ejecuta una secuencia de comandos DTP contra un cliente conectado.\n * Lanza en el primer error.\n * Retorna documentNumber y totalAmount cuando se ejecuta F5 (cerrar factura).\n */\nexport async function executeDtpCommands(\n\tclient: DtpClient,\n\tcommands: DtpPrinterCommand[],\n): Promise<ExecuteDtpCommandsResult> {\n\tlet documentNumber: number | undefined;\n\tlet totalAmount: number | undefined;\n\tfor (const cmd of commands) {\n\t\tswitch (cmd.cmd) {\n\t\t\tcase \"F0\": {\n\t\t\t\tconst r = await openFiscalDoc(client, cmd.data);\n\t\t\t\tif (r.code !== 0) throw new Error(`F0 falló: código ${r.code}`);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase \"F1\": {\n\t\t\t\tconst r = await addFiscalItem(client, cmd.data);\n\t\t\t\tif (r.code !== 0) throw new Error(`F1 falló: código ${r.code}`);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase \"F2\": {\n\t\t\t\tconst r = await subtotalFiscalDoc(\n\t\t\t\t\tclient,\n\t\t\t\t\tcmd.data?.mode ?? 1,\n\t\t\t\t\tcmd.data?.foreignCurrencyAmount ?? 0,\n\t\t\t\t);\n\t\t\t\tif (r.code !== 0) throw new Error(`F2 falló: código ${r.code}`);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase \"F4\": {\n\t\t\t\tconst r = await payFiscalDoc(client, cmd.data);\n\t\t\t\tif (r.code !== 0) throw new Error(`F4 falló: código ${r.code}`);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase \"F5\": {\n\t\t\t\tconst r = await closeFiscalDoc(client, cmd.data?.additionalLine ?? \"\");\n\t\t\t\tif (r.code !== 0) throw new Error(`F5 falló: código ${r.code}`);\n\t\t\t\tdocumentNumber = r.documentNumber;\n\t\t\t\ttotalAmount = r.totalAmount;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase \"F11\": {\n\t\t\t\tconst r = await payFiscalDocForeignCurrency(client, cmd.data);\n\t\t\t\tif (r.code !== 0)\n\t\t\t\t\tthrow new Error(`F11 falló: código ${r.code}`);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase \"N0\": {\n\t\t\t\tconst r = await openNonFiscalDoc(client);\n\t\t\t\tif (r.code !== 0) throw new Error(`N0 falló: código ${r.code}`);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase \"N1\": {\n\t\t\t\tconst r = await addNonFiscalLine(\n\t\t\t\t\tclient,\n\t\t\t\t\tcmd.data.line,\n\t\t\t\t\tcmd.data.size ?? 0,\n\t\t\t\t\tcmd.data.align ?? 0,\n\t\t\t\t\tcmd.data.style ?? 0,\n\t\t\t\t);\n\t\t\t\tif (r.code !== 0) throw new Error(`N1 falló: código ${r.code}`);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase \"N3\": {\n\t\t\t\tconst r = await closeNonFiscalDoc(client);\n\t\t\t\tif (r.code !== 0) throw new Error(`N3 falló: código ${r.code}`);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tdefault: {\n\t\t\t\tconst _: never = cmd;\n\t\t\t\tthrow new Error(`Comando DTP desconocido: ${String((cmd as { cmd: string }).cmd)}`);\n\t\t\t}\n\t\t}\n\t}\n\treturn { documentNumber, totalAmount };\n}\n","import type {\n\tPrinterCommandResponse,\n\tPrinterResponse,\n\tSendPrinterCommandsAeg,\n\tSendPrinterCommandsArgs,\n} from \"./types.js\";\n\nfunction normalizeBaseUrl(address: string): string {\n\tconst trimmed = address.trim();\n\tif (!trimmed) return trimmed;\n\tconst withProtocol = /^https?:\\/\\//i.test(trimmed)\n\t\t? trimmed\n\t\t: `http://${trimmed}`;\n\treturn withProtocol.replace(/\\/+$/, \"\");\n}\n\n/**\n * Envía comandos a una impresora fiscal.\n *\n * - **AEG-R1**: POST HTTP a {ip}/cmdoJson con body = commands (JSON)\n * - **DTP-80i**: No soportado en esta librería (usa TCP vía módulo nativo).\n * El consumidor debe usar ExpoDtpFiscalPrinter directamente.\n */\nexport async function sendPrinterCommands(\n\targs: SendPrinterCommandsArgs,\n\toptions?: { timeout?: number },\n): Promise<PrinterResponse> {\n\tconst { brand, model, commands } = args;\n\n\tif (!commands || commands.length === 0) {\n\t\tthrow new Error(\"No hay comandos para enviar\");\n\t}\n\n\tswitch (brand) {\n\t\tcase \"AEG\":\n\t\t\tif (model !== \"R1\") {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Modelo inválido para AEG: \"${model}\". Solo se soporta \"R1\".`,\n\t\t\t\t);\n\t\t\t}\n\t\t\treturn sendAegCommands(args as SendPrinterCommandsAeg, options);\n\t\tcase \"DTP\":\n\t\t\tif (model !== \"80i\") {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Modelo inválido para DTP: \"${model}\". Solo se soporta \"80i\".`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tthrow new Error(\n\t\t\t\t\"DTP-80i requiere el módulo nativo ExpoDtpFiscalPrinter. \" +\n\t\t\t\t\t\"Use la conexión TCP directamente desde su aplicación.\",\n\t\t\t);\n\t\tdefault: {\n\t\t\tconst _exhaustive: never = brand;\n\t\t\tthrow new Error(\n\t\t\t\t`Marca de impresora no soportada: ${String(_exhaustive)}`,\n\t\t\t);\n\t\t}\n\t}\n}\n\nasync function sendAegCommands(\n\targs: SendPrinterCommandsAeg,\n\toptions?: { timeout?: number },\n): Promise<PrinterResponse> {\n\tconst { ip, commands } = args;\n\tconst baseUrl = normalizeBaseUrl(ip);\n\tconst url = `${baseUrl}/cmdoJson`;\n\tconst controller = new AbortController();\n\tconst timeoutId =\n\t\toptions?.timeout != null\n\t\t\t? setTimeout(() => controller.abort(), options.timeout)\n\t\t\t: undefined;\n\n\ttry {\n\t\tconst response = await fetch(url, {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: {\n\t\t\t\t\"Content-Type\": \"application/json\",\n\t\t\t},\n\t\t\tbody: JSON.stringify(commands),\n\t\t\tsignal: controller.signal,\n\t\t});\n\n\t\tif (!response.ok) {\n\t\t\tthrow new Error(`Error HTTP ${response.status}: ${response.statusText}`);\n\t\t}\n\n\t\tconst data = (await response.json()) as unknown;\n\n\t\tif (!Array.isArray(data)) {\n\t\t\tthrow new Error(\n\t\t\t\t`Respuesta inválida de la impresora: se esperaba un array, se recibió ${typeof data}`,\n\t\t\t);\n\t\t}\n\n\t\tconst result = data as PrinterCommandResponse[];\n\n\t\tconst failedCommands: PrinterCommandResponse[] = [];\n\t\tfor (const commandResponse of result) {\n\t\t\tconst codeValue =\n\t\t\t\ttypeof commandResponse.code === \"string\"\n\t\t\t\t\t? Number.parseInt(commandResponse.code, 10)\n\t\t\t\t\t: commandResponse.code;\n\n\t\t\tif (Number.isNaN(codeValue) || codeValue !== 0) {\n\t\t\t\tfailedCommands.push(commandResponse);\n\t\t\t}\n\t\t}\n\n\t\tif (failedCommands.length > 0) {\n\t\t\tconst errorMessages = failedCommands\n\t\t\t\t.map(\n\t\t\t\t\t(cmd) =>\n\t\t\t\t\t\t`Comando ${cmd.cmd}: código ${cmd.code}${cmd.message ? ` - ${cmd.message}` : \"\"}`,\n\t\t\t\t)\n\t\t\t\t.join(\"; \");\n\t\t\tthrow new Error(\n\t\t\t\t`Error en la impresora: ${failedCommands.length} comando(s) fallaron. ${errorMessages}`,\n\t\t\t);\n\t\t}\n\n\t\treturn result;\n\t} catch (error) {\n\t\tif (error instanceof Error) {\n\t\t\tif (error.name === \"AbortError\") {\n\t\t\t\tthrow new Error(\"Timeout al enviar comandos a la impresora\");\n\t\t\t}\n\t\t\tthrow error;\n\t\t}\n\t\tthrow new Error(\"Error desconocido al enviar comandos a la impresora\");\n\t} finally {\n\t\tif (timeoutId) clearTimeout(timeoutId);\n\t}\n}\n"],"mappings":"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","names":["TaxValues","PrinterTaxValues","PaymentMethodId","truncateString","formatDate","formatTime","mapPaymentMethod"]}
package/dist/index.d.cts CHANGED
@@ -1,24 +1,5 @@
1
- type DtpOptions = {
2
- host: string;
3
- port: number;
4
- connectTimeoutMs?: number;
5
- commandTimeoutMs?: number;
6
- };
7
- declare class DtpClient {
8
- private opts;
9
- private socket;
10
- private buffer;
11
- private pending;
12
- constructor(opts: DtpOptions);
13
- connect(): Promise<void>;
14
- close(): void;
15
- send(parts: string[]): Promise<string[]>;
16
- private buildFrame;
17
- private tryParseOneFrame;
18
- private onData;
19
- private onError;
20
- private onClose;
21
- }
1
+ import { P as PrinterDriver } from './node-DVAcYJpM.cjs';
2
+ export { B as BuildInvoiceOptions, a as BuildReceiptOptions, D as DocumentType, b as DtpPrinterCommand, E as ExecuteDtpCommandsResult, F as FiscalClient, I as ItemTax, O as Order, c as OrderItem, d as OrderPayment, e as PrinterCommandResponse, f as dtpPrinter, g as executeDtpCommands } from './node-DVAcYJpM.cjs';
22
3
 
23
4
  /**
24
5
  * Comandos JSON para impresora fiscal AEG-R1.
@@ -112,206 +93,12 @@ type AegPrinterCommand = {
112
93
  data: number;
113
94
  };
114
95
 
115
- /**
116
- * Cliente para facturación fiscal.
117
- * Interface mínima requerida para construir comandos de impresora.
118
- */
119
- interface FiscalClient {
120
- id: string;
121
- name: string;
122
- email?: string;
123
- phone?: string;
124
- address?: string;
125
- }
126
- /**
127
- * Impuesto de un item (usado para mapeo a códigos de impresora).
128
- * id puede ser null (ej: GraphQL ItemTax).
129
- */
130
- interface ItemTax {
131
- id: string | null;
132
- }
133
- /**
134
- * Item de orden para facturación fiscal.
135
- */
136
- interface OrderItem {
137
- id: string;
138
- name: string;
139
- sku: string;
140
- price: number;
141
- quantity: number;
142
- total: number;
143
- taxes?: ItemTax[];
144
- selectedQuantity?: number;
145
- }
146
- /**
147
- * Pago completado de una orden.
148
- */
149
- interface OrderPayment {
150
- amount: number;
151
- paymentMethod: string;
152
- cardLast4?: string;
153
- }
154
- /**
155
- * Orden para facturación.
156
- * Interface mínima para construir comandos de impresora.
157
- */
158
- interface Order {
159
- items: OrderItem[];
160
- payments: OrderPayment[];
161
- total: number;
162
- client: FiscalClient | null;
163
- status?: "pending" | "completed" | "canceled" | null;
164
- }
165
-
166
- /**
167
- * Tipo de documento a imprimir.
168
- */
169
- type DocumentType = "invoice" | "receipt" | "credit_note";
170
- /**
171
- * Resultado de envío de comandos a una impresora.
172
- */
173
- interface PrinterCommandResponse$1 {
174
- cmd: string;
175
- code: number;
176
- dataD?: number;
177
- dataS?: Record<string, unknown>;
178
- message?: string;
179
- }
180
- /**
181
- * Opciones para construir comandos de factura.
182
- */
183
- interface BuildInvoiceOptions {
184
- paymentMethodId: "pos_credit" | "pos_debit" | "pos_debit_credit_int" | "cash_int" | "cash_nat";
185
- storeName?: string;
186
- }
187
- /**
188
- * Opciones para construir comandos de recibo de pago.
189
- */
190
- interface BuildReceiptOptions {
191
- orderId: string;
192
- amountPaid: number;
193
- paymentMethod: string;
194
- organizationName?: string;
195
- paidAt?: Date;
196
- cardLast4?: string | null;
197
- }
198
- /**
199
- * Interface abstracta para un driver de impresora.
200
- * Cada modelo (AEG-R1, DTP, etc.) implementa esta interface.
201
- */
202
- interface PrinterDriver<TCmd = unknown> {
203
- readonly model: string;
204
- /**
205
- * Construye comandos para imprimir una factura fiscal.
206
- */
207
- buildInvoiceCommands(order: Order, options: BuildInvoiceOptions): TCmd[];
208
- /**
209
- * Construye comandos para imprimir un recibo de pago (DNF).
210
- */
211
- buildReceiptCommands(options: BuildReceiptOptions): TCmd[];
212
- }
213
-
214
96
  /**
215
97
  * Driver para impresora fiscal AEG-R1.
216
98
  * Construye comandos JSON según documentación oficial.
217
99
  */
218
100
  declare const aegPrinter: PrinterDriver<AegPrinterCommand>;
219
101
 
220
- type AbrirCfArgs = {
221
- iTipo?: number;
222
- sNombreCliente: string;
223
- sRifCliente: string;
224
- iFacturaReferencia?: number;
225
- fechaReferencia?: Date;
226
- sSerialReferencia?: string;
227
- bLogo?: boolean;
228
- sLineaAdicional?: string;
229
- };
230
- type ItemCfArgs = {
231
- iTipo?: number;
232
- sDescripcion: string;
233
- sCodigo: string;
234
- lCantidad: number;
235
- sUnidad: string;
236
- lPrecio: number;
237
- iImpuesto: number;
238
- iDecPrecio: number;
239
- iDecCantidad: number;
240
- };
241
- type PagoCfArgs = {
242
- iTipoPago?: number;
243
- iFormaPago: number;
244
- sDescripcion: string;
245
- lMonto: number;
246
- };
247
-
248
- /**
249
- * Comandos para impresora fiscal DTP-80i.
250
- * Cada comando se ejecuta secuencialmente contra un DtpClient.
251
- */
252
- type DtpPrinterCommand = {
253
- cmd: "F0";
254
- data: AbrirCfArgs;
255
- } | {
256
- cmd: "F1";
257
- data: ItemCfArgs;
258
- } | {
259
- cmd: "F2";
260
- data: {
261
- mode?: number;
262
- foreignCurrencyAmount?: number;
263
- };
264
- } | {
265
- cmd: "F4";
266
- data: PagoCfArgs;
267
- } | {
268
- cmd: "F5";
269
- data?: {
270
- additionalLine?: string;
271
- };
272
- } | {
273
- cmd: "F11";
274
- data: {
275
- iFormaPago: number;
276
- sDescripcion: string;
277
- lMonto: number;
278
- lTasaCambio: number;
279
- sSimbolo: string;
280
- };
281
- } | {
282
- cmd: "N0";
283
- } | {
284
- cmd: "N1";
285
- data: {
286
- line: string;
287
- size?: number;
288
- align?: number;
289
- style?: number;
290
- };
291
- } | {
292
- cmd: "N3";
293
- };
294
-
295
- /**
296
- * Driver para impresora fiscal DTP-80i.
297
- * Construye comandos DTP compatibles con el protocolo TCP.
298
- */
299
- declare const dtpPrinter: PrinterDriver<DtpPrinterCommand>;
300
- /**
301
- * Resultado de ejecutar comandos DTP.
302
- * Incluye documentNumber y totalAmount cuando el último comando es F5 (cerrar factura).
303
- */
304
- interface ExecuteDtpCommandsResult {
305
- documentNumber?: number;
306
- totalAmount?: number;
307
- }
308
- /**
309
- * Ejecuta una secuencia de comandos DTP contra un cliente conectado.
310
- * Lanza en el primer error.
311
- * Retorna documentNumber y totalAmount cuando se ejecuta F5 (cerrar factura).
312
- */
313
- declare function executeDtpCommands(client: DtpClient, commands: DtpPrinterCommand[]): Promise<ExecuteDtpCommandsResult>;
314
-
315
102
  /**
316
103
  * Marcas de impresoras soportadas.
317
104
  */
@@ -416,4 +203,4 @@ declare enum PaymentMethodId {
416
203
  CASH_INT = 12
417
204
  }
418
205
 
419
- export { type AegModel, type AegPrinterCommand, type BuildInvoiceOptions, type BuildReceiptOptions, type DocumentType, DtpClient, type DtpModel, type DtpOptions, type DtpPrinterCommand, type ExecuteDtpCommandsResult, type FiscalClient, type ItemTax, type Order, type OrderItem, type OrderPayment, PaymentMethodId, type PrinterBrand, type PrinterCommandResponse$1 as PrinterCommandResponse, type PrinterDriver, PrinterTaxValues, type SendPrinterCommandsAeg, type SendPrinterCommandsArgs, type SendPrinterCommandsDtp, TaxValues, aegPrinter, dtpPrinter, executeDtpCommands, sendPrinterCommands };
206
+ export { type AegModel, type AegPrinterCommand, type DtpModel, PaymentMethodId, type PrinterBrand, PrinterDriver, PrinterTaxValues, type SendPrinterCommandsAeg, type SendPrinterCommandsArgs, type SendPrinterCommandsDtp, TaxValues, aegPrinter, sendPrinterCommands };