Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 73 additions & 0 deletions Controller/SendTicket.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
namespace FacturaScripts\Plugins\Tickets\Controller;

use FacturaScripts\Core\Base\Controller;
use FacturaScripts\Core\Base\DataBase\DataBaseWhere;
use FacturaScripts\Core\Model\Base\ModelClass;
use FacturaScripts\Core\Tools;
use FacturaScripts\Dinamic\Lib\Tickets\Gift;
Expand All @@ -14,6 +15,7 @@
use FacturaScripts\Dinamic\Lib\Tickets\Service;
use FacturaScripts\Dinamic\Lib\Tickets\TicketBai;
use FacturaScripts\Dinamic\Model\ServicioAT;
use FacturaScripts\Dinamic\Model\Ticket;
use FacturaScripts\Dinamic\Model\TicketPrinter;

/**
Expand Down Expand Up @@ -90,9 +92,80 @@ public function privateCore(&$response, $user, $permissions)
$action = $this->request->request->get('action', '');
if ($action === 'print') {
$this->printAction($model);
} elseif ($action === 'get-escpos') {
$this->getEscposAction($model);
}
}

protected function getEscposAction(ModelClass $model): void
{
$this->setTemplate(false);

$translator = Tools::lang();
$printerId = (int)$this->request->request->get('printer');
$printer = new TicketPrinter();
if (false === $printer->loadFromCode($printerId)) {
$this->response->setContent(json_encode(['ok' => false, 'error' => $translator->trans('printer-not-found')]));
return;
}

// Modificamos la longitud de línea según el ancho de papel seleccionado en el frontend.
$paperWidth = (string)$this->request->request->get('paperWidth', $printer->linelen);
$originalPaperWidth = $printer->linelen;
if ($paperWidth === '58') {
$printer->linelen = 32;
} elseif ($paperWidth === '80') {
$printer->linelen = 48;
}

// Obtiene la clase de formato dinámicamente desde la petición.
$formatClass = $this->request->request->get('format', '');
if (empty($formatClass)) {
$this->response->setContent(json_encode(['ok' => false, 'error' => $translator->trans('format-class-not-provided')]));
return;
}

$formatClass = '\\' . $formatClass;
if (false === class_exists($formatClass)) {
$this->response->setContent(json_encode(['ok' => false, 'error' => $translator->trans('invalid-format-class')]));
return;
}

// 1. Llama a la función print de la clase dinámica para guardar el ticket.
if (false === $formatClass::print($model, $printer, $this->user)) {
$this->response->setContent(json_encode(['ok' => false, 'error' => $translator->trans('failed-to-create-temporary-ticket')]));
return;
}

// 2. Busca el ticket recién creado para esta impresora, ordenado por fecha de creación.
$where = [new DataBaseWhere('printed', false)];
$tickets = Ticket::all($where, ['creationdate' => 'DESC'], 0, 1);
if (empty($tickets)) {
$this->response->setContent(json_encode(['ok' => false, 'error' => $translator->trans('could-not-retrieve-temporary-ticket')]));
return;
}

$tempTicket = $tickets[0];
$rawData = base64_decode($tempTicket->body);

// Restaura la longitud de línea original.
$printer->linelen = $originalPaperWidth;

// 3. Borra el ticket temporal de la base de datos.
if (false === $tempTicket->delete()) {
Tools::log()->error($translator->trans('failed-to-delete-temporary-ticket') . ': ' . $tempTicket->id);
}

// 4. Comprueba que el cuerpo del ticket no esté vacío.
if (empty($rawData)) {
$this->response->setContent(json_encode(['ok' => false, 'error' => $translator->trans('generated-ticket-body-is-empty')]));
return;
}

// 5. Devuelve una respuesta JSON correcta.
$this->response->setContent(json_encode(['ok' => true, 'data' => $rawData]));
}

protected function getPrinter(int $id): TicketPrinter
{
foreach ($this->printers as $printer) {
Expand Down
4 changes: 4 additions & 0 deletions Init.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
use FacturaScripts\Dinamic\Lib\Tickets\Gift;
use FacturaScripts\Dinamic\Lib\Tickets\Normal;
use FacturaScripts\Dinamic\Lib\Tickets\PaymentReceipt;
use FacturaScripts\Dinamic\Lib\AssetManager;

/**
* @author Carlos Garcia Gomez <carlos@facturascripts.com>
Expand All @@ -25,6 +26,9 @@ public function init(): void
{
ExportManager::addOption('Ticket', 'ticket', 'fa-solid fa-receipt');
$this->loadFormatTickets();

// assets
AssetManager::addJs(FS_ROUTE . '/Plugins/Tickets/node_modules/qz-tray/qz-tray.js');
}

public function uninstall(): void
Expand Down
7 changes: 7 additions & 0 deletions Lib/Tickets/BaseTicket.php
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,7 @@ protected static function init(): void
// inicializamos la impresora virtual, para posteriormente obtener los comandos
static::$connector = new DummyPrintConnector();
static::$escpos = new Printer(static::$connector);
static::$connector->clear();
static::$escpos->initialize();
}

Expand Down Expand Up @@ -363,6 +364,12 @@ protected static function printLines(TicketPrinter $printer, array $lines): void
$jump = true;
}

if ($printer->print_lines_price_tax) {
$priceVat = $line->pvpunitario * (100 + $line->iva + $line->recargo) / 100;
$td .= "\n" . sprintf("%11s", Tools::lang()->trans('price-abb') . ': ' . Tools::number($priceVat));
$jump = true;
}

if ($printer->print_lines_discount && $line->dtopor > 0) {
$td .= $printer->print_lines_price ? ' ' : "\n";
$td .= sprintf("%11s", Tools::lang()->trans('discount-abb') . ': ' . $line->dtopor . '%');
Expand Down
4 changes: 4 additions & 0 deletions Model/TicketPrinter.php
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,9 @@ class TicketPrinter extends ModelClass
/** @var bool */
public $print_lines_price;

/** @var bool */
public $print_lines_price_tax;

/** @var bool */
public $print_lines_price_unitary;

Expand Down Expand Up @@ -124,6 +127,7 @@ public function clear()
$this->print_lines_net = false;
$this->print_lines_price = false;
$this->print_lines_price_unitary = false;
$this->print_lines_price_tax = false;
$this->print_lines_quantity = true;
$this->print_lines_reference = false;
$this->print_lines_total = true;
Expand Down
5 changes: 5 additions & 0 deletions Table/tickets_printers.xml
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,11 @@
<type>boolean</type>
<default>true</default>
</column>
<column>
<name>print_lines_price_tax</name>
<type>boolean</type>
<default>false</default>
</column>
<column>
<name>print_lines_quantity</name>
<type>boolean</type>
Expand Down
73 changes: 71 additions & 2 deletions Translation/en_EN.json
Original file line number Diff line number Diff line change
@@ -1,37 +1,106 @@
{
"check-connection-and-parameters": "Check connection and parameters.",
"connect-a-printer": "Connect a printer",
"connect-a-printer-p": "To connect a printer you must first add it and then use the application to print tickets.",
"connect-to-qz-tray": "Connect to QZ Tray",
"configure-printer": "Configure printer",
"could-not-retrieve-temporary-ticket": "Could not retrieve temporary ticket",
"cut-command": "Cut command",
"data-sent-to-usb-successfully": "Data sent to USB device successfully.",
"description-abb": "Desc.",
"detected-usb-devices": "Detected USB devices",
"device-connection-error": "Device connection error: ",
"discount-abb": "Disc.",
"download-app": "Download App",
"endpoint": "Endpoint",
"ensure-correct-settings-before-print": "Make sure the settings are correct before trying to print.",
"ensure-device-connected-and-qz-permissions": "Make sure the device is connected and QZ Tray has permissions.",
"error-ajax-preview": "AJAX error loading preview:",
"error-connecting-to-qz-tray": "Error connecting to QZ Tray: ",
"error-printing": "Error printing: ",
"error-scanning-devices": "Error scanning devices: ",
"error-scanning-usb-devices": "Error scanning USB devices: ",
"expiration-abb": "Expt.",
"failed-to-create-temporary-ticket": "Failed to create temporary ticket",
"failed-to-delete-temporary-ticket": "Failed to delete temporary ticket",
"format-class-not-provided": "Format class not provided",
"generated-ticket-body-is-empty": "Generated ticket body is empty",
"gift": "Gift",
"interface": "Interface",
"invalid-format-class": "Invalid format class",
"line-length": "Line length",
"loading": "Loading...",
"loading-ticket-preview": "Loading ticket preview...",
"manual-configuration": "Manual configuration",
"manual-config-updated-for": "Manual configuration updated for %name% (Vendor: %vendorId%, Product: %productId%).",
"manual-config-updated-for-user": "Configuration updated for %name%.",
"net-abb": "Net",
"no-devices-detected-scan-usb": "No devices detected. Try scanning.",
"no-printer-connected": "No printer connected or configured.",
"no-ticket-data-to-print-load-first": "No ticket data to print. Load a preview first.",
"no-usb-devices-found": "No USB devices found.",
"no-valid-ticket-data-received": "No valid ticket data received from the server.",
"num-usb-devices-detected": "%num% USB devices detected.",
"open-command": "Open command",
"paper-width": "Paper width",
"please-select-a-format": "Please select a format.",
"please-select-a-printer": "Please select a printer.",
"preparing-to-send-data": "Preparing to send data...",
"preview-cut-paper": "[Cut Paper]",
"preview-init-printer": "[Init Printer]",
"preview-pulse-drawer": "[Pulse Drawer]",
"price-abb": "Price",
"print-comp-shortname": "Print company shortname",
"print-comp-tlf": "Print company telephone",
"print-delay": "Printing delay (s)",
"print-invoice-receipts": "Imprimir recibos en facturas",
"print-invoice-receipts": "Print receipts on invoices",
"print-lines-description": "Print descriptions",
"print-lines-discount": "Print discounts",
"print-lines-net": "Print net amount on lines",
"print-lines-price": "Print prices on the lines",
"print-lines-price-tax": "Print prices with VAT on the lines",
"print-lines-quantity": "Print quantities",
"print-lines-reference": "Print references",
"print-lines-total": "Print total",
"print-logo": "Print logo",
"print-payment-methods": "Print payment methods",
"print-preticket": "Pre-print tickets",
"print-stored-logo": "Print logo stored in the printer",
"print-test-ticket": "Print test ticket",
"print-ticket": "Print Ticket",
"print-with-ticket-printer": "Print with ticket printer",
"printer": "Printer",
"printer-not-found": "Printer not found",
"printers": "Printers",
"product-id": "Product ID",
"qz-tray-connected": "QZ Tray connected",
"qz-tray-connected-successfully": "Connected to QZ Tray successfully.",
"qz-tray-connection-error": "QZ Tray connection error.",
"qz-tray-disconnected": "QZ Tray disconnected",
"qz-tray-disconnected-reload": "QZ Tray disconnected. Reload the page if necessary.",
"qz-tray-not-connected-before-print": "QZ Tray is not connected. Connect before printing.",
"qz-tray-not-connected-before-scan": "QZ Tray is not connected. Connect before scanning.",
"qz-tray-not-connected-click-to-start": "QZ Tray is not connected. Click Connect to start it.",
"reference-abb": "Ref.",
"scan-usb-devices": "Scan USB devices",
"select": "Select",
"select-a-printer": "Select a printer",
"select-printer-and-load-preview": "Select a printer and format to load the preview.",
"sending-data-to-printer": "Sending data to printer...",
"sending-to-printer": "Sending to printer",
"settings-loaded-from-local-storage": "Settings loaded from local storage.",
"settings-saved-automatically": "Settings saved automatically to local storage.",
"ticket-footer": "Footer",
"ticket-head": "Header",
"total-abb": "Total"
"ticket-preview-and-print": "Ticket printing",
"ticket-preview-html": "Ticket Preview (HTML)",
"ticket-ready-to-print": "Ticket ready to print.",
"total-abb": "Total",
"trying-to-connect-qz-tray": "Trying to connect to QZ Tray...",
"unknown-device": "Unknown device",
"vendor-id": "Vendor ID",
"vendor-product-id-required-to-print": "Vendor ID and Product ID are required to print.",
"you-can-adjust-parameters": "You can adjust the parameters if necessary.",
"last-activity": "Last activity",
"print-with-qz-tray": "Print with QZ Tray"
}
71 changes: 70 additions & 1 deletion Translation/es_ES.json
Original file line number Diff line number Diff line change
@@ -1,16 +1,54 @@
{
"check-connection-and-parameters": "Compruebe la conexión y los parámetros.",
"connect-a-printer": "Conectar una impresora",
"connect-a-printer-p": "Para conectar una impresora primero debe añadirla y después usar la aplicación para imprimir tickets.",
"connect-to-qz-tray": "Conectar a QZ Tray",
"configure-printer": "Configurar impresora",
"could-not-retrieve-temporary-ticket": "No se pudo recuperar el ticket temporal",
"cut-command": "Comando de corte",
"data-sent-to-usb-successfully": "Datos enviados al dispositivo USB correctamente.",
"description-abb": "Desc.",
"detected-usb-devices": "Dispositivos USB detectados",
"device-connection-error": "Error de conexión con el dispositivo: ",
"discount-abb": "Dto.",
"download-app": "Descargar App",
"endpoint": "Endpoint",
"ensure-correct-settings-before-print": "Asegúrese de que los ajustes son correctos antes de intentar imprimir.",
"ensure-device-connected-and-qz-permissions": "Asegúrese de que el dispositivo está conectado y QZ Tray tiene permisos.",
"error-ajax-preview": "Error AJAX al cargar la previsualización:",
"error-connecting-to-qz-tray": "Error al conectar con QZ Tray: ",
"error-printing": "Error al imprimir: ",
"error-scanning-devices": "Error al escanear dispositivos: ",
"error-scanning-usb-devices": "Error al escanear dispositivos USB: ",
"expiration-abb": "Vcto.",
"failed-to-create-temporary-ticket": "No se pudo crear el ticket temporal",
"failed-to-delete-temporary-ticket": "No se pudo eliminar el ticket temporal",
"format-class-not-provided": "Clase de formato no proporcionada",
"generated-ticket-body-is-empty": "El cuerpo del ticket generado está vacío",
"gift": "Regalo",
"interface": "Interfaz",
"invalid-format-class": "Clase de formato no válida",
"line-length": "Caracteres por línea",
"loading": "Cargando...",
"loading-ticket-preview": "Cargando previsualización del ticket...",
"manual-configuration": "Configuración manual",
"manual-config-updated-for": "Configuración manual actualizada para %name% (Vendor: %vendorId%, Product: %productId%).",
"manual-config-updated-for-user": "Configuración actualizada para %name%.",
"net-abb": "Neto",
"no-devices-detected-scan-usb": "No se han detectado dispositivos. Pruebe a escanear.",
"no-printer-connected": "Ninguna impresora conectada o configurada.",
"no-ticket-data-to-print-load-first": "No hay datos de ticket para imprimir. Cargue una previsualización primero.",
"no-usb-devices-found": "No se encontraron dispositivos USB.",
"no-valid-ticket-data-received": "No se han recibido datos de ticket válidos del servidor.",
"num-usb-devices-detected": "%num% dispositivos USB detectados.",
"open-command": "Comando de apertura",
"paper-width": "Ancho del papel",
"please-select-a-format": "Por favor, seleccione un formato.",
"please-select-a-printer": "Por favor, seleccione una impresora.",
"preparing-to-send-data": "Preparando para enviar los datos...",
"preview-cut-paper": "[Cortar Papel]",
"preview-init-printer": "[Init Printer]",
"preview-pulse-drawer": "[Abrir Cajón]",
"price-abb": "Precio",
"print-comp-shortname": "Imprimir nombre corto de empresa",
"print-comp-tlf": "Imprimir teléfono empresa",
Expand All @@ -20,18 +58,49 @@
"print-lines-discount": "Imprimir descuentos",
"print-lines-net": "Imprimir importe neto en las líneas",
"print-lines-price": "Imprimir precios en las líneas",
"print-lines-price-tax": "Imprimir precios con IVA en las líneas",
"print-lines-quantity": "Imprimir cantidades",
"print-lines-reference": "Imprimir referencias",
"print-lines-total": "Imprimir totales",
"print-logo": "Imprimir logo",
"print-payment-methods": "Imprimir formas de pago",
"print-preticket": "Pre-imprimir tickets",
"print-stored-logo": "Imprimir logotipo almacenado en la impresora",
"print-test-ticket": "Imprimir ticket de prueba",
"print-ticket": "Imprimir Ticket",
"print-with-ticket-printer": "Imprimir con impresora de tickets",
"printer": "Impresora",
"printer-not-found": "Impresora no encontrada",
"printers": "Impresoras",
"product-id": "Product ID",
"qz-tray-connected": "QZ Tray conectado",
"qz-tray-connected-successfully": "Conectado a QZ Tray correctamente.",
"qz-tray-connection-error": "Error de conexión con QZ Tray.",
"qz-tray-disconnected": "QZ Tray desconectado",
"qz-tray-disconnected-reload": "QZ Tray desconectado. Recargue la página si es necesario.",
"qz-tray-not-connected-before-print": "QZ Tray no está conectado. Conéctese antes de imprimir.",
"qz-tray-not-connected-before-scan": "QZ Tray no está conectado. Conéctese antes de escanear.",
"qz-tray-not-connected-click-to-start": "QZ Tray no está conectado. Haga clic en Conectar para iniciarlo.",
"reference-abb": "Ref.",
"scan-usb-devices": "Escanear dispositivos USB",
"select": "Seleccionar",
"select-a-printer": "Seleccione una impresora",
"select-printer-and-load-preview": "Seleccione una impresora y un formato para cargar la previsualización.",
"sending-data-to-printer": "Enviando datos a la impresora...",
"sending-to-printer": "Enviando a la impresora",
"settings-loaded-from-local-storage": "Ajustes cargados desde el almacenamiento local.",
"settings-saved-automatically": "Ajustes guardados automáticamente en el almacenamiento local.",
"ticket-footer": "Pié de página",
"ticket-head": "Cabecera",
"total-abb": "Total"
"ticket-preview-and-print": "Impresión de tickets",
"ticket-preview-html": "Previsualización del Ticket (HTML)",
"ticket-ready-to-print": "Ticket listo para imprimir.",
"total-abb": "Total",
"trying-to-connect-qz-tray": "Intentando conectar con QZ Tray...",
"unknown-device": "Dispositivo desconocido",
"vendor-id": "Vendor ID",
"vendor-product-id-required-to-print": "El Vendor ID y el Product ID son necesarios para imprimir.",
"you-can-adjust-parameters": "Puede ajustar los parámetros si es necesario.",
"last-activity": "Última actividad",
"print-with-qz-tray": "Imprimir con QZ Tray"
}
Loading
Loading