diff --git a/.vscode/launch.json b/.vscode/launch.json
index 55e4357..3d256b9 100644
--- a/.vscode/launch.json
+++ b/.vscode/launch.json
@@ -1,6 +1,20 @@
{
"version": "0.2.0",
"configurations": [
+ {
+ "type": "java",
+ "name": "test_print",
+ "request": "launch",
+ "mainClass": "BsK.client.ui.component.CheckUpPage.PrintDialog.print_forms.test_print",
+ "projectName": "ldS_BsK"
+ },
+ {
+ "type": "java",
+ "name": "test_print",
+ "request": "launch",
+ "mainClass": "test_print",
+ "projectName": "ldS_BsK"
+ },
{
"type": "java",
"name": "Client",
diff --git a/medical_invoice.pdf b/medical_invoice.pdf
index 1a1915e..a0ea4cb 100644
Binary files a/medical_invoice.pdf and b/medical_invoice.pdf differ
diff --git a/pom.xml b/pom.xml
index e93e953..57fbe1a 100644
--- a/pom.xml
+++ b/pom.xml
@@ -246,5 +246,26 @@
opencv-platform
4.9.0-1.5.10
+
+
+ net.sf.jasperreports
+ jasperreports
+ 7.0.3
+
+
+
+
+ net.sf.barcode4j
+ barcode4j
+ 2.1
+
+
+
+
+ net.sf.jasperreports
+ jasperreports-barcode4j
+ 7.0.3
+
+
diff --git a/src/main/java/BsK/client/ui/component/CheckUpPage/CheckUpPage.java b/src/main/java/BsK/client/ui/component/CheckUpPage/CheckUpPage.java
index 6cb0169..31047bc 100644
--- a/src/main/java/BsK/client/ui/component/CheckUpPage/CheckUpPage.java
+++ b/src/main/java/BsK/client/ui/component/CheckUpPage/CheckUpPage.java
@@ -7,6 +7,7 @@ import BsK.client.ui.component.CheckUpPage.AddDialog.AddDialog;
import BsK.client.ui.component.CheckUpPage.HistoryViewDialog.HistoryViewDialog;
import BsK.client.ui.component.CheckUpPage.MedicineDialog.MedicineDialog;
import BsK.client.ui.component.CheckUpPage.PrintDialog.MedicineInvoice;
+import BsK.client.ui.component.CheckUpPage.PrintDialog.UltrasoundResult;
import BsK.client.ui.component.CheckUpPage.ServiceDialog.ServiceDialog;
import BsK.client.ui.component.CheckUpPage.TemplateDialog.TemplateDialog;
import BsK.client.ui.component.MainFrame;
@@ -87,6 +88,7 @@ import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
+import java.util.stream.Collectors;
import javax.swing.JFrame;
import javax.swing.JTextPane;
import javax.swing.JToolBar;
@@ -167,6 +169,8 @@ public class CheckUpPage extends JPanel {
private JLabel overallTotalCostLabel;
private static final DecimalFormat df = new DecimalFormat("#,##0");
+ private List selectedImagesForPrint = new ArrayList<>();
+
// New member variables for Supersonic View
private JPanel supersonicViewPanelGlobal;
private JPanel imageGalleryPanel; // Displays thumbnails
@@ -1328,7 +1332,35 @@ public class CheckUpPage extends JPanel {
medicineInvoice.createDialog(mainFrame);
break;
case "ultrasound":
- // No dialog needed for now
+ if (selectedImagesForPrint.isEmpty()) {
+ JOptionPane.showMessageDialog(this,
+ "Vui lòng chọn ít nhất một hình ảnh để in kết quả.",
+ "Chưa chọn ảnh", JOptionPane.WARNING_MESSAGE);
+ return;
+ }
+ if (photoNum != 0 && selectedImagesForPrint.size() > photoNum) {
+ JOptionPane.showMessageDialog(this,
+ "Số lượng ảnh đã chọn (" + selectedImagesForPrint.size() + ") nhiều hơn số lượng cho phép trong mẫu (" + photoNum + ").",
+ "Quá nhiều ảnh", JOptionPane.WARNING_MESSAGE);
+ return;
+ }
+
+ UltrasoundResult ultrasoundDialog = new UltrasoundResult(
+ checkupIdField.getText(),
+ customerLastNameField.getText() + " " + customerFirstNameField.getText(),
+ dobPicker.getJFormattedTextField().getText(),
+ (String) genderComboBox.getSelectedItem(),
+ customerAddressField.getText() + ", " + (wardComboBox.getSelectedItem() != null ? wardComboBox.getSelectedItem().toString() : "") + ", " + (districtComboBox.getSelectedItem() != null ? districtComboBox.getSelectedItem().toString() : "") + ", " + (provinceComboBox.getSelectedItem() != null ? provinceComboBox.getSelectedItem().toString() : ""),
+ (String) doctorComboBox.getSelectedItem(),
+ datePicker.getJFormattedTextField().getText(),
+ getRtfContentAsString(),
+ conclusionField.getText(),
+ suggestionField.getText(),
+ selectedImagesForPrint,
+ printType,
+ templateTitle
+ );
+ ultrasoundDialog.createDialog(mainFrame);
break;
}
}
@@ -1420,6 +1452,8 @@ public class CheckUpPage extends JPanel {
imageRefreshTimer.stop();
}
+ selectedImagesForPrint.clear();
+
// Only stop recording if it's active, don't cleanup webcam
if (isRecording) {
stopRecording();
@@ -2469,14 +2503,50 @@ public class CheckUpPage extends JPanel {
Image scaledImage = image.getScaledInstance(newWidth, newHeight, Image.SCALE_SMOOTH);
JLabel imageLabel = new JLabel(new ImageIcon(scaledImage));
- imageLabel.setToolTipText(file.getName() + " (" + originalWidth + "x" + originalHeight + ")");
- imageLabel.setBorder(BorderFactory.createLineBorder(Color.DARK_GRAY));
- // Set fixed size for the label to ensure FlowLayout behaves
- imageLabel.setPreferredSize(new Dimension(THUMBNAIL_WIDTH, THUMBNAIL_HEIGHT));
+ imageLabel.setToolTipText(file.getName());
+ // These are important to center the image if it's smaller than the thumbnail bounds
imageLabel.setHorizontalAlignment(SwingConstants.CENTER);
imageLabel.setVerticalAlignment(SwingConstants.CENTER);
- imageGalleryPanel.add(imageLabel);
+ JCheckBox selectCheckBox = new JCheckBox(""); // "box only"
+ selectCheckBox.setToolTipText("Chọn để in");
+ selectCheckBox.setOpaque(false); // Make it transparent to see the image behind
+
+ // Check if the file is already in the list to maintain state on refresh
+ if (selectedImagesForPrint.contains(file)) {
+ selectCheckBox.setSelected(true);
+ }
+
+ final File imageFile = file;
+ selectCheckBox.addActionListener(e -> {
+ if (selectCheckBox.isSelected()) {
+ if (!selectedImagesForPrint.contains(imageFile)) {
+ selectedImagesForPrint.add(imageFile);
+ }
+ } else {
+ selectedImagesForPrint.remove(imageFile);
+ }
+ if (log.isInfoEnabled()) {
+ log.info("Selected images for printing: {}", selectedImagesForPrint.stream().map(File::getName).collect(Collectors.toList()));
+ }
+ });
+
+ // Use a JLayeredPane to overlay checkbox on the image
+ JLayeredPane layeredPane = new JLayeredPane();
+ layeredPane.setPreferredSize(new Dimension(THUMBNAIL_WIDTH, THUMBNAIL_HEIGHT));
+ layeredPane.setBorder(BorderFactory.createLineBorder(Color.GRAY));
+
+ // The label will fill the entire pane
+ imageLabel.setBounds(0, 0, THUMBNAIL_WIDTH, THUMBNAIL_HEIGHT);
+
+ // Position the checkbox at the top-right corner
+ int checkboxSize = 20;
+ selectCheckBox.setBounds(THUMBNAIL_WIDTH - checkboxSize - 2, 2, checkboxSize, checkboxSize); // 2px padding
+
+ layeredPane.add(imageLabel, JLayeredPane.DEFAULT_LAYER);
+ layeredPane.add(selectCheckBox, JLayeredPane.PALETTE_LAYER); // PALETTE_LAYER is on top of DEFAULT_LAYER
+
+ imageGalleryPanel.add(layeredPane);
} catch (Exception ex) {
log.error("Error loading image thumbnail: {}", file.getAbsolutePath(), ex);
JLabel errorLabel = new JLabel("Lỗi ảnh
" + file.getName().substring(0, Math.min(file.getName().length(),10)) + "...");
diff --git a/src/main/java/BsK/client/ui/component/CheckUpPage/PrintDialog/UltrasoundResult.java b/src/main/java/BsK/client/ui/component/CheckUpPage/PrintDialog/UltrasoundResult.java
new file mode 100644
index 0000000..aaeda0d
--- /dev/null
+++ b/src/main/java/BsK/client/ui/component/CheckUpPage/PrintDialog/UltrasoundResult.java
@@ -0,0 +1,568 @@
+package BsK.client.ui.component.CheckUpPage.PrintDialog;
+
+import BsK.client.LocalStorage;
+import com.itextpdf.io.font.constants.StandardFonts;
+import com.itextpdf.io.image.ImageDataFactory;
+import com.itextpdf.kernel.colors.ColorConstants;
+import com.itextpdf.kernel.font.PdfFont;
+import com.itextpdf.kernel.font.PdfFontFactory;
+import com.itextpdf.kernel.geom.PageSize;
+import com.itextpdf.kernel.pdf.PdfDocument;
+import com.itextpdf.kernel.pdf.PdfWriter;
+import com.itextpdf.layout.Document;
+import com.itextpdf.layout.borders.Border;
+import com.itextpdf.layout.borders.SolidBorder;
+import com.itextpdf.layout.element.Cell;
+import com.itextpdf.layout.element.Image;
+import com.itextpdf.layout.element.Paragraph;
+import com.itextpdf.layout.element.Table;
+import com.itextpdf.layout.element.Text;
+import com.itextpdf.layout.property.HorizontalAlignment;
+import com.itextpdf.layout.property.TextAlignment;
+import com.itextpdf.layout.property.UnitValue;
+import com.itextpdf.layout.property.VerticalAlignment;
+import com.itextpdf.layout.element.AreaBreak;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.pdfbox.pdmodel.PDDocument;
+import org.apache.pdfbox.rendering.PDFRenderer;
+
+import javax.imageio.ImageIO;
+import javax.swing.*;
+import javax.swing.text.rtf.RTFEditorKit;
+import java.awt.*;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+import java.awt.image.BufferedImage;
+import java.awt.print.PageFormat;
+import java.awt.print.Printable;
+import java.awt.print.PrinterException;
+import java.awt.print.PrinterJob;
+import java.io.*;
+import java.util.List;
+
+@Slf4j
+public class UltrasoundResult {
+
+ private JDialog dialog;
+ private final String checkupId;
+ private final String patientName;
+ private final String patientDOB;
+ private final String patientGender;
+ private final String patientAddress;
+ private final String doctorName;
+ private final String checkupDate;
+ private final String rtfContent;
+ private final String conclusion;
+ private final String suggestion;
+ private final List selectedImages;
+ private final String printType; // "ngang" or "dọc"
+ private final String templateTitle;
+
+ private static final String PDF_PATH = "ultrasound_result.pdf";
+
+ public UltrasoundResult(String checkupId, String patientName, String patientDOB, String patientGender,
+ String patientAddress, String doctorName, String checkupDate,
+ String rtfContent, String conclusion, String suggestion,
+ List selectedImages, String printType, String templateTitle) {
+ this.checkupId = checkupId;
+ this.patientName = patientName;
+ this.patientDOB = patientDOB;
+ this.patientGender = patientGender;
+ this.patientAddress = patientAddress;
+ this.doctorName = doctorName;
+ this.checkupDate = checkupDate;
+ this.rtfContent = rtfContent;
+ this.conclusion = conclusion;
+ this.suggestion = suggestion;
+ this.selectedImages = selectedImages;
+ this.printType = printType;
+ this.templateTitle = templateTitle;
+ }
+
+ public void createDialog(JFrame parent) {
+ dialog = new JDialog(parent, "Kết quả siêu âm", true);
+ dialog.setSize(800, 700);
+ dialog.setResizable(true);
+ dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
+ dialog.setLayout(new BorderLayout());
+
+ dialog.setModalityType(Dialog.ModalityType.APPLICATION_MODAL);
+
+ dialog.addWindowListener(new WindowAdapter() {
+ @Override
+ public void windowIconified(WindowEvent e) {
+ if (parent != null) parent.setState(Frame.ICONIFIED);
+ }
+
+ @Override
+ public void windowDeiconified(WindowEvent e) {
+ if (parent != null && parent.getState() == Frame.ICONIFIED) parent.setState(Frame.NORMAL);
+ }
+ });
+
+ JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT));
+ JButton saveButton = new JButton("Lưu PDF");
+ JButton printButton = new JButton("In PDF");
+ buttonPanel.add(saveButton);
+ buttonPanel.add(printButton);
+
+ JPanel pdfViewer = new JPanel();
+ JScrollPane scrollPane = new JScrollPane(pdfViewer);
+ dialog.add(scrollPane, BorderLayout.CENTER);
+ dialog.add(buttonPanel, BorderLayout.SOUTH);
+
+ try {
+ generatePdf(PDF_PATH);
+ displayPdfInLabel(PDF_PATH, pdfViewer);
+ } catch (Exception e) {
+ log.error("Error generating ultrasound PDF", e);
+ JOptionPane.showMessageDialog(dialog, "Lỗi khi tạo PDF: " + e.getMessage(), "Lỗi", JOptionPane.ERROR_MESSAGE);
+ }
+
+ saveButton.addActionListener(e -> savePdf());
+ printButton.addActionListener(e -> printPdf());
+
+ dialog.setLocationRelativeTo(parent);
+ dialog.setVisible(true);
+ }
+
+ private void generatePdf(String pdfPath) throws Exception {
+ PdfWriter writer = new PdfWriter(pdfPath);
+ PdfDocument pdfDoc = new PdfDocument(writer);
+ Document document;
+
+ boolean isLandscape = "ngang".equalsIgnoreCase(this.printType);
+ if (isLandscape) {
+ document = new Document(pdfDoc, PageSize.A4.rotate());
+ } else {
+ document = new Document(pdfDoc, PageSize.A4);
+ }
+ document.setMargins(20, 20, 20, 20);
+
+ String boldFontPath = "src/main/java/BsK/client/ui/assets/font/SVN-Arial Bold.ttf";
+ PdfFont boldFont = PdfFontFactory.createFont(boldFontPath, "Identity-H", true);
+ String fontPath = "src/main/java/BsK/client/ui/assets/font/SVN-Arial Regular.ttf";
+ PdfFont font = PdfFontFactory.createFont(fontPath, "Identity-H", true);
+
+ String title = templateTitle != null ? templateTitle.toUpperCase() : "KẾT QUẢ SIÊU ÂM";
+
+ if (isLandscape) {
+ generateLandscapeLayout(document, boldFont, font, title);
+ } else {
+ addHeader(document, boldFont, font);
+ document.add(new Paragraph(title)
+ .setFont(boldFont).setFontSize(14)
+ .setTextAlignment(TextAlignment.CENTER)
+ .setMarginBottom(5));
+ generatePortraitLayout(document, boldFont, font);
+ }
+
+ document.close();
+ }
+
+ private Cell createHeaderBlock(PdfFont boldFont, PdfFont font) {
+ Cell headerContainer = new Cell().setBorder(Border.NO_BORDER).setPadding(0);
+ Table headerTable = new Table(UnitValue.createPercentArray(new float[]{0.3f, 0.7f}))
+ .setWidth(UnitValue.createPercentValue(100))
+ .setBorder(Border.NO_BORDER)
+ .setMarginBottom(2);
+ try {
+ String logoPath = "src/main/java/BsK/client/ui/assets/icon/clinic_logo.png";
+ Image logo = new Image(ImageDataFactory.create(logoPath)).scaleToFit(50, 50);
+ headerTable.addCell(new Cell().add(logo).setBorder(Border.NO_BORDER).setVerticalAlignment(VerticalAlignment.MIDDLE));
+ } catch (Exception e) {
+ headerTable.addCell(new Cell().setBorder(Border.NO_BORDER));
+ log.warn("Clinic logo not found", e);
+ }
+
+ Paragraph clinicInfo = new Paragraph()
+ .add(new Text(LocalStorage.ClinicName + "\n").setFont(boldFont).setFontSize(10))
+ .add(new Text("Địa chỉ: " + LocalStorage.ClinicAddress + "\n").setFontSize(8))
+ .add(new Text("Điện thoại: " + LocalStorage.ClinicPhone).setFontSize(8))
+ .setFont(font);
+ headerTable.addCell(new Cell().add(clinicInfo).setBorder(Border.NO_BORDER).setVerticalAlignment(VerticalAlignment.MIDDLE));
+
+ headerContainer.add(headerTable);
+ return headerContainer;
+ }
+
+ private void generateLandscapeLayout(Document document, PdfFont boldFont, PdfFont font, String title) throws Exception {
+ Table titleTable = new Table(UnitValue.createPercentArray(new float[]{1, 1}))
+ .setWidth(UnitValue.createPercentValue(100))
+ .setMarginBottom(2);
+
+ Paragraph titleParagraph = new Paragraph(title)
+ .setFont(boldFont).setFontSize(14)
+ .setTextAlignment(TextAlignment.CENTER)
+ .setMarginBottom(2);
+
+ Table mainTable = new Table(UnitValue.createPercentArray(new float[]{1.2f, 0.8f}))
+ .setWidth(UnitValue.createPercentValue(100))
+ .setMarginTop(0);
+
+ Cell leftCell = new Cell().setBorder(Border.NO_BORDER).setPadding(1).setVerticalAlignment(VerticalAlignment.TOP);
+
+ leftCell.add(createHeaderBlock(boldFont, font));
+
+ leftCell.add(new Paragraph(title)
+ .setFont(boldFont).setFontSize(14)
+ .setTextAlignment(TextAlignment.CENTER)
+ .setMarginBottom(2));
+
+ addPatientInfo(leftCell, boldFont, font, 8);
+ leftCell.add(new Paragraph("NỘI DUNG").setFont(boldFont).setFontSize(10).setMarginTop(2)
+ .setTextAlignment(TextAlignment.LEFT).setUnderline());
+
+ Image rtfImage = createRtfImage(this.rtfContent, PageSize.A4.rotate().getWidth() * 0.58f);
+ if (rtfImage != null) {
+ // Set maximum height to prevent page overflow - ensure single page layout
+ rtfImage.setMaxHeight(320); // Fixed max height to ensure single page
+ rtfImage.setAutoScale(false);
+ leftCell.add(rtfImage);
+ }
+
+ // Add conclusion and suggestion to left column
+ leftCell.add(new Paragraph("KẾT LUẬN").setFont(boldFont).setFontSize(10).setMarginTop(3)
+ .setTextAlignment(TextAlignment.LEFT).setUnderline());
+ leftCell.add(new Paragraph(this.conclusion).setFont(font).setFontSize(8));
+
+ leftCell.add(new Paragraph("ĐỀ NGHỊ").setFont(boldFont).setFontSize(10).setMarginTop(2)
+ .setTextAlignment(TextAlignment.LEFT).setUnderline());
+ leftCell.add(new Paragraph(this.suggestion).setFont(font).setFontSize(8));
+
+ Cell rightCell = new Cell().setBorder(Border.NO_BORDER).setPadding(1).setVerticalAlignment(VerticalAlignment.TOP);
+ rightCell.add(new Paragraph("HÌNH ẢNH SIÊU ÂM").setFont(boldFont).setFontSize(10)
+ .setTextAlignment(TextAlignment.LEFT).setUnderline().setMarginBottom(1));
+ Table imageTable = createImageTable(selectedImages);
+ rightCell.add(imageTable);
+
+ rightCell.add(createSignatureBlock(font, boldFont));
+
+ mainTable.addCell(leftCell);
+ mainTable.addCell(rightCell);
+ document.add(mainTable);
+ }
+
+ private void generatePortraitLayout(Document document, PdfFont boldFont, PdfFont font) throws Exception {
+ boolean multiPage = selectedImages.size() > 4;
+ addPatientInfo(document, boldFont, font, 8);
+
+ if (multiPage) {
+ Table contentTable = new Table(1).setWidth(UnitValue.createPercentValue(100));
+ Cell contentCell = new Cell().setBorder(Border.NO_BORDER).setPadding(0);
+
+ contentCell.add(new Paragraph("NỘI DUNG").setFont(boldFont).setFontSize(10).setMarginTop(5)
+ .setTextAlignment(TextAlignment.LEFT).setUnderline());
+ Image rtfImage = createRtfImage(this.rtfContent, PageSize.A4.getWidth() - 60);
+ if (rtfImage != null) {
+ contentCell.add(rtfImage);
+ }
+
+ contentCell.add(new Paragraph("KẾT LUẬN").setFont(boldFont).setFontSize(10).setMarginTop(5)
+ .setTextAlignment(TextAlignment.LEFT).setUnderline());
+ contentCell.add(new Paragraph(this.conclusion).setFont(font).setFontSize(8));
+ contentCell.add(new Paragraph("ĐỀ NGHỊ").setFont(boldFont).setFontSize(10).setMarginTop(5)
+ .setTextAlignment(TextAlignment.LEFT).setUnderline());
+ contentCell.add(new Paragraph(this.suggestion).setFont(font).setFontSize(8));
+
+ contentTable.addCell(contentCell);
+ document.add(contentTable);
+ addSignature(document, font, boldFont);
+
+ document.add(new AreaBreak());
+ addHeader(document, boldFont, font);
+ document.add(new Paragraph("HÌNH ẢNH SIÊU ÂM (tt)").setFont(boldFont).setFontSize(10)
+ .setTextAlignment(TextAlignment.LEFT).setUnderline());
+ Table imageTable = createImageTable(selectedImages);
+ document.add(imageTable);
+ } else {
+ Table mainTable = new Table(UnitValue.createPercentArray(new float[]{1.2f, 0.8f}))
+ .setWidth(UnitValue.createPercentValue(100))
+ .setMarginTop(5);
+
+ Cell leftCell = new Cell().setBorder(Border.NO_BORDER).setPaddingRight(5);
+ leftCell.add(new Paragraph("NỘI DUNG").setFont(boldFont).setFontSize(10)
+ .setTextAlignment(TextAlignment.LEFT).setUnderline());
+ Image rtfImage = createRtfImage(this.rtfContent, PageSize.A4.getWidth() * 0.55f - 40);
+ if (rtfImage != null) {
+ leftCell.add(rtfImage);
+ }
+
+ Cell rightCell = new Cell().setBorder(Border.NO_BORDER);
+ rightCell.add(new Paragraph("HÌNH ẢNH").setFont(boldFont).setFontSize(10)
+ .setTextAlignment(TextAlignment.LEFT).setUnderline());
+ Table imageTable = createImageTable(selectedImages);
+ rightCell.add(imageTable);
+
+ mainTable.addCell(leftCell);
+ mainTable.addCell(rightCell);
+ document.add(mainTable);
+
+ document.add(new Paragraph("KẾT LUẬN").setFont(boldFont).setFontSize(10).setMarginTop(5)
+ .setTextAlignment(TextAlignment.LEFT).setUnderline());
+ document.add(new Paragraph(this.conclusion).setFont(font).setFontSize(8));
+ document.add(new Paragraph("ĐỀ NGHỊ").setFont(boldFont).setFontSize(10).setMarginTop(5)
+ .setTextAlignment(TextAlignment.LEFT).setUnderline());
+ document.add(new Paragraph(this.suggestion).setFont(font).setFontSize(8));
+
+ addSignature(document, font, boldFont);
+ }
+ }
+
+ private Table createImageTable(List images) throws IOException {
+ int numImages = images.size();
+ int numCols = numImages == 1 ? 1 : 2;
+
+ Table imageTable = new Table(numCols)
+ .useAllAvailableWidth()
+ .setMarginTop(1).setMarginBottom(1);
+
+ for(File imgFile : images) {
+ Image img = new Image(ImageDataFactory.create(imgFile.getAbsolutePath()));
+
+ img.setAutoScale(true);
+ img.setMaxWidth(110f);
+ img.setMaxHeight(85f);
+
+ Cell imgCell = new Cell()
+ .add(img)
+ .setBorder(new SolidBorder(ColorConstants.GRAY, 0.5f))
+ .setPadding(1)
+ .setHorizontalAlignment(HorizontalAlignment.CENTER)
+ .setVerticalAlignment(VerticalAlignment.MIDDLE);
+ imageTable.addCell(imgCell);
+ }
+
+ int remainder = numImages % numCols;
+ if (remainder != 0 && numImages > 1) {
+ imageTable.addCell(new Cell().setBorder(Border.NO_BORDER));
+ }
+ return imageTable;
+ }
+
+ private Image createRtfImage(String rtf, float availableWidth) {
+ if (rtf == null || rtf.trim().isEmpty()) {
+ return null;
+ }
+ try {
+ JTextPane pane = new JTextPane();
+ pane.setEditorKit(new RTFEditorKit());
+ pane.setBackground(Color.WHITE);
+ pane.setOpaque(true);
+
+ pane.read(new ByteArrayInputStream(rtf.getBytes("ISO-8859-1")), null);
+
+ pane.setSize(new Dimension((int) availableWidth, Integer.MAX_VALUE));
+ Dimension prefSize = pane.getPreferredSize();
+ pane.setSize(prefSize);
+
+ int renderDPI = 240; // Further reduced DPI to make text appear even smaller
+ float scale = renderDPI / 72f;
+
+ int imgWidth = (int) (prefSize.width * scale);
+ int imgHeight = (int) (prefSize.height * scale);
+
+ if (imgWidth <= 0 || imgHeight <= 0) {
+ log.warn("Invalid image dimensions for RTF rendering: {}x{}", imgWidth, imgHeight);
+ return null;
+ }
+
+ BufferedImage img = new BufferedImage(imgWidth, imgHeight, BufferedImage.TYPE_INT_ARGB);
+ Graphics2D g2d = img.createGraphics();
+
+ g2d.scale(scale, scale);
+
+ g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
+ g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
+ g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
+
+ pane.paint(g2d);
+ g2d.dispose();
+
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ ImageIO.write(img, "png", baos);
+ Image itextImage = new Image(ImageDataFactory.create(baos.toByteArray()));
+
+ // Set width directly. The reduced DPI has already made the content smaller.
+ itextImage.setWidth(UnitValue.createPointValue(prefSize.width));
+
+ return itextImage;
+
+ } catch (Exception e) {
+ log.error("Failed to convert RTF to Image", e);
+ return null;
+ }
+ }
+
+ private void addHeader(Document document, PdfFont boldFont, PdfFont font) {
+ Table headerTable = new Table(UnitValue.createPercentArray(new float[]{1.2f, 3.8f, 2f}))
+ .setWidth(UnitValue.createPercentValue(100))
+ .setBorder(Border.NO_BORDER)
+ .setMarginBottom(5);
+ try {
+ String logoPath = "src/main/java/BsK/client/ui/assets/icon/clinic_logo.png";
+ Image logo = new Image(ImageDataFactory.create(logoPath)).scaleToFit(50, 50);
+ headerTable.addCell(new Cell().add(logo).setBorder(Border.NO_BORDER).setVerticalAlignment(VerticalAlignment.MIDDLE));
+ } catch (Exception e) {
+ headerTable.addCell(new Cell().setBorder(Border.NO_BORDER));
+ log.warn("Clinic logo not found", e);
+ }
+
+ Paragraph clinicInfo = new Paragraph()
+ .add(new Text(LocalStorage.ClinicName + "\n").setFont(boldFont).setFontSize(10))
+ .add(new Text("Địa chỉ: " + LocalStorage.ClinicAddress + "\n").setFontSize(8))
+ .add(new Text("Điện thoại: " + LocalStorage.ClinicPhone).setFontSize(8))
+ .setFont(font);
+ headerTable.addCell(new Cell().add(clinicInfo).setBorder(Border.NO_BORDER).setVerticalAlignment(VerticalAlignment.MIDDLE));
+
+ headerTable.addCell(new Cell().setBorder(Border.NO_BORDER));
+ document.add(headerTable);
+ }
+
+ private void addPatientInfo(Object container, PdfFont boldFont, PdfFont font, int fontSize) {
+ Table table = new Table(UnitValue.createPercentArray(new float[]{1,1}))
+ .setWidth(UnitValue.createPercentValue(100))
+ .setFontSize(fontSize).setFont(font)
+ .setBorder(new SolidBorder(ColorConstants.GRAY, 0.5f))
+ .setMarginBottom(1); // Reduced margin for compactness
+
+ Cell left = new Cell().setBorder(Border.NO_BORDER).setPadding(1);
+ left.add(new Paragraph().add(new Text("Họ tên: ").setFont(boldFont)).add(patientName));
+ left.add(new Paragraph().add(new Text("Năm sinh: ").setFont(boldFont)).add(patientDOB));
+ left.add(new Paragraph().add(new Text("Giới tính: ").setFont(boldFont)).add(patientGender));
+
+ Cell right = new Cell().setBorder(Border.NO_BORDER).setPadding(1);
+ right.add(new Paragraph().add(new Text("Địa chỉ: ").setFont(boldFont)).add(patientAddress));
+ right.add(new Paragraph().add(new Text("Ngày khám: ").setFont(boldFont)).add(checkupDate));
+ right.add(new Paragraph().add(new Text("Mã khám: ").setFont(boldFont)).add(checkupId));
+
+ table.addCell(left);
+ table.addCell(right);
+
+ if (container instanceof Document) {
+ ((Document) container).add(table);
+ } else if (container instanceof Cell) {
+ ((Cell) container).add(table);
+ }
+ }
+
+ private void addSignature(Document document, PdfFont font, PdfFont boldFont) {
+ Table signatureTable = new Table(UnitValue.createPercentArray(new float[]{1, 1}))
+ .setWidth(UnitValue.createPercentValue(100))
+ .setMarginTop(5);
+
+ signatureTable.addCell(new Cell().setBorder(Border.NO_BORDER)); // empty cell for alignment
+
+ Paragraph signParagraph = new Paragraph()
+ .add("Ngày " + checkupDate.substring(0,2) + " tháng " + checkupDate.substring(3,5) + " năm " + checkupDate.substring(6) + "\n")
+ .add(new Text("BÁC SĨ ĐIỀU TRỊ\n").setFont(boldFont))
+ .add(new Text("(Ký và ghi rõ họ tên)\n\n").setFontSize(9).setItalic()) // Reduced newlines for signature space
+ .add(doctorName)
+ .setTextAlignment(TextAlignment.CENTER)
+ .setFont(font).setFontSize(10);
+
+ signatureTable.addCell(new Cell().add(signParagraph).setBorder(Border.NO_BORDER));
+ document.add(signatureTable);
+ }
+
+ private void displayPdfInLabel(String pdfPath, JPanel pdfPanel) {
+ pdfPanel.removeAll();
+ pdfPanel.setLayout(new BoxLayout(pdfPanel, BoxLayout.Y_AXIS));
+
+ try (PDDocument document = PDDocument.load(new File(pdfPath))) {
+ PDFRenderer pdfRenderer = new PDFRenderer(document);
+ float scale = 0.6f;
+ for (int i = 0; i < document.getNumberOfPages(); i++) {
+ BufferedImage image = pdfRenderer.renderImageWithDPI(i, 120);
+ int newWidth = (int) (image.getWidth() * scale);
+ int newHeight = (int) (image.getHeight() * scale);
+ ImageIcon icon = new ImageIcon(image.getScaledInstance(newWidth, newHeight, java.awt.Image.SCALE_SMOOTH));
+ JLabel pageLabel = new JLabel(icon);
+ pageLabel.setAlignmentX(Component.CENTER_ALIGNMENT);
+ pageLabel.setBorder(BorderFactory.createEmptyBorder(5, 0, 5, 0));
+ pdfPanel.add(pageLabel);
+ }
+ } catch (IOException e) {
+ log.error("Error displaying PDF", e);
+ pdfPanel.add(new JLabel("Lỗi khi hiển thị PDF: " + e.getMessage()));
+ }
+ pdfPanel.revalidate();
+ pdfPanel.repaint();
+ }
+
+ private void savePdf() {
+ JFileChooser fileChooser = new JFileChooser();
+ fileChooser.setDialogTitle("Lưu file PDF");
+ fileChooser.setSelectedFile(new File("ultrasound_" + checkupId + ".pdf"));
+ int userSelection = fileChooser.showSaveDialog(dialog);
+ if (userSelection == JFileChooser.APPROVE_OPTION) {
+ File fileToSave = fileChooser.getSelectedFile();
+ try {
+ generatePdf(fileToSave.getAbsolutePath());
+ JOptionPane.showMessageDialog(dialog, "PDF đã được lưu: " + fileToSave.getAbsolutePath());
+ } catch (Exception ex) {
+ log.error("Error saving PDF", ex);
+ JOptionPane.showMessageDialog(dialog, "Lỗi khi lưu PDF: " + ex.getMessage(), "Lỗi", JOptionPane.ERROR_MESSAGE);
+ }
+ }
+ }
+
+ private void printPdf() {
+ File pdfFile = new File(PDF_PATH);
+ try (PDDocument document = PDDocument.load(pdfFile)) {
+ PrinterJob printerJob = PrinterJob.getPrinterJob();
+ printerJob.setJobName("In kết quả siêu âm - " + patientName);
+
+ if (printerJob.printDialog()) {
+ printerJob.setPrintable(new Printable() {
+ @Override
+ public int print(Graphics graphics, PageFormat pageFormat, int pageIndex) throws PrinterException {
+ if (pageIndex >= document.getNumberOfPages()) {
+ return NO_SUCH_PAGE;
+ }
+ try {
+ PDFRenderer pdfRenderer = new PDFRenderer(document);
+ BufferedImage pageImage = pdfRenderer.renderImageWithDPI(pageIndex, 300);
+
+ Graphics2D g2d = (Graphics2D) graphics;
+ g2d.translate(pageFormat.getImageableX(), pageFormat.getImageableY());
+
+ double scale = Math.min(pageFormat.getImageableWidth() / pageImage.getWidth(), pageFormat.getImageableHeight() / pageImage.getHeight());
+ g2d.drawImage(pageImage, 0, 0, (int) (pageImage.getWidth() * scale), (int) (pageImage.getHeight() * scale), null);
+
+ return PAGE_EXISTS;
+ } catch (IOException e) {
+ log.error("Error rendering page for printing", e);
+ throw new PrinterException(e.getMessage());
+ }
+ }
+ });
+ printerJob.print();
+ }
+ } catch (Exception e) {
+ log.error("Error printing PDF", e);
+ JOptionPane.showMessageDialog(dialog, "Lỗi khi in PDF: " + e.getMessage(), "Lỗi", JOptionPane.ERROR_MESSAGE);
+ }
+ }
+
+ private Table createSignatureBlock(PdfFont font, PdfFont boldFont) {
+ Table signatureTable = new Table(UnitValue.createPercentArray(new float[]{1, 1}))
+ .setWidth(UnitValue.createPercentValue(100))
+ .setMarginTop(2); // Reduced margin for compactness
+
+ signatureTable.addCell(new Cell().setBorder(Border.NO_BORDER)); // empty cell for alignment
+
+ Paragraph signParagraph = new Paragraph()
+ .add("Ngày " + checkupDate.substring(0,2) + " tháng " + checkupDate.substring(3,5) + " năm " + checkupDate.substring(6) + "\n")
+ .add(new Text("BÁC SĨ ĐIỀU TRỊ\n").setFont(boldFont))
+ .add(new Text("(Ký và ghi rõ họ tên)\n\n").setFontSize(9).setItalic()) // Reduced newlines for signature space
+ .add(doctorName)
+ .setTextAlignment(TextAlignment.CENTER)
+ .setFont(font).setFontSize(10);
+
+ signatureTable.addCell(new Cell().add(signParagraph).setBorder(Border.NO_BORDER));
+ return signatureTable;
+ }
+
+
+}
\ No newline at end of file
diff --git a/src/main/java/BsK/client/ui/component/CheckUpPage/PrintDialog/print_forms/InvoiceItem.java b/src/main/java/BsK/client/ui/component/CheckUpPage/PrintDialog/print_forms/InvoiceItem.java
new file mode 100644
index 0000000..aa0898f
--- /dev/null
+++ b/src/main/java/BsK/client/ui/component/CheckUpPage/PrintDialog/print_forms/InvoiceItem.java
@@ -0,0 +1,86 @@
+package BsK.client.ui.component.CheckUpPage.PrintDialog.print_forms;
+
+/**
+ * Represents a single item on the invoice, which can be a medicine, a service, or a supplement.
+ * This class matches the fields defined in the 'med_pre' dataset in the JRXML.
+ */
+public class InvoiceItem {
+ // --- Common Fields ---
+ private String type; // "MED", "SER", "SUP"
+
+ // --- Medicine Fields ---
+ private String medName;
+ private String dosage;
+ private Integer amount;
+ private Double unitPrice;
+ private String medNote;
+
+ // --- Service Fields ---
+ private String serName;
+ private String serNote;
+ private Double serUnitPrice;
+ private Integer serAmount;
+
+ // --- Supplement Fields ---
+ private String supName;
+ private String supNote;
+ private String supDosage;
+ private Integer supAmount;
+ private Double supUnitPrice;
+
+ // Private constructor to be used by factory methods
+ private InvoiceItem() {}
+
+ // --- Factory Methods ---
+
+ public static InvoiceItem createMedicine(String medName, String dosage, Integer amount, Double unitPrice, String medNote) {
+ InvoiceItem item = new InvoiceItem();
+ item.type = "MED";
+ item.medName = medName;
+ item.dosage = dosage;
+ item.amount = amount;
+ item.unitPrice = unitPrice;
+ item.medNote = medNote;
+ return item;
+ }
+
+ public static InvoiceItem createService(String serName, String serNote, Integer serAmount, Double serUnitPrice) {
+ InvoiceItem item = new InvoiceItem();
+ item.type = "SER";
+ item.serName = serName;
+ item.serNote = serNote;
+ item.serAmount = serAmount;
+ item.serUnitPrice = serUnitPrice;
+ return item;
+ }
+
+ public static InvoiceItem createSupplement(String supName, String supNote, String supDosage, Integer supAmount, Double supUnitPrice) {
+ InvoiceItem item = new InvoiceItem();
+ item.type = "SUP";
+ item.supName = supName;
+ item.supNote = supNote;
+ item.supDosage = supDosage;
+ item.supAmount = supAmount;
+ item.supUnitPrice = supUnitPrice;
+ return item;
+ }
+
+
+ // --- Getters ---
+
+ public String getType() { return type; }
+ public String getMedName() { return medName; }
+ public String getDosage() { return dosage; }
+ public Integer getAmount() { return amount; }
+ public Double getUnitPrice() { return unitPrice; }
+ public String getMedNote() { return medNote; }
+ public String getSerName() { return serName; }
+ public String getSerNote() { return serNote; }
+ public Double getSerUnitPrice() { return serUnitPrice; }
+ public Integer getSerAmount() { return serAmount; }
+ public String getSupName() { return supName; }
+ public String getSupNote() { return supNote; }
+ public String getSupDosage() { return supDosage; }
+ public Integer getSupAmount() { return supAmount; }
+ public Double getSupUnitPrice() { return supUnitPrice; }
+}
\ No newline at end of file
diff --git a/src/main/java/BsK/client/ui/component/CheckUpPage/PrintDialog/print_forms/medserinvoice.jrxml b/src/main/java/BsK/client/ui/component/CheckUpPage/PrintDialog/print_forms/medserinvoice.jrxml
new file mode 100644
index 0000000..669c1f0
--- /dev/null
+++ b/src/main/java/BsK/client/ui/component/CheckUpPage/PrintDialog/print_forms/medserinvoice.jrxml
@@ -0,0 +1,854 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/main/java/BsK/client/ui/component/CheckUpPage/PrintDialog/print_forms/test_print.java b/src/main/java/BsK/client/ui/component/CheckUpPage/PrintDialog/print_forms/test_print.java
new file mode 100644
index 0000000..f2dcee2
--- /dev/null
+++ b/src/main/java/BsK/client/ui/component/CheckUpPage/PrintDialog/print_forms/test_print.java
@@ -0,0 +1,94 @@
+package BsK.client.ui.component.CheckUpPage.PrintDialog.print_forms;
+
+import net.sf.jasperreports.engine.JREmptyDataSource;
+import net.sf.jasperreports.engine.JRException;
+import net.sf.jasperreports.engine.JasperReport;
+import net.sf.jasperreports.engine.xml.JRXmlLoader;
+import net.sf.jasperreports.engine.data.JRBeanCollectionDataSource;
+import net.sf.jasperreports.engine.design.JasperDesign;
+import net.sf.jasperreports.engine.JasperCompileManager;
+import net.sf.jasperreports.engine.JasperFillManager;
+import net.sf.jasperreports.engine.JasperPrint;
+import net.sf.jasperreports.view.JasperViewer;
+import net.sf.jasperreports.engine.JasperExportManager;
+import net.sf.jasperreports.engine.JRParameter;
+
+import java.io.FileNotFoundException;
+import java.io.InputStream;
+import java.io.FileInputStream;
+import java.io.File;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Map;
+import java.util.HashMap;
+import java.util.Locale;
+import java.util.stream.Collectors;
+
+
+public class test_print {
+ public static void main(String[] args) {
+ try {
+ // 1. Create a master list with all item types
+ List allItems = new ArrayList<>();
+ // Medicines
+ allItems.add(InvoiceItem.createMedicine("Paracetamol", "2 viên/lần, 3 lần/ngày", 10, 10000.0, "Uống sau ăn"));
+ allItems.add(InvoiceItem.createMedicine("Amoxicillin", "1 viên/lần, 2 lần/ngày", 20, 5000.0, "Uống trước ăn 30 phút"));
+ // Services
+ allItems.add(InvoiceItem.createService("Khám tổng quát", "Kiểm tra sức khoẻ định kỳ", 1, 200000.0));
+ allItems.add(InvoiceItem.createService("Siêu âm ổ bụng", "", 1, 150000.0));
+
+ // Supplements
+ allItems.add(InvoiceItem.createSupplement("Vitamin C", "Uống sau ăn sáng", "1 viên/lần, 1 lần/ngày", 30, 2000.0));
+ allItems.add(InvoiceItem.createSupplement("Vitamin C", "Uống sau ăn sáng", "1 viên/lần, 1 lần/ngày", 30, 2000.0));
+ // 2. Filter the master list into separate lists for each type
+ List medicines = allItems.stream().filter(item -> "MED".equals(item.getType())).collect(Collectors.toList());
+ List services = allItems.stream().filter(item -> "SER".equals(item.getType())).collect(Collectors.toList());
+ List supplements = allItems.stream().filter(item -> "SUP".equals(item.getType())).collect(Collectors.toList());
+
+ // 3. Create a JRBeanCollectionDataSource for each list
+ JRBeanCollectionDataSource medicineDS = new JRBeanCollectionDataSource(medicines);
+ JRBeanCollectionDataSource serviceDS = new JRBeanCollectionDataSource(services);
+ JRBeanCollectionDataSource supplementDS = new JRBeanCollectionDataSource(supplements);
+
+
+ // 4. Put the data sources into the parameters map
+ Map parameters = new HashMap();
+ parameters.put("medicineDS", medicineDS);
+ parameters.put("serviceDS", serviceDS);
+ parameters.put("supplementDS", supplementDS);
+
+ // Set locale to Vietnamese for number formatting
+ parameters.put(JRParameter.REPORT_LOCALE, new Locale("vi", "VN"));
+
+ // Sample data parameters
+ parameters.put("name", "John Doe");
+ parameters.put("clinicName", " BSK CLINIC");
+ parameters.put("clinicPhone", "0123-456-789");
+ parameters.put("patientName", "Nguyen Van A");
+ parameters.put("clinicAddress", "123 Main Street, City, Country");
+
+ // Add logo image path
+ String logoPath = System.getProperty("user.dir") + "/src/main/java/BsK/client/ui/assets/icon/logo.jpg";
+ parameters.put("logoImage", logoPath);
+
+ // Add barcode number
+ parameters.put("barcodeNumber", "2024001234");
+
+ // Use relative path for jrxml file
+ String jrxmlPath = System.getProperty("user.dir") + "/src/main/java/BsK/client/ui/component/CheckUpPage/PrintDialog/print_forms/medserinvoice.jrxml";
+ InputStream inputStream = new FileInputStream(new File(jrxmlPath));
+
+ JasperDesign jasperDesign = JRXmlLoader.load(inputStream);
+ JasperReport jasperReport = JasperCompileManager.compileReport(jasperDesign);
+
+ JasperPrint jasperPrint = JasperFillManager.fillReport(jasperReport, parameters, new JREmptyDataSource());
+
+ // view the report
+ JasperViewer.viewReport(jasperPrint);
+
+ //JasperExportManager.exportReportToPdfFile(jasperPrint, "D:\\Github Clones\\BSK-All-in-One-Clinic-Management-System\\src\\main\\resources\\print_forms\\medserinvoice.pdf");
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+}
diff --git a/src/main/resources/database/BSK.db b/src/main/resources/database/BSK.db
index 215b3df..da950b5 100644
Binary files a/src/main/resources/database/BSK.db and b/src/main/resources/database/BSK.db differ
diff --git a/ultrasound_result.pdf b/ultrasound_result.pdf
new file mode 100644
index 0000000..1f8acde
Binary files /dev/null and b/ultrasound_result.pdf differ