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*
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+ Ventas
+ |
+
+
+
+ Cobro
+ |
+
+
+
+
+
+ Productos
+ |
+
+
+
+ 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 @@
-