diff --git a/pom.xml b/pom.xml index a5d5f46..a3f416f 100644 --- a/pom.xml +++ b/pom.xml @@ -29,6 +29,12 @@ <version>21</version> </dependency> + <dependency> + <groupId>org.openjfx</groupId> + <artifactId>javafx-graphics</artifactId> + <version>${javafx.version}</version> + </dependency> + <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> @@ -52,7 +58,7 @@ <dependency> <groupId>org.apache.pdfbox</groupId> <artifactId>pdfbox</artifactId> - <version>3.0.3</version> + <version>2.0.24</version> </dependency> </dependencies> diff --git a/src/main/java/org/example/saladeconciertos/EscogerEvento.java b/src/main/java/org/example/saladeconciertos/EscogerEvento.java index 2995b9f..6af9fe3 100644 --- a/src/main/java/org/example/saladeconciertos/EscogerEvento.java +++ b/src/main/java/org/example/saladeconciertos/EscogerEvento.java @@ -3,6 +3,7 @@ package org.example.saladeconciertos; import javafx.geometry.Insets; import javafx.geometry.Pos; import javafx.scene.Scene; +import javafx.scene.control.Alert; import javafx.scene.control.Button; import javafx.scene.control.ComboBox; import javafx.scene.control.Label; @@ -10,12 +11,17 @@ import javafx.scene.image.Image; import javafx.scene.image.ImageView; import javafx.scene.layout.VBox; import javafx.stage.Stage; +import javafx.scene.control.ButtonType; import java.sql.Connection; +import java.sql.Date; import java.sql.DriverManager; +import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; +import java.util.ArrayList; +import java.util.List; public class EscogerEvento { // Datos de conexión a la base de datos @@ -40,6 +46,10 @@ public class EscogerEvento { Button confirmButton = new Button("Confirmar"); confirmButton.getStyleClass().add("button"); + // Crear y configurar el botón de generar reporte + Button reportButton = new Button("Generar Reporte"); + reportButton.getStyleClass().add("button"); + // Cargar eventos desde la base de datos try (Connection conexion = DriverManager.getConnection(DB_URL, DB_USER, DB_PASSWORD)) { String query = "SELECT id, nombre FROM conciertos"; @@ -78,20 +88,116 @@ public class EscogerEvento { } }); + // Acción del botón de generar reporte + reportButton.setOnAction(e -> { + String selectedEvent = eventComboBox.getValue(); + if (selectedEvent != null) { + int eventId = Integer.parseInt(selectedEvent.split(" - ")[0]); + generarReporte(eventId, selectedEvent.split(" - ")[1]); + } else { + ventaBoletos.mostrarAlerta("Advertencia", "No se ha seleccionado un evento", "Por favor, seleccione un evento."); + } + }); + // Agregar el logo de la aplicación ImageView logo = new ImageView(new Image(getClass().getResourceAsStream("/logo.png"))); logo.setFitWidth(100); logo.setFitHeight(100); // Crear y configurar el layout principal - VBox layout = new VBox(20, logo, selectEventLabel, eventComboBox, selectedEventLabel, confirmButton); + VBox layout = new VBox(20, logo, selectEventLabel, eventComboBox, selectedEventLabel, confirmButton, reportButton); layout.setAlignment(Pos.CENTER); layout.setPadding(new Insets(20)); // Crear y configurar la escena - Scene scene = new Scene(layout, 400, 300); + Scene scene = new Scene(layout, 400, 400); scene.getStylesheets().add(getClass().getResource("/styles.css").toExternalForm()); mainStage.setScene(scene); mainStage.show(); } + + // Método para convertir IDs de asientos a nombres de asientos + private String convertirIdAsientoANombre(int seatId) { + int fila = (seatId - 1) / 5; + int numero = (seatId - 1) % 5 + 1; + char filaLetra = (char) ('A' + fila); + return filaLetra + String.valueOf(numero); + } + + // Método para generar el reporte de boletos vendidos + private void generarReporte(int eventId, String eventName) { + List<String> seatDetails = new ArrayList<>(); + StringBuilder reportContent = new StringBuilder(); + reportContent.append("Reporte de Boletos Vendidos\n"); + + // Obtener la fecha del evento + String eventDate = ""; + try (Connection conexion = DriverManager.getConnection(DB_URL, DB_USER, DB_PASSWORD)) { + String eventQuery = "SELECT fecha FROM conciertos WHERE id = ?"; + PreparedStatement eventStatement = conexion.prepareStatement(eventQuery); + eventStatement.setInt(1, eventId); + ResultSet eventResultSet = eventStatement.executeQuery(); + if (eventResultSet.next()) { + eventDate = eventResultSet.getDate("fecha").toString(); + } + } catch (SQLException e) { + System.out.println("Error al obtener la fecha del evento."); + e.printStackTrace(); + } + + reportContent.append("Evento: ").append(eventName).append(" - Fecha: ").append(eventDate).append("\n\n"); + + try (Connection conexion = DriverManager.getConnection(DB_URL, DB_USER, DB_PASSWORD)) { + String query = "SELECT a.id, a.precio_base, b.fechaVenta FROM asientos a JOIN boleto b ON a.id = b.id_asiento WHERE b.idevento = ? AND b.status = 'vendido'"; + PreparedStatement statement = conexion.prepareStatement(query); + statement.setInt(1, eventId); + ResultSet resultSet = statement.executeQuery(); + + while (resultSet.next()) { + int seatId = resultSet.getInt("id"); + double price = resultSet.getDouble("precio_base"); + Date saleDate = resultSet.getDate("fechaVenta"); + String seatName = convertirIdAsientoANombre(seatId); + String seatDetail = "Asiento: " + seatName + ", Precio: $" + price + ", Fecha de Venta: " + saleDate; + seatDetails.add(seatDetail); + reportContent.append(seatDetail).append("\n"); + } + } catch (SQLException e) { + System.out.println("Error al generar el reporte."); + e.printStackTrace(); + } + + // Mostrar el reporte en una alerta + mostrarAlertaConBotonPDF("Reporte de Boletos Vendidos", "Detalles del Reporte", reportContent.toString(), eventName + " - Fecha: " + eventDate, seatDetails); + } + + // Método para mostrar una alerta con un botón para generar PDF + private void mostrarAlertaConBotonPDF(String titulo, String encabezado, String contenido, String eventName, List<String> seatDetails) { + Alert alert = new Alert(Alert.AlertType.INFORMATION); + alert.setTitle(titulo); + alert.setHeaderText(encabezado); + alert.setContentText(contenido); + + ButtonType buttonTypePDF = new ButtonType("Generar PDF"); + alert.getButtonTypes().add(buttonTypePDF); + + alert.showAndWait().ifPresent(response -> { + if (response == buttonTypePDF) { + // Generar el PDF del reporte usando la clase PDFGenerator + String qrImagePath = "src/main/resources/qrcode.png"; // Cambia esto por la ruta de tu imagen QR + String timestamp = new java.text.SimpleDateFormat("yyyyMMddHHmmss").format(new java.util.Date()); + String pdfFileName = eventName.replace(" ", "_") + "_" + timestamp + ".pdf"; + PDFGenerator.generarPDF(eventName, "", "", 0.0, qrImagePath, String.join("\n", seatDetails), pdfFileName); + } + }); + } + + // Método para mostrar una alerta + private void mostrarAlerta(String titulo, String encabezado, String contenido) { + Alert alert = new Alert(Alert.AlertType.INFORMATION); + alert.setTitle(titulo); + alert.setHeaderText(encabezado); + alert.setContentText(contenido); + alert.showAndWait(); + } } \ No newline at end of file diff --git a/src/main/java/org/example/saladeconciertos/PDFGenerator.java b/src/main/java/org/example/saladeconciertos/PDFGenerator.java index 4a2ffac..ac29bdc 100644 --- a/src/main/java/org/example/saladeconciertos/PDFGenerator.java +++ b/src/main/java/org/example/saladeconciertos/PDFGenerator.java @@ -3,7 +3,6 @@ package org.example.saladeconciertos; import org.apache.pdfbox.pdmodel.PDDocument; import org.apache.pdfbox.pdmodel.PDPage; import org.apache.pdfbox.pdmodel.PDPageContentStream; -import org.apache.pdfbox.pdmodel.font.Standard14Fonts; import org.apache.pdfbox.pdmodel.font.PDType1Font; import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject; @@ -11,12 +10,11 @@ import java.io.IOException; public class PDFGenerator { - // Método para generar un PDF con los detalles del ticket - public static void generarPDF(String eventName, String eventDate, String clientName, double totalPrice, String qrImagePath) { + // Método para generar un PDF con los detalles del reporte de ventas + public static void generarPDF(String eventName, String eventDate, String clientName, double totalPrice, String qrImagePath, String ticketDetails, String pdfFileName) { // Ruta donde se guardará el PDF String downloadsPath = System.getProperty("user.home") + "/Downloads/"; - String fileName = "Ticket_" + eventName.replace(" ", "_") + ".pdf"; - String pdfPath = downloadsPath + fileName; + String pdfPath = downloadsPath + pdfFileName; try (PDDocument document = new PDDocument()) { // Crear una nueva página @@ -25,26 +23,87 @@ public class PDFGenerator { // Crear un flujo de contenido para la página try (PDPageContentStream contentStream = new PDPageContentStream(document, page)) { - // Configurar la fuente y el tamaño (usando Standard14Fonts) - PDType1Font font = new PDType1Font(Standard14Fonts.FontName.HELVETICA_BOLD); - contentStream.setFont(font, 12); - - // Escribir los detalles del ticket + // Configurar la fuente y el tamaño para el título del evento + contentStream.setFont(PDType1Font.HELVETICA_BOLD, 24); contentStream.beginText(); - contentStream.newLineAtOffset(50, 700); - contentStream.showText("Evento: " + eventName); - contentStream.newLineAtOffset(0, -20); - contentStream.showText("Fecha: " + eventDate); - contentStream.newLineAtOffset(0, -20); - contentStream.showText("Cliente: " + clientName); - contentStream.newLineAtOffset(0, -20); - contentStream.showText("Total: $" + String.format("%.2f", totalPrice)); + contentStream.newLineAtOffset(50, 750); + contentStream.showText(eventName); + contentStream.endText(); + + // Configurar la fuente y el tamaño para la fecha del evento + contentStream.setFont(PDType1Font.HELVETICA_BOLD, 18); + contentStream.beginText(); + contentStream.newLineAtOffset(50, 720); + contentStream.endText(); + + // Configurar la fuente y el tamaño para el contenido del reporte + contentStream.setFont(PDType1Font.HELVETICA, 12); + contentStream.beginText(); + contentStream.newLineAtOffset(50, 680); + + // Dividir el texto en líneas y escribir cada línea por separado + String[] lines = ticketDetails.split("\n"); + for (String line : lines) { + contentStream.showText(line); + contentStream.newLineAtOffset(0, -15); // Mover hacia abajo para la siguiente línea + } + contentStream.endText(); // Agregar la imagen del código QR (si existe) if (qrImagePath != null && !qrImagePath.isEmpty()) { PDImageXObject qrImage = PDImageXObject.createFromFile(qrImagePath, document); - contentStream.drawImage(qrImage, 50, 500, 150, 150); // Ajusta la posición y el tamaño de la imagen + contentStream.drawImage(qrImage, 50, 50, 150, 150); // Ajusta la posición y el tamaño de la imagen + } + } + + // Guardar el PDF en la carpeta de descargas + document.save(pdfPath); + System.out.println("Reporte generado y guardado en: " + pdfPath); + } catch (IOException e) { + e.printStackTrace(); + System.out.println("Error al generar el PDF del reporte."); + } + } + + // Método para generar un PDF con los detalles del ticket de compra + public static void generarTicketPDF(String eventName, String eventDate, String clientName, double totalPrice, String qrImagePath, String ticketDetails, String pdfFileName) { + // Ruta donde se guardará el PDF + String downloadsPath = System.getProperty("user.home") + "/Downloads/"; + String pdfPath = downloadsPath + pdfFileName; + + try (PDDocument document = new PDDocument()) { + // Crear una nueva página + PDPage page = new PDPage(); + document.addPage(page); + + // Crear un flujo de contenido para la página + try (PDPageContentStream contentStream = new PDPageContentStream(document, page)) { + // Configurar la fuente y el tamaño para el título + contentStream.setFont(PDType1Font.HELVETICA_BOLD, 20); + contentStream.beginText(); + contentStream.newLineAtOffset(50, 750); + contentStream.showText("Ticket de Compra"); + contentStream.endText(); + + // Configurar la fuente y el tamaño para el contenido + contentStream.setFont(PDType1Font.HELVETICA, 12); + contentStream.beginText(); + contentStream.newLineAtOffset(50, 700); + + // Dividir el texto en líneas y escribir cada línea por separado + String[] lines = ticketDetails.split("\n"); + for (String line : lines) { + contentStream.showText(line); + contentStream.newLineAtOffset(0, -15); // Mover hacia abajo para la siguiente línea + } + + contentStream.endText(); + + // Agregar la imagen del código QR + if (qrImagePath != null && !qrImagePath.isEmpty()) { + PDImageXObject qrImage = PDImageXObject.createFromFile(qrImagePath, document); + contentStream.drawImage(qrImage, 50, 50, 150, 150); // Ajusta la posición y el tamaño de la imagen } } diff --git a/src/main/java/org/example/saladeconciertos/VentaBoletos.java b/src/main/java/org/example/saladeconciertos/VentaBoletos.java index e901f85..bcd0ea5 100644 --- a/src/main/java/org/example/saladeconciertos/VentaBoletos.java +++ b/src/main/java/org/example/saladeconciertos/VentaBoletos.java @@ -4,9 +4,9 @@ import javafx.application.Application; import javafx.geometry.Insets; import javafx.geometry.Pos; import javafx.scene.Scene; +import javafx.scene.control.Alert; import javafx.scene.control.Button; import javafx.scene.control.Label; -import javafx.scene.control.Alert; import javafx.scene.effect.DropShadow; import javafx.scene.image.Image; import javafx.scene.image.ImageView; @@ -16,11 +16,12 @@ import javafx.scene.layout.VBox; import javafx.scene.paint.Color; import javafx.stage.Stage; -import java.sql.*; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.*; public class VentaBoletos extends Application { private static final String DB_URL = "jdbc:mysql://sql10.freesqldatabase.com:3306/sql10766655"; @@ -41,6 +42,10 @@ public class VentaBoletos extends Application { escogerEvento.mostrarVentanaSeleccionEvento(mainStage, this); } + public int getEventId() { + return eventId; + } + public void setEventId(int eventId) { this.eventId = eventId; } @@ -255,6 +260,24 @@ public class VentaBoletos extends Application { alert.showAndWait(); } + public void actualizarEstadoBoletos(List<Integer> selectedSeats, int idevento) { + try (Connection conexion = DriverManager.getConnection(DB_URL, DB_USER, DB_PASSWORD)) { + String updateQuery = "UPDATE boleto SET status = 'vendido', fechaVenta = CURDATE() WHERE id_asiento = ? AND idevento = ?"; + PreparedStatement preparedStatement = conexion.prepareStatement(updateQuery); + + for (int seat : selectedSeats) { + preparedStatement.setInt(1, seat); + preparedStatement.setInt(2, idevento); + preparedStatement.executeUpdate(); + } + + System.out.println("Estado de los boletos actualizado correctamente."); + } catch (SQLException e) { + System.out.println("Error al actualizar el estado de los boletos."); + e.printStackTrace(); + } + } + public static void main(String[] args) { launch(args); } diff --git a/src/main/java/org/example/saladeconciertos/VentanaPago.java b/src/main/java/org/example/saladeconciertos/VentanaPago.java index 384037c..5d29319 100644 --- a/src/main/java/org/example/saladeconciertos/VentanaPago.java +++ b/src/main/java/org/example/saladeconciertos/VentanaPago.java @@ -7,6 +7,8 @@ import javafx.stage.Stage; import javafx.geometry.Insets; import javafx.geometry.Pos; import java.sql.*; +import java.text.SimpleDateFormat; +import java.util.Date; import java.util.List; import java.util.Map; @@ -45,11 +47,19 @@ public class VentanaPago { Label totalLabel = new Label("Total a pagar: $" + String.format("%.2f", totalPrice)); totalLabel.getStyleClass().add("label"); // Aplicar clase CSS - // Campo para ingresar el nombre del cliente + // Campos para ingresar el nombre del cliente TextField nameField = new TextField(); - nameField.setPromptText("Nombre del cliente"); + nameField.setPromptText("Nombre"); nameField.setMaxWidth(200); + TextField lastNameField = new TextField(); + lastNameField.setPromptText("Apellido Paterno"); + lastNameField.setMaxWidth(200); + + TextField secondLastNameField = new TextField(); + secondLastNameField.setPromptText("Apellido Materno"); + secondLastNameField.setMaxWidth(200); + // Selección de método de pago ChoiceBox<String> paymentMethod = new ChoiceBox<>(); paymentMethod.getItems().addAll("Tarjeta de Crédito/Débito", "PayPal"); @@ -88,6 +98,11 @@ public class VentanaPago { payButton.getStyleClass().add("button"); // Aplicar clase CSS payButton.setDisable(true); // Deshabilitar al inicio + // Botón para generar el PDF + Button pdfButton = new Button("Generar PDF"); + pdfButton.getStyleClass().add("button"); // Aplicar clase CSS + pdfButton.setDisable(true); // Deshabilitar al inicio + // Contenedor dinámico para campos y botón VBox dynamicContainer = new VBox(10); dynamicContainer.setAlignment(Pos.TOP_CENTER); // Centrar el contenido @@ -102,22 +117,27 @@ public class VentanaPago { // Habilitar el botón de pago si se selecciona un método payButton.setDisable(newVal == null); + pdfButton.setDisable(newVal == null); // Actualizar el contenedor dinámico dynamicContainer.getChildren().clear(); if (isCard) { - dynamicContainer.getChildren().addAll(cardFields, payButton); + dynamicContainer.getChildren().addAll(cardFields, payButton, pdfButton); } else if (isPayPal) { - dynamicContainer.getChildren().addAll(paypalFields, payButton); + dynamicContainer.getChildren().addAll(paypalFields, payButton, pdfButton); } else { - dynamicContainer.getChildren().add(payButton); + dynamicContainer.getChildren().addAll(payButton, pdfButton); } }); payButton.setOnAction(e -> { - String clientName = nameField.getText(); - if (clientName.isEmpty()) { - mostrarAlerta("Advertencia", "Nombre del cliente vacío", "Por favor, ingrese el nombre del cliente."); + String name = nameField.getText(); + String lastName = lastNameField.getText(); + String secondLastName = secondLastNameField.getText(); + String clientName = name + " " + lastName + " " + secondLastName; + + if (name.isEmpty() || lastName.isEmpty() || secondLastName.isEmpty()) { + mostrarAlerta("Advertencia", "Nombre del cliente vacío", "Por favor, ingrese el nombre completo del cliente."); return; } @@ -140,15 +160,50 @@ public class VentanaPago { } // Si todo está correcto, generar el ticket - generarTicket(clientName, selectedSeats, seatPrices, eventName, eventDate, totalPrice); + generarTicket(clientName, selectedSeats, seatPrices, eventName, eventDate, totalPrice, paymentLayout, method); paymentStage.close(); ventaBoletos.refrescarInterfaz(); }); + pdfButton.setOnAction(e -> { + String name = nameField.getText(); + String lastName = lastNameField.getText(); + String secondLastName = secondLastNameField.getText(); + String clientName = name + " " + lastName + " " + secondLastName; + + if (name.isEmpty() || lastName.isEmpty() || secondLastName.isEmpty()) { + mostrarAlerta("Advertencia", "Nombre del cliente vacío", "Por favor, ingrese el nombre completo del cliente."); + return; + } + + String method = paymentMethod.getValue(); + if (method.equals("Tarjeta de Crédito/Débito")) { + String cardNumber = cardNumberField.getText(); + String expiryDate = expiryDateField.getText(); + String cvv = cvvField.getText(); + + if (!validarTarjeta(cardNumber, expiryDate, cvv)) { + mostrarAlerta("Error", "Datos de tarjeta inválidos", "Por favor, ingrese un número de tarjeta válido (13 dígitos), fecha (MM/YY) y CVV."); + return; + } + } else if (method.equals("PayPal")) { + String email = emailField.getText(); + if (!validarEmail(email)) { + mostrarAlerta("Error", "Correo inválido", "Por favor, ingrese un correo electrónico válido."); + return; + } + } + + // Generar el PDF del ticket + generarPDF(clientName, selectedSeats, seatPrices, eventName, eventDate, totalPrice, method); + }); + // Agregar elementos al layout paymentLayout.getChildren().addAll( titleLabel, eventLabel, dateLabel, totalLabel, - new Label("Nombre del cliente:"), nameField, + new Label("Nombre:"), nameField, + new Label("Apellido Paterno:"), lastNameField, + new Label("Apellido Materno:"), secondLastNameField, new Label("Método de pago:"), paymentMethod, dynamicContainer ); @@ -175,26 +230,52 @@ public class VentanaPago { return email.matches("^[A-Za-z0-9+_.-]+@(.+)$"); // Validación básica de correo } - private void generarTicket(String clientName, List<Integer> selectedSeats, Map<Integer, Double> seatPrices, String eventName, String eventDate, double totalPrice) { - // Mostrar el ticket en una ventana (como antes) + private void generarTicket(String clientName, List<Integer> selectedSeats, Map<Integer, Double> seatPrices, String eventName, String eventDate, double totalPrice, VBox paymentLayout, String paymentMethod) { + // Mostrar el ticket en una ventana StringBuilder ticketDetails = new StringBuilder(); - ticketDetails.append("Evento: ").append(eventName).append("\n"); - ticketDetails.append("Fecha: ").append(eventDate).append("\n"); ticketDetails.append("Cliente: ").append(clientName).append("\n"); - ticketDetails.append("Asientos: "); + ticketDetails.append("Evento: ").append(eventName).append("\n"); + ticketDetails.append("Fecha de evento: ").append(eventDate).append("\n"); + ticketDetails.append("Fecha de compra: ").append(new SimpleDateFormat("yyyy/MM/dd").format(new Date())).append("\n"); + ticketDetails.append("Método de pago: ").append(paymentMethod).append("\n"); + ticketDetails.append("Asientos: ").append(selectedSeats.size() > 1 ? "\n" : ""); for (int seat : selectedSeats) { - ticketDetails.append(seat).append(" ($").append(String.format("%.2f", seatPrices.get(seat))).append("), "); + String seatName = convertirIdAsientoANombre(seat); + ticketDetails.append(seatName).append(" ($").append(String.format("%.2f", seatPrices.get(seat))).append("), "); } ticketDetails.append("\nTotal: $").append(String.format("%.2f", totalPrice)); mostrarAlerta("Ticket Generado", "Detalles del Ticket", ticketDetails.toString()); - // Generar el PDF del ticket usando la clase PDFGenerator - String qrImagePath = "src/main/resources/qrcode.png"; // Cambia esto por la ruta de tu imagen QR - PDFGenerator.generarPDF(eventName, eventDate, clientName, totalPrice, qrImagePath); - // Actualizar el estado de los boletos comprados en la base de datos - actualizarEstadoBoletos(selectedSeats, 1); // Cambia el idevento según corresponda + actualizarEstadoBoletos(selectedSeats, ventaBoletos.getEventId()); // Cambia el idevento según corresponda + + // Generar el PDF del ticket usando la clase PDFGenerator + String qrImagePath = "src/main/resources/qrcode.png"; // Ruta de tu imagen QR + String pdfFileName = "ticket_" + System.currentTimeMillis() + ".pdf"; + PDFGenerator.generarTicketPDF(eventName, eventDate, clientName, totalPrice, qrImagePath, ticketDetails.toString(), pdfFileName); + + // Mostrar alerta de que el ticket fue guardado + mostrarAlertaTicketGuardado(pdfFileName, paymentLayout); + } + + private void generarPDF(String clientName, List<Integer> selectedSeats, Map<Integer, Double> seatPrices, String eventName, String eventDate, double totalPrice, String paymentMethod) { + // Generar el PDF del ticket usando la clase PDFGenerator + String qrImagePath = "src/main/resources/qrcode.png"; // Ruta de tu imagen QR + StringBuilder ticketDetails = new StringBuilder(); + ticketDetails.append("Evento: ").append(eventName).append("\n"); + ticketDetails.append("Fecha: ").append(new SimpleDateFormat("dd/MM/yyyy").format(new Date())).append("\n"); + ticketDetails.append("Cliente: ").append(clientName).append("\n"); + ticketDetails.append("Método de pago: ").append(paymentMethod).append("\n"); + ticketDetails.append("Asientos: "); + for (int seat : selectedSeats) { + String seatName = convertirIdAsientoANombre(seat); + ticketDetails.append(seatName).append(" ($").append(String.format("%.2f", seatPrices.get(seat))).append("), "); + } + ticketDetails.append("\nTotal: $").append(String.format("%.2f", totalPrice)); + + String pdfFileName = "ticket_" + System.currentTimeMillis() + ".pdf"; + PDFGenerator.generarTicketPDF(eventName, eventDate, clientName, totalPrice, qrImagePath, ticketDetails.toString(), pdfFileName); } private void actualizarEstadoBoletos(List<Integer> selectedSeats, int idevento) { @@ -222,4 +303,25 @@ public class VentanaPago { alert.setContentText(contenido); alert.showAndWait(); } + + private void mostrarAlertaTicketGuardado(String pdfFileName, VBox paymentLayout) { + Alert alert = new Alert(Alert.AlertType.INFORMATION); + alert.setTitle("Ticket Guardado"); + alert.setHeaderText("Ticket Guardado"); + alert.setContentText("El ticket ha sido guardado en la carpeta Descargas como " + pdfFileName); + + alert.showAndWait().ifPresent(response -> { + // Cerrar la ventana de pago y regresar a la ventana de selección de asientos + Stage stage = (Stage) paymentLayout.getScene().getWindow(); + stage.close(); + ventaBoletos.refrescarInterfaz(); + }); + } + + private String convertirIdAsientoANombre(int seatId) { + int fila = (seatId - 1) / 5; + int numero = (seatId - 1) % 5 + 1; + char filaLetra = (char) ('A' + fila); + return filaLetra + String.valueOf(numero); + } } \ No newline at end of file