Skip to content

Commit b18cdee

Browse files
authored
Añadir importación de copias de seguridad, capturas en readme, qr en ticket y quitar valores hardcodeados (#39)
1 parent 312ffd0 commit b18cdee

8 files changed

Lines changed: 131 additions & 52 deletions

File tree

README.md

Lines changed: 28 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -160,19 +160,34 @@ Para ejecutarlo desde IntelliJ IDEA, añade estas opciones de VM en la configura
160160

161161
## Capturas de pantalla
162162

163-
> 📸 *Próximamente*
164-
165-
<!-- Pantalla de login -->
166-
<!-- ![Login](images/screenshot_login.png) -->
167-
168-
<!-- Pantalla de ventas -->
169-
<!-- ![Ventas](images/screenshot_ventas.png) -->
170-
171-
<!-- Gestión de productos -->
172-
<!-- ![Productos](images/screenshot_productos.png) -->
173-
174-
<!-- Ajustes -->
175-
<!-- ![Ajustes](images/screenshot_ajustes.png) -->
163+
<table>
164+
<tr>
165+
<td align="center">
166+
<img src="landing/public/images/screenshots/screenshot-ventas.webp" alt="Pantalla de ventas de FreeTPV" width="420">
167+
<br>
168+
<sub>Ventas</sub>
169+
</td>
170+
<td align="center">
171+
<img src="landing/public/images/screenshots/screenshot-cobro.webp" alt="Pantalla de cobro de FreeTPV" width="420">
172+
<br>
173+
<sub>Cobro</sub>
174+
</td>
175+
</tr>
176+
<tr>
177+
<td align="center">
178+
<img src="landing/public/images/screenshots/screenshot-productos.webp" alt="Gestión de productos en FreeTPV" width="420">
179+
<br>
180+
<sub>Productos</sub>
181+
</td>
182+
<td align="center">
183+
<img src="landing/public/images/screenshots/screenshot-ajustes.webp" alt="Pantalla de ajustes de FreeTPV" width="420">
184+
<br>
185+
<sub>Ajustes</sub>
186+
</td>
187+
</tr>
188+
</table>
189+
190+
> También hay capturas en modo oscuro disponibles en la [web del proyecto](https://freetpv.pages.dev).
176191
177192
---
178193

pom.xml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,20 @@
9797
<version>4.1.0</version>
9898
<scope>compile</scope>
9999
</dependency>
100+
<!-- Source: https://mvnrepository.com/artifact/com.google.zxing/core -->
101+
<dependency>
102+
<groupId>com.google.zxing</groupId>
103+
<artifactId>core</artifactId>
104+
<version>3.5.4</version>
105+
<scope>compile</scope>
106+
</dependency>
107+
<!-- Source: https://mvnrepository.com/artifact/com.google.zxing/javase -->
108+
<dependency>
109+
<groupId>com.google.zxing</groupId>
110+
<artifactId>javase</artifactId>
111+
<version>3.5.4</version>
112+
<scope>compile</scope>
113+
</dependency>
100114
</dependencies>
101115

102116
<build>

src/main/java/com/mateo/freetpv/controller/AjustesController.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ public void initialize() {
122122
600
123123
);
124124

125-
ImprimirService.imprimirTicket(impresora.get(), datosTicket);
125+
ImprimirService.imprimirTicket(impresora.get(), datosTicket, ajustesService.getImpresoraAncho(), ajustesService.getImpresoraCodepage(), ajustesService.getImpresoraCortarPapel());
126126
} catch (IOException e) {
127127
log.error("No se pudo imprimir una prueba", e);
128128
}

src/main/java/com/mateo/freetpv/controller/LoadController.java

Lines changed: 35 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,17 @@
33
import com.mateo.freetpv.FreeTPVApplication;
44
import com.mateo.freetpv.dao.UsuarioDAO;
55
import com.mateo.freetpv.service.AjustesService;
6+
import com.mateo.freetpv.service.BackupService;
67
import com.mateo.freetpv.util.DatabaseConnection;
78
import javafx.application.Platform;
89
import javafx.fxml.FXML;
910
import javafx.fxml.FXMLLoader;
1011
import javafx.scene.Scene;
11-
import javafx.scene.control.*;
12+
import javafx.scene.control.Button;
13+
import javafx.scene.control.Label;
14+
import javafx.scene.control.PasswordField;
15+
import javafx.scene.control.TextField;
16+
import javafx.stage.FileChooser;
1217
import javafx.stage.Stage;
1318
import org.slf4j.Logger;
1419
import org.slf4j.LoggerFactory;
@@ -19,18 +24,13 @@
1924
public class LoadController {
2025

2126
private static final Logger log = LoggerFactory.getLogger(LoadController.class);
22-
@FXML
23-
private TableColumn<?, ?> cantidadTableColumn;
2427

2528
@FXML
2629
private Button crearButton;
2730

2831
@FXML
2932
private Button importarButton;
3033

31-
@FXML
32-
private TableView<?> importarTableView;
33-
3434
@FXML
3535
private PasswordField newPinField;
3636

@@ -40,18 +40,19 @@ public class LoadController {
4040
@FXML
4141
private Label errorLabel;
4242

43-
@FXML
44-
private TableColumn<?, ?> resultadoTableColumn;
45-
4643
@FXML
4744
private Button seleccionarButton;
4845

4946
@FXML
50-
private TableColumn<?, ?> verTableColumn;
47+
private Label seleccionadoLabel;
5148

5249
private final String path = System.getProperty("user.home") + "/.freetpv";
5350

54-
private UsuarioDAO usuarioDAO = new UsuarioDAO();
51+
private final UsuarioDAO usuarioDAO = new UsuarioDAO();
52+
53+
private final BackupService backupService = new BackupService();
54+
55+
private File archivoSeleccionado;
5556

5657
public void initialize() {
5758
new File(path).mkdirs();
@@ -72,6 +73,29 @@ public void initialize() {
7273
Platform.runLater(() -> cargarLogin());
7374
}
7475

76+
@FXML
77+
public void seleccionarBackup() {
78+
FileChooser fc = new FileChooser();
79+
fc.getExtensionFilters().add(new FileChooser.ExtensionFilter("Copia de seguridad", "*.tpv"));
80+
File archivo = fc.showOpenDialog(crearButton.getScene().getWindow());
81+
if (archivo != null && archivo.exists()) {
82+
archivoSeleccionado = archivo;
83+
seleccionadoLabel.setText("Has seleccionado " + archivo.getName());
84+
importarButton.setDisable(false);
85+
}
86+
}
87+
88+
@FXML
89+
public void importarBackup() {
90+
if (archivoSeleccionado == null) return;
91+
92+
if (backupService.restaurarBackup(archivoSeleccionado)) {
93+
initialize();
94+
} else {
95+
seleccionadoLabel.setText("No se ha podido importar la copia de seguridad");
96+
}
97+
}
98+
7599
private void cargarLogin() {
76100
try {
77101
// Cargar ventana principal

src/main/java/com/mateo/freetpv/controller/VentasController.java

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -269,8 +269,10 @@ public void seleccionarTarjeta() {
269269
Optional<PrintService> impresora = buscarImpresora();
270270
if (impresora.isPresent()) {
271271
try {
272-
ImprimirService.imprimirTicket(impresora.get(), datosTicket);
273-
ImprimirService.abrirCajon(impresora.get());
272+
ImprimirService.imprimirTicket(impresora.get(), datosTicket, ajustesService.getImpresoraAncho(), ajustesService.getImpresoraCodepage(), ajustesService.getImpresoraCortarPapel());
273+
if (ajustesService.getImpresoraAbrirCajon()) {
274+
ImprimirService.abrirCajon(impresora.get());
275+
}
274276
} catch (IOException e) {
275277
log.error("Error al imprimir ticket", e);
276278
}
@@ -296,10 +298,7 @@ public void seleccionarTarjeta() {
296298
Optional<PrintService> impresora = buscarImpresora();
297299
if (impresora.isPresent()) {
298300
try {
299-
ImprimirService.imprimirTicket(impresora.get(), datosTicket);
300-
if (ajustesService.getImpresoraAbrirCajon()) {
301-
ImprimirService.abrirCajon(impresora.get());
302-
}
301+
ImprimirService.imprimirTicket(impresora.get(), datosTicket, ajustesService.getImpresoraAncho(), ajustesService.getImpresoraCodepage(), ajustesService.getImpresoraCortarPapel());
303302
} catch (IOException e) {
304303
log.error("Error al imprimir preticket", e);
305304
}

src/main/java/com/mateo/freetpv/service/ImprimirService.java

Lines changed: 35 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,23 @@
33
import com.github.anastaciocintra.escpos.EscPos;
44
import com.github.anastaciocintra.escpos.EscPosConst;
55
import com.github.anastaciocintra.escpos.Style;
6+
import com.github.anastaciocintra.escpos.image.BitonalThreshold;
7+
import com.github.anastaciocintra.escpos.image.CoffeeImageImpl;
8+
import com.github.anastaciocintra.escpos.image.EscPosImage;
9+
import com.github.anastaciocintra.escpos.image.GraphicsImageWrapper;
610
import com.github.anastaciocintra.output.PrinterOutputStream;
11+
import com.google.zxing.BarcodeFormat;
12+
import com.google.zxing.WriterException;
13+
import com.google.zxing.client.j2se.MatrixToImageWriter;
14+
import com.google.zxing.common.BitMatrix;
15+
import com.google.zxing.qrcode.QRCodeWriter;
716
import com.mateo.freetpv.model.DatosTicket;
817
import com.mateo.freetpv.model.LineaTicket;
918
import org.slf4j.Logger;
1019
import org.slf4j.LoggerFactory;
1120

1221
import javax.print.PrintService;
22+
import java.awt.image.BufferedImage;
1323
import java.io.IOException;
1424
import java.time.LocalDateTime;
1525
import java.time.format.DateTimeFormatter;
@@ -21,11 +31,14 @@
2131
import static com.mateo.freetpv.util.ConversionUtil.centimosEuros;
2232

2333
public class ImprimirService {
24-
private static final int WIDTH = 32;
34+
private static int WIDTH = 32;
2535

2636
private static final Logger log = LoggerFactory.getLogger(ImprimirService.class);
2737

28-
public static void imprimirTicket(PrintService printService, DatosTicket ticket) throws IOException {
38+
public static void imprimirTicket(PrintService printService, DatosTicket ticket, int ancho, String codepage, boolean cortar) throws IOException {
39+
WIDTH = ancho == 58 ? 32 : 48;
40+
41+
2942
PrinterOutputStream printerOutputStream = new PrinterOutputStream(printService);
3043
EscPos escpos = new EscPos(printerOutputStream);
3144

@@ -48,9 +61,12 @@ public static void imprimirTicket(PrintService printService, DatosTicket ticket)
4861
String hora = ahora.format(DateTimeFormatter.ofPattern("HH:mm"));
4962

5063
escpos.initializePrinter();
64+
EscPos.CharacterCodeTable charset = switch (codepage) {
65+
case "CP850" -> EscPos.CharacterCodeTable.CP850_Multilingual;
66+
default -> EscPos.CharacterCodeTable.CP858_Euro;
67+
};
68+
escpos.setCharacterCodeTable(charset);
5169

52-
// Charset / codepage para tildes y ñ
53-
escpos.setCharacterCodeTable(EscPos.CharacterCodeTable.CP858_Euro);
5470

5571
escpos.feed(1);
5672
escpos.writeLF(centerBold, ticket.nombreEmpresa());
@@ -131,8 +147,22 @@ public static void imprimirTicket(PrintService printService, DatosTicket ticket)
131147
escpos.feed(1);
132148
if (ticket.mostrarWeb()) escpos.writeLF(center, ticket.web());
133149

150+
if (ticket.mostrarQr() && !ticket.qr().isBlank()) {
151+
try {
152+
BitMatrix bitMatrix = new QRCodeWriter().encode(ticket.qr(), BarcodeFormat.QR_CODE, 200, 200);
153+
BufferedImage qrImage = MatrixToImageWriter.toBufferedImage(bitMatrix);
154+
155+
GraphicsImageWrapper imageWrapper = new GraphicsImageWrapper();
156+
imageWrapper.setJustification(EscPosConst.Justification.Center);
157+
EscPosImage escposImage = new EscPosImage(new CoffeeImageImpl(qrImage), new BitonalThreshold());
158+
escpos.write(imageWrapper, escposImage);
159+
} catch (WriterException e) {
160+
log.error("Error al dibujar el código QR", e);
161+
}
162+
}
163+
134164
escpos.feed(2);
135-
escpos.cut(EscPos.CutMode.FULL);
165+
if (cortar) escpos.cut(EscPos.CutMode.FULL);
136166
escpos.close();
137167
}
138168

src/main/java/module-info.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@
1111
requires bcrypt;
1212
requires java.desktop;
1313
requires escpos.coffee;
14+
requires com.google.zxing;
15+
requires com.google.zxing.javase;
16+
1417

1518
opens com.mateo.freetpv.model to javafx.base;
1619
opens com.mateo.freetpv.controller to javafx.fxml;

src/main/resources/com/mateo/freetpv/view/load-view.fxml

Lines changed: 10 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,11 @@
11
<?xml version="1.0" encoding="UTF-8"?>
22

3+
<?import javafx.geometry.*?>
4+
<?import javafx.scene.control.*?>
5+
<?import javafx.scene.layout.*?>
6+
<?import javafx.scene.text.*?>
7+
<?import org.kordamp.ikonli.javafx.*?>
38
<?import java.lang.String?>
4-
<?import javafx.geometry.Insets?>
5-
<?import javafx.scene.control.Button?>
6-
<?import javafx.scene.control.Label?>
7-
<?import javafx.scene.control.PasswordField?>
8-
<?import javafx.scene.control.Separator?>
9-
<?import javafx.scene.control.TextField?>
10-
<?import javafx.scene.layout.BorderPane?>
11-
<?import javafx.scene.layout.HBox?>
12-
<?import javafx.scene.layout.StackPane?>
13-
<?import javafx.scene.layout.VBox?>
14-
<?import javafx.scene.text.Font?>
15-
<?import javafx.scene.text.Text?>
16-
<?import org.kordamp.ikonli.javafx.FontIcon?>
17-
189
<StackPane maxHeight="500.0" maxWidth="850.0" minHeight="500.0" minWidth="800.0" xmlns="http://javafx.com/javafx/25" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.mateo.freetpv.controller.LoadController">
1910
<children>
2011
<BorderPane prefHeight="200.0" prefWidth="200.0">
@@ -115,12 +106,15 @@
115106
</Text>
116107
</children>
117108
</HBox>
118-
<Button fx:id="seleccionarButton" graphicTextGap="8.0" maxWidth="1.7976931348623157E308" mnemonicParsing="false" text="Seleccionar archivo .tpv">
109+
<Button fx:id="seleccionarButton" graphicTextGap="8.0" maxWidth="1.7976931348623157E308"
110+
mnemonicParsing="false" onAction="#seleccionarBackup" text="Seleccionar archivo .tpv">
119111
<graphic>
120112
<FontIcon iconLiteral="far-folder" iconSize="16" />
121113
</graphic>
122114
</Button>
123-
<Button fx:id="importarButton" graphicTextGap="8.0" maxWidth="1.7976931348623157E308" mnemonicParsing="false" styleClass="accent" text="Importar copia">
115+
<Label fx:id="seleccionadoLabel"/>
116+
<Button fx:id="importarButton" disable="true" graphicTextGap="8.0" maxWidth="1.7976931348623157E308"
117+
mnemonicParsing="false" onAction="#importarBackup" styleClass="accent" text="Importar copia">
124118
<VBox.margin>
125119
<Insets />
126120
</VBox.margin>

0 commit comments

Comments
 (0)