diff --git a/README.md b/README.md index 5c1ac1f..fa16291 100644 --- a/README.md +++ b/README.md @@ -160,19 +160,34 @@ Para ejecutarlo desde IntelliJ IDEA, añade estas opciones de VM en la configura ## Capturas de pantalla -> 📸 *Próximamente* - - - - - - - - - - - - + + + + + + + + + +
+ Pantalla de ventas de FreeTPV +
+ Ventas +
+ Pantalla de cobro de FreeTPV +
+ Cobro +
+ Gestión de productos en FreeTPV +
+ Productos +
+ Pantalla de ajustes de FreeTPV +
+ Ajustes +
+ +> También hay capturas en modo oscuro disponibles en la [web del proyecto](https://freetpv.pages.dev). --- diff --git a/pom.xml b/pom.xml index eb692a4..c55cfed 100644 --- a/pom.xml +++ b/pom.xml @@ -97,6 +97,20 @@ 4.1.0 compile + + + com.google.zxing + core + 3.5.4 + compile + + + + com.google.zxing + javase + 3.5.4 + compile + diff --git a/src/main/java/com/mateo/freetpv/controller/AjustesController.java b/src/main/java/com/mateo/freetpv/controller/AjustesController.java index 06a2bb1..8f7e0b8 100644 --- a/src/main/java/com/mateo/freetpv/controller/AjustesController.java +++ b/src/main/java/com/mateo/freetpv/controller/AjustesController.java @@ -122,7 +122,7 @@ public void initialize() { 600 ); - ImprimirService.imprimirTicket(impresora.get(), datosTicket); + ImprimirService.imprimirTicket(impresora.get(), datosTicket, ajustesService.getImpresoraAncho(), ajustesService.getImpresoraCodepage(), ajustesService.getImpresoraCortarPapel()); } catch (IOException e) { log.error("No se pudo imprimir una prueba", e); } diff --git a/src/main/java/com/mateo/freetpv/controller/LoadController.java b/src/main/java/com/mateo/freetpv/controller/LoadController.java index 8a89f1f..d93397c 100644 --- a/src/main/java/com/mateo/freetpv/controller/LoadController.java +++ b/src/main/java/com/mateo/freetpv/controller/LoadController.java @@ -3,12 +3,17 @@ import com.mateo.freetpv.FreeTPVApplication; import com.mateo.freetpv.dao.UsuarioDAO; import com.mateo.freetpv.service.AjustesService; +import com.mateo.freetpv.service.BackupService; import com.mateo.freetpv.util.DatabaseConnection; import javafx.application.Platform; import javafx.fxml.FXML; import javafx.fxml.FXMLLoader; import javafx.scene.Scene; -import javafx.scene.control.*; +import javafx.scene.control.Button; +import javafx.scene.control.Label; +import javafx.scene.control.PasswordField; +import javafx.scene.control.TextField; +import javafx.stage.FileChooser; import javafx.stage.Stage; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -19,8 +24,6 @@ public class LoadController { private static final Logger log = LoggerFactory.getLogger(LoadController.class); - @FXML - private TableColumn cantidadTableColumn; @FXML private Button crearButton; @@ -28,9 +31,6 @@ public class LoadController { @FXML private Button importarButton; - @FXML - private TableView importarTableView; - @FXML private PasswordField newPinField; @@ -40,18 +40,19 @@ public class LoadController { @FXML private Label errorLabel; - @FXML - private TableColumn resultadoTableColumn; - @FXML private Button seleccionarButton; @FXML - private TableColumn verTableColumn; + private Label seleccionadoLabel; private final String path = System.getProperty("user.home") + "/.freetpv"; - private UsuarioDAO usuarioDAO = new UsuarioDAO(); + private final UsuarioDAO usuarioDAO = new UsuarioDAO(); + + private final BackupService backupService = new BackupService(); + + private File archivoSeleccionado; public void initialize() { new File(path).mkdirs(); @@ -72,6 +73,29 @@ public void initialize() { Platform.runLater(() -> cargarLogin()); } + @FXML + public void seleccionarBackup() { + FileChooser fc = new FileChooser(); + fc.getExtensionFilters().add(new FileChooser.ExtensionFilter("Copia de seguridad", "*.tpv")); + File archivo = fc.showOpenDialog(crearButton.getScene().getWindow()); + if (archivo != null && archivo.exists()) { + archivoSeleccionado = archivo; + seleccionadoLabel.setText("Has seleccionado " + archivo.getName()); + importarButton.setDisable(false); + } + } + + @FXML + public void importarBackup() { + if (archivoSeleccionado == null) return; + + if (backupService.restaurarBackup(archivoSeleccionado)) { + initialize(); + } else { + seleccionadoLabel.setText("No se ha podido importar la copia de seguridad"); + } + } + private void cargarLogin() { try { // Cargar ventana principal diff --git a/src/main/java/com/mateo/freetpv/controller/VentasController.java b/src/main/java/com/mateo/freetpv/controller/VentasController.java index cc1f7f5..c05c441 100644 --- a/src/main/java/com/mateo/freetpv/controller/VentasController.java +++ b/src/main/java/com/mateo/freetpv/controller/VentasController.java @@ -269,8 +269,10 @@ public void seleccionarTarjeta() { Optional impresora = buscarImpresora(); if (impresora.isPresent()) { try { - ImprimirService.imprimirTicket(impresora.get(), datosTicket); - ImprimirService.abrirCajon(impresora.get()); + ImprimirService.imprimirTicket(impresora.get(), datosTicket, ajustesService.getImpresoraAncho(), ajustesService.getImpresoraCodepage(), ajustesService.getImpresoraCortarPapel()); + if (ajustesService.getImpresoraAbrirCajon()) { + ImprimirService.abrirCajon(impresora.get()); + } } catch (IOException e) { log.error("Error al imprimir ticket", e); } @@ -296,10 +298,7 @@ public void seleccionarTarjeta() { Optional impresora = buscarImpresora(); if (impresora.isPresent()) { try { - ImprimirService.imprimirTicket(impresora.get(), datosTicket); - if (ajustesService.getImpresoraAbrirCajon()) { - ImprimirService.abrirCajon(impresora.get()); - } + ImprimirService.imprimirTicket(impresora.get(), datosTicket, ajustesService.getImpresoraAncho(), ajustesService.getImpresoraCodepage(), ajustesService.getImpresoraCortarPapel()); } catch (IOException e) { log.error("Error al imprimir preticket", e); } diff --git a/src/main/java/com/mateo/freetpv/service/ImprimirService.java b/src/main/java/com/mateo/freetpv/service/ImprimirService.java index fee1c3c..0d3561f 100644 --- a/src/main/java/com/mateo/freetpv/service/ImprimirService.java +++ b/src/main/java/com/mateo/freetpv/service/ImprimirService.java @@ -3,13 +3,23 @@ import com.github.anastaciocintra.escpos.EscPos; import com.github.anastaciocintra.escpos.EscPosConst; import com.github.anastaciocintra.escpos.Style; +import com.github.anastaciocintra.escpos.image.BitonalThreshold; +import com.github.anastaciocintra.escpos.image.CoffeeImageImpl; +import com.github.anastaciocintra.escpos.image.EscPosImage; +import com.github.anastaciocintra.escpos.image.GraphicsImageWrapper; import com.github.anastaciocintra.output.PrinterOutputStream; +import com.google.zxing.BarcodeFormat; +import com.google.zxing.WriterException; +import com.google.zxing.client.j2se.MatrixToImageWriter; +import com.google.zxing.common.BitMatrix; +import com.google.zxing.qrcode.QRCodeWriter; import com.mateo.freetpv.model.DatosTicket; import com.mateo.freetpv.model.LineaTicket; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.print.PrintService; +import java.awt.image.BufferedImage; import java.io.IOException; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; @@ -21,11 +31,14 @@ import static com.mateo.freetpv.util.ConversionUtil.centimosEuros; public class ImprimirService { - private static final int WIDTH = 32; + private static int WIDTH = 32; private static final Logger log = LoggerFactory.getLogger(ImprimirService.class); - public static void imprimirTicket(PrintService printService, DatosTicket ticket) throws IOException { + public static void imprimirTicket(PrintService printService, DatosTicket ticket, int ancho, String codepage, boolean cortar) throws IOException { + WIDTH = ancho == 58 ? 32 : 48; + + PrinterOutputStream printerOutputStream = new PrinterOutputStream(printService); EscPos escpos = new EscPos(printerOutputStream); @@ -48,9 +61,12 @@ public static void imprimirTicket(PrintService printService, DatosTicket ticket) String hora = ahora.format(DateTimeFormatter.ofPattern("HH:mm")); escpos.initializePrinter(); + EscPos.CharacterCodeTable charset = switch (codepage) { + case "CP850" -> EscPos.CharacterCodeTable.CP850_Multilingual; + default -> EscPos.CharacterCodeTable.CP858_Euro; + }; + escpos.setCharacterCodeTable(charset); - // Charset / codepage para tildes y ñ - escpos.setCharacterCodeTable(EscPos.CharacterCodeTable.CP858_Euro); escpos.feed(1); escpos.writeLF(centerBold, ticket.nombreEmpresa()); @@ -131,8 +147,22 @@ public static void imprimirTicket(PrintService printService, DatosTicket ticket) escpos.feed(1); if (ticket.mostrarWeb()) escpos.writeLF(center, ticket.web()); + if (ticket.mostrarQr() && !ticket.qr().isBlank()) { + try { + BitMatrix bitMatrix = new QRCodeWriter().encode(ticket.qr(), BarcodeFormat.QR_CODE, 200, 200); + BufferedImage qrImage = MatrixToImageWriter.toBufferedImage(bitMatrix); + + GraphicsImageWrapper imageWrapper = new GraphicsImageWrapper(); + imageWrapper.setJustification(EscPosConst.Justification.Center); + EscPosImage escposImage = new EscPosImage(new CoffeeImageImpl(qrImage), new BitonalThreshold()); + escpos.write(imageWrapper, escposImage); + } catch (WriterException e) { + log.error("Error al dibujar el código QR", e); + } + } + escpos.feed(2); - escpos.cut(EscPos.CutMode.FULL); + if (cortar) escpos.cut(EscPos.CutMode.FULL); escpos.close(); } diff --git a/src/main/java/module-info.java b/src/main/java/module-info.java index a19d433..4a36358 100644 --- a/src/main/java/module-info.java +++ b/src/main/java/module-info.java @@ -11,6 +11,9 @@ requires bcrypt; requires java.desktop; requires escpos.coffee; + requires com.google.zxing; + requires com.google.zxing.javase; + opens com.mateo.freetpv.model to javafx.base; opens com.mateo.freetpv.controller to javafx.fxml; diff --git a/src/main/resources/com/mateo/freetpv/view/load-view.fxml b/src/main/resources/com/mateo/freetpv/view/load-view.fxml index 1057aa6..84d13bf 100644 --- a/src/main/resources/com/mateo/freetpv/view/load-view.fxml +++ b/src/main/resources/com/mateo/freetpv/view/load-view.fxml @@ -1,20 +1,11 @@ + + + + + - - - - - - - - - - - - - - @@ -115,12 +106,15 @@ - -