[update] Enhance medical invoice generation and management. Add route of administration field in MedicineManagementPanel and MedicineDialog. Update PDF templates to include clinic prefix and improve layout. Refactor data handling in ServerHandler and Client for better integration of new fields. Remove unused report templates to streamline resources.

This commit is contained in:
Lê Thành Đạt committed 2025-08-02 04:23:20 +07:00
1 parent e246ed18ea
commit e87da4bc27
28 files changed
+677 -1221

No files matched your search

+1 -1
View File
@@ -1,4 +1,4 @@
{
"java.configuration.updateBuildConfiguration": "interactive",
"java.configuration.updateBuildConfiguration": "automatic",
"java.debug.settings.onBuildFailureProceed": true
}
+1
View File
@@ -9,3 +9,4 @@ server.address=127.0.0.1
server.port=1999
storage.checkup_media_base_dir=src/main/resources/image/checkup_media
storage.image_db_path=img_db
app.project_path=D:/Github Clones/BSK-All-in-One-Clinic-Management-System
Binary file not shown.
+5
View File
@@ -316,5 +316,10 @@
<artifactId>poi-ooxml</artifactId>
<version>5.2.5</version>
</dependency>
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
<version>5.1.0</version>
</dependency>
</dependencies>
</project>
+9
View File
@@ -136,6 +136,15 @@ public class Client {
log.info("Using default auto change status: {}", LocalStorage.autoChangeStatusToFinished);
}
//load projectPath
String projectPath = config.getProperty("app.project_path");
if (projectPath != null && !projectPath.trim().isEmpty()) {
LocalStorage.pathToProject = projectPath.trim();
log.info("Using configured project path: {}", projectPath);
} else {
log.info("Using default project path: {}", LocalStorage.pathToProject);
}
// Use defaults if not configured
if (portStr != null) {
int port = Integer.parseInt(portStr);
+4 -1
View File
@@ -22,8 +22,11 @@ public class LocalStorage {
public static String ClinicName = "Phòng khám BSK";
public static String ClinicAddress = "Số ABC, Đường XYZ, Quận 1, TP.HCM";
public static String ClinicPhone = "0123456789";
public static String ClinicPrefix = "BSK";
public static List<String> chatHistory = new ArrayList<>();
public static String pathToProject = "";
public static String dataDialogSearchTerm = "";
public static Date dataDialogFromDate = new Date(); // Default to today
public static Date dataDialogToDate = new Date(); // Default to today
@@ -66,6 +66,7 @@ public class ClientHandler extends SimpleChannelInboundHandler<TextWebSocketFram
LocalStorage.ClinicName = clinicInfoResponse.getClinicName();
LocalStorage.ClinicAddress = clinicInfoResponse.getClinicAddress();
LocalStorage.ClinicPhone = clinicInfoResponse.getClinicPhone();
LocalStorage.ClinicPrefix = clinicInfoResponse.getClinicPrefix();
return;
}
@@ -29,6 +29,7 @@ import java.text.DecimalFormat;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.concurrent.CompletableFuture;
import java.io.IOException;
public class MedicineInvoice{
@@ -44,10 +45,9 @@ public class MedicineInvoice{
private String date;
private String id;
private String driveURL;
private String[][] med; // Name, Quantity, Price
private String[][] services; // Name, Quantity, Price
private String[][] supplements; // Name, Quantity, Price
private static final DecimalFormat vndFormatter = new DecimalFormat("#,##0");
private String[][] med; // Prescription data for medicines
private String[][] services; // Prescription data for services
private String[][] supplements; // Prescription data for supplements
public CompletableFuture<byte[]> generatePdfBytesAsync() {
return CompletableFuture.supplyAsync(() -> {
@@ -62,105 +62,9 @@ public class MedicineInvoice{
});
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
JFrame frame = new JFrame("Medicine Invoice Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(600, 400);
frame.setLayout(new GridLayout(3, 2, 10, 10));
// Test Case 1: Only Medicines
JButton medicineOnlyButton = new JButton("Only Medicines");
medicineOnlyButton.addActionListener(e -> new MedicineInvoice("1001", "Nguyễn Văn A", "01/01/1990", "0123456789",
"Nam", "123 Đường ABC, Quận XYZ, TP HCM", "Bác sĩ XYZ", "Sốt cao",
"Nghỉ ngơi nhiều, uống nhiều nước", "https://example.com/drive1",
new String[][]{
{"1", "Paracetamol", "2 viên", "viên", "1", "2", "1", "5000", "10000", "Uống sau ăn"}
},
new String[][]{}, // No services
new String[][]{} // No supplements
).createDialog(frame));
// Test Case 2: Only Services
JButton serviceOnlyButton = new JButton("Only Services");
serviceOnlyButton.addActionListener(e -> new MedicineInvoice("1002", "Trần Thị B", "15/05/1985", "0987654321",
"Nữ", "456 Đường DEF, Quận ABC, TP HCM", "Bác sĩ ABC", "Khám tổng quát",
"Theo dõi định kỳ", "https://example.com/drive2",
new String[][]{}, // No medicines
new String[][] {
{"1", "Khám tổng quát", "1", "150000", "150000", "Kiểm tra sức khỏe tổng quát"},
{"2", "Xét nghiệm máu", "1", "80000", "80000", "Xét nghiệm công thức máu"}
},
new String[][]{} // No supplements
).createDialog(frame));
// Test Case 3: Only Supplements
JButton supplementOnlyButton = new JButton("Only Supplements");
supplementOnlyButton.addActionListener(e -> new MedicineInvoice("1003", "Lê Văn C", "20/12/1992", "0456789123",
"Nam", "789 Đường GHI, Quận DEF, TP HCM", "Bác sĩ DEF", "Tư vấn dinh dưỡng",
"Bổ sung vitamin và khoáng chất", "https://example.com/drive3",
new String[][]{}, // No medicines
new String[][]{}, // No services
new String[][] {
{"1", "Vitamin D3", "1", "viên", "1 viên/ngày sau ăn sáng", "30 viên", "2000", "60000", "Bổ sung vitamin D"},
{"2", "Omega 3", "2", "viên", "2 viên/ngày sau ăn", "60 viên", "1500", "90000", "Bổ sung dầu cá"}
}
).createDialog(frame));
// Test Case 4: Medicines + Services (No Supplements)
JButton medServiceButton = new JButton("Medicines + Services");
medServiceButton.addActionListener(e -> new MedicineInvoice("1004", "Phạm Thị D", "10/03/1988", "0789123456",
"Nữ", "321 Đường JKL, Quận GHI, TP HCM", "Bác sĩ GHI", "Viêm họng",
"Điều trị kháng sinh và theo dõi", "https://example.com/drive4",
new String[][]{
{"1", "Amoxicillin", "1 vỉ", "viên", "1", "1", "0", "20000", "20000", "Uống trước ăn 30 phút"}
},
new String[][] {
{"1", "Khám tai mũi họng", "1", "100000", "100000", "Khám chuyên khoa"}
},
new String[][]{} // No supplements
).createDialog(frame));
// Test Case 5: All Three Categories
JButton allCategoriesButton = new JButton("All Categories");
allCategoriesButton.addActionListener(e -> new MedicineInvoice("1005", "Hoàng Văn E", "25/07/1990", "0654321987",
"Nam", "654 Đường MNO, Quận JKL, TP HCM", "Bác sĩ JKL", "Kiểm tra sức khỏe định kỳ",
"Tổng quát + bổ sung dinh dưỡng", "https://example.com/drive5",
new String[][]{
{"1", "Vitamin C", "1 hộp", "viên", "1", "0", "0", "10000", "10000", "Uống buổi sáng"}
},
new String[][] {
{"1", "Khám tổng quát", "1", "150000", "150000", "Kiểm tra sức khỏe tổng quát"}
},
new String[][] {
{"1", "Calcium 500mg", "1 lọ", "viên", "1 viên/ngày sau ăn tối", "30 viên", "2500", "75000", "Bổ sung canxi"}
}
).createDialog(frame));
// Test Case 6: Empty Invoice (No data)
JButton emptyButton = new JButton("Empty Invoice");
emptyButton.addActionListener(e -> new MedicineInvoice("1006", "Võ Thị F", "05/11/1995", "0321654987",
"Nữ", "987 Đường PQR, Quận MNO, TP HCM", "Bác sĩ MNO", "Tư vấn y tế",
"Chỉ tư vấn, không kê đơn", null,
new String[][]{}, // No medicines
new String[][]{}, // No services
new String[][]{} // No supplements
).createDialog(frame));
frame.add(medicineOnlyButton);
frame.add(serviceOnlyButton);
frame.add(supplementOnlyButton);
frame.add(medServiceButton);
frame.add(allCategoriesButton);
frame.add(emptyButton);
frame.setVisible(true);
});
}
public MedicineInvoice(String id, String patientName, String patientDOB, String patientPhone,
String patientGender, String patientAddress, String doctorName, String diagnosis,
String notes, String driveURL, String[][] med, String[][] services, String[][] supplements) {
String patientGender, String patientAddress, String doctorName, String diagnosis,
String notes, String driveURL, String[][] med, String[][] services, String[][] supplements) {
this.id = id;
this.patientName = patientName;
this.patientDOB = patientDOB;
@@ -185,13 +89,15 @@ public class MedicineInvoice{
}
private JasperPrint jasperPrint; // Store JasperPrint for reuse
/**
* Shows the invoice directly in JasperViewer without creating a custom dialog
*/
public void showDirectJasperViewer() {
try {
String pdfPath = "medical_invoice.pdf";
generatePdf(pdfPath);
// This method now only fills the report and shows the viewer
fillJasperPrint();
// Use the constructor to prevent the application from closing
JasperViewer viewer = new JasperViewer(jasperPrint, false);
viewer.setVisible(true);
@@ -241,7 +147,7 @@ public class MedicineInvoice{
dialog.add(scrollPane, BorderLayout.CENTER);
dialog.add(buttonPanel, BorderLayout.SOUTH);
String pdfPath = "medical_invoice.pdf";
String pdfPath = "temp_medical_invoice.pdf"; // Use a temporary file name
try {
generatePdf(pdfPath);
displayPdfInLabel(pdfPath, pdfViewer);
@@ -255,21 +161,20 @@ public class MedicineInvoice{
try {
JFileChooser fileChooser = new JFileChooser();
fileChooser.setDialogTitle("Save PDF As");
fileChooser.setSelectedFile(new File("medical_invoice.pdf"));
// Suggest a file name based on patient name and date
fileChooser.setSelectedFile(new File(patientName.replace(" ", "_") + "_invoice_" + date.replace("/", "-") + ".pdf"));
int userSelection = fileChooser.showSaveDialog(dialog);
if (userSelection == JFileChooser.APPROVE_OPTION) {
File fileToSave = fileChooser.getSelectedFile();
File generatedFile = new File(pdfPath);
try (InputStream in = new FileInputStream(generatedFile);
OutputStream out = new FileOutputStream(fileToSave)) {
byte[] buffer = new byte[1024];
int bytesRead;
while ((bytesRead = in.read(buffer)) != -1) {
out.write(buffer, 0, bytesRead);
}
JOptionPane.showMessageDialog(dialog, "PDF saved: " + fileToSave.getAbsolutePath());
// Ensure the file has a .pdf extension
if (!fileToSave.getName().toLowerCase().endsWith(".pdf")) {
fileToSave = new File(fileToSave.getAbsolutePath() + ".pdf");
}
// Export the already generated JasperPrint object to the chosen file
JasperExportManager.exportReportToPdfFile(jasperPrint, fileToSave.getAbsolutePath());
JOptionPane.showMessageDialog(dialog, "PDF saved: " + fileToSave.getAbsolutePath());
}
} catch (Exception ex) {
ex.printStackTrace();
@@ -300,8 +205,6 @@ public class MedicineInvoice{
dialog.setVisible(true);
}
private JasperPrint jasperPrint; // Store JasperPrint for reuse
private byte[] generatePdfBytes() throws Exception {
try {
// This method is almost identical to generatePdf, but exports to a byte array
@@ -329,181 +232,129 @@ public class MedicineInvoice{
* Common method to fill the JasperPrint object with data and parameters.
* This avoids code duplication between generating a file and a byte array.
*/
private void fillJasperPrint() throws JRException, FileNotFoundException {
// Only fill if it hasn't been filled already
private void fillJasperPrint() throws JRException, IOException {
if (jasperPrint != null) {
return;
}
// 1. Create data sources for medicines, services, and supplements
java.util.List<InvoiceItem> medicines = new ArrayList<>();
java.util.List<InvoiceItem> serviceItems = new ArrayList<>();
java.util.List<InvoiceItem> supplementItems = new ArrayList<>();
// Convert medicine data to InvoiceItem objects
java.util.List<InvoiceItem> medicineItems = new ArrayList<>();
java.util.List<InvoiceItem> serviceItems = new ArrayList<>();
java.util.List<InvoiceItem> supplementItems = new ArrayList<>();
if (med != null) {
for (String[] medicine : med) {
if (medicine != null && medicine.length >= 10) {
try {
String dosageInfo = String.format("S: %s, T: %s, C: %s",
medicine[4] != null ? medicine[4] : "0",
medicine[5] != null ? medicine[5] : "0",
medicine[6] != null ? medicine[6] : "0");
String amount = medicine[2] + " " + medicine[3];
medicines.add(InvoiceItem.createMedicine(
medicine[1] != null ? medicine[1] : "", // medName
dosageInfo, // dosage
amount // amount
));
} catch (NumberFormatException e) {
System.err.println("Error parsing medicine data: " + e.getMessage());
}
if (medicine != null && medicine.length >= 12) {
try {
String medName = medicine[1];
String amount = medicine[2] + " " + medicine[3];
String dosageInfo = String.format("S: %s, T: %s, C: %s", medicine[4], medicine[5], medicine[6]);
String note = medicine[9];
String route = medicine[11];
// Call signature: (Tên, Ghi chú, Liều dùng, Đường dùng, Số lượng)
medicineItems.add(InvoiceItem.createMedicine(medName, note, dosageInfo, route, amount));
} catch (Exception e) {
System.err.println("Error parsing medicine data row: " + java.util.Arrays.toString(medicine) + " | Error: " + e.getMessage());
}
}
}
}
// Convert service data to InvoiceItem objects
if (services != null) {
if (services != null) {
for (String[] service : services) {
if (service != null && service.length >= 5) {
try {
serviceItems.add(InvoiceItem.createService(
service[1] != null ? service[1] : "", // serName
service.length > 5 && service[5] != null ? service[5] : "", // serNote
service[2] != null ? Integer.parseInt(service[2]) : 0, // serAmount
service[3] != null ? Double.parseDouble(service[3]) : 0.0 // serUnitPrice
));
} catch (NumberFormatException e) {
System.err.println("Error parsing service data: " + e.getMessage());
}
if (service != null && service.length >= 5) {
try {
serviceItems.add(InvoiceItem.createService(
service[1],
service.length > 5 ? service[5] : "",
Integer.parseInt(service[2]),
Double.parseDouble(service[3])
));
} catch (NumberFormatException e) {
System.err.println("Error parsing service data: " + e.getMessage());
}
}
}
}
// Convert supplement data to InvoiceItem objects
if (supplements != null) {
for (String[] supplement : supplements) {
if (supplement != null && supplement.length >= 10) {
try {
String dosageInfo = String.format("S: %s, T: %s, C: %s",
supplement[4] != null ? supplement[4] : "0",
supplement[5] != null ? supplement[5] : "0",
supplement[6] != null ? supplement[6] : "0");
String amount = supplement[2] + " " + supplement[3]; // Quantity + Unit
supplementItems.add(InvoiceItem.createSupplement(
supplement[1] != null ? supplement[1] : "", // supName
supplement[9] != null ? supplement[9] : "", // supNote
dosageInfo, // supDosage
amount, // supAmount
0.0 // supUnitPrice, since it's not displayed for supplements
));
} catch (Exception e) {
System.err.println("Error parsing supplement data: " + e.getMessage());
}
if (supplements != null) {
for (String[] supplement : supplements) {
if (supplement != null && supplement.length >= 12) {
try {
String supName = supplement[1];
String amount = supplement[2] + " " + supplement[3];
String dosageInfo = String.format("S: %s, T: %s, C: %s", supplement[4], supplement[5], supplement[6]);
String supNote = supplement[9];
String supRoute = supplement[11];
// --- CORRECTED THIS LINE ---
// Swapped 'amount' and 'supRoute' to match the method signature in InvoiceItem.java
// Call signature: (Tên, Ghi chú, Liều dùng, Số lượng, Đường dùng)
supplementItems.add(InvoiceItem.createSupplement(supName, supNote, dosageInfo, amount, supRoute));
} catch (Exception e) {
System.err.println("Error parsing supplement data row: " + java.util.Arrays.toString(supplement) + " | Error: " + e.getMessage());
}
}
}
}
// Create data sources
JRBeanCollectionDataSource medicineDS = new JRBeanCollectionDataSource(medicines);
JRBeanCollectionDataSource serviceDS = new JRBeanCollectionDataSource(serviceItems);
JRBeanCollectionDataSource supplementDS = new JRBeanCollectionDataSource(supplementItems);
JRBeanCollectionDataSource medicineDS = new JRBeanCollectionDataSource(medicineItems);
JRBeanCollectionDataSource serviceDS = new JRBeanCollectionDataSource(serviceItems);
JRBeanCollectionDataSource supplementDS = new JRBeanCollectionDataSource(supplementItems);
// 2. Create parameters map
java.util.Map<String, Object> parameters = new java.util.HashMap<>();
// Data sources
parameters.put("medicineDS", medicineDS);
parameters.put("serviceDS", serviceDS);
parameters.put("supplementDS", supplementDS);
java.util.Map<String, Object> parameters = new java.util.HashMap<>();
parameters.put("medicineDS", medicineDS);
parameters.put("serviceDS", serviceDS);
parameters.put("supplementDS", supplementDS);
parameters.put(JRParameter.REPORT_LOCALE, new java.util.Locale("vi", "VN"));
parameters.put("patientName", patientName != null ? patientName : "");
parameters.put("patientDOB", patientDOB != null ? patientDOB : "");
parameters.put("patientGender", patientGender != null ? patientGender : "");
parameters.put("patientAddress", patientAddress != null ? patientAddress : "");
parameters.put("clinicPrefix", LocalStorage.ClinicPrefix != null ? LocalStorage.ClinicPrefix : "");
parameters.put("clinicName", LocalStorage.ClinicName != null ? LocalStorage.ClinicName : "");
parameters.put("clinicPhone", LocalStorage.ClinicPhone != null ? LocalStorage.ClinicPhone : "");
parameters.put("clinicAddress", LocalStorage.ClinicAddress != null ? LocalStorage.ClinicAddress : "");
parameters.put("doctorName", doctorName != null ? doctorName : "");
parameters.put("checkupDate", date != null ? date : "");
parameters.put("patientDiagnos", diagnosis != null ? diagnosis : "");
parameters.put("checkupNote", notes != null ? notes : "");
parameters.put("barcodeNumber", id != null ? id : "");
parameters.put("driveURL", driveURL != null ? driveURL : "");
parameters.put("logoImage", LocalStorage.pathToProject + "/src/main/java/BsK/client/ui/assets/icon/logo.jpg");
parameters.put("hasMedicines", !medicineItems.isEmpty());
parameters.put("hasServices", !serviceItems.isEmpty());
parameters.put("hasSupplements", !supplementItems.isEmpty());
// Set locale for Vietnamese formatting
parameters.put(JRParameter.REPORT_LOCALE, new java.util.Locale("vi", "VN"));
// Patient information
parameters.put("patientName", patientName != null ? patientName : "");
parameters.put("patientDOB", patientDOB != null ? patientDOB : "");
parameters.put("patientGender", patientGender != null ? patientGender : "");
parameters.put("patientAddress", patientAddress != null ? patientAddress : "");
// Clinic information
parameters.put("clinicName", LocalStorage.ClinicName != null ? LocalStorage.ClinicName : "");
parameters.put("clinicPhone", LocalStorage.ClinicPhone != null ? LocalStorage.ClinicPhone : "");
parameters.put("clinicAddress", LocalStorage.ClinicAddress != null ? LocalStorage.ClinicAddress : "");
// Doctor and medical information
parameters.put("doctorName", doctorName != null ? doctorName : "");
parameters.put("checkupDate", date != null ? date : "");
parameters.put("patientDiagnos", diagnosis != null ? diagnosis : "");
parameters.put("checkupNote", notes != null ? notes : "");
// Barcode
parameters.put("barcodeNumber", id != null ? id : "");
// Drive URL for QR Code
parameters.put("driveURL", driveURL != null ? driveURL : "");
// Logo image path
String logoPath = System.getProperty("user.dir") + "/src/main/java/BsK/client/ui/assets/icon/logo.jpg";
parameters.put("logoImage", logoPath);
// Add conditional parameters to check if data sources have data
parameters.put("hasMedicines", medicines != null && !medicines.isEmpty());
parameters.put("hasServices", serviceItems != null && !serviceItems.isEmpty());
parameters.put("hasSupplements", supplementItems != null && !supplementItems.isEmpty());
// 3. Load and compile the JRXML template
String jrxmlPath = System.getProperty("user.dir") + "/src/main/java/BsK/client/ui/component/CheckUpPage/PrintDialog/print_forms/medserinvoice.jrxml";
java.io.InputStream inputStream = new java.io.FileInputStream(new java.io.File(jrxmlPath));
String resourcePath = "/BsK/client/ui/component/CheckUpPage/PrintDialog/print_forms/medserinvoice.jrxml";
try (InputStream inputStream = MedicineInvoice.class.getResourceAsStream(resourcePath)) {
if (inputStream == null) {
throw new FileNotFoundException("Không thể tìm thấy tệp mẫu Jasper report trong classpath: " + resourcePath);
}
JasperDesign jasperDesign = JRXmlLoader.load(inputStream);
JasperReport jasperReport = JasperCompileManager.compileReport(jasperDesign);
// 4. Fill the report with data
jasperPrint = JasperFillManager.fillReport(jasperReport, parameters, new JREmptyDataSource());
}
}
private void displayPdfInLabel(String pdfPath, JPanel pdfPanel) throws Exception {
PDDocument document = PDDocument.load(new File(pdfPath));
PDFRenderer pdfRenderer = new PDFRenderer(document);
// Create a panel to hold all pages
pdfPanel.setLayout(new BoxLayout(pdfPanel, BoxLayout.Y_AXIS)); // Stack pages vertically
pdfPanel.setLayout(new BoxLayout(pdfPanel, BoxLayout.Y_AXIS));
// Render each page and add it to the pdfPanel
for (int i = 0; i < document.getNumberOfPages(); i++) {
BufferedImage image = pdfRenderer.renderImageWithDPI(i, 150); // Adjust DPI as needed
// Scale the image to a smaller size (e.g., 50% of the original size)
int scaledWidth = image.getWidth() / 2; // Make it half of the original width
int scaledHeight = image.getHeight() / 2; // Make it half of the original height
// Scale the image using getScaledInstance
java.awt.Image scaledImage = image.getScaledInstance(scaledWidth, scaledHeight, java.awt.Image.SCALE_SMOOTH);
// Create an ImageIcon from the scaled image
ImageIcon icon = new ImageIcon(scaledImage);
// Create a label for the image and add it to the panel
BufferedImage image = pdfRenderer.renderImageWithDPI(i, 150);
ImageIcon icon = new ImageIcon(image);
JLabel pageLabel = new JLabel(icon);
pdfPanel.add(pageLabel);
}
document.close();
// Put the panel inside a JScrollPane to make it scrollable
JScrollPane scrollPane = new JScrollPane(pdfPanel);
scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
scrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED); // Added for horizontal scroll if needed
// Increase scroll sensitivity
JScrollBar verticalScrollBar = scrollPane.getVerticalScrollBar();
verticalScrollBar.setUnitIncrement(20); // Increase for finer control, adjust as needed
verticalScrollBar.setBlockIncrement(100); // Increase for page-like scrolling, adjust as needed
// Assuming `dialog` is the parent component
dialog.add(scrollPane, BorderLayout.CENTER);
dialog.validate();
dialog.revalidate();
dialog.repaint();
}
@@ -514,39 +365,31 @@ public class MedicineInvoice{
printerJob.setJobName("Print Medicine Invoice");
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;
}
Graphics2D g2 = (Graphics2D) graphics;
g2.translate(pageFormat.getImageableX(), pageFormat.getImageableY());
try {
PDFRenderer pdfRenderer = new PDFRenderer(document);
BufferedImage pageImage = pdfRenderer.renderImageWithDPI(pageIndex, 300); // Render at 300 DPI
double pageWidth = pageImage.getWidth();
double pageHeight = pageImage.getHeight();
double scaleX = pageFormat.getImageableWidth() / pageWidth;
double scaleY = pageFormat.getImageableHeight() / pageHeight;
double scale = Math.min(scaleX, scaleY);
g2.scale(scale, scale);
g2.drawImage(pageImage, 0, 0, null);
} catch (IOException e) {
e.printStackTrace();
return NO_SUCH_PAGE;
}
return PAGE_EXISTS;
printerJob.setPrintable((graphics, pageFormat, pageIndex) -> {
if (pageIndex >= document.getNumberOfPages()) {
return Printable.NO_SUCH_PAGE;
}
});
Graphics2D g2 = (Graphics2D) graphics;
g2.translate(pageFormat.getImageableX(), pageFormat.getImageableY());
try {
PDFRenderer pdfRenderer = new PDFRenderer(document);
BufferedImage pageImage = pdfRenderer.renderImageWithDPI(pageIndex, 300);
double scale = Math.min(pageFormat.getImageableWidth() / pageImage.getWidth(),
pageFormat.getImageableHeight() / pageImage.getHeight());
g2.scale(scale, scale);
g2.drawImage(pageImage, 0, 0, null);
} catch (IOException e) {
e.printStackTrace();
return Printable.NO_SUCH_PAGE;
}
return Printable.PAGE_EXISTS;
});
printerJob.print();
System.out.println("Printing completed.");
@@ -559,4 +402,4 @@ public class MedicineInvoice{
}
}
}
}
@@ -173,9 +173,9 @@ public class UltrasoundResult {
public JasperPrint createJasperPrint() throws JRException, IOException {
String jrxmlPath;
if ("Dọc".equalsIgnoreCase(this.printType)) {
jrxmlPath = System.getProperty("user.dir") + "/src/main/java/BsK/client/ui/component/CheckUpPage/PrintDialog/print_forms/ultrasoundresult_potrait.jrxml";
jrxmlPath = LocalStorage.pathToProject + "/src/main/java/BsK/client/ui/component/CheckUpPage/PrintDialog/print_forms/ultrasoundresult_potrait.jrxml";
} else {
jrxmlPath = System.getProperty("user.dir") + "/src/main/java/BsK/client/ui/component/CheckUpPage/PrintDialog/print_forms/ultrasoundresult.jrxml";
jrxmlPath =LocalStorage.pathToProject + "/src/main/java/BsK/client/ui/component/CheckUpPage/PrintDialog/print_forms/ultrasoundresult.jrxml";
}
log.info("Using JRXML template: {}", jrxmlPath);
@@ -187,6 +187,7 @@ public class UltrasoundResult {
parameters.put(JRParameter.REPORT_LOCALE, new Locale("vi", "VN"));
// Populate all the string parameters
parameters.put("clinicPrefix", LocalStorage.ClinicPrefix != null ? LocalStorage.ClinicPrefix : "");
parameters.put("clinicName", convertNullToEmpty(LocalStorage.ClinicName, "Phòng khám BSK"));
parameters.put("clinicAddress", convertNullToEmpty(LocalStorage.ClinicAddress, "Địa chỉ phòng khám"));
parameters.put("clinicPhone", convertNullToEmpty(LocalStorage.ClinicPhone, "SĐT phòng khám"));
@@ -200,16 +201,16 @@ public class UltrasoundResult {
parameters.put("barcodeNumber", this.checkupId);
// RTF and plain text content
parameters.put("checkupNote", this.rtfContent);
parameters.put("checkupConclusion", this.conclusion);
parameters.put("checkupSuggestion", this.suggestion);
parameters.put("reCheckupDate", this.recheckupDate);
parameters.put("checkupNote", this.rtfContent != null ? this.rtfContent : "");
parameters.put("checkupConclusion", this.conclusion != null ? this.conclusion : "");
parameters.put("checkupSuggestion", this.suggestion != null ? this.suggestion : "");
parameters.put("reCheckupDate", this.recheckupDate != null ? this.recheckupDate : "");
// Vitals data
parameters.put("checkupHeight", this.customerHeight);
parameters.put("checkupWeight", this.customerWeight);
parameters.put("checkupHeartBeat", this.heartRate);
parameters.put("checkupBloodPressure", this.bloodPressure);
parameters.put("checkupHeight", this.customerHeight != null ? this.customerHeight : "");
parameters.put("checkupWeight", this.customerWeight != null ? this.customerWeight : "");
parameters.put("checkupHeartBeat", this.heartRate != null ? this.heartRate : "");
parameters.put("checkupBloodPressure", this.bloodPressure != null ? this.bloodPressure : "");
// Template title
parameters.put("templateTitle", this.templateTitle);
@@ -226,7 +227,7 @@ public class UltrasoundResult {
int numberOfImages = this.selectedImages.size();
parameters.put("numberImage", numberOfImages);
String projectDir = System.getProperty("user.dir");
String projectDir = LocalStorage.pathToProject;
parameters.put("logoImage", projectDir + "/src/main/java/BsK/client/ui/assets/icon/logo.jpg");
for (int i = 0; i < 6; i++) {
@@ -362,7 +363,7 @@ public class UltrasoundResult {
}
Paragraph clinicInfo = new Paragraph()
.add(new Text(LocalStorage.ClinicName + "\n").setFont(boldFont).setFontSize(10))
.add(new Text(LocalStorage.ClinicPrefix + " " + 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);
@@ -13,6 +13,7 @@ public class InvoiceItem {
private String dosage;
private String amount;
private Double unitPrice;
private String medRoute;
private String medNote;
// --- Service Fields ---
@@ -26,21 +27,21 @@ public class InvoiceItem {
private String supNote;
private String supDosage;
private String supAmount;
private Double supUnitPrice;
private String supRoute;
// Private constructor to be used by factory methods
private InvoiceItem() {}
// --- Factory Methods ---
public static InvoiceItem createMedicine(String medName, String dosage, String amount) {
public static InvoiceItem createMedicine(String medName, String medNote, String dosage, String route, String amount) {
InvoiceItem item = new InvoiceItem();
item.type = "MED";
item.medName = medName;
item.dosage = dosage;
item.medRoute = route;
item.amount = amount;
item.unitPrice = 0.0;
item.medNote = "";
item.medNote = medNote;
return item;
}
@@ -54,14 +55,14 @@ public class InvoiceItem {
return item;
}
public static InvoiceItem createSupplement(String supName, String supNote, String supDosage, String supAmount, Double supUnitPrice) {
public static InvoiceItem createSupplement(String supName, String supNote, String supDosage, String supAmount, String supRoute) {
InvoiceItem item = new InvoiceItem();
item.type = "SUP";
item.supName = supName;
item.supNote = supNote;
item.supDosage = supDosage;
item.supAmount = supAmount;
item.supUnitPrice = supUnitPrice;
item.supRoute = supRoute;
return item;
}
@@ -71,6 +72,7 @@ public class InvoiceItem {
public String getType() { return type; }
public String getMedName() { return medName; }
public String getDosage() { return dosage; }
public String getMedRoute() { return medRoute; }
public String getAmount() { return amount; }
public Double getUnitPrice() { return unitPrice; }
public String getMedNote() { return medNote; }
@@ -82,5 +84,5 @@ public class InvoiceItem {
public String getSupNote() { return supNote; }
public String getSupDosage() { return supDosage; }
public String getSupAmount() { return supAmount; }
public Double getSupUnitPrice() { return supUnitPrice; }
public String getSupRoute() { return supRoute; }
}
@@ -27,7 +27,8 @@
<field name="supNote" class="java.lang.String"/>
<field name="supDosage" class="java.lang.String"/>
<field name="supAmount" class="java.lang.String"/>
<field name="supUnitPrice" class="java.lang.Double"/>
<field name="medRoute" class="java.lang.String"/>
<field name="supRoute" class="java.lang.String"/>
<variable name="medRowTotal" class="java.math.BigDecimal">
<expression><![CDATA[new java.math.BigDecimal(0)]]></expression>
</variable>
@@ -68,6 +69,7 @@
<parameter name="hasServices" class="java.lang.Boolean"/>
<parameter name="hasSupplements" class="java.lang.Boolean"/>
<parameter name="driveURL" class="java.lang.String"/>
<parameter name="clinicPrefix" class="java.lang.String"/>
<query language="sql"><![CDATA[]]></query>
<variable name="MedicineGrandTotal" calculation="System" class="java.math.BigDecimal">
<initialValueExpression><![CDATA[new java.math.BigDecimal(0)]]></initialValueExpression>
@@ -86,12 +88,12 @@
<printWhenExpression><![CDATA[$P{hasMedicines}]]></printWhenExpression>
<component kind="table">
<datasetRun uuid="ee5be970-758d-4ae3-91fa-3b3a0a5fd160" subDataset="med_pre">
<dataSourceExpression><![CDATA[$P{medicineDS}]]></dataSourceExpression>
<dataSourceExpression><![CDATA[$P{medicineDS} == null ? new net.sf.jasperreports.engine.JREmptyDataSource() : $P{medicineDS}]]></dataSourceExpression>
<returnValue toVariable="MedicineGrandTotal" fromVariable="medTotal"/>
</datasetRun>
<column kind="single" uuid="249a6076-168a-4d8c-ba6c-92ca1d870834" width="430">
<column kind="single" uuid="249a6076-168a-4d8c-ba6c-92ca1d870834" width="350">
<columnHeader height="19" rowSpan="1">
<element kind="staticText" uuid="9b6682e0-0e7a-48be-baa3-932a54d0c959" x="0" y="0" width="430" height="19" fontName="Times New Roman" fontSize="16.0" bold="true" hTextAlign="Left" vTextAlign="Middle">
<element kind="staticText" uuid="9b6682e0-0e7a-48be-baa3-932a54d0c959" x="0" y="0" width="350" height="19" fontName="Times New Roman" fontSize="16.0" bold="true" hTextAlign="Left" vTextAlign="Middle">
<text><![CDATA[THUỐC]]></text>
<box>
<topPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
@@ -110,7 +112,7 @@
</box>
</columnHeader>
<detailCell height="41" style="Table_TD">
<element kind="textField" uuid="bc690d0f-bc31-4bcc-a134-ff5deb5be586" x="0" y="0" width="430" height="21" fontName="Times New Roman" fontSize="12.0" bold="true" hTextAlign="Left" vTextAlign="Middle">
<element kind="textField" uuid="bc690d0f-bc31-4bcc-a134-ff5deb5be586" x="0" y="0" width="350" height="21" fontName="Times New Roman" fontSize="12.0" bold="true" hTextAlign="Left" vTextAlign="Middle">
<expression><![CDATA[$F{medName}]]></expression>
<box topPadding="3" leftPadding="20">
<topPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
@@ -119,7 +121,7 @@
<rightPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
</box>
</element>
<element kind="textField" uuid="9b848a7f-a2e8-4360-9e6c-b5fde8d00361" x="0" y="21" width="430" height="20" fontName="Times New Roman" italic="true">
<element kind="textField" uuid="9b848a7f-a2e8-4360-9e6c-b5fde8d00361" x="0" y="21" width="350" height="20" fontName="Times New Roman" italic="true">
<expression><![CDATA["Ghi chú: " + $F{medNote} +", " + $F{dosage}]]></expression>
<box leftPadding="20">
<topPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
@@ -138,6 +140,26 @@
</detailCell>
<property name="com.jaspersoft.studio.components.table.model.column.name" value="Column1"/>
</column>
<column kind="single" uuid="e837d1ea-d140-455a-9e05-b87838d5f2ca" width="90">
<columnHeader height="19" rowSpan="1" style="Table_TD">
<element kind="staticText" uuid="21134b98-2109-4984-9f1b-fe622b448a3c" x="0" y="0" width="90" height="19" fontName="Times New Roman" fontSize="12.0" bold="true" hTextAlign="Center" vTextAlign="Middle">
<text><![CDATA[Đường dùng]]></text>
<box>
<topPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
<leftPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
<bottomPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
<rightPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
</box>
</element>
</columnHeader>
<detailCell height="41" style="Table_TD">
<element kind="textField" uuid="d9bc9aed-4662-4dab-bb9f-8cbfe5410786" x="0" y="0" width="90" height="41" fontName="Times New Roman" fontSize="12.0" hTextAlign="Center" vTextAlign="Top">
<expression><![CDATA[$F{medRoute}]]></expression>
<box topPadding="3" leftPadding="3"/>
</element>
</detailCell>
<property name="com.jaspersoft.studio.components.table.model.column.name" value="Column2"/>
</column>
<column kind="single" uuid="dd7c9141-b6c3-4471-916b-43e980f65a47" width="110">
<columnHeader height="19" rowSpan="1">
<element kind="staticText" uuid="ae479f63-bbbf-4271-85e3-59bf587e90b6" x="0" y="0" width="110" height="19" fontName="Times New Roman" fontSize="12.0" bold="true" hTextAlign="Center" vTextAlign="Middle">
@@ -173,7 +195,7 @@
<rightPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
</box>
</detailCell>
<property name="com.jaspersoft.studio.components.table.model.column.name" value="Column2"/>
<property name="com.jaspersoft.studio.components.table.model.column.name" value="Column3"/>
</column>
</component>
<property name="com.jaspersoft.studio.layout" value="com.jaspersoft.studio.editor.layout.VerticalRowLayout"/>
@@ -188,17 +210,17 @@
<groupHeader>
<band height="62">
<printWhenExpression><![CDATA[$P{hasSupplements}]]></printWhenExpression>
<element kind="component" uuid="8e6641e8-03a4-48cd-89cd-9ec07d345682" x="0" y="1" width="555" height="60">
<printWhenExpression><![CDATA[$P{hasSupplements}]]></printWhenExpression>
<element kind="component" uuid="71f6b965-7b44-475c-aa38-89e77ce55e87" x="0" y="1" width="555" height="59">
<printWhenExpression><![CDATA[$P{hasMedicines}]]></printWhenExpression>
<component kind="table">
<datasetRun uuid="337bab96-7cf8-4764-83a3-81b43a7bf99b" subDataset="med_pre">
<dataSourceExpression><![CDATA[$P{supplementDS}]]></dataSourceExpression>
<returnValue toVariable="SupplementGrandTotal" fromVariable="supTotal"/>
<datasetRun uuid="bddd7b63-0aeb-492a-99ec-561999a49e96" subDataset="med_pre">
<dataSourceExpression><![CDATA[$P{medicineDS} == null ? new net.sf.jasperreports.engine.JREmptyDataSource() : $P{medicineDS}]]></dataSourceExpression>
<returnValue toVariable="MedicineGrandTotal" fromVariable="medTotal"/>
</datasetRun>
<column kind="single" uuid="198ad555-d724-401f-b44c-9836083a0116" width="430">
<column kind="single" uuid="6ecff449-3a01-40a2-a424-cb32c6291fa4" width="350">
<columnHeader height="19" rowSpan="1">
<element kind="staticText" uuid="5b04a93c-9a79-43ec-9df9-f6b0215d18c4" x="0" y="0" width="430" height="19" fontName="Times New Roman" fontSize="16.0" bold="true" hTextAlign="Left" vTextAlign="Middle">
<text><![CDATA[THỰC PHẨM BỔ SUNG]]></text>
<element kind="staticText" uuid="3891585b-57df-4552-a45b-87caaa47f731" x="0" y="0" width="350" height="19" fontName="Times New Roman" fontSize="16.0" bold="true" hTextAlign="Left" vTextAlign="Middle">
<text><![CDATA[THUỐC]]></text>
<box>
<topPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
<leftPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
@@ -216,7 +238,7 @@
</box>
</columnHeader>
<detailCell height="41" style="Table_TD">
<element kind="textField" uuid="638849d8-7f5c-41cb-8c6d-a4fc7510c2f6" x="0" y="0" width="430" height="21" fontName="Times New Roman" fontSize="12.0" bold="true" hTextAlign="Left" vTextAlign="Middle">
<element kind="textField" uuid="28b25c33-2b21-48f8-bf1d-97d30448d60c" x="0" y="0" width="350" height="21" fontName="Times New Roman" fontSize="12.0" bold="true" hTextAlign="Left" vTextAlign="Middle">
<expression><![CDATA[$F{supName}]]></expression>
<box topPadding="3" leftPadding="20">
<topPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
@@ -225,7 +247,7 @@
<rightPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
</box>
</element>
<element kind="textField" uuid="9043e924-94a3-4920-b90b-036f94fb5202" x="0" y="21" width="430" height="20" fontName="Times New Roman" italic="true">
<element kind="textField" uuid="0ff5f50f-e5e5-48f6-b4e9-59bec18299c4" x="0" y="21" width="350" height="20" fontName="Times New Roman" italic="true">
<expression><![CDATA["Ghi chú: " + $F{supNote} +", " + $F{supDosage}]]></expression>
<box leftPadding="20">
<topPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
@@ -244,9 +266,29 @@
</detailCell>
<property name="com.jaspersoft.studio.components.table.model.column.name" value="Column1"/>
</column>
<column kind="single" uuid="0969f21d-e428-4907-a565-3f61ffbacdd6" width="110">
<column kind="single" uuid="7dc649b9-d114-4f50-b7a9-0dd11ef951fe" width="90">
<columnHeader height="19" rowSpan="1" style="Table_TD">
<element kind="staticText" uuid="c0236d00-a187-4b7d-9fc4-5992556e2ed8" x="0" y="0" width="90" height="19" fontName="Times New Roman" fontSize="12.0" bold="true" hTextAlign="Center" vTextAlign="Middle">
<text><![CDATA[Đường dùng]]></text>
<box>
<topPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
<leftPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
<bottomPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
<rightPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
</box>
</element>
</columnHeader>
<detailCell height="41" style="Table_TD">
<element kind="textField" uuid="0523ba25-ecc0-4c36-bab4-e0b14cd5246b" x="0" y="0" width="90" height="41" fontName="Times New Roman" fontSize="12.0" hTextAlign="Center" vTextAlign="Top">
<expression><![CDATA[$F{supRoute}]]></expression>
<box topPadding="3" leftPadding="3"/>
</element>
</detailCell>
<property name="com.jaspersoft.studio.components.table.model.column.name" value="Column2"/>
</column>
<column kind="single" uuid="41d8c9d4-eeb8-45b8-abb7-776c0d6c27ef" width="110">
<columnHeader height="19" rowSpan="1">
<element kind="staticText" uuid="6685e147-3802-4b7a-9a96-2cc2f04d4ed6" x="0" y="0" width="110" height="19" fontName="Times New Roman" fontSize="12.0" bold="true" hTextAlign="Center" vTextAlign="Middle">
<element kind="staticText" uuid="248e7337-3a42-49fe-9802-258570b3f37b" x="0" y="0" width="110" height="19" fontName="Times New Roman" fontSize="12.0" bold="true" hTextAlign="Center" vTextAlign="Middle">
<text><![CDATA[Số lượng]]></text>
<box>
<topPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
@@ -263,7 +305,7 @@
</box>
</columnHeader>
<detailCell height="41" style="Table_TD">
<element kind="textField" uuid="746b5d1f-3d79-4a26-8099-1f2105c5ecfe" x="0" y="0" width="110" height="41" fontName="Times New Roman" fontSize="12.0" hTextAlign="Center" vTextAlign="Top">
<element kind="textField" uuid="a5d2bc15-bc45-400f-bb9b-15dacee02c42" x="0" y="0" width="110" height="41" fontName="Times New Roman" fontSize="12.0" hTextAlign="Center" vTextAlign="Top">
<expression><![CDATA[$F{supAmount}]]></expression>
<box topPadding="3" leftPadding="3" bottomPadding="0" rightPadding="0">
<topPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
@@ -279,7 +321,7 @@
<rightPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
</box>
</detailCell>
<property name="com.jaspersoft.studio.components.table.model.column.name" value="Column2"/>
<property name="com.jaspersoft.studio.components.table.model.column.name" value="Column3"/>
</column>
</component>
<property name="com.jaspersoft.studio.layout" value="com.jaspersoft.studio.editor.layout.VerticalRowLayout"/>
@@ -292,13 +334,13 @@
</group>
<group name="group_dichvu">
<groupHeader>
<band height="90">
<band height="109">
<printWhenExpression><![CDATA[$P{hasServices}]]></printWhenExpression>
<element kind="component" uuid="68c80e54-2998-4cf3-91c0-42fde9130772" positionType="Float" x="0" y="24" width="555" height="65">
<element kind="component" uuid="68c80e54-2998-4cf3-91c0-42fde9130772" positionType="Float" x="0" y="24" width="555" height="85">
<printWhenExpression><![CDATA[$P{hasServices}]]></printWhenExpression>
<component kind="table">
<datasetRun uuid="24cf5328-ecae-4c68-8955-73475b8823b4" subDataset="med_pre">
<dataSourceExpression><![CDATA[$P{serviceDS}]]></dataSourceExpression>
<dataSourceExpression><![CDATA[$P{serviceDS} == null ? new net.sf.jasperreports.engine.JREmptyDataSource() : $P{serviceDS}]]></dataSourceExpression>
<returnValue toVariable="ServiceGrandTotal" fromVariable="serTotal"/>
</datasetRun>
<column kind="single" uuid="9be00b0a-9844-4037-a53e-be1970a83d48" width="320">
@@ -329,8 +371,8 @@
<rightPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
</box>
</columnFooter>
<detailCell height="29" style="Table_TD">
<element kind="textField" uuid="a16334e1-e3e0-4c20-a22d-7ce6a546edc8" x="0" y="0" width="320" height="15" fontName="Times New Roman" fontSize="10.0" bold="true" hTextAlign="Left" vTextAlign="Top">
<detailCell height="39" style="Table_TD">
<element kind="textField" uuid="a16334e1-e3e0-4c20-a22d-7ce6a546edc8" x="0" y="0" width="320" height="20" fontName="Times New Roman" fontSize="12.0" bold="true" hTextAlign="Left" vTextAlign="Top">
<expression><![CDATA[$F{serName}]]></expression>
<box topPadding="3" leftPadding="20">
<topPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
@@ -339,7 +381,7 @@
<rightPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
</box>
</element>
<element kind="textField" uuid="48a3aa97-2f44-433e-a5b3-28fbcc0b0877" x="0" y="15" width="320" height="14" fontName="Times New Roman" fontSize="8.0" italic="true">
<element kind="textField" uuid="48a3aa97-2f44-433e-a5b3-28fbcc0b0877" x="0" y="20" width="320" height="19" fontName="Times New Roman" fontSize="10.0" italic="true">
<expression><![CDATA["Ghi chú: " + $F{serNote}]]></expression>
<box leftPadding="20">
<topPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
@@ -383,8 +425,8 @@
<rightPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
</box>
</columnFooter>
<detailCell height="29" style="Table_TD">
<element kind="textField" uuid="48ad7d8f-6a79-4804-9f36-9f5c8b6ce888" x="0" y="0" width="39" height="29" fontName="Times New Roman" fontSize="8.0" hTextAlign="Center" vTextAlign="Middle">
<detailCell height="39" style="Table_TD">
<element kind="textField" uuid="48ad7d8f-6a79-4804-9f36-9f5c8b6ce888" x="0" y="0" width="39" height="39" fontName="Times New Roman" fontSize="12.0" hTextAlign="Center" vTextAlign="Middle">
<expression><![CDATA[$F{serAmount}]]></expression>
<box topPadding="3" leftPadding="3" bottomPadding="0" rightPadding="0">
<topPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
@@ -434,8 +476,8 @@
<rightPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
</box>
</columnFooter>
<detailCell height="29" style="Table_TD">
<element kind="textField" uuid="6bf24316-39cd-4805-8548-52ea9d23818e" x="0" y="0" width="110" height="29" fontName="Times New Roman" fontSize="8.0" pattern="#,##0" hTextAlign="Right" vTextAlign="Middle">
<detailCell height="39" style="Table_TD">
<element kind="textField" uuid="6bf24316-39cd-4805-8548-52ea9d23818e" x="0" y="0" width="110" height="39" fontName="Times New Roman" fontSize="12.0" pattern="#,##0" hTextAlign="Right" vTextAlign="Middle">
<expression><![CDATA[$F{serUnitPrice}]]></expression>
<box topPadding="3" leftPadding="3" rightPadding="3">
<pen lineWidth="1.0"/>
@@ -473,7 +515,7 @@
</box>
</columnHeader>
<columnFooter height="30" rowSpan="1">
<element kind="textField" uuid="a0606f4b-6dad-47cd-b470-f401e298612e" x="0" y="0" width="85" height="30" fontName="Times New Roman" pattern="#,##0" bold="true" hTextAlign="Right" vTextAlign="Top">
<element kind="textField" uuid="a0606f4b-6dad-47cd-b470-f401e298612e" x="0" y="0" width="85" height="30" fontName="Times New Roman" fontSize="12.0" pattern="#,##0" bold="true" hTextAlign="Right" vTextAlign="Top">
<expression><![CDATA[$V{serTotal}]]></expression>
<box topPadding="3" rightPadding="3">
<topPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/>
@@ -489,8 +531,8 @@
<rightPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
</box>
</columnFooter>
<detailCell height="29" style="Table_TD">
<element kind="textField" uuid="035cfa1b-9187-4bfe-8fa1-1d149d789768" x="0" y="0" width="85" height="29" fontName="Times New Roman" fontSize="8.0" pattern="#,##0" hTextAlign="Right" vTextAlign="Middle">
<detailCell height="39" style="Table_TD">
<element kind="textField" uuid="035cfa1b-9187-4bfe-8fa1-1d149d789768" x="0" y="0" width="85" height="39" fontName="Times New Roman" fontSize="12.0" pattern="#,##0" hTextAlign="Right" vTextAlign="Middle">
<expression><![CDATA[$V{serRowTotal}]]></expression>
<box topPadding="3" leftPadding="0" rightPadding="3">
<topPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
@@ -521,84 +563,88 @@
</groupHeader>
</group>
<background splitType="Stretch"/>
<title height="79" splitType="Stretch">
<title height="96" splitType="Stretch">
<element kind="image" uuid="c596ac6f-18d9-4cfe-a74e-58b1f7d11ecc" x="-10" y="-4" width="90" height="83">
<expression><![CDATA[$P{logoImage}]]></expression>
</element>
<element kind="textField" uuid="48bf4793-8d8d-427d-b739-8f34f051192f" x="80" y="-4" width="350" height="25" fontName="Times New Roman" fontSize="18.0" bold="true">
<expression><![CDATA[$P{clinicName}]]></expression>
<element kind="textField" uuid="48bf4793-8d8d-427d-b739-8f34f051192f" x="80" y="-4" width="359" height="25" forecolor="#FF0905" fontName="Times New Roman" fontSize="18.0" bold="true" hTextAlign="Center">
<expression><![CDATA[$P{clinicPrefix}]]></expression>
</element>
<element kind="staticText" uuid="d8e95ce7-3ac0-44a7-ac8f-65821b7f373c" x="80" y="20" width="150" height="15" fontName="Times New Roman" fontSize="12.0" bold="true" hTextAlign="Left">
<element kind="staticText" uuid="d8e95ce7-3ac0-44a7-ac8f-65821b7f373c" x="80" y="47" width="150" height="15" fontName="Times New Roman" fontSize="12.0" bold="true" hTextAlign="Left">
<text><![CDATA[Địa chỉ: ]]></text>
</element>
<element kind="textField" uuid="9883203e-fd4b-4110-a4b9-2c8c257ce5fa" x="126" y="20" width="314" height="15" fontName="Times New Roman" fontSize="12.0">
<element kind="textField" uuid="9883203e-fd4b-4110-a4b9-2c8c257ce5fa" x="126" y="47" width="314" height="15" fontName="Times New Roman" fontSize="12.0">
<expression><![CDATA[$P{clinicAddress}]]></expression>
</element>
<element kind="staticText" uuid="f00706ca-903c-4089-b3a1-33be68f6112b" x="80" y="36" width="150" height="15" fontName="Times New Roman" fontSize="12.0" bold="true" hTextAlign="Left">
<element kind="staticText" uuid="f00706ca-903c-4089-b3a1-33be68f6112b" x="80" y="62" width="150" height="15" fontName="Times New Roman" fontSize="12.0" bold="true" hTextAlign="Left">
<text><![CDATA[SĐT:]]></text>
</element>
<element kind="textField" uuid="2af00e22-702e-42cb-a6fb-19d401a58170" x="110" y="36" width="330" height="15" fontName="Times New Roman" fontSize="12.0">
<element kind="textField" uuid="2af00e22-702e-42cb-a6fb-19d401a58170" x="110" y="62" width="330" height="15" fontName="Times New Roman" fontSize="12.0">
<expression><![CDATA[$P{clinicPhone}]]></expression>
</element>
<element kind="component" uuid="35037abf-0984-4b9e-8a05-f8fae38d7dcc" x="440" y="8" width="65" height="43">
<element kind="component" uuid="35037abf-0984-4b9e-8a05-f8fae38d7dcc" x="490" y="0" width="65" height="43">
<component kind="barcode4j:Code128">
<codeExpression><![CDATA[$P{barcodeNumber}]]></codeExpression>
</component>
</element>
<element kind="staticText" uuid="de38fb46-49af-4f48-8c33-f97680bcc7fa" x="135" y="52" width="284" height="25" fontName="Times New Roman" fontSize="18.0" bold="true" hTextAlign="Center">
<element kind="staticText" uuid="de38fb46-49af-4f48-8c33-f97680bcc7fa" x="135" y="71" width="284" height="21" fontName="Times New Roman" fontSize="18.0" bold="true" hTextAlign="Center">
<text><![CDATA[TOA THUỐC & DỊCH VỤ]]></text>
<property name="com.jaspersoft.studio.unit.height" value="pixel"/>
</element>
<element kind="component" uuid="b8dc3582-162b-47d9-9501-fbf3bfc63fbd" x="505" y="3" width="50" height="43">
<element kind="component" uuid="b8dc3582-162b-47d9-9501-fbf3bfc63fbd" x="440" y="0" width="46" height="39">
<component kind="barcode4j:QRCode">
<codeExpression><![CDATA[$P{driveURL}]]></codeExpression>
</component>
</element>
<element kind="staticText" uuid="53b28743-6b3c-4700-b84d-a96a93371dbf" x="500" y="46" width="55" height="14" fontName="Times New Roman" fontSize="8.0" bold="false" hTextAlign="Center">
<element kind="staticText" uuid="53b28743-6b3c-4700-b84d-a96a93371dbf" x="434" y="43" width="55" height="14" fontName="Times New Roman" fontSize="8.0" bold="false" hTextAlign="Center">
<printWhenExpression><![CDATA[$P{driveURL} != null && !$P{driveURL}.trim().isEmpty()]]></printWhenExpression>
<text><![CDATA[Xem KQ online]]></text>
</element>
<element kind="textField" uuid="9dcab6b1-a9ce-4aa9-9df9-232869b3ab24" x="80" y="21" width="359" height="25" forecolor="#FF0905" fontName="Times New Roman" fontSize="18.0" bold="true" hTextAlign="Center">
<expression><![CDATA[$P{clinicName}]]></expression>
</element>
</title>
<pageHeader height="72" splitType="Stretch">
<element kind="staticText" uuid="e6997cbd-6cea-4ab2-ab14-402c6487566b" x="0" y="5" width="50" height="15" fontName="Times New Roman" fontSize="10.0" bold="true" hTextAlign="Left">
<element kind="staticText" uuid="e6997cbd-6cea-4ab2-ab14-402c6487566b" x="0" y="4" width="59" height="14" fontName="Times New Roman" fontSize="12.0" bold="true" hTextAlign="Left">
<text><![CDATA[Họ và tên:]]></text>
</element>
<element kind="staticText" uuid="3dc3cfae-fb07-4ee2-a477-9e14e1a88a55" x="0" y="18" width="80" height="15" fontName="Times New Roman" fontSize="10.0" bold="true" hTextAlign="Left">
<element kind="staticText" uuid="3dc3cfae-fb07-4ee2-a477-9e14e1a88a55" x="0" y="18" width="80" height="15" fontName="Times New Roman" fontSize="12.0" bold="true" hTextAlign="Left">
<text><![CDATA[Ngày sinh:]]></text>
</element>
<element kind="staticText" uuid="1c26d386-0d3f-4e81-80b7-19e6d99c8bb6" x="140" y="18" width="80" height="15" fontName="Times New Roman" fontSize="10.0" bold="true" hTextAlign="Left">
<element kind="staticText" uuid="1c26d386-0d3f-4e81-80b7-19e6d99c8bb6" x="140" y="18" width="80" height="15" fontName="Times New Roman" fontSize="12.0" bold="true" hTextAlign="Left">
<text><![CDATA[Giới tính:]]></text>
</element>
<element kind="staticText" uuid="0d2b2914-3291-41e1-b026-6258b8b7c9bc" x="0" y="32" width="49" height="15" fontName="Times New Roman" bold="true" hTextAlign="Left">
<element kind="staticText" uuid="0d2b2914-3291-41e1-b026-6258b8b7c9bc" x="0" y="32" width="49" height="15" fontName="Times New Roman" fontSize="12.0" bold="true" hTextAlign="Left">
<text><![CDATA[Địa chỉ:]]></text>
</element>
<element kind="staticText" uuid="4da3f19a-8dcb-4a94-b1c0-68ad61615197" x="274" y="4" width="50" height="15" fontName="Times New Roman" fontSize="10.0" bold="true" hTextAlign="Left">
<element kind="staticText" uuid="4da3f19a-8dcb-4a94-b1c0-68ad61615197" x="274" y="4" width="50" height="15" fontName="Times New Roman" fontSize="12.0" bold="true" hTextAlign="Left">
<text><![CDATA[Bác sĩ:]]></text>
</element>
<element kind="staticText" uuid="9b7c5e15-fd8b-4314-8941-863bf39db57d" x="274" y="18" width="60" height="15" fontName="Times New Roman" fontSize="10.0" bold="true" hTextAlign="Left">
<element kind="staticText" uuid="9b7c5e15-fd8b-4314-8941-863bf39db57d" x="274" y="18" width="66" height="15" fontName="Times New Roman" fontSize="12.0" bold="true" hTextAlign="Left">
<text><![CDATA[Ngày khám:]]></text>
</element>
<element kind="textField" uuid="f2f20167-fbd0-47d5-a7ce-03d7da78f342" x="60" y="5" width="214" height="15" fontName="Times New Roman" fontSize="10.0">
<element kind="textField" uuid="f2f20167-fbd0-47d5-a7ce-03d7da78f342" x="60" y="4" width="214" height="15" fontName="Times New Roman" fontSize="12.0">
<expression><![CDATA[$P{patientName}]]></expression>
</element>
<element kind="textField" uuid="46ef6929-7796-4d92-9478-8ed269d8708f" x="60" y="18" width="80" height="15" fontName="Times New Roman" fontSize="10.0">
<element kind="textField" uuid="46ef6929-7796-4d92-9478-8ed269d8708f" x="60" y="18" width="80" height="15" fontName="Times New Roman" fontSize="12.0">
<expression><![CDATA[$P{patientDOB}]]></expression>
</element>
<element kind="textField" uuid="2f307864-3cbc-4110-8d5a-34d78080a316" x="184" y="18" width="46" height="15" fontName="Times New Roman" fontSize="10.0">
<element kind="textField" uuid="2f307864-3cbc-4110-8d5a-34d78080a316" x="194" y="18" width="46" height="15" fontName="Times New Roman" fontSize="12.0">
<expression><![CDATA[$P{patientGender}]]></expression>
</element>
<element kind="textField" uuid="3e0c0023-37b8-490a-b839-ba0a50fb1629" x="60" y="32" width="214" height="15" fontName="Times New Roman" fontSize="10.0">
<element kind="textField" uuid="3e0c0023-37b8-490a-b839-ba0a50fb1629" x="60" y="32" width="214" height="15" fontName="Times New Roman" fontSize="12.0">
<expression><![CDATA[$P{patientAddress}]]></expression>
</element>
<element kind="textField" uuid="7ed16435-adca-4e26-aae4-4acad15ed344" x="330" y="4" width="160" height="15" fontName="Times New Roman" fontSize="10.0">
<element kind="textField" uuid="7ed16435-adca-4e26-aae4-4acad15ed344" x="340" y="4" width="160" height="15" fontName="Times New Roman" fontSize="12.0">
<expression><![CDATA[$P{doctorName}]]></expression>
</element>
<element kind="textField" uuid="4a444f9a-544f-4ce5-b812-5704bc2bbfce" x="330" y="18" width="124" height="15" fontName="Times New Roman" fontSize="10.0">
<element kind="textField" uuid="4a444f9a-544f-4ce5-b812-5704bc2bbfce" x="340" y="18" width="160" height="15" fontName="Times New Roman" fontSize="12.0">
<expression><![CDATA[$P{checkupDate}]]></expression>
</element>
<element kind="staticText" uuid="c089f2a4-115e-4739-a0c7-7aa1e98b5c6a" x="0" y="46" width="59" height="16" fontName="Times New Roman" fontSize="10.0" bold="true" hTextAlign="Left">
<element kind="staticText" uuid="c089f2a4-115e-4739-a0c7-7aa1e98b5c6a" x="0" y="46" width="70" height="16" fontName="Times New Roman" fontSize="12.0" bold="true" hTextAlign="Left">
<text><![CDATA[Chuẩn đoán:]]></text>
</element>
<element kind="textField" uuid="d44e5d8d-1ebd-45e3-a8bd-941e1c2a1392" x="60" y="46" width="494" height="26" fontName="Times New Roman" fontSize="10.0">
<element kind="textField" uuid="d44e5d8d-1ebd-45e3-a8bd-941e1c2a1392" x="69" y="46" width="486" height="26" fontName="Times New Roman" fontSize="12.0">
<expression><![CDATA[$P{patientDiagnos}]]></expression>
</element>
</pageHeader>
@@ -38,24 +38,25 @@
<parameter name="templateTitle" class="java.lang.String"/>
<parameter name="driveURL" class="java.lang.String"/>
<parameter name="ultrasoundDoctorName" class="java.lang.String"/>
<parameter name="clinicPrefix" class="java.lang.String"/>
<query language="sql"><![CDATA[]]></query>
<background splitType="Stretch"/>
<title splitType="Stretch"/>
<pageHeader splitType="Stretch"/>
<columnHeader splitType="Stretch"/>
<detail>
<band height="540" splitType="Stretch">
<element kind="frame" uuid="2b7ec588-953c-4145-87b7-1d861c272fe0" x="0" y="0" width="400" height="539">
<band height="538" splitType="Stretch">
<element kind="frame" uuid="2b7ec588-953c-4145-87b7-1d861c272fe0" x="0" y="0" width="399" height="538">
<element kind="image" uuid="fd80ab38-4cae-409b-84b9-356220d2b1e5" x="0" y="1" width="60" height="60">
<expression><![CDATA[$P{logoImage}]]></expression>
</element>
<element kind="textField" uuid="eb56d4c8-2a0d-45fa-89a2-ad6528f9a99b" x="60" y="0" width="290" height="20" forecolor="#FF0905" fontName="Times New Roman" fontSize="14.0" bold="true">
<expression><![CDATA[$P{clinicName}]]></expression>
<element kind="textField" uuid="eb56d4c8-2a0d-45fa-89a2-ad6528f9a99b" x="60" y="0" width="260" height="20" forecolor="#FF0905" fontName="Times New Roman" fontSize="14.0" bold="true" hTextAlign="Center">
<expression><![CDATA[$P{clinicPrefix}]]></expression>
</element>
<element kind="textField" uuid="796d9ffd-6d2e-4ae3-bdfb-b08183d7d9c0" x="60" y="20" width="235" height="25" fontName="Times New Roman" fontSize="10.0">
<element kind="textField" uuid="796d9ffd-6d2e-4ae3-bdfb-b08183d7d9c0" x="63" y="30" width="229" height="20" fontName="Times New Roman" fontSize="10.0">
<expression><![CDATA[$P{clinicAddress}]]></expression>
</element>
<element kind="textField" uuid="260bb33d-1d11-4178-aceb-3fbf8fcb4b45" x="60" y="45" width="162" height="12" fontName="Times New Roman" fontSize="8.0">
<element kind="textField" uuid="260bb33d-1d11-4178-aceb-3fbf8fcb4b45" x="63" y="42" width="162" height="12" fontName="Times New Roman" fontSize="8.0">
<expression><![CDATA["SDT: " + $P{clinicPhone}]]></expression>
</element>
<element kind="staticText" uuid="6f89a93f-2d10-4506-baa5-226bdd047b17" x="0" y="65" width="100" height="30" forecolor="#FF0905" fontName="Times New Roman" fontSize="14.0" bold="true">
@@ -88,28 +89,28 @@
<element kind="textField" uuid="f4df20b4-920c-491e-882b-6e0733cb4866" x="184" y="94" width="36" height="15" fontName="Times New Roman" fontSize="10.0">
<expression><![CDATA[$P{patientGender}]]></expression>
</element>
<element kind="textField" uuid="3b8ac40e-85aa-4ab8-8445-64bcddb8b267" x="39" y="109" width="361" height="15" fontName="Times New Roman" fontSize="10.0">
<element kind="textField" uuid="3b8ac40e-85aa-4ab8-8445-64bcddb8b267" x="39" y="109" width="359" height="15" fontName="Times New Roman" fontSize="10.0">
<expression><![CDATA[$P{patientAddress}]]></expression>
</element>
<element kind="textField" uuid="db40cdb0-2850-4d66-8430-addc54f90321" x="290" y="80" width="110" height="15" fontName="Times New Roman" fontSize="10.0">
<element kind="textField" uuid="db40cdb0-2850-4d66-8430-addc54f90321" x="290" y="80" width="108" height="15" fontName="Times New Roman" fontSize="10.0">
<expression><![CDATA[$P{doctorName}]]></expression>
</element>
<element kind="textField" uuid="eb9cf54a-3b50-43c5-8696-cfc1e21bddfe" x="276" y="94" width="124" height="15" fontName="Times New Roman" fontSize="10.0">
<element kind="textField" uuid="eb9cf54a-3b50-43c5-8696-cfc1e21bddfe" x="276" y="94" width="122" height="15" fontName="Times New Roman" fontSize="10.0">
<expression><![CDATA[$P{checkupDate}]]></expression>
</element>
<element kind="staticText" uuid="9f7de81c-4c38-41a2-9fea-a165eff19431" x="1" y="124" width="59" height="16" fontName="Times New Roman" fontSize="10.0" bold="true" hTextAlign="Left">
<text><![CDATA[Chuẩn đoán:]]></text>
</element>
<element kind="textField" uuid="5ae67e13-7a79-437f-bfb8-c720d896720d" x="60" y="124" width="340" height="26" fontName="Times New Roman" fontSize="10.0">
<element kind="textField" uuid="5ae67e13-7a79-437f-bfb8-c720d896720d" x="60" y="124" width="338" height="26" fontName="Times New Roman" fontSize="10.0">
<expression><![CDATA[$P{patientDiagnos}]]></expression>
</element>
<element kind="staticText" uuid="b1fa845a-48da-4e45-82b8-8b9d972650f6" x="0" y="162" width="100" height="30" forecolor="#FF0905" fontName="Times New Roman" fontSize="14.0" bold="true">
<text><![CDATA[II.Nội dung]]></text>
</element>
<element kind="textField" uuid="6d652a25-b701-45bd-91ba-750842650004" x="0" y="177" width="398" height="362" markup="rtf" fontName="Times New Roman" fontSize="14.0">
<element kind="textField" uuid="6d652a25-b701-45bd-91ba-750842650004" x="0" y="177" width="398" height="360" markup="rtf" fontName="Times New Roman" fontSize="16.0">
<expression><![CDATA[$P{checkupNote}]]></expression>
</element>
<element kind="staticText" uuid="8f720f6a-0257-4556-b3bc-3b81ad4f8099" x="1" y="150" width="59" height="16" fontName="Times New Roman" fontSize="10.0" bold="true" hTextAlign="Left">
<element kind="staticText" uuid="8f720f6a-0257-4556-b3bc-3b81ad4f8099" x="290" y="150" width="59" height="16" fontName="Times New Roman" fontSize="10.0" bold="true" hTextAlign="Left">
<text><![CDATA[Chiều cao:]]></text>
</element>
<element kind="staticText" uuid="a57e7a9d-4ac7-4219-b268-cd08ce943327" x="100" y="150" width="59" height="16" fontName="Times New Roman" fontSize="10.0" bold="true" hTextAlign="Left">
@@ -118,10 +119,10 @@
<element kind="staticText" uuid="2b9cfd9d-ec8f-4036-9c96-039fd7855e24" x="200" y="150" width="59" height="16" fontName="Times New Roman" fontSize="10.0" bold="true" hTextAlign="Left">
<text><![CDATA[Nhịp tim:]]></text>
</element>
<element kind="staticText" uuid="c1356370-11ce-4b68-97d6-ce6e18e306c5" x="290" y="150" width="59" height="16" fontName="Times New Roman" fontSize="10.0" bold="true" hTextAlign="Left">
<element kind="staticText" uuid="c1356370-11ce-4b68-97d6-ce6e18e306c5" x="0" y="150" width="51" height="16" fontName="Times New Roman" fontSize="10.0" bold="true" hTextAlign="Left">
<text><![CDATA[Huyết áp:]]></text>
</element>
<element kind="textField" uuid="3e1069a6-daea-45c2-b21f-935b49baba45" x="50" y="150" width="50" height="16" fontName="Times New Roman" fontSize="10.0">
<element kind="textField" uuid="3e1069a6-daea-45c2-b21f-935b49baba45" x="340" y="150" width="58" height="16" fontName="Times New Roman" fontSize="10.0">
<expression><![CDATA[$P{checkupWeight} +" cm"]]></expression>
</element>
<element kind="textField" uuid="fb080012-3196-4535-bcd2-e87274c66fa5" x="147" y="150" width="53" height="16" fontName="Times New Roman" fontSize="10.0">
@@ -130,20 +131,23 @@
<element kind="textField" uuid="e4185ffe-8712-41e3-a9ff-2be6569dff15" x="243" y="150" width="47" height="16" fontName="Times New Roman" fontSize="10.0">
<expression><![CDATA[$P{checkupHeartBeat} + " l/p"]]></expression>
</element>
<element kind="textField" uuid="6b0b21be-2ca3-4594-bbe9-34868e13eb1e" x="335" y="150" width="63" height="16" fontName="Times New Roman" fontSize="10.0">
<element kind="textField" uuid="6b0b21be-2ca3-4594-bbe9-34868e13eb1e" x="45" y="150" width="55" height="16" fontName="Times New Roman" fontSize="10.0">
<expression><![CDATA[$P{checkupBloodPressure} +" mmHg"]]></expression>
</element>
<element kind="component" uuid="e8842007-3343-4399-a101-76a302d0755d" x="362" y="19" width="38" height="35">
<element kind="component" uuid="e8842007-3343-4399-a101-76a302d0755d" x="354" y="1" width="44" height="37">
<component kind="barcode4j:QRCode">
<codeExpression><![CDATA[$P{driveURL}]]></codeExpression>
</component>
</element>
<element kind="textField" uuid="9763a634-05c2-4f64-a903-c914455b7ee6" x="70" y="57" width="282" height="20" forecolor="#FF0905" fontName="Times New Roman" fontSize="12.0" bold="true" hTextAlign="Center">
<element kind="textField" uuid="9763a634-05c2-4f64-a903-c914455b7ee6" x="70" y="60" width="282" height="22" forecolor="#FF0905" fontName="Times New Roman" fontSize="12.0" bold="true" hTextAlign="Center">
<printWhenExpression><![CDATA[$P{templateTitle} != null && !$P{templateTitle}.trim().isEmpty()]]></printWhenExpression>
<expression><![CDATA["PHIẾU " + $P{templateTitle}]]></expression>
</element>
<element kind="textField" uuid="40902efd-728a-46df-8432-f4a5798a4ee3" x="60" y="13" width="260" height="20" forecolor="#FF0905" fontName="Times New Roman" fontSize="14.0" bold="true" hTextAlign="Center">
<expression><![CDATA[$P{clinicName}]]></expression>
</element>
</element>
<element kind="frame" uuid="a72ffc70-007e-43af-a566-b34e6e07b312" x="400" y="0" width="400" height="540">
<element kind="frame" uuid="a72ffc70-007e-43af-a566-b34e6e07b312" x="400" y="0" width="400" height="538">
<element kind="staticText" uuid="246a04b0-2565-4987-b7f3-dd369703035c" x="0" y="340" width="100" height="30" forecolor="#FF0905" fontName="Times New Roman" fontSize="15.0" bold="true">
<text><![CDATA[III.Kết luận]]></text>
</element>
@@ -153,19 +157,19 @@
<element kind="staticText" uuid="a38b1187-ddb8-4410-9b52-dc041f894b7b" x="250" y="440" width="96" height="15" fontName="Times New Roman" fontSize="12.0" bold="true" hTextAlign="Center">
<text><![CDATA[Bác sĩ siêu âm]]></text>
</element>
<element kind="textField" uuid="b548d99d-bedf-4e90-b13b-bdbc763aa974" x="200" y="513" width="200" height="21" fontName="Times New Roman" fontSize="14.0" bold="true" hTextAlign="Center">
<element kind="textField" uuid="b548d99d-bedf-4e90-b13b-bdbc763aa974" x="199" y="512" width="200" height="21" fontName="Times New Roman" fontSize="14.0" bold="true" hTextAlign="Center">
<expression><![CDATA[$P{ultrasoundDoctorName}]]></expression>
</element>
<element kind="textField" uuid="8bca58ab-0958-40fe-8e51-2a39a9d379a5" x="200" y="521" width="200" height="19" fontName="Times New Roman" pattern="MMMMM dd, yyyy" hTextAlign="Center" vTextAlign="Bottom">
<element kind="textField" uuid="8bca58ab-0958-40fe-8e51-2a39a9d379a5" x="199" y="518" width="200" height="19" fontName="Times New Roman" pattern="MMMMM dd, yyyy" hTextAlign="Center" vTextAlign="Bottom">
<expression><![CDATA[new java.text.SimpleDateFormat("'Đức Hoà, ngày ' dd ' tháng ' MM ' năm ' yyyy", new java.util.Locale("vi", "VN")).format(new java.util.Date())]]></expression>
</element>
<element kind="staticText" uuid="c062ce0e-80cb-4e67-a5d9-d85e769c6c4e" x="0" y="525" width="110" height="14" forecolor="#FF0905" fontName="Times New Roman" fontSize="10.0" bold="true">
<element kind="staticText" uuid="c062ce0e-80cb-4e67-a5d9-d85e769c6c4e" x="0" y="523" width="110" height="14" forecolor="#FF0905" fontName="Times New Roman" fontSize="10.0" bold="true">
<text><![CDATA[Tái khám:]]></text>
</element>
<element kind="textField" uuid="e90ad772-4425-482d-9e75-f2bc66b9084d" x="0" y="358" width="400" height="70" fontName="Times New Roman" fontSize="12.0">
<element kind="textField" uuid="e90ad772-4425-482d-9e75-f2bc66b9084d" x="0" y="358" width="400" height="70" fontName="Times New Roman" fontSize="12.0" bold="true">
<expression><![CDATA[$P{checkupConclusion}]]></expression>
</element>
<element kind="component" uuid="cb28d811-1328-45dc-9461-cfbb88b7eeae" x="-105" y="19" width="64" height="40">
<element kind="component" uuid="cb28d811-1328-45dc-9461-cfbb88b7eeae" x="-105" y="30" width="59" height="32">
<component kind="barcode4j:Code128">
<codeExpression><![CDATA[$P{barcodeNumber}]]></codeExpression>
</component>
@@ -173,7 +177,7 @@
<element kind="textField" uuid="d63165c2-19e2-43ad-8a3f-004e00bffdfe" x="0" y="450" width="240" height="66" fontName="Times New Roman" fontSize="12.0">
<expression><![CDATA[$P{checkupSuggestion}]]></expression>
</element>
<element kind="textField" uuid="cece8e5b-67db-4019-b52a-bf73abae535e" x="48" y="525" width="150" height="15" fontName="Times New Roman" fontSize="12.0">
<element kind="textField" uuid="cece8e5b-67db-4019-b52a-bf73abae535e" x="48" y="522" width="150" height="15" fontName="Times New Roman" fontSize="12.0" bold="true">
<expression><![CDATA[$P{reCheckupDate}]]></expression>
</element>
<element kind="frame" uuid="2f301804-acfa-4b6f-9f52-236c04fd1197" x="0" y="0" width="400" height="344">
@@ -260,11 +264,17 @@
<expression><![CDATA[$P{image1}]]></expression>
</element>
</element>
<element kind="staticText" uuid="8f35aa72-22a4-45f0-a35e-8e35e832404e" x="-55" y="53" width="55" height="14" fontName="Times New Roman" fontSize="8.0" bold="false" hTextAlign="Center">
<element kind="staticText" uuid="8f35aa72-22a4-45f0-a35e-8e35e832404e" x="-46" y="39" width="44" height="21" fontName="Times New Roman" fontSize="8.0" bold="false" hTextAlign="Center">
<printWhenExpression><![CDATA[$P{driveURL} != null && !$P{driveURL}.trim().isEmpty()]]></printWhenExpression>
<text><![CDATA[Xem KQ online]]></text>
</element>
</element>
</band>
</detail>
<pageFooter height="17">
<element kind="textField" uuid="cd8229a4-b862-407a-88e2-807ab7c61699" x="548" y="2" width="252" height="12" fontName="Times New Roman" pattern="MMMMM dd, yyyy" hTextAlign="Right" vTextAlign="Bottom">
<expression><![CDATA[new java.text.SimpleDateFormat("dd/MM/yyyy HH:mm").format(new java.util.Date()) + " | Trang " + $V{PAGE_NUMBER}]]></expression>
<property name="com.jaspersoft.studio.unit.height" value="px"/>
</element>
</pageFooter>
</jasperReport>
@@ -38,6 +38,7 @@
<parameter name="templateTitle" class="java.lang.String"/>
<parameter name="driveURL" class="java.lang.String"/>
<parameter name="ultrasoundDoctorName" class="java.lang.String"/>
<parameter name="clinicPrefix" class="java.lang.String"/>
<query language="sql"><![CDATA[]]></query>
<background splitType="Stretch"/>
<title splitType="Stretch"/>
@@ -49,58 +50,58 @@
<element kind="image" uuid="fd80ab38-4cae-409b-84b9-356220d2b1e5" x="0" y="-5" width="70" height="64">
<expression><![CDATA[$P{logoImage}]]></expression>
</element>
<element kind="textField" uuid="eb56d4c8-2a0d-45fa-89a2-ad6528f9a99b" x="70" y="0" width="323" height="20" forecolor="#FF0905" fontName="Times New Roman" fontSize="14.0" bold="true">
<expression><![CDATA[$P{clinicName}]]></expression>
<element kind="textField" uuid="eb56d4c8-2a0d-45fa-89a2-ad6528f9a99b" x="70" y="-5" width="358" height="22" forecolor="#FF0905" fontName="Times New Roman" fontSize="14.0" bold="true" hTextAlign="Center">
<expression><![CDATA[$P{clinicPrefix}]]></expression>
</element>
<element kind="textField" uuid="796d9ffd-6d2e-4ae3-bdfb-b08183d7d9c0" x="70" y="20" width="323" height="22" fontName="Times New Roman" fontSize="10.0">
<element kind="textField" uuid="796d9ffd-6d2e-4ae3-bdfb-b08183d7d9c0" x="70" y="29" width="358" height="20" fontName="Times New Roman" fontSize="10.0">
<expression><![CDATA[$P{clinicAddress}]]></expression>
</element>
<element kind="textField" uuid="260bb33d-1d11-4178-aceb-3fbf8fcb4b45" x="70" y="42" width="276" height="15" fontName="Times New Roman" fontSize="8.0">
<element kind="textField" uuid="260bb33d-1d11-4178-aceb-3fbf8fcb4b45" x="70" y="41" width="276" height="15" fontName="Times New Roman" fontSize="8.0">
<expression><![CDATA[$P{clinicPhone}]]></expression>
</element>
<element kind="staticText" uuid="6f89a93f-2d10-4506-baa5-226bdd047b17" x="0" y="65" width="100" height="30" forecolor="#FF0905" fontName="Times New Roman" fontSize="14.0" bold="true">
<text><![CDATA[I.Thông tin]]></text>
</element>
<element kind="staticText" uuid="b8dfca43-cf97-49e5-b58d-4667143dba62" x="0" y="79" width="50" height="15" fontName="Times New Roman" fontSize="10.0" bold="true" hTextAlign="Left">
<element kind="staticText" uuid="b8dfca43-cf97-49e5-b58d-4667143dba62" x="0" y="79" width="59" height="15" fontName="Times New Roman" fontSize="12.0" bold="true" hTextAlign="Left">
<text><![CDATA[Họ và tên:]]></text>
</element>
<element kind="staticText" uuid="0a9ca0c8-f2bd-4ade-a025-a6d79c13613f" x="1" y="94" width="80" height="15" fontName="Times New Roman" fontSize="10.0" bold="true" hTextAlign="Left">
<element kind="staticText" uuid="0a9ca0c8-f2bd-4ade-a025-a6d79c13613f" x="1" y="94" width="80" height="15" fontName="Times New Roman" fontSize="12.0" bold="true" hTextAlign="Left">
<text><![CDATA[Ngày sinh:]]></text>
</element>
<element kind="staticText" uuid="21917ab8-ae07-44c8-ba4e-bc6c4c54b440" x="140" y="94" width="80" height="15" fontName="Times New Roman" fontSize="10.0" bold="true" hTextAlign="Left">
<element kind="staticText" uuid="21917ab8-ae07-44c8-ba4e-bc6c4c54b440" x="130" y="95" width="80" height="15" fontName="Times New Roman" fontSize="12.0" bold="true" hTextAlign="Left">
<text><![CDATA[Giới tính:]]></text>
</element>
<element kind="staticText" uuid="bcbb614e-7a4d-48a3-83c2-198e4fb62c5f" x="1" y="109" width="49" height="15" fontName="Times New Roman" bold="true" hTextAlign="Left">
<element kind="staticText" uuid="bcbb614e-7a4d-48a3-83c2-198e4fb62c5f" x="1" y="109" width="49" height="15" fontName="Times New Roman" fontSize="12.0" bold="true" hTextAlign="Left">
<text><![CDATA[Địa chỉ:]]></text>
</element>
<element kind="staticText" uuid="45fe4be1-9e21-459b-aeee-2efc8354f372" x="221" y="80" width="68" height="15" fontName="Times New Roman" fontSize="10.0" bold="true" hTextAlign="Left">
<element kind="staticText" uuid="45fe4be1-9e21-459b-aeee-2efc8354f372" x="221" y="80" width="89" height="15" fontName="Times New Roman" fontSize="12.0" bold="true" hTextAlign="Left">
<text><![CDATA[Bác sĩ chỉ định:]]></text>
</element>
<element kind="staticText" uuid="f2ff4b17-63cc-4e8c-a3b0-2523f534f21a" x="221" y="94" width="60" height="15" fontName="Times New Roman" fontSize="10.0" bold="true" hTextAlign="Left">
<element kind="staticText" uuid="f2ff4b17-63cc-4e8c-a3b0-2523f534f21a" x="221" y="94" width="69" height="15" fontName="Times New Roman" fontSize="12.0" bold="true" hTextAlign="Left">
<text><![CDATA[Ngày khám:]]></text>
</element>
<element kind="textField" uuid="1511f53a-b282-41b1-b233-612b6106c07a" x="48" y="79" width="172" height="15" fontName="Times New Roman" fontSize="10.0">
<element kind="textField" uuid="1511f53a-b282-41b1-b233-612b6106c07a" x="56" y="79" width="165" height="15" fontName="Times New Roman" fontSize="12.0">
<expression><![CDATA[$P{patientName}]]></expression>
</element>
<element kind="textField" uuid="5bdac267-523d-4931-926b-76233ce9b84d" x="50" y="94" width="80" height="15" fontName="Times New Roman" fontSize="10.0">
<element kind="textField" uuid="5bdac267-523d-4931-926b-76233ce9b84d" x="60" y="93" width="70" height="15" fontName="Times New Roman" fontSize="12.0">
<expression><![CDATA[$P{patientDOB}]]></expression>
</element>
<element kind="textField" uuid="f4df20b4-920c-491e-882b-6e0733cb4866" x="184" y="94" width="36" height="15" fontName="Times New Roman" fontSize="10.0">
<element kind="textField" uuid="f4df20b4-920c-491e-882b-6e0733cb4866" x="185" y="95" width="36" height="15" fontName="Times New Roman" fontSize="12.0">
<expression><![CDATA[$P{patientGender}]]></expression>
</element>
<element kind="textField" uuid="3b8ac40e-85aa-4ab8-8445-64bcddb8b267" x="39" y="109" width="361" height="15" fontName="Times New Roman" fontSize="10.0">
<element kind="textField" uuid="3b8ac40e-85aa-4ab8-8445-64bcddb8b267" x="50" y="109" width="350" height="15" fontName="Times New Roman" fontSize="12.0">
<expression><![CDATA[$P{patientAddress}]]></expression>
</element>
<element kind="textField" uuid="db40cdb0-2850-4d66-8430-addc54f90321" x="290" y="80" width="110" height="15" fontName="Times New Roman" fontSize="10.0">
<element kind="textField" uuid="db40cdb0-2850-4d66-8430-addc54f90321" x="300" y="80" width="110" height="15" fontName="Times New Roman" fontSize="12.0">
<expression><![CDATA[$P{doctorName}]]></expression>
</element>
<element kind="textField" uuid="eb9cf54a-3b50-43c5-8696-cfc1e21bddfe" x="276" y="94" width="124" height="15" fontName="Times New Roman" fontSize="10.0">
<element kind="textField" uuid="eb9cf54a-3b50-43c5-8696-cfc1e21bddfe" x="290" y="94" width="110" height="15" fontName="Times New Roman" fontSize="12.0">
<expression><![CDATA[$P{checkupDate}]]></expression>
</element>
<element kind="staticText" uuid="9f7de81c-4c38-41a2-9fea-a165eff19431" x="1" y="124" width="59" height="16" fontName="Times New Roman" fontSize="10.0" bold="true" hTextAlign="Left">
<element kind="staticText" uuid="9f7de81c-4c38-41a2-9fea-a165eff19431" x="1" y="124" width="69" height="16" fontName="Times New Roman" fontSize="12.0" bold="true" hTextAlign="Left">
<text><![CDATA[Chuẩn đoán:]]></text>
</element>
<element kind="textField" uuid="5ae67e13-7a79-437f-bfb8-c720d896720d" x="60" y="124" width="340" height="26" fontName="Times New Roman" fontSize="10.0">
<element kind="textField" uuid="5ae67e13-7a79-437f-bfb8-c720d896720d" x="70" y="124" width="329" height="26" fontName="Times New Roman" fontSize="12.0">
<expression><![CDATA[$P{patientDiagnos}]]></expression>
</element>
<element kind="staticText" uuid="b1fa845a-48da-4e45-82b8-8b9d972650f6" x="0" y="162" width="100" height="30" forecolor="#FF0905" fontName="Times New Roman" fontSize="14.0" bold="true">
@@ -109,44 +110,44 @@
<element kind="textField" uuid="6d652a25-b701-45bd-91ba-750842650004" x="0" y="177" width="400" height="421" markup="rtf" fontName="Times New Roman" fontSize="16.0">
<expression><![CDATA[$P{checkupNote}]]></expression>
</element>
<element kind="staticText" uuid="8f720f6a-0257-4556-b3bc-3b81ad4f8099" x="1" y="150" width="59" height="16" fontName="Times New Roman" fontSize="10.0" bold="true" hTextAlign="Left">
<element kind="staticText" uuid="8f720f6a-0257-4556-b3bc-3b81ad4f8099" x="300" y="150" width="59" height="16" fontName="Times New Roman" fontSize="12.0" bold="true" hTextAlign="Left">
<text><![CDATA[Chiều cao:]]></text>
</element>
<element kind="staticText" uuid="a57e7a9d-4ac7-4219-b268-cd08ce943327" x="100" y="150" width="59" height="16" fontName="Times New Roman" fontSize="10.0" bold="true" hTextAlign="Left">
<element kind="staticText" uuid="a57e7a9d-4ac7-4219-b268-cd08ce943327" x="110" y="150" width="59" height="16" fontName="Times New Roman" fontSize="12.0" bold="true" hTextAlign="Left">
<text><![CDATA[Cân nặng:]]></text>
</element>
<element kind="staticText" uuid="2b9cfd9d-ec8f-4036-9c96-039fd7855e24" x="200" y="150" width="59" height="16" fontName="Times New Roman" fontSize="10.0" bold="true" hTextAlign="Left">
<element kind="staticText" uuid="2b9cfd9d-ec8f-4036-9c96-039fd7855e24" x="210" y="150" width="59" height="16" fontName="Times New Roman" fontSize="12.0" bold="true" hTextAlign="Left">
<text><![CDATA[Nhịp tim:]]></text>
</element>
<element kind="staticText" uuid="c1356370-11ce-4b68-97d6-ce6e18e306c5" x="290" y="150" width="59" height="16" fontName="Times New Roman" fontSize="10.0" bold="true" hTextAlign="Left">
<element kind="staticText" uuid="c1356370-11ce-4b68-97d6-ce6e18e306c5" x="0" y="150" width="59" height="16" fontName="Times New Roman" fontSize="12.0" bold="true" hTextAlign="Left">
<text><![CDATA[Huyết áp:]]></text>
</element>
<element kind="textField" uuid="3e1069a6-daea-45c2-b21f-935b49baba45" x="50" y="150" width="50" height="16" fontName="Times New Roman" fontSize="10.0">
<element kind="textField" uuid="3e1069a6-daea-45c2-b21f-935b49baba45" x="356" y="150" width="44" height="16" fontName="Times New Roman" fontSize="12.0">
<expression><![CDATA[$P{checkupWeight} +" cm"]]></expression>
</element>
<element kind="textField" uuid="fb080012-3196-4535-bcd2-e87274c66fa5" x="147" y="150" width="53" height="16" fontName="Times New Roman" fontSize="10.0">
<element kind="textField" uuid="fb080012-3196-4535-bcd2-e87274c66fa5" x="165" y="150" width="45" height="16" fontName="Times New Roman" fontSize="12.0">
<expression><![CDATA[$P{checkupWeight} + " kg"]]></expression>
</element>
<element kind="textField" uuid="e4185ffe-8712-41e3-a9ff-2be6569dff15" x="243" y="150" width="47" height="16" fontName="Times New Roman" fontSize="10.0">
<element kind="textField" uuid="e4185ffe-8712-41e3-a9ff-2be6569dff15" x="261" y="150" width="39" height="16" fontName="Times New Roman" fontSize="12.0">
<expression><![CDATA[$P{checkupHeartBeat} + " l/p"]]></expression>
</element>
<element kind="textField" uuid="6b0b21be-2ca3-4594-bbe9-34868e13eb1e" x="335" y="150" width="65" height="16" fontName="Times New Roman" fontSize="10.0">
<element kind="textField" uuid="6b0b21be-2ca3-4594-bbe9-34868e13eb1e" x="52" y="150" width="58" height="16" fontName="Times New Roman" fontSize="12.0">
<expression><![CDATA[$P{checkupBloodPressure} +" mmHg"]]></expression>
</element>
<element kind="component" uuid="e8842007-3343-4399-a101-76a302d0755d" x="486" y="16" width="53" height="49">
<element kind="component" uuid="e8842007-3343-4399-a101-76a302d0755d" x="499" y="17" width="52" height="48">
<component kind="barcode4j:QRCode">
<codeExpression><![CDATA[$P{driveURL}]]></codeExpression>
</component>
</element>
<element kind="textField" uuid="9763a634-05c2-4f64-a903-c914455b7ee6" x="70" y="57" width="282" height="20" forecolor="#FF0905" fontName="Times New Roman" fontSize="12.0" bold="true" hTextAlign="Center">
<element kind="textField" uuid="9763a634-05c2-4f64-a903-c914455b7ee6" x="70" y="61" width="282" height="20" forecolor="#FF0905" fontName="Times New Roman" fontSize="12.0" bold="true" hTextAlign="Center">
<printWhenExpression><![CDATA[$P{templateTitle} != null && !$P{templateTitle}.trim().isEmpty()]]></printWhenExpression>
<expression><![CDATA["PHIẾU " + $P{templateTitle}]]></expression>
</element>
<element kind="staticText" uuid="8f35aa72-22a4-45f0-a35e-8e35e832404e" x="484" y="65" width="55" height="14" fontName="Times New Roman" fontSize="8.0" bold="false" hTextAlign="Center">
<element kind="staticText" uuid="8f35aa72-22a4-45f0-a35e-8e35e832404e" x="495" y="64" width="55" height="14" fontName="Times New Roman" fontSize="8.0" bold="false" hTextAlign="Center">
<printWhenExpression><![CDATA[$P{driveURL} != null && !$P{driveURL}.trim().isEmpty()]]></printWhenExpression>
<text><![CDATA[Xem KQ online]]></text>
</element>
<element kind="component" uuid="73f562ce-2891-4577-aec2-7284203c8430" x="394" y="21" width="70" height="49">
<element kind="component" uuid="73f562ce-2891-4577-aec2-7284203c8430" x="429" y="15" width="70" height="49">
<component kind="barcode4j:Code128">
<codeExpression><![CDATA[$P{barcodeNumber}]]></codeExpression>
</component>
@@ -160,12 +161,21 @@
<element kind="image" uuid="2902cf3c-31dd-4b96-be87-fa8a13ba88ae" x="400" y="342" width="151" height="124">
<expression><![CDATA[$P{image3}]]></expression>
</element>
<element kind="image" uuid="129e6c61-d572-48a9-925e-1ab2e4e573e2" x="400" y="468" width="151" height="129">
<element kind="image" uuid="129e6c61-d572-48a9-925e-1ab2e4e573e2" x="400" y="466" width="151" height="124">
<expression><![CDATA[$P{image4}]]></expression>
</element>
<element kind="textField" uuid="5fde8538-8d26-4761-9a19-dd716a74749a" x="70" y="12" width="358" height="20" forecolor="#FF0905" fontName="Times New Roman" fontSize="14.0" bold="true" hTextAlign="Center">
<expression><![CDATA[$P{clinicName}]]></expression>
</element>
</element>
</band>
</detail>
<pageFooter height="20">
<element kind="textField" uuid="e94aab84-4f90-4496-bc35-17547a2fa18a" x="300" y="0" width="252" height="17" fontName="Times New Roman" pattern="MMMMM dd, yyyy" hTextAlign="Right" vTextAlign="Bottom">
<expression><![CDATA[new java.text.SimpleDateFormat("dd/MM/yyyy HH:mm").format(new java.util.Date()) + " | Trang " + $V{PAGE_NUMBER}]]></expression>
<property name="com.jaspersoft.studio.unit.height" value="px"/>
</element>
</pageFooter>
<summary height="179">
<element kind="staticText" uuid="b6ee4329-aeb1-4ddf-99e8-41ebebaff12b" x="0" y="0" width="100" height="30" forecolor="#FF0905" fontName="Times New Roman" fontSize="15.0" bold="true">
<text><![CDATA[III.Kết luận]]></text>
@@ -530,9 +530,9 @@ public class DataDialog extends JDialog {
public ActionButtonRenderer() {
setLayout(new FlowLayout(FlowLayout.CENTER, 2, 2));
ImageIcon editIcon = createIcon("/BsK/client/ui/assets/icon/edit.png", 16, 16);
ImageIcon editIcon = createIcon("src/main/java/BsK/client/ui/assets/icon/edit.png", 16, 16);
editButton = new JButton(editIcon);
ImageIcon deleteIcon = createIcon("/BsK/client/ui/assets/icon/delete.png", 16, 16);
ImageIcon deleteIcon = createIcon("src/main/java/BsK/client/ui/assets/icon/delete.png", 16, 16);
deleteButton = new JButton(deleteIcon);
editButton.setPreferredSize(new Dimension(30, 25));
@@ -564,9 +564,9 @@ public class DataDialog extends JDialog {
super(new JCheckBox());
panel = new JPanel(new FlowLayout(FlowLayout.CENTER, 2, 2));
ImageIcon editIcon = createIcon("/BsK/client/ui/assets/icon/edit.png", 16, 16);
ImageIcon editIcon = createIcon("src/main/java/BsK/client/ui/assets/icon/edit.png", 16, 16);
editButton = new JButton(editIcon);
ImageIcon deleteIcon = createIcon("/BsK/client/ui/assets/icon/delete.png", 16, 16);
ImageIcon deleteIcon = createIcon("src/main/java/BsK/client/ui/assets/icon/delete.png", 16, 16);
deleteButton = new JButton(deleteIcon);
editButton.setPreferredSize(new Dimension(30, 25));
@@ -37,12 +37,13 @@ public class MedicineManagementPanel extends JPanel {
private JTextField medicineNameField;
private JTextField medicineCompanyField;
private JTextArea medicineDescriptionField;
private JTextField routeField; // --- ADDED --- Field for Route of Administration
private JTextField medicineUnitField;
private JTextField medicinePriceField;
private JSpinner morningSpinner, noonSpinner, eveningSpinner;
private JTextArea noteField;
private JCheckBox chkIsDeleted; // Checkbox for soft delete
private JCheckBox chkIsSupplement; // Checkbox for supplement status
private JCheckBox chkIsDeleted; // Checkbox for soft delete
private JCheckBox chkIsSupplement; // Checkbox for supplement status
// --- Action Buttons ---
private JButton btnAdd, btnEdit, btnClear;
@@ -151,6 +152,22 @@ public class MedicineManagementPanel extends JPanel {
medicineInfoPanel.add(descriptionScrollPane, gbc);
gbc.weightx = 0.0;
// --- ADDED: Route of Administration Field ---
gbc.gridy++;
gbc.gridx = 0;
JLabel routeLabel = new JLabel("Đường dùng:");
routeLabel.setFont(labelFont);
medicineInfoPanel.add(routeLabel, gbc);
gbc.gridx = 1;
gbc.weightx = 1.0;
routeField = new JTextField(20);
routeField.setFont(textFont);
routeField.setPreferredSize(textFieldSize);
medicineInfoPanel.add(routeField, gbc);
gbc.weightx = 0.0;
// --- END ADDED ---
mainGbc.gridx = 0; mainGbc.gridy = 0;
mainInputPanel.add(medicineInfoPanel, mainGbc);
@@ -331,6 +348,7 @@ public class MedicineManagementPanel extends JPanel {
// 2. Gather data from all other fields
String company = medicineCompanyField.getText().trim();
String description = medicineDescriptionField.getText().trim();
String route = routeField.getText().trim(); // --- ADDED ---
String unit = medicineUnitField.getText().trim();
Boolean isSupplement = chkIsSupplement.isSelected();
Boolean isDeleted = false; // New medicines are active by default
@@ -352,13 +370,13 @@ public class MedicineManagementPanel extends JPanel {
// 4. Construct the special 'preferredNote' string
String preferredNote = morningSpinner.getValue().toString() + ","
+ noonSpinner.getValue().toString() + ","
+ eveningSpinner.getValue().toString() + ","
+ noteField.getText().trim();
+ noonSpinner.getValue().toString() + ","
+ eveningSpinner.getValue().toString() + ","
+ noteField.getText().trim();
// 5. Create the request packet and send it to the server
// IMPORTANT: Assumes your AddMedicineRequest packet is updated to include 'supplement'
AddMedicineRequest request = new AddMedicineRequest(name, company, description, unit, price, preferredNote, isSupplement, isDeleted);
// --- UPDATED ---: Added 'route' to the request constructor
AddMedicineRequest request = new AddMedicineRequest(name, company, description, unit, price, preferredNote, isSupplement, isDeleted, route);
NetworkUtil.sendPacket(ClientHandler.ctx.channel(), request);
// 6. Provide feedback and reset the form
@@ -393,6 +411,7 @@ public class MedicineManagementPanel extends JPanel {
String id = selectedMedicineId;
String company = medicineCompanyField.getText().trim();
String description = medicineDescriptionField.getText().trim();
String route = routeField.getText().trim(); // --- ADDED ---
String unit = medicineUnitField.getText().trim();
Boolean isSupplement = chkIsSupplement.isSelected();
Boolean isDeleted = chkIsDeleted.isSelected();
@@ -414,13 +433,13 @@ public class MedicineManagementPanel extends JPanel {
// 5. Construct the 'preferredNote' string
String preferredNote = morningSpinner.getValue().toString() + ","
+ noonSpinner.getValue().toString() + ","
+ eveningSpinner.getValue().toString() + ","
+ noteField.getText().trim();
+ noonSpinner.getValue().toString() + ","
+ eveningSpinner.getValue().toString() + ","
+ noteField.getText().trim();
// 6. Create the request packet and send it
// IMPORTANT: Assumes your EditMedicineRequest packet is updated to include 'supplement'
EditMedicineRequest request = new EditMedicineRequest(id, name, company, description, unit, price, preferredNote, isSupplement, isDeleted);
// --- UPDATED ---: Added 'route' to the request constructor
EditMedicineRequest request = new EditMedicineRequest(id, name, company, description, unit, price, preferredNote, isSupplement, isDeleted, route);
NetworkUtil.sendPacket(ClientHandler.ctx.channel(), request);
// 7. Provide user feedback and clear the form
@@ -507,6 +526,7 @@ public class MedicineManagementPanel extends JPanel {
medicineNameField.setText(med.getName());
medicineCompanyField.setText(med.getCompany());
medicineDescriptionField.setText(med.getDescription());
routeField.setText(med.getRoute()); // --- ADDED ---
medicineUnitField.setText(med.getUnit());
medicinePriceField.setText(med.getSellingPrice());
@@ -552,6 +572,7 @@ public class MedicineManagementPanel extends JPanel {
medicineNameField.setText("");
medicineCompanyField.setText("");
medicineDescriptionField.setText("");
routeField.setText(""); // --- ADDED ---
medicineUnitField.setText("");
medicinePriceField.setText("");
@@ -149,7 +149,7 @@ public class UserManagementPanel extends JPanel {
panel.add(new JLabel("Vai trò:"), gbc);
gbc.gridx = 1;
gbc.weightx = 1;
roleComboBox = new JComboBox<>(new String[]{"ADMIN", "DOCTOR", "STAFF"});
roleComboBox = new JComboBox<>(new String[]{"ADMIN", "USER"});
panel.add(roleComboBox, gbc);
}
@@ -18,17 +18,18 @@ import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableColumnModel;
import java.awt.*;
import java.awt.event.*;
import java.text.NumberFormat; // --- ADD THIS IMPORT ---
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Locale; // --- ADD THIS IMPORT ---
import java.util.Locale;
@Slf4j
public class MedicineDialog extends JDialog {
private JTextField medicineNameField;
private JTextField medicineCompanyField;
private JTextArea medicineDescriptionField;
private JTextField routeField; // --- ADDED ---
private JCheckBox chkIsSupplement; // The new checkbox
private JSpinner quantitySpinner;
private JComboBox<String> UnitComboBox;
@@ -258,6 +259,23 @@ public class MedicineDialog extends JDialog {
medicineInfoPanel.add(descriptionScrollPane, gbc);
gbc.weightx = 0.0;
// --- ADDED: Route of Administration Field ---
gbc.gridy++;
gbc.gridx = 0;
JLabel routeLabel = new JLabel("Đường dùng:");
routeLabel.setFont(labelFont);
medicineInfoPanel.add(routeLabel, gbc);
gbc.gridx = 1;
gbc.weightx = 1.0;
routeField = new JTextField(20);
routeField.setFont(textFont);
routeField.setPreferredSize(textFieldSize);
routeField.setEditable(false);
medicineInfoPanel.add(routeField, gbc);
gbc.weightx = 0.0;
// --- END ADDED ---
gbc.gridy++;
gbc.gridx = 0;
gbc.gridwidth = 2;
@@ -408,10 +426,12 @@ public class MedicineDialog extends JDialog {
suggestionPopup.add(suggestionScrollPane, BorderLayout.CENTER);
suggestionPopup.setFocusable(false);
String[] selectedColumnNames = {"ID", "Tên thuốc", "SL", "ĐVT", "Sáng", "Trưa", "Chiều", "Đơn giá", "Thành tiền", "Ghi chú", "Supplement"};
// --- UPDATED: Added "Đường dùng" column ---
String[] selectedColumnNames = {"ID", "Tên thuốc", "SL", "ĐVT", "Sáng", "Trưa", "Chiều", "Đơn giá", "Thành tiền", "Ghi chú", "Supplement", "Đường dùng"};
selectedTableModel = new DefaultTableModel(new String[][]{}, selectedColumnNames) {
@Override
public boolean isCellEditable(int row, int column) {
// Allow editing Quantity, Dosage, and Note
return column == 2 || column == 4 || column == 5 || column == 6 || column == 9;
}
};
@@ -603,8 +623,9 @@ public class MedicineDialog extends JDialog {
logger.info("Prescription saved.");
if (medicinePrescription != null) {
for (String[] row : medicinePrescription) {
logger.info("Med: ID={}, Name={}, Qty={}, Unit={}, M={}, N={}, E={}, Price={}, Total={}, Note={}",
row[0], row[1], row[2], row[3], row[4], row[5], row[6], row[7], row[8], row[9]);
// --- UPDATED: Logged the new 'route' field ---
logger.info("Med: ID={}, Name={}, Qty={}, Unit={}, M={}, N={}, E={}, Price={}, Total={}, Note={}, Supp={}, Route={}",
row[0], row[1], row[2], row[3], row[4], row[5], row[6], row[7], row[8], row[9], row[10], row[11]);
}
}
dispose();
@@ -724,6 +745,7 @@ public class MedicineDialog extends JDialog {
medicineCompanyField.setText(medicine.getCompany());
medicineDescriptionField.setText(medicine.getDescription());
routeField.setText(medicine.getRoute()); // --- ADDED ---
UnitComboBox.setSelectedItem(medicine.getUnit());
priceField.setText(medicine.getSellingPrice());
@@ -764,6 +786,7 @@ public class MedicineDialog extends JDialog {
// Don't clear the name field as the user is typing in it
medicineCompanyField.setText("");
medicineDescriptionField.setText("");
routeField.setText(""); // --- ADDED ---
UnitComboBox.setSelectedIndex(0);
priceField.setText("");
totalField.setText("");
@@ -800,7 +823,7 @@ public class MedicineDialog extends JDialog {
private void addSelectedMedicine() {
int selectedRowInSuggestionTable = suggestionTable.getSelectedRow();
String medicineId, name, unit, currentPrice, supplement;
String medicineId, name, unit, currentPrice, supplement, route; // --- UPDATED ---
String searchName = medicineNameField.getText().trim();
if (searchName.isEmpty()) {
@@ -835,6 +858,7 @@ public class MedicineDialog extends JDialog {
unit = selectedMedicine.getUnit();
currentPrice = selectedMedicine.getSellingPrice();
supplement = selectedMedicine.getSupplement();
route = selectedMedicine.getRoute(); // --- ADDED ---
int quantity = (Integer) quantitySpinner.getValue();
int morningVal = (Integer) morningSpinner.getValue();
@@ -848,8 +872,8 @@ public class MedicineDialog extends JDialog {
return;
}
// Include supplement information
selectedTableModel.addRow(new Object[]{medicineId, name, quantity, unit, morningVal, noonVal, eveningVal, currentPrice, totalAmount, note, supplement});
// --- UPDATED: Add 'route' to the table row data ---
selectedTableModel.addRow(new Object[]{medicineId, name, quantity, unit, morningVal, noonVal, eveningVal, currentPrice, totalAmount, note, supplement, route});
// Clear fields for next entry
isProgrammaticallySettingMedicineNameField = true;
@@ -874,22 +898,27 @@ public class MedicineDialog extends JDialog {
medicinePrescription = new String[0][0];
return;
}
medicinePrescription = new String[rowCount][11];
// --- UPDATED: Array size changed from 11 to 12 ---
medicinePrescription = new String[rowCount][12];
for (int i = 0; i < rowCount; i++) {
medicinePrescription[i][0] = selectedTableModel.getValueAt(i, 0).toString();
medicinePrescription[i][1] = selectedTableModel.getValueAt(i, 1).toString();
medicinePrescription[i][2] = selectedTableModel.getValueAt(i, 2).toString();
medicinePrescription[i][3] = selectedTableModel.getValueAt(i, 3).toString();
medicinePrescription[i][4] = selectedTableModel.getValueAt(i, 4).toString();
medicinePrescription[i][5] = selectedTableModel.getValueAt(i, 5).toString();
medicinePrescription[i][6] = selectedTableModel.getValueAt(i, 6).toString();
medicinePrescription[i][7] = selectedTableModel.getValueAt(i, 7).toString();
medicinePrescription[i][8] = selectedTableModel.getValueAt(i, 8).toString();
medicinePrescription[i][9] = selectedTableModel.getValueAt(i, 9).toString();
medicinePrescription[i][0] = selectedTableModel.getValueAt(i, 0).toString(); // ID
medicinePrescription[i][1] = selectedTableModel.getValueAt(i, 1).toString(); // Tên
medicinePrescription[i][2] = selectedTableModel.getValueAt(i, 2).toString(); // SL
medicinePrescription[i][3] = selectedTableModel.getValueAt(i, 3).toString(); // ĐVT
medicinePrescription[i][4] = selectedTableModel.getValueAt(i, 4).toString(); // Sáng
medicinePrescription[i][5] = selectedTableModel.getValueAt(i, 5).toString(); // Trưa
medicinePrescription[i][6] = selectedTableModel.getValueAt(i, 6).toString(); // Chiều
medicinePrescription[i][7] = selectedTableModel.getValueAt(i, 7).toString(); // Đơn giá
medicinePrescription[i][8] = selectedTableModel.getValueAt(i, 8).toString(); // Thành tiền
medicinePrescription[i][9] = selectedTableModel.getValueAt(i, 9).toString(); // Ghi chú
// Get supplement value (0/1) or default to "0" if null
Object supplementObj = selectedTableModel.getValueAt(i, 10);
medicinePrescription[i][10] = (supplementObj != null) ? supplementObj.toString() : "0";
medicinePrescription[i][10] = (supplementObj != null) ? supplementObj.toString() : "0"; // Supplement
// --- ADDED: Get route value ---
Object routeObj = selectedTableModel.getValueAt(i, 11);
medicinePrescription[i][11] = (routeObj != null) ? routeObj.toString() : ""; // Đường dùng
}
}
@@ -958,7 +987,8 @@ public class MedicineDialog extends JDialog {
if (prescription != null && prescription.length > 0) {
System.out.println("Prescription obtained:");
for (String[] item : prescription) {
System.out.println(String.format("ID:%s, Name:%s, Qty:%s, Unit:%s, M:%s, N:%s, E:%s, Price:%s, Total:%s, Note:%s",
// --- UPDATED: Test printout format ---
System.out.println(String.format("ID:%s, Name:%s, Qty:%s, Unit:%s, M:%s, N:%s, E:%s, Price:%s, Total:%s, Note:%s, Supp:%s, Route:%s",
(Object[]) item));
}
} else {
@@ -20,6 +20,7 @@ public class Medicine {
private String preferredNote;
private String supplement; // 0: no, 1: yes
private String deleted; // 0: no, 1: yes
private String route;
/**
* Constructor to create Medicine from array data
@@ -38,6 +39,7 @@ public class Medicine {
this.preferredNote = data[6];
this.supplement = data[7];
this.deleted = data[8];
this.route = data[9];
}
/**
@@ -45,6 +47,6 @@ public class Medicine {
* @return String array representation of Medicine
*/
public String[] toStringArray() {
return new String[]{id, name, company, description, unit, sellingPrice, preferredNote, supplement, deleted};
return new String[]{id, name, company, description, unit, sellingPrice, preferredNote, supplement, deleted, route};
}
}
@@ -15,4 +15,5 @@ public class AddMedicineRequest implements Packet{
private String preferredNote;
private Boolean supplement;
private Boolean deleted;
private String route;
}
@@ -16,4 +16,5 @@ public class EditMedicineRequest implements Packet {
private String preferredNote;
private Boolean supplement;
private Boolean deleted;
private String route;
}
@@ -12,4 +12,5 @@ public class ClinicInfoResponse implements Packet {
private String clinicName;
private String clinicAddress;
private String clinicPhone;
private String clinicPrefix;
}
+104 -181
View File
@@ -2,6 +2,8 @@ package BsK.server;
import BsK.server.network.handler.ServerHandler;
import BsK.server.service.GoogleDriveServiceOAuth;
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
@@ -23,32 +25,32 @@ import java.io.IOException;
import java.io.InputStream;
import java.net.InetSocketAddress;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;
import java.util.concurrent.TimeUnit;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class Server {
private static int PORT;
public static Connection connection;
public static GoogleDriveServiceOAuth googleDriveService;
private static boolean googleDriveEnabled = true; // Can be configured
private static String googleDriveRootFolderName = "BSK_Clinic_Patient_Files"; // Default
public static String imageDbPath = "img_db"; // Default
public static String checkupMediaBaseDir = "src/main/resources/image/checkup_media"; // Default
private static int PORT;
// --- REFACTORED DATABASE CONNECTION ---
// The single, static connection pool (DataSource). This is thread-safe.
private static HikariDataSource dataSource;
// These static fields are still okay as they are configured once at startup.
public static GoogleDriveServiceOAuth googleDriveService;
private static boolean googleDriveEnabled = true;
private static String googleDriveRootFolderName = "BSK_Clinic_Patient_Files";
public static String imageDbPath = "img_db";
public static String checkupMediaBaseDir = "src/main/resources/image/checkup_media";
// Static initializer block to set up the server configuration and connection pool
static {
try {
// Load configuration
// --- Load configuration ---
Properties props = new Properties();
// First try to load from external config file
File externalConfig = new File("config/config.properties");
if (externalConfig.exists()) {
try (var input = Files.newInputStream(externalConfig.toPath())) {
@@ -56,7 +58,6 @@ public class Server {
log.info("Loaded configuration from external file: {}", externalConfig.getAbsolutePath());
}
} else {
// Fall back to internal config
try (InputStream input = Server.class.getClassLoader().getResourceAsStream("config.properties")) {
if (input == null) {
log.error("Unable to find config.properties");
@@ -66,67 +67,108 @@ public class Server {
log.info("Loaded configuration from internal resources");
}
}
// Get port configuration
String portStr = props.getProperty("server.port");
String addressStr = props.getProperty("server.address");
// Log address configuration
if (addressStr != null) {
log.info("Server address configured as: {}", addressStr);
} else {
log.info("No server address configured, clients will need to use the correct address to connect");
}
// Get port configuration
if (portStr != null) {
PORT = Integer.parseInt(portStr);
log.info("Using configured port: {}", PORT);
} else {
PORT = 1999;
log.info("Using default port: {}", PORT);
}
// Get Google Drive configuration
String driveEnabledStr = props.getProperty("google.drive.enabled");
if (driveEnabledStr != null) {
googleDriveEnabled = Boolean.parseBoolean(driveEnabledStr);
}
String driveRootFolderStr = props.getProperty("google.drive.root.folder");
if (driveRootFolderStr != null && !driveRootFolderStr.trim().isEmpty()) {
googleDriveRootFolderName = driveRootFolderStr.trim();
}
log.info("Google Drive integration enabled: {}", googleDriveEnabled);
PORT = Integer.parseInt(props.getProperty("server.port", "1999"));
log.info("Using port: {}", PORT);
// Load other properties
googleDriveEnabled = Boolean.parseBoolean(props.getProperty("google.drive.enabled", "true"));
googleDriveRootFolderName = props.getProperty("google.drive.root.folder", "BSK_Clinic_Patient_Files").trim();
imageDbPath = props.getProperty("storage.image_db_path", "img_db").trim();
checkupMediaBaseDir = props.getProperty("storage.checkup_media_base_dir", "src/main/resources/image/checkup_media").trim();
log.info("Google Drive enabled: {}", googleDriveEnabled);
log.info("Google Drive root folder: {}", googleDriveRootFolderName);
// Get Storage paths configuration
String imageDbPathStr = props.getProperty("storage.image_db_path");
if (imageDbPathStr != null && !imageDbPathStr.trim().isEmpty()) {
imageDbPath = imageDbPathStr.trim();
}
String checkupMediaBaseDirStr = props.getProperty("storage.checkup_media_base_dir");
if (checkupMediaBaseDirStr != null && !checkupMediaBaseDirStr.trim().isEmpty()) {
checkupMediaBaseDir = checkupMediaBaseDirStr.trim();
}
log.info("Image DB path: {}", imageDbPath);
log.info("Checkup media base dir: {}", checkupMediaBaseDir);
// Directly use the provided database path
// --- DATABASE POOL INITIALIZATION ---
String dbPath = "src/main/resources/database/BSK.db";
connection = DriverManager.getConnection("jdbc:sqlite:" + dbPath);
// 1. Configure HikariCP
HikariConfig config = new HikariConfig();
config.setJdbcUrl("jdbc:sqlite:" + dbPath);
config.setConnectionTestQuery("SELECT 1");
config.setMaximumPoolSize(10); // Max 10 concurrent connections, perfect for your use case
config.setPoolName("BsK-DB-Pool");
config.addDataSourceProperty("cachePrepStmts", "true");
config.addDataSourceProperty("prepStmtCacheSize", "250");
config.addDataSourceProperty("prepStmtCacheSqlLimit", "2048");
// 2. Create the DataSource (the pool itself)
dataSource = new HikariDataSource(config);
log.info("✅ Database connection pool initialized successfully for {}", dbPath);
// Initialize Google Drive service if enabled
initializeGoogleDriveService();
} catch (Exception e) {
log.error("❌ Failed to initialize server", e);
throw new RuntimeException("Failed to initialize server", e);
}
}
/**
* This is the new, safe way for handlers to get a database connection.
* @return A database connection from the pool.
* @throws SQLException if a connection cannot be obtained.
*/
public static Connection getConnection() throws SQLException {
return dataSource.getConnection();
}
public static void main(String[] args) throws InterruptedException {
log.info("\n____ _____ _ __\n| _ \\ / ____| |/ \n| |_) | (___ | ' / \n| _ < \\___ \\| <\n| |_) |____) | . \\\n|____/|_____/|_|\\_\n");
ServerDashboard dashboard = ServerDashboard.getInstance();
dashboard.setVisible(true);
dashboard.updateStatus("Starting...", Color.ORANGE);
dashboard.updatePort(PORT);
dashboard.updateGoogleDriveStatus(isGoogleDriveConnected(), isGoogleDriveConnected() ? "Connected" : "Disconnected");
EventLoopGroup parentGroup = Epoll.isAvailable() ? new EpollEventLoopGroup() : new NioEventLoopGroup();
EventLoopGroup childGroup = Epoll.isAvailable() ? new EpollEventLoopGroup() : new NioEventLoopGroup();
try {
ServerBootstrap bootstrap = new ServerBootstrap()
.group(parentGroup, childGroup)
.channel(Epoll.isAvailable() ? EpollServerSocketChannel.class : NioServerSocketChannel.class)
.localAddress(new InetSocketAddress(PORT))
.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ch.pipeline()
.addLast(new IdleStateHandler(60 * 30, 0, 0, TimeUnit.SECONDS))
.addLast(new HttpServerCodec())
.addLast(new ChunkedWriteHandler())
.addLast(new HttpObjectAggregator(50 * 1024 * 1024))
.addLast(new WebSocketServerProtocolHandler("/", null, true, 50 * 1024 * 1024))
.addLast(new ServerHandler()); // A new handler for each client
}
});
ChannelFuture f = bootstrap.bind().sync();
log.info("Server started on port {}", PORT);
dashboard.updateStatus("Running", Color.GREEN);
dashboard.addLog("Server started successfully on port " + PORT);
f.channel().closeFuture().sync();
} catch (Exception e) {
dashboard.updateStatus("Error", Color.RED);
dashboard.addLog("Server error: " + e.getMessage());
log.error("Server crashed", e);
} finally {
dashboard.updateStatus("Shutting down", Color.ORANGE);
dashboard.addLog("Server shutting down...");
parentGroup.shutdownGracefully();
childGroup.shutdownGracefully();
if (dataSource != null) {
dataSource.close(); // Close the connection pool on shutdown
log.info("Database connection pool closed.");
}
}
}
// --- Google Drive and other helper methods ---
private static void initializeGoogleDriveService() {
if (!googleDriveEnabled) {
log.info("Google Drive integration is disabled");
@@ -139,7 +181,6 @@ public class Server {
googleDriveService = new GoogleDriveServiceOAuth(googleDriveRootFolderName);
log.info("✅ Google Drive OAuth service initialized successfully");
// Update dashboard if it exists
if (ServerDashboard.getInstance() != null) {
ServerDashboard.getInstance().updateGoogleDriveStatus(true, "Connected");
}
@@ -147,48 +188,31 @@ public class Server {
} catch (Exception e) {
log.error("❌ Failed to initialize Google Drive OAuth service: {}", e.getMessage());
log.info("💡 Server will continue without Google Drive integration");
log.info("🔧 To fix this, ensure google-oauth-credentials.json is properly configured");
googleDriveService = null;
// Update dashboard if it exists
if (ServerDashboard.getInstance() != null) {
ServerDashboard.getInstance().updateGoogleDriveStatus(false, "Failed: " + e.getMessage());
}
}
}
/**
* Manually retry Google Drive connection
*/
public static void retryGoogleDriveConnection() {
log.info("🔄 Retrying Google Drive connection...");
initializeGoogleDriveService();
}
/**
* Check if Google Drive is connected
*/
public static boolean isGoogleDriveConnected() {
return googleDriveService != null;
}
/**
* Get Google Drive service instance
*/
public static GoogleDriveServiceOAuth getGoogleDriveService() {
return googleDriveService;
}
/**
* Get the current Google Drive root folder name
*/
public static String getGoogleDriveRootFolderName() {
return googleDriveRootFolderName;
}
/**
* Update Google Drive root folder name and reinitialize service
*/
public static void updateGoogleDriveRootFolder(String newRootFolderName) throws Exception {
if (newRootFolderName == null || newRootFolderName.trim().isEmpty()) {
throw new IllegalArgumentException("Root folder name cannot be empty");
@@ -197,23 +221,17 @@ public class Server {
googleDriveRootFolderName = newRootFolderName.trim();
log.info("🔄 Updating Google Drive root folder to: {}", googleDriveRootFolderName);
// Save to configuration file
saveGoogleDriveRootFolderToConfig(googleDriveRootFolderName);
// Reinitialize Google Drive service with new root folder
if (googleDriveEnabled) {
initializeGoogleDriveService();
}
}
/**
* Save Google Drive root folder name to config file
*/
private static void saveGoogleDriveRootFolderToConfig(String rootFolderName) {
try {
Properties props = new Properties();
// Load existing properties
File externalConfig = new File("config/config.properties");
if (externalConfig.exists()) {
try (var input = Files.newInputStream(externalConfig.toPath())) {
@@ -227,16 +245,13 @@ public class Server {
}
}
// Update the root folder property
props.setProperty("google.drive.root.folder", rootFolderName);
// Create config directory if it doesn't exist
File configDir = new File("config");
if (!configDir.exists()) {
configDir.mkdirs();
}
// Save to external config file
try (var output = Files.newOutputStream(externalConfig.toPath())) {
props.store(output, "BSK Server Configuration - Updated by Dashboard");
log.info("💾 Saved Google Drive root folder setting to config file");
@@ -247,96 +262,6 @@ public class Server {
}
}
private static String extractDatabaseFile() throws IOException {
throw new UnsupportedOperationException("extractDatabaseFile is not used anymore. Database is read directly from the specified path.");
}
public static Statement statement;
static {
try {
statement = connection.createStatement();
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
public Server() throws SQLException {
}
public static void main(String[] args) throws InterruptedException, SQLException {
log.info("\n____ _____ _ __\n| _ \\ / ____| |/\n| |_) | (___ | ' /\n| _ < \\___ \\| <\n| |_) |____) | . \\\n|____/|_____/|_|\\_\n");
// Initialize and show server dashboard
ServerDashboard dashboard = ServerDashboard.getInstance();
dashboard.setVisible(true);
dashboard.updateStatus("Starting...", Color.ORANGE);
dashboard.updatePort(PORT);
// Update Google Drive status on dashboard
dashboard.updateGoogleDriveStatus(isGoogleDriveConnected(),
isGoogleDriveConnected() ? "Connected" : "Disconnected");
EventLoopGroup parentGroup =
Epoll.isAvailable() ? new EpollEventLoopGroup() : new NioEventLoopGroup();
EventLoopGroup childGroup =
Epoll.isAvailable() ? new EpollEventLoopGroup() : new NioEventLoopGroup();
try {
ServerBootstrap bootstrap =
new ServerBootstrap()
.group(parentGroup, childGroup)
.channel(
Epoll.isAvailable()
? EpollServerSocketChannel.class
: NioServerSocketChannel.class)
.localAddress(new InetSocketAddress(PORT))
.childHandler(
new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ch.pipeline()
.addLast(new IdleStateHandler(60 * 30, 0, 0, TimeUnit.SECONDS))
.addLast(new HttpServerCodec())
.addLast(new ChunkedWriteHandler())
.addLast(new HttpObjectAggregator(50 * 1024 * 1024))
.addLast(new WebSocketServerProtocolHandler("/", null, true, 50 * 1024 * 1024))
.addLast(new ServerHandler());
}
});
ChannelFuture f = bootstrap.bind().sync();
log.info("Server started on port {}", PORT);
log.info("To connect, clients should use:");
log.info(" - If on same machine: ws://localhost:{} or ws://127.0.0.1:{}", PORT, PORT);
log.info(" - If on network: ws://<this-computer's-ip>:{}", PORT);
// Update dashboard status to running
dashboard.updateStatus("Running", Color.GREEN);
dashboard.addLog("Server started successfully on port " + PORT);
if (isGoogleDriveConnected()) {
dashboard.addLog("Google Drive integration: Connected ✅");
} else {
dashboard.addLog("Google Drive integration: Disconnected ❌");
}
f.channel().closeFuture().sync();
} catch (Exception e) {
dashboard.updateStatus("Error", Color.RED);
dashboard.addLog("Server error: " + e.getMessage());
throw e;
} finally {
dashboard.updateStatus("Shutting down", Color.ORANGE);
dashboard.addLog("Server shutting down...");
parentGroup.shutdownGracefully();
childGroup.shutdownGracefully();
}
}
/**
* Initiates the backup of the main database file to Google Drive.
* This is intended to be called from the ServerDashboard.
* @throws IOException if the file cannot be found or the upload fails.
*/
public static void backupDatabaseToDrive() throws IOException {
ServerDashboard dashboard = ServerDashboard.getInstance();
@@ -345,7 +270,6 @@ public class Server {
throw new IOException("Google Drive service is not available.");
}
// Define the path to the database
String dbPath = "src/main/resources/database/BSK.db";
java.io.File dbFile = new java.io.File(dbPath);
@@ -354,7 +278,6 @@ public class Server {
throw new IOException("Database file not found: " + dbPath);
}
// Call the service to perform the backup
googleDriveService.backupDatabaseFile(dbFile);
}
}
}
@@ -116,7 +116,8 @@ public class ServerHandler extends SimpleChannelInboundHandler<TextWebSocketFram
"from checkup as a\n" +
"join customer as c on a.customer_id = c.customer_id\n" +
"join Doctor D on a.doctor_id = D.doctor_id\n" +
"where a.status = 'ĐANG KHÁM' or a.status = 'CHỜ KHÁM'"
"where a.checkup_date >= CAST(strftime('%s', date('now', 'start of day')) AS INTEGER) * 1000\n" +
"AND a.checkup_date < CAST(strftime('%s', date('now', 'start of day', '+1 day')) AS INTEGER) * 1000"
);
if (!rs.isBeforeFirst()) {
@@ -310,7 +311,7 @@ public class ServerHandler extends SimpleChannelInboundHandler<TextWebSocketFram
log.debug("Received ClinicInfoRequest");
try {
ResultSet rs = statement.executeQuery(
"select name, address, phone\n" +
"select name, address, phone, prefix\n" +
" from Clinic"
);
@@ -320,8 +321,9 @@ public class ServerHandler extends SimpleChannelInboundHandler<TextWebSocketFram
String clinicName = rs.getString("name");
String clinicAddress = rs.getString("address");
String clinicPhone = rs.getString("phone");
String clinicPrefix = rs.getString("prefix");
UserUtil.sendPacket(currentUser.getSessionId(), new ClinicInfoResponse(clinicName, clinicAddress, clinicPhone));
UserUtil.sendPacket(currentUser.getSessionId(), new ClinicInfoResponse(clinicName, clinicAddress, clinicPhone, clinicPrefix));
}
}
catch (SQLException e) {
@@ -566,107 +568,113 @@ public class ServerHandler extends SimpleChannelInboundHandler<TextWebSocketFram
}
if (packet instanceof AddCheckupRequest addCheckupRequest) {
log.debug("Received AddCheckupRequest to add patient{}", addCheckupRequest.getCustomerId());
log.debug("Received AddCheckupRequest to add for customer {}", addCheckupRequest.getCustomerId());
// Khai báo các biến ID ở ngoài khối try để có thể sử dụng sau này
int generatedCheckupId = 0;
int queueNumber = 0;
try {
// Disable auto-commit
Server.connection.setAutoCommit(false);
int queueNumber = 0;
// Use a transaction to ensure atomic operations
try {
// First, try to update an existing counter for today
try (PreparedStatement updateStmt = Server.connection.prepareStatement(
"UPDATE DailyQueueCounter SET current_count = current_count + 1 " +
"WHERE date = date('now', 'localtime') RETURNING current_count")) {
ResultSet rs = updateStmt.executeQuery();
if (rs.next()) {
// Update successful, get the new value
queueNumber = rs.getInt(1);
} else {
// No row for today exists yet, insert one
try (PreparedStatement insertStmt = Server.connection.prepareStatement(
"INSERT INTO DailyQueueCounter (date, current_count) VALUES (date('now', 'localtime'), 1) " +
"RETURNING current_count")) {
ResultSet insertRs = insertStmt.executeQuery();
if (insertRs.next()) {
queueNumber = insertRs.getInt(1); // Should be 1
} else {
throw new SQLException("Failed to insert new queue counter");
}
}
}
}
} catch (SQLException e) {
log.error("Error updating queue counter", e);
throw new RuntimeException(e);
}
// First query: Insert Checkup
PreparedStatement checkupStmt = Server.connection.prepareStatement(
"INSERT INTO Checkup (customer_id, doctor_id, checkup_type, status, queue_number) VALUES (?, ?, ?, ?, ?)");
checkupStmt.setInt(1, addCheckupRequest.getCustomerId());
checkupStmt.setInt(2, addCheckupRequest.getDoctorId());
checkupStmt.setString(3, addCheckupRequest.getCheckupType());
checkupStmt.setString(4, addCheckupRequest.getStatus());
checkupStmt.setInt(5, queueNumber);
checkupStmt.executeUpdate();
// Second query: Insert MedicineOrder
PreparedStatement medOrderStmt = Server.connection.prepareStatement(
"INSERT INTO MedicineOrder (checkup_id, customer_id, processed_by) VALUES (last_insert_rowid(), ?, ?)");
medOrderStmt.setInt(1, addCheckupRequest.getCustomerId());
medOrderStmt.setInt(2, addCheckupRequest.getProcessedById());
medOrderStmt.executeUpdate();
// Third query: Update Checkup
PreparedStatement updateStmt = Server.connection.prepareStatement(
"UPDATE Checkup SET prescription_id = last_insert_rowid() WHERE checkup_id = (SELECT MAX(checkup_id) FROM Checkup WHERE customer_id = ?)");
updateStmt.setInt(1, addCheckupRequest.getCustomerId());
updateStmt.executeUpdate();
// Get the generated checkup ID safely
int generatedCheckupId = 0;
PreparedStatement getCheckupIdStmt = Server.connection.prepareStatement(
"SELECT MAX(checkup_id) FROM Checkup WHERE customer_id = ?");
getCheckupIdStmt.setInt(1, addCheckupRequest.getCustomerId());
ResultSet checkupIdRs = getCheckupIdStmt.executeQuery();
if (checkupIdRs.next()) {
generatedCheckupId = checkupIdRs.getInt(1);
}
getCheckupIdStmt.close();
checkupIdRs.close();
// Commit the transaction
Server.connection.commit();
// Send immediate response to client
UserUtil.sendPacket(currentUser.getSessionId(), new AddCheckupResponse(true, "Thêm bệnh nhân thành công", queueNumber));
broadcastQueueUpdate();
// Create Google Drive folder asynchronously (don't block the response)
createCheckupGoogleDriveFolderAsync(generatedCheckupId, addCheckupRequest.getCustomerId());
// Bắt đầu một transaction
Server.connection.setAutoCommit(false);
// --- 1. LẤY SỐ THỨ TỰ (QUEUE NUMBER) MỘT CÁCH AN TOÀN ---
// Sử dụng UPSERT (INSERT ON CONFLICT) để đảm bảo thao tác là nguyên tử
String queueSql = "INSERT INTO DailyQueueCounter (date, current_count) " +
"VALUES (date('now', 'localtime'), 1) " +
"ON CONFLICT(date) DO UPDATE SET current_count = current_count + 1 " +
"RETURNING current_count";
try (PreparedStatement queueStmt = Server.connection.prepareStatement(queueSql)) {
ResultSet rs = queueStmt.executeQuery();
if (rs.next()) {
queueNumber = rs.getInt(1);
} else {
throw new SQLException("Failed to get or update queue number.");
}
}
// --- 2. CHÈN VÀO BẢNG CHECKUP VÀ LẤY LẠI CHECKUP_ID ---
String checkupSql = "INSERT INTO Checkup (customer_id, doctor_id, checkup_type, status, queue_number) VALUES (?, ?, ?, ?, ?)";
try (PreparedStatement checkupStmt = Server.connection.prepareStatement(checkupSql, Statement.RETURN_GENERATED_KEYS)) {
checkupStmt.setInt(1, addCheckupRequest.getCustomerId());
checkupStmt.setInt(2, addCheckupRequest.getDoctorId());
checkupStmt.setString(3, addCheckupRequest.getCheckupType());
checkupStmt.setString(4, addCheckupRequest.getStatus());
checkupStmt.setInt(5, queueNumber);
checkupStmt.executeUpdate();
// Lấy checkup_id vừa được tạo ra một cách an toàn
try (ResultSet generatedKeys = checkupStmt.getGeneratedKeys()) {
if (generatedKeys.next()) {
generatedCheckupId = generatedKeys.getInt(1);
} else {
throw new SQLException("Creating checkup failed, no ID obtained.");
}
}
}
// --- 3. CHÈN VÀO BẢNG MEDICINEORDER VÀ LẤY LẠI PRESCRIPTION_ID ---
int generatedPrescriptionId = 0;
String medOrderSql = "INSERT INTO MedicineOrder (checkup_id, customer_id, processed_by) VALUES (?, ?, ?)";
try (PreparedStatement medOrderStmt = Server.connection.prepareStatement(medOrderSql, Statement.RETURN_GENERATED_KEYS)) {
medOrderStmt.setInt(1, generatedCheckupId); // Sử dụng ID đã lấy được
medOrderStmt.setInt(2, addCheckupRequest.getCustomerId());
medOrderStmt.setInt(3, addCheckupRequest.getProcessedById());
medOrderStmt.executeUpdate();
// Lấy prescription_id vừa được tạo ra một cách an toàn
try (ResultSet generatedKeys = medOrderStmt.getGeneratedKeys()) {
if (generatedKeys.next()) {
generatedPrescriptionId = generatedKeys.getInt(1);
} else {
throw new SQLException("Creating medicine order failed, no ID obtained.");
}
}
}
// --- 4. CẬP NHẬT BẢNG CHECKUP VỚI PRESCRIPTION_ID ---
String updateSql = "UPDATE Checkup SET prescription_id = ? WHERE checkup_id = ?";
try (PreparedStatement updateStmt = Server.connection.prepareStatement(updateSql)) {
updateStmt.setInt(1, generatedPrescriptionId); // Sử dụng ID đã lấy được
updateStmt.setInt(2, generatedCheckupId); // Sử dụng ID đã lấy được
updateStmt.executeUpdate();
}
// Nếu tất cả các bước thành công, commit transaction
Server.connection.commit();
// Gửi phản hồi thành công về cho client
UserUtil.sendPacket(currentUser.getSessionId(), new AddCheckupResponse(true, "Thêm bệnh nhân thành công", queueNumber));
// Broadcast cập nhật hàng chờ cho các client khác
broadcastQueueUpdate();
// Tạo thư mục Google Drive bất đồng bộ (không làm chậm phản hồi)
// generatedCheckupId bây giờ đã có giá trị chính xác
createCheckupGoogleDriveFolderAsync(generatedCheckupId, addCheckupRequest.getCustomerId());
} catch (SQLException e) {
log.error("SQLException during AddCheckupRequest, rolling back transaction.", e);
try {
// Rollback nếu có lỗi
Server.connection.rollback();
} catch (SQLException rollbackEx) {
log.error("Error during rollback", rollbackEx);
}
String errorMessage = e.getMessage();
UserUtil.sendPacket(currentUser.getSessionId(), new AddCheckupResponse(false, "Lỗi Server: " + errorMessage, -1));
// Không cần throw RuntimeException nữa để server không bị sập
} finally {
try {
// Luôn luôn reset auto-commit về true
Server.connection.setAutoCommit(true);
} catch (SQLException e) {
log.error("Error resetting auto-commit", e);
}
}
catch (SQLException e) {
try {
// Rollback on error
Server.connection.rollback();
} catch (SQLException rollbackEx) {
log.error("Error during rollback", rollbackEx);
}
String errorMessage = e.getMessage();
UserUtil.sendPacket(currentUser.getSessionId(), new AddCheckupResponse(false, "Lỗi: " + errorMessage, -1));
throw new RuntimeException(e);
}
finally {
try {
// Reset auto-commit
Server.connection.setAutoCommit(true);
} catch (SQLException e) {
log.error("Error resetting auto-commit", e);
}
}
}
}
if (packet instanceof CallPatientRequest callPatientRequest) {
log.debug("Received CallPatientRequest to call patient checkup_id: {}", callPatientRequest.getPatientId());
@@ -894,7 +902,8 @@ public class ServerHandler extends SimpleChannelInboundHandler<TextWebSocketFram
OI.price_per_unit,
OI.total_price,
OI.notes,
M.supplement
M.supplement,
M.route
FROM OrderItem OI
JOIN Medicine M ON OI.med_id = M.med_id
WHERE OI.checkup_id = ?
@@ -905,7 +914,7 @@ public class ServerHandler extends SimpleChannelInboundHandler<TextWebSocketFram
ArrayList<String[]> medList = new ArrayList<>();
while(medRs.next()) {
String[] med = new String[11];
String[] med = new String[12];
med[0] = medRs.getString("med_id");
med[1] = medRs.getString("med_name");
med[2] = medRs.getString("quantity_ordered");
@@ -933,6 +942,7 @@ public class ServerHandler extends SimpleChannelInboundHandler<TextWebSocketFram
med[8] = medRs.getString("total_price");
med[9] = medRs.getString("notes");
med[10] = medRs.getString("supplement");
med[11] = medRs.getString("route");
medList.add(med);
}
medicinePrescription = medList.toArray(new String[0][]);
@@ -1458,7 +1468,7 @@ public class ServerHandler extends SimpleChannelInboundHandler<TextWebSocketFram
}
log.info("Received AddMedRequest");
try {
String sql = "INSERT INTO Medicine (med_name, med_company, med_description, med_unit, med_selling_price, preferred_note, supplement, deleted) VALUES (?, ?, ?, ?, ?, ?, ?, ?)";
String sql = "INSERT INTO Medicine (med_name, med_company, med_description, med_unit, med_selling_price, preferred_note, supplement, deleted, route) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)";
PreparedStatement stmt = Server.connection.prepareStatement(sql);
stmt.setString(1, addMedicineRequest.getName());
stmt.setString(2, addMedicineRequest.getCompany());
@@ -1468,6 +1478,7 @@ public class ServerHandler extends SimpleChannelInboundHandler<TextWebSocketFram
stmt.setString(6, addMedicineRequest.getPreferredNote());
stmt.setBoolean(7, addMedicineRequest.getSupplement());
stmt.setBoolean(8, addMedicineRequest.getDeleted());
stmt.setString(9, addMedicineRequest.getRoute());
stmt.executeUpdate();
log.info("Added medicine: {}", addMedicineRequest.getName());
getMedInfo(currentUser.getSessionId());
@@ -1483,7 +1494,7 @@ public class ServerHandler extends SimpleChannelInboundHandler<TextWebSocketFram
}
log.info("Received EditMedRequest");
try {
String sql = "UPDATE Medicine SET med_name = ?, med_company = ?, med_description = ?, med_unit = ?, med_selling_price = ?, preferred_note = ?, supplement = ?, deleted = ? WHERE med_id = ?";
String sql = "UPDATE Medicine SET med_name = ?, med_company = ?, med_description = ?, med_unit = ?, med_selling_price = ?, preferred_note = ?, supplement = ?, deleted = ?, route = ? WHERE med_id = ?";
PreparedStatement stmt = Server.connection.prepareStatement(sql);
stmt.setString(1, editMedicineRequest.getName());
stmt.setString(2, editMedicineRequest.getCompany());
@@ -1493,7 +1504,8 @@ public class ServerHandler extends SimpleChannelInboundHandler<TextWebSocketFram
stmt.setString(6, editMedicineRequest.getPreferredNote());
stmt.setBoolean(7, editMedicineRequest.getSupplement());
stmt.setBoolean(8, editMedicineRequest.getDeleted());
stmt.setString(9, editMedicineRequest.getId());
stmt.setString(9, editMedicineRequest.getRoute());
stmt.setString(10, editMedicineRequest.getId());
stmt.executeUpdate();
log.info("Updated medicine: {}", editMedicineRequest.getName());
getMedInfo(currentUser.getSessionId());
@@ -1666,7 +1678,7 @@ public class ServerHandler extends SimpleChannelInboundHandler<TextWebSocketFram
private void getMedInfo(int sessionId) {
try {
ResultSet rs = statement.executeQuery(
"select med_id, med_name, med_company, med_description, med_unit, med_selling_price, preferred_note, supplement, deleted\n" +
"select med_id, med_name, med_company, med_description, med_unit, med_selling_price, preferred_note, supplement, deleted, route\n" +
" from Medicine"
);
@@ -1684,9 +1696,10 @@ public class ServerHandler extends SimpleChannelInboundHandler<TextWebSocketFram
String preferredNote = rs.getString("preferred_note");
String supplement = rs.getString("supplement");
String deleted = rs.getString("deleted");
String route = rs.getString("route");
String result = String.join("|",medId, medName, medCompany, medDescription, medUnit,
medSellingPrice, preferredNote != null ? preferredNote : "", supplement != null ? supplement : "0", deleted);
medSellingPrice, preferredNote != null ? preferredNote : "", supplement != null ? supplement : "0", deleted, route);
resultList.add(result);
}
@@ -2156,7 +2169,8 @@ public class ServerHandler extends SimpleChannelInboundHandler<TextWebSocketFram
"from checkup as a\n" +
"join customer as c on a.customer_id = c.customer_id\n" +
"join Doctor D on a.doctor_id = D.doctor_id\n" +
"where a.status = 'ĐANG KHÁM' or a.status = 'CHỜ KHÁM'"
"where a.checkup_date >= CAST(strftime('%s', date('now', 'start of day')) AS INTEGER) * 1000\n" +
"AND a.checkup_date < CAST(strftime('%s', date('now', 'start of day', '+1 day')) AS INTEGER) * 1000"
);
String[][] resultArray;
Binary file not shown.

Before

Width:  |  Height:  |  Size: 87 KiB

Binary file not shown.
Binary file not shown.
@@ -1,270 +0,0 @@
<!-- Created with Jaspersoft Studio version 7.0.3.final using JasperReports Library version 7.0.3-41034ca841d452f3305ba55b9042260aaa1ab5dd -->
<jasperReport name="Blank_A4_Landscape" language="java" columnCount="1" pageWidth="842" pageHeight="595" orientation="Landscape" columnWidth="802" leftMargin="20" rightMargin="20" topMargin="20" bottomMargin="20" uuid="e7f9ca7e-f0db-48b0-bef9-93be21b3b0a3">
<property name="com.jaspersoft.studio.data.defaultdataadapter" value="One Empty Record"/>
<parameter name="checkupNote" class="java.lang.String"/>
<parameter name="checkupDate" class="java.lang.String"/>
<parameter name="patientDiagnos" class="java.lang.String"/>
<parameter name="doctorName" class="java.lang.String"/>
<parameter name="medicineDS" class="net.sf.jasperreports.engine.data.JRBeanCollectionDataSource"/>
<parameter name="serviceDS" class="net.sf.jasperreports.engine.data.JRBeanCollectionDataSource"/>
<parameter name="supplementDS" class="net.sf.jasperreports.engine.data.JRBeanCollectionDataSource"/>
<parameter name="name" class="java.lang.String"/>
<parameter name="clinicName" class="java.lang.String"/>
<parameter name="patientAddress" class="java.lang.String"/>
<parameter name="clinicPhone" class="java.lang.String"/>
<parameter name="patientName" class="java.lang.String"/>
<parameter name="patientDOB" class="java.lang.String"/>
<parameter name="clinicAddress" class="java.lang.String"/>
<parameter name="logoImage" class="java.lang.String"/>
<parameter name="barcodeNumber" class="java.lang.String"/>
<parameter name="patientGender" class="java.lang.String"/>
<parameter name="hasMedicines" class="java.lang.Boolean"/>
<parameter name="hasServices" class="java.lang.Boolean"/>
<parameter name="hasSupplements" class="java.lang.Boolean"/>
<parameter name="checkupConclusion" class="java.lang.String"/>
<parameter name="checkupSuggestion" class="java.lang.String"/>
<parameter name="reCheckupDate" class="java.lang.String"/>
<parameter name="image1" class="java.lang.String"/>
<parameter name="image2" class="java.lang.String"/>
<parameter name="image3" class="java.lang.String"/>
<parameter name="checkupHeight" class="java.lang.String"/>
<parameter name="image4" class="java.lang.String"/>
<parameter name="image5" class="java.lang.String"/>
<parameter name="numberImage" class="java.lang.Integer"/>
<parameter name="image6" class="java.lang.String"/>
<parameter name="checkupBloodPressure" class="java.lang.String"/>
<parameter name="checkupHeartBeat" class="java.lang.String"/>
<parameter name="checkupWeight" class="java.lang.String"/>
<parameter name="templateTitle" class="java.lang.String"/>
<parameter name="driveURL" class="java.lang.String"/>
<parameter name="ultrasoundDoctorName" class="java.lang.String"/>
<query language="sql"><![CDATA[]]></query>
<background splitType="Stretch"/>
<title splitType="Stretch"/>
<pageHeader splitType="Stretch"/>
<columnHeader splitType="Stretch"/>
<detail>
<band height="540" splitType="Stretch">
<element kind="frame" uuid="2b7ec588-953c-4145-87b7-1d861c272fe0" x="0" y="0" width="400" height="539">
<element kind="image" uuid="fd80ab38-4cae-409b-84b9-356220d2b1e5" x="0" y="1" width="60" height="60">
<expression><![CDATA[$P{logoImage}]]></expression>
</element>
<element kind="textField" uuid="eb56d4c8-2a0d-45fa-89a2-ad6528f9a99b" x="60" y="0" width="290" height="20" forecolor="#FF0905" fontName="Times New Roman" fontSize="14.0" bold="true">
<expression><![CDATA[$P{clinicName}]]></expression>
</element>
<element kind="textField" uuid="796d9ffd-6d2e-4ae3-bdfb-b08183d7d9c0" x="60" y="20" width="235" height="25" fontName="Times New Roman" fontSize="10.0">
<expression><![CDATA[$P{clinicAddress}]]></expression>
</element>
<element kind="textField" uuid="260bb33d-1d11-4178-aceb-3fbf8fcb4b45" x="60" y="45" width="162" height="12" fontName="Times New Roman" fontSize="8.0">
<expression><![CDATA["SDT: " + $P{clinicPhone}]]></expression>
</element>
<element kind="staticText" uuid="6f89a93f-2d10-4506-baa5-226bdd047b17" x="0" y="65" width="100" height="30" forecolor="#FF0905" fontName="Times New Roman" fontSize="14.0" bold="true">
<text><![CDATA[I.Thông tin]]></text>
</element>
<element kind="staticText" uuid="b8dfca43-cf97-49e5-b58d-4667143dba62" x="0" y="79" width="50" height="15" fontName="Times New Roman" fontSize="10.0" bold="true" hTextAlign="Left">
<text><![CDATA[Họ và tên:]]></text>
</element>
<element kind="staticText" uuid="0a9ca0c8-f2bd-4ade-a025-a6d79c13613f" x="1" y="94" width="80" height="15" fontName="Times New Roman" fontSize="10.0" bold="true" hTextAlign="Left">
<text><![CDATA[Ngày sinh:]]></text>
</element>
<element kind="staticText" uuid="21917ab8-ae07-44c8-ba4e-bc6c4c54b440" x="140" y="94" width="80" height="15" fontName="Times New Roman" fontSize="10.0" bold="true" hTextAlign="Left">
<text><![CDATA[Giới tính:]]></text>
</element>
<element kind="staticText" uuid="bcbb614e-7a4d-48a3-83c2-198e4fb62c5f" x="1" y="109" width="49" height="15" fontName="Times New Roman" bold="true" hTextAlign="Left">
<text><![CDATA[Địa chỉ:]]></text>
</element>
<element kind="staticText" uuid="45fe4be1-9e21-459b-aeee-2efc8354f372" x="221" y="80" width="68" height="15" fontName="Times New Roman" fontSize="10.0" bold="true" hTextAlign="Left">
<text><![CDATA[Bác sĩ chỉ định:]]></text>
</element>
<element kind="staticText" uuid="f2ff4b17-63cc-4e8c-a3b0-2523f534f21a" x="221" y="94" width="60" height="15" fontName="Times New Roman" fontSize="10.0" bold="true" hTextAlign="Left">
<text><![CDATA[Ngày khám:]]></text>
</element>
<element kind="textField" uuid="1511f53a-b282-41b1-b233-612b6106c07a" x="48" y="79" width="172" height="15" fontName="Times New Roman" fontSize="10.0">
<expression><![CDATA[$P{patientName}]]></expression>
</element>
<element kind="textField" uuid="5bdac267-523d-4931-926b-76233ce9b84d" x="50" y="94" width="80" height="15" fontName="Times New Roman" fontSize="10.0">
<expression><![CDATA[$P{patientDOB}]]></expression>
</element>
<element kind="textField" uuid="f4df20b4-920c-491e-882b-6e0733cb4866" x="184" y="94" width="36" height="15" fontName="Times New Roman" fontSize="10.0">
<expression><![CDATA[$P{patientGender}]]></expression>
</element>
<element kind="textField" uuid="3b8ac40e-85aa-4ab8-8445-64bcddb8b267" x="39" y="109" width="361" height="15" fontName="Times New Roman" fontSize="10.0">
<expression><![CDATA[$P{patientAddress}]]></expression>
</element>
<element kind="textField" uuid="db40cdb0-2850-4d66-8430-addc54f90321" x="290" y="80" width="110" height="15" fontName="Times New Roman" fontSize="10.0">
<expression><![CDATA[$P{doctorName}]]></expression>
</element>
<element kind="textField" uuid="eb9cf54a-3b50-43c5-8696-cfc1e21bddfe" x="276" y="94" width="124" height="15" fontName="Times New Roman" fontSize="10.0">
<expression><![CDATA[$P{checkupDate}]]></expression>
</element>
<element kind="staticText" uuid="9f7de81c-4c38-41a2-9fea-a165eff19431" x="1" y="124" width="59" height="16" fontName="Times New Roman" fontSize="10.0" bold="true" hTextAlign="Left">
<text><![CDATA[Chuẩn đoán:]]></text>
</element>
<element kind="textField" uuid="5ae67e13-7a79-437f-bfb8-c720d896720d" x="60" y="124" width="340" height="26" fontName="Times New Roman" fontSize="10.0">
<expression><![CDATA[$P{patientDiagnos}]]></expression>
</element>
<element kind="staticText" uuid="b1fa845a-48da-4e45-82b8-8b9d972650f6" x="0" y="162" width="100" height="30" forecolor="#FF0905" fontName="Times New Roman" fontSize="14.0" bold="true">
<text><![CDATA[II.Nội dung]]></text>
</element>
<element kind="textField" uuid="6d652a25-b701-45bd-91ba-750842650004" x="0" y="177" width="398" height="362" markup="rtf" fontName="Times New Roman" fontSize="14.0">
<expression><![CDATA[$P{checkupNote}]]></expression>
</element>
<element kind="staticText" uuid="8f720f6a-0257-4556-b3bc-3b81ad4f8099" x="1" y="150" width="59" height="16" fontName="Times New Roman" fontSize="10.0" bold="true" hTextAlign="Left">
<text><![CDATA[Chiều cao:]]></text>
</element>
<element kind="staticText" uuid="a57e7a9d-4ac7-4219-b268-cd08ce943327" x="100" y="150" width="59" height="16" fontName="Times New Roman" fontSize="10.0" bold="true" hTextAlign="Left">
<text><![CDATA[Cân nặng:]]></text>
</element>
<element kind="staticText" uuid="2b9cfd9d-ec8f-4036-9c96-039fd7855e24" x="200" y="150" width="59" height="16" fontName="Times New Roman" fontSize="10.0" bold="true" hTextAlign="Left">
<text><![CDATA[Nhịp tim:]]></text>
</element>
<element kind="staticText" uuid="c1356370-11ce-4b68-97d6-ce6e18e306c5" x="290" y="150" width="59" height="16" fontName="Times New Roman" fontSize="10.0" bold="true" hTextAlign="Left">
<text><![CDATA[Huyết áp:]]></text>
</element>
<element kind="textField" uuid="3e1069a6-daea-45c2-b21f-935b49baba45" x="50" y="150" width="50" height="16" fontName="Times New Roman" fontSize="10.0">
<expression><![CDATA[$P{checkupWeight} +" cm"]]></expression>
</element>
<element kind="textField" uuid="fb080012-3196-4535-bcd2-e87274c66fa5" x="147" y="150" width="53" height="16" fontName="Times New Roman" fontSize="10.0">
<expression><![CDATA[$P{checkupWeight} + " kg"]]></expression>
</element>
<element kind="textField" uuid="e4185ffe-8712-41e3-a9ff-2be6569dff15" x="243" y="150" width="47" height="16" fontName="Times New Roman" fontSize="10.0">
<expression><![CDATA[$P{checkupHeartBeat} + " l/p"]]></expression>
</element>
<element kind="textField" uuid="6b0b21be-2ca3-4594-bbe9-34868e13eb1e" x="335" y="150" width="63" height="16" fontName="Times New Roman" fontSize="10.0">
<expression><![CDATA[$P{checkupBloodPressure} +" mmHg"]]></expression>
</element>
<element kind="component" uuid="e8842007-3343-4399-a101-76a302d0755d" x="362" y="19" width="38" height="35">
<component kind="barcode4j:QRCode">
<codeExpression><![CDATA[$P{driveURL}]]></codeExpression>
</component>
</element>
<element kind="textField" uuid="9763a634-05c2-4f64-a903-c914455b7ee6" x="70" y="57" width="282" height="20" forecolor="#FF0905" fontName="Times New Roman" fontSize="12.0" bold="true" hTextAlign="Center">
<printWhenExpression><![CDATA[$P{templateTitle} != null && !$P{templateTitle}.trim().isEmpty()]]></printWhenExpression>
<expression><![CDATA["PHIẾU " + $P{templateTitle}]]></expression>
</element>
</element>
<element kind="frame" uuid="a72ffc70-007e-43af-a566-b34e6e07b312" x="400" y="0" width="400" height="540">
<element kind="staticText" uuid="246a04b0-2565-4987-b7f3-dd369703035c" x="0" y="340" width="100" height="30" forecolor="#FF0905" fontName="Times New Roman" fontSize="15.0" bold="true">
<text><![CDATA[III.Kết luận]]></text>
</element>
<element kind="staticText" uuid="c53ef0ab-a702-47fc-9b7c-24307a495b30" x="0" y="430" width="100" height="30" forecolor="#FF0905" fontName="Times New Roman" fontSize="15.0" bold="true">
<text><![CDATA[Đề nghị:]]></text>
</element>
<element kind="staticText" uuid="a38b1187-ddb8-4410-9b52-dc041f894b7b" x="250" y="440" width="96" height="15" fontName="Times New Roman" fontSize="12.0" bold="true" hTextAlign="Center">
<text><![CDATA[Bác sĩ siêu âm]]></text>
</element>
<element kind="textField" uuid="b548d99d-bedf-4e90-b13b-bdbc763aa974" x="200" y="513" width="200" height="21" fontName="Times New Roman" fontSize="14.0" bold="true" hTextAlign="Center">
<expression><![CDATA[$P{ultrasoundDoctorName}]]></expression>
</element>
<element kind="textField" uuid="8bca58ab-0958-40fe-8e51-2a39a9d379a5" x="200" y="521" width="200" height="19" fontName="Times New Roman" pattern="MMMMM dd, yyyy" hTextAlign="Center" vTextAlign="Bottom">
<expression><![CDATA[new java.text.SimpleDateFormat("'Đức Hoà, ngày ' dd ' tháng ' MM ' năm ' yyyy", new java.util.Locale("vi", "VN")).format(new java.util.Date())]]></expression>
</element>
<element kind="staticText" uuid="c062ce0e-80cb-4e67-a5d9-d85e769c6c4e" x="0" y="525" width="110" height="14" forecolor="#FF0905" fontName="Times New Roman" fontSize="10.0" bold="true">
<text><![CDATA[Tái khám:]]></text>
</element>
<element kind="textField" uuid="e90ad772-4425-482d-9e75-f2bc66b9084d" x="0" y="358" width="400" height="70" fontName="Times New Roman" fontSize="12.0">
<expression><![CDATA[$P{checkupConclusion}]]></expression>
</element>
<element kind="component" uuid="cb28d811-1328-45dc-9461-cfbb88b7eeae" x="-105" y="19" width="64" height="40">
<component kind="barcode4j:Code128">
<codeExpression><![CDATA[$P{barcodeNumber}]]></codeExpression>
</component>
</element>
<element kind="textField" uuid="d63165c2-19e2-43ad-8a3f-004e00bffdfe" x="0" y="450" width="240" height="66" fontName="Times New Roman" fontSize="12.0">
<expression><![CDATA[$P{checkupSuggestion}]]></expression>
</element>
<element kind="textField" uuid="cece8e5b-67db-4019-b52a-bf73abae535e" x="48" y="525" width="150" height="15" fontName="Times New Roman" fontSize="12.0">
<expression><![CDATA[$P{reCheckupDate}]]></expression>
</element>
<element kind="frame" uuid="2f301804-acfa-4b6f-9f52-236c04fd1197" x="0" y="0" width="400" height="344">
<printWhenExpression><![CDATA[$P{numberImage}.intValue() == 6]]></printWhenExpression>
<element kind="image" uuid="fe4e4fa7-8b26-4817-ae86-4c147a25abbe" x="83" y="3" width="111" height="113">
<expression><![CDATA[$P{image1}]]></expression>
</element>
<element kind="image" uuid="9c6302ea-8b4a-48d6-8c42-68313154be77" x="83" y="117" width="111" height="113">
<expression><![CDATA[$P{image3}]]></expression>
</element>
<element kind="image" uuid="d7d6a47e-a129-4726-80b1-701113d0d9c2" x="83" y="231" width="111" height="113">
<expression><![CDATA[$P{image5}]]></expression>
</element>
<element kind="image" uuid="7cd3d01b-f3ac-48d1-9749-ab5787497ab9" x="198" y="232" width="111" height="113">
<expression><![CDATA[$P{image6}]]></expression>
</element>
<element kind="image" uuid="65610203-a91f-4b55-9a33-d6bfb7ffa7a6" x="199" y="117" width="111" height="113">
<expression><![CDATA[$P{image4}]]></expression>
</element>
<element kind="image" uuid="127b0f54-33e9-43a5-af62-64152d74958f" x="199" y="3" width="111" height="113">
<expression><![CDATA[$P{image2}]]></expression>
</element>
</element>
<element kind="frame" uuid="58523878-7ef9-46fe-aad7-ee5bd65115aa" x="0" y="1" width="400" height="344">
<printWhenExpression><![CDATA[$P{numberImage}.intValue() == 5]]></printWhenExpression>
<element kind="image" uuid="6870ae02-5ee4-40e8-9787-1ad084dc3b7f" x="83" y="3" width="111" height="113">
<expression><![CDATA[$P{image1}]]></expression>
</element>
<element kind="image" uuid="4216a22f-f20f-4bf1-9e93-79ccc3bbd5c6" x="83" y="117" width="111" height="113">
<expression><![CDATA[$P{image3}]]></expression>
</element>
<element kind="image" uuid="3069d087-6d97-455c-bb0d-211b0698b54c" x="142" y="231" width="111" height="113">
<expression><![CDATA[$P{image5}]]></expression>
</element>
<element kind="image" uuid="34187787-d55d-495a-be82-9ff67702211f" x="199" y="117" width="111" height="113">
<expression><![CDATA[$P{image4}]]></expression>
</element>
<element kind="image" uuid="7b2d4efb-1f35-4c37-80a1-685195e1218e" x="199" y="3" width="111" height="113">
<expression><![CDATA[$P{image2}]]></expression>
</element>
</element>
<element kind="frame" uuid="33b6f6ef-93e4-4488-a421-08de09b5458c" x="0" y="0" width="400" height="344">
<printWhenExpression><![CDATA[$P{numberImage}.intValue() == 4]]></printWhenExpression>
<element kind="image" uuid="1378905c-276f-42ba-9101-18b27ba14e0b" x="28" y="3" width="161" height="165">
<expression><![CDATA[$P{image1}]]></expression>
</element>
<element kind="image" uuid="58917767-70d5-4822-bb6f-7f5aba6f660e" x="29" y="173" width="161" height="165">
<expression><![CDATA[$P{image3}]]></expression>
</element>
<element kind="image" uuid="6026efa4-cfd7-4b1d-90be-fe8912eb43c3" x="210" y="3" width="161" height="165">
<expression><![CDATA[$P{image2}]]></expression>
</element>
<element kind="image" uuid="6c5adc41-f3d7-4e32-997a-e1845d7170c5" x="211" y="173" width="161" height="165">
<expression><![CDATA[$P{image4}]]></expression>
</element>
</element>
<element kind="frame" uuid="94e66ae9-8863-45e0-9b9d-1a5fb7df84f5" x="0" y="0" width="400" height="344">
<printWhenExpression><![CDATA[$P{numberImage}.intValue() == 3]]></printWhenExpression>
<property name="com.jaspersoft.studio.unit.y" value="px"/>
<property name="com.jaspersoft.studio.unit.x" value="px"/>
<element kind="image" uuid="3ab88449-e282-41cd-898e-ab91aeef70b9" x="28" y="3" width="161" height="165">
<expression><![CDATA[$P{image1}]]></expression>
</element>
<element kind="image" uuid="119378b1-674d-457a-bc69-a9823f2160b7" x="121" y="173" width="161" height="165">
<expression><![CDATA[$P{image3}]]></expression>
</element>
<element kind="image" uuid="8ac7bc19-5ae6-4569-87fb-c9cf72936b50" x="210" y="3" width="161" height="165">
<expression><![CDATA[$P{image2}]]></expression>
</element>
</element>
<element kind="frame" uuid="935efa61-0cd7-47ab-b7d8-6508a1726537" x="0" y="0" width="400" height="344">
<printWhenExpression><![CDATA[$P{numberImage}.intValue() == 2]]></printWhenExpression>
<element kind="image" uuid="8f2957f9-fb76-49d1-94ce-08c723aec7ce" x="121" y="3" width="161" height="165">
<expression><![CDATA[$P{image1}]]></expression>
</element>
<element kind="image" uuid="f5585019-40b7-4b1b-9c7a-8b10386cf210" x="121" y="173" width="161" height="165">
<expression><![CDATA[$P{image2}]]></expression>
</element>
</element>
<element kind="frame" uuid="dfa0c283-dbfc-40de-97e0-d1d04db85c96" x="0" y="0" width="400" height="344">
<printWhenExpression><![CDATA[$P{numberImage}.intValue() == 1]]></printWhenExpression>
<property name="com.jaspersoft.studio.unit.y" value="px"/>
<element kind="image" uuid="a7cef70f-1dbe-4d6f-a007-7543bbc2b9b8" x="29" y="4" width="342" height="335">
<expression><![CDATA[$P{image1}]]></expression>
</element>
</element>
<element kind="staticText" uuid="8f35aa72-22a4-45f0-a35e-8e35e832404e" x="-55" y="53" width="55" height="14" fontName="Times New Roman" fontSize="8.0" bold="false" hTextAlign="Center">
<printWhenExpression><![CDATA[$P{driveURL} != null && !$P{driveURL}.trim().isEmpty()]]></printWhenExpression>
<text><![CDATA[Xem KQ online]]></text>
</element>
</element>
</band>
</detail>
</jasperReport>
@@ -1,198 +0,0 @@
<!-- Created with Jaspersoft Studio version 7.0.3.final using JasperReports Library version 7.0.3-41034ca841d452f3305ba55b9042260aaa1ab5dd -->
<jasperReport name="Blank_A4_Potrait" language="java" columnCount="1" pageWidth="595" pageHeight="842" orientation="Landscape" columnWidth="555" leftMargin="20" rightMargin="20" topMargin="20" bottomMargin="20" uuid="e7f9ca7e-f0db-48b0-bef9-93be21b3b0a3">
<property name="com.jaspersoft.studio.data.defaultdataadapter" value="One Empty Record"/>
<parameter name="checkupNote" class="java.lang.String"/>
<parameter name="checkupDate" class="java.lang.String"/>
<parameter name="patientDiagnos" class="java.lang.String"/>
<parameter name="doctorName" class="java.lang.String"/>
<parameter name="medicineDS" class="net.sf.jasperreports.engine.data.JRBeanCollectionDataSource"/>
<parameter name="serviceDS" class="net.sf.jasperreports.engine.data.JRBeanCollectionDataSource"/>
<parameter name="supplementDS" class="net.sf.jasperreports.engine.data.JRBeanCollectionDataSource"/>
<parameter name="name" class="java.lang.String"/>
<parameter name="clinicName" class="java.lang.String"/>
<parameter name="patientAddress" class="java.lang.String"/>
<parameter name="clinicPhone" class="java.lang.String"/>
<parameter name="patientName" class="java.lang.String"/>
<parameter name="patientDOB" class="java.lang.String"/>
<parameter name="clinicAddress" class="java.lang.String"/>
<parameter name="logoImage" class="java.lang.String"/>
<parameter name="barcodeNumber" class="java.lang.String"/>
<parameter name="patientGender" class="java.lang.String"/>
<parameter name="hasMedicines" class="java.lang.Boolean"/>
<parameter name="hasServices" class="java.lang.Boolean"/>
<parameter name="hasSupplements" class="java.lang.Boolean"/>
<parameter name="checkupConclusion" class="java.lang.String"/>
<parameter name="checkupSuggestion" class="java.lang.String"/>
<parameter name="reCheckupDate" class="java.lang.String"/>
<parameter name="image1" class="java.lang.String"/>
<parameter name="image2" class="java.lang.String"/>
<parameter name="image3" class="java.lang.String"/>
<parameter name="checkupHeight" class="java.lang.String"/>
<parameter name="image4" class="java.lang.String"/>
<parameter name="image5" class="java.lang.String"/>
<parameter name="numberImage" class="java.lang.Integer"/>
<parameter name="image6" class="java.lang.String"/>
<parameter name="checkupBloodPressure" class="java.lang.String"/>
<parameter name="checkupHeartBeat" class="java.lang.String"/>
<parameter name="checkupWeight" class="java.lang.String"/>
<parameter name="templateTitle" class="java.lang.String"/>
<parameter name="driveURL" class="java.lang.String"/>
<parameter name="ultrasoundDoctorName" class="java.lang.String"/>
<query language="sql"><![CDATA[]]></query>
<background splitType="Stretch"/>
<title splitType="Stretch"/>
<pageHeader splitType="Stretch"/>
<columnHeader splitType="Stretch"/>
<detail>
<band height="598" splitType="Stretch">
<element kind="frame" uuid="2b7ec588-953c-4145-87b7-1d861c272fe0" x="0" y="0" width="551" height="598">
<element kind="image" uuid="fd80ab38-4cae-409b-84b9-356220d2b1e5" x="0" y="-5" width="70" height="64">
<expression><![CDATA[$P{logoImage}]]></expression>
</element>
<element kind="textField" uuid="eb56d4c8-2a0d-45fa-89a2-ad6528f9a99b" x="70" y="0" width="323" height="20" forecolor="#FF0905" fontName="Times New Roman" fontSize="14.0" bold="true">
<expression><![CDATA[$P{clinicName}]]></expression>
</element>
<element kind="textField" uuid="796d9ffd-6d2e-4ae3-bdfb-b08183d7d9c0" x="70" y="20" width="323" height="22" fontName="Times New Roman" fontSize="10.0">
<expression><![CDATA[$P{clinicAddress}]]></expression>
</element>
<element kind="textField" uuid="260bb33d-1d11-4178-aceb-3fbf8fcb4b45" x="70" y="42" width="276" height="15" fontName="Times New Roman" fontSize="8.0">
<expression><![CDATA[$P{clinicPhone}]]></expression>
</element>
<element kind="staticText" uuid="6f89a93f-2d10-4506-baa5-226bdd047b17" x="0" y="65" width="100" height="30" forecolor="#FF0905" fontName="Times New Roman" fontSize="14.0" bold="true">
<text><![CDATA[I.Thông tin]]></text>
</element>
<element kind="staticText" uuid="b8dfca43-cf97-49e5-b58d-4667143dba62" x="0" y="79" width="50" height="15" fontName="Times New Roman" fontSize="10.0" bold="true" hTextAlign="Left">
<text><![CDATA[Họ và tên:]]></text>
</element>
<element kind="staticText" uuid="0a9ca0c8-f2bd-4ade-a025-a6d79c13613f" x="1" y="94" width="80" height="15" fontName="Times New Roman" fontSize="10.0" bold="true" hTextAlign="Left">
<text><![CDATA[Ngày sinh:]]></text>
</element>
<element kind="staticText" uuid="21917ab8-ae07-44c8-ba4e-bc6c4c54b440" x="140" y="94" width="80" height="15" fontName="Times New Roman" fontSize="10.0" bold="true" hTextAlign="Left">
<text><![CDATA[Giới tính:]]></text>
</element>
<element kind="staticText" uuid="bcbb614e-7a4d-48a3-83c2-198e4fb62c5f" x="1" y="109" width="49" height="15" fontName="Times New Roman" bold="true" hTextAlign="Left">
<text><![CDATA[Địa chỉ:]]></text>
</element>
<element kind="staticText" uuid="45fe4be1-9e21-459b-aeee-2efc8354f372" x="221" y="80" width="68" height="15" fontName="Times New Roman" fontSize="10.0" bold="true" hTextAlign="Left">
<text><![CDATA[Bác sĩ chỉ định:]]></text>
</element>
<element kind="staticText" uuid="f2ff4b17-63cc-4e8c-a3b0-2523f534f21a" x="221" y="94" width="60" height="15" fontName="Times New Roman" fontSize="10.0" bold="true" hTextAlign="Left">
<text><![CDATA[Ngày khám:]]></text>
</element>
<element kind="textField" uuid="1511f53a-b282-41b1-b233-612b6106c07a" x="48" y="79" width="172" height="15" fontName="Times New Roman" fontSize="10.0">
<expression><![CDATA[$P{patientName}]]></expression>
</element>
<element kind="textField" uuid="5bdac267-523d-4931-926b-76233ce9b84d" x="50" y="94" width="80" height="15" fontName="Times New Roman" fontSize="10.0">
<expression><![CDATA[$P{patientDOB}]]></expression>
</element>
<element kind="textField" uuid="f4df20b4-920c-491e-882b-6e0733cb4866" x="184" y="94" width="36" height="15" fontName="Times New Roman" fontSize="10.0">
<expression><![CDATA[$P{patientGender}]]></expression>
</element>
<element kind="textField" uuid="3b8ac40e-85aa-4ab8-8445-64bcddb8b267" x="39" y="109" width="361" height="15" fontName="Times New Roman" fontSize="10.0">
<expression><![CDATA[$P{patientAddress}]]></expression>
</element>
<element kind="textField" uuid="db40cdb0-2850-4d66-8430-addc54f90321" x="290" y="80" width="110" height="15" fontName="Times New Roman" fontSize="10.0">
<expression><![CDATA[$P{doctorName}]]></expression>
</element>
<element kind="textField" uuid="eb9cf54a-3b50-43c5-8696-cfc1e21bddfe" x="276" y="94" width="124" height="15" fontName="Times New Roman" fontSize="10.0">
<expression><![CDATA[$P{checkupDate}]]></expression>
</element>
<element kind="staticText" uuid="9f7de81c-4c38-41a2-9fea-a165eff19431" x="1" y="124" width="59" height="16" fontName="Times New Roman" fontSize="10.0" bold="true" hTextAlign="Left">
<text><![CDATA[Chuẩn đoán:]]></text>
</element>
<element kind="textField" uuid="5ae67e13-7a79-437f-bfb8-c720d896720d" x="60" y="124" width="340" height="26" fontName="Times New Roman" fontSize="10.0">
<expression><![CDATA[$P{patientDiagnos}]]></expression>
</element>
<element kind="staticText" uuid="b1fa845a-48da-4e45-82b8-8b9d972650f6" x="0" y="162" width="100" height="30" forecolor="#FF0905" fontName="Times New Roman" fontSize="14.0" bold="true">
<text><![CDATA[II.Nội dung]]></text>
</element>
<element kind="textField" uuid="6d652a25-b701-45bd-91ba-750842650004" x="0" y="177" width="400" height="421" markup="rtf" fontName="Times New Roman" fontSize="16.0">
<expression><![CDATA[$P{checkupNote}]]></expression>
</element>
<element kind="staticText" uuid="8f720f6a-0257-4556-b3bc-3b81ad4f8099" x="1" y="150" width="59" height="16" fontName="Times New Roman" fontSize="10.0" bold="true" hTextAlign="Left">
<text><![CDATA[Chiều cao:]]></text>
</element>
<element kind="staticText" uuid="a57e7a9d-4ac7-4219-b268-cd08ce943327" x="100" y="150" width="59" height="16" fontName="Times New Roman" fontSize="10.0" bold="true" hTextAlign="Left">
<text><![CDATA[Cân nặng:]]></text>
</element>
<element kind="staticText" uuid="2b9cfd9d-ec8f-4036-9c96-039fd7855e24" x="200" y="150" width="59" height="16" fontName="Times New Roman" fontSize="10.0" bold="true" hTextAlign="Left">
<text><![CDATA[Nhịp tim:]]></text>
</element>
<element kind="staticText" uuid="c1356370-11ce-4b68-97d6-ce6e18e306c5" x="290" y="150" width="59" height="16" fontName="Times New Roman" fontSize="10.0" bold="true" hTextAlign="Left">
<text><![CDATA[Huyết áp:]]></text>
</element>
<element kind="textField" uuid="3e1069a6-daea-45c2-b21f-935b49baba45" x="50" y="150" width="50" height="16" fontName="Times New Roman" fontSize="10.0">
<expression><![CDATA[$P{checkupWeight} +" cm"]]></expression>
</element>
<element kind="textField" uuid="fb080012-3196-4535-bcd2-e87274c66fa5" x="147" y="150" width="53" height="16" fontName="Times New Roman" fontSize="10.0">
<expression><![CDATA[$P{checkupWeight} + " kg"]]></expression>
</element>
<element kind="textField" uuid="e4185ffe-8712-41e3-a9ff-2be6569dff15" x="243" y="150" width="47" height="16" fontName="Times New Roman" fontSize="10.0">
<expression><![CDATA[$P{checkupHeartBeat} + " l/p"]]></expression>
</element>
<element kind="textField" uuid="6b0b21be-2ca3-4594-bbe9-34868e13eb1e" x="335" y="150" width="65" height="16" fontName="Times New Roman" fontSize="10.0">
<expression><![CDATA[$P{checkupBloodPressure} +" mmHg"]]></expression>
</element>
<element kind="component" uuid="e8842007-3343-4399-a101-76a302d0755d" x="486" y="16" width="53" height="49">
<component kind="barcode4j:QRCode">
<codeExpression><![CDATA[$P{driveURL}]]></codeExpression>
</component>
</element>
<element kind="textField" uuid="9763a634-05c2-4f64-a903-c914455b7ee6" x="70" y="57" width="282" height="20" forecolor="#FF0905" fontName="Times New Roman" fontSize="12.0" bold="true" hTextAlign="Center">
<printWhenExpression><![CDATA[$P{templateTitle} != null && !$P{templateTitle}.trim().isEmpty()]]></printWhenExpression>
<expression><![CDATA["PHIẾU " + $P{templateTitle}]]></expression>
</element>
<element kind="staticText" uuid="8f35aa72-22a4-45f0-a35e-8e35e832404e" x="484" y="65" width="55" height="14" fontName="Times New Roman" fontSize="8.0" bold="false" hTextAlign="Center">
<printWhenExpression><![CDATA[$P{driveURL} != null && !$P{driveURL}.trim().isEmpty()]]></printWhenExpression>
<text><![CDATA[Xem KQ online]]></text>
</element>
<element kind="component" uuid="73f562ce-2891-4577-aec2-7284203c8430" x="394" y="21" width="70" height="49">
<component kind="barcode4j:Code128">
<codeExpression><![CDATA[$P{barcodeNumber}]]></codeExpression>
</component>
</element>
<element kind="image" uuid="692eae9f-a304-4cda-856d-7a3a95fac3df" stretchType="NoStretch" x="400" y="91" width="151" height="124">
<expression><![CDATA[$P{image1}]]></expression>
</element>
<element kind="image" uuid="9a15475c-d08c-4c8f-bbdf-70cf98f97e90" x="400" y="216" width="151" height="124">
<expression><![CDATA[$P{image2}]]></expression>
</element>
<element kind="image" uuid="2902cf3c-31dd-4b96-be87-fa8a13ba88ae" x="400" y="342" width="151" height="124">
<expression><![CDATA[$P{image3}]]></expression>
</element>
<element kind="image" uuid="129e6c61-d572-48a9-925e-1ab2e4e573e2" x="400" y="468" width="151" height="129">
<expression><![CDATA[$P{image4}]]></expression>
</element>
</element>
</band>
</detail>
<summary height="179">
<element kind="staticText" uuid="b6ee4329-aeb1-4ddf-99e8-41ebebaff12b" x="0" y="0" width="100" height="30" forecolor="#FF0905" fontName="Times New Roman" fontSize="15.0" bold="true">
<text><![CDATA[III.Kết luận]]></text>
</element>
<element kind="staticText" uuid="f4c12e4d-9aac-428d-bd79-59c3d15f0d87" x="0" y="60" width="100" height="30" forecolor="#FF0905" fontName="Times New Roman" fontSize="15.0" bold="true">
<text><![CDATA[Đề nghị:]]></text>
</element>
<element kind="staticText" uuid="d1d33b8f-b79a-45a1-b33b-1eecb656f49a" x="400" y="70" width="96" height="15" fontName="Times New Roman" fontSize="12.0" bold="true" hTextAlign="Center">
<text><![CDATA[Bác sĩ siêu âm]]></text>
</element>
<element kind="textField" uuid="de0d077c-f1d6-4d0c-8bbd-fb08c19b07c6" x="347" y="140" width="200" height="21" fontName="Times New Roman" fontSize="14.0" bold="true" hTextAlign="Center">
<expression><![CDATA[$P{ultrasoundDoctorName}]]></expression>
</element>
<element kind="textField" uuid="0b5be2b8-8837-41ee-a805-81f562f5f961" x="347" y="157" width="200" height="19" fontName="Times New Roman" pattern="MMMMM dd, yyyy" hTextAlign="Center" vTextAlign="Bottom">
<expression><![CDATA[new java.text.SimpleDateFormat("'Đức Hoà, ngày ' dd ' tháng ' MM ' năm ' yyyy", new java.util.Locale("vi", "VN")).format(new java.util.Date())]]></expression>
</element>
<element kind="staticText" uuid="0b4ca7da-4831-4ca6-8272-94af19fd3089" x="0" y="155" width="110" height="14" forecolor="#FF0905" fontName="Times New Roman" fontSize="10.0" bold="true">
<text><![CDATA[Tái khám:]]></text>
</element>
<element kind="textField" uuid="e4fb5d0b-bbc3-4e42-a431-1bd20bcfb25d" x="0" y="20" width="546" height="38" fontName="Times New Roman" fontSize="12.0">
<expression><![CDATA[$P{checkupConclusion}]]></expression>
</element>
<element kind="textField" uuid="16b6dfab-1434-4de5-a1c4-619470f3d867" x="0" y="80" width="347" height="66" fontName="Times New Roman" fontSize="12.0">
<expression><![CDATA[$P{checkupSuggestion}]]></expression>
</element>
<element kind="textField" uuid="4d8aeb33-ab41-4a5b-a5d1-52bab4043246" x="48" y="155" width="150" height="15" fontName="Times New Roman" fontSize="12.0">
<expression><![CDATA[$P{reCheckupDate}]]></expression>
</element>
</summary>
</jasperReport>