[update] Enhance CheckUpPage with new ultrasound doctor selection and re-checkup features. Introduce compact layouts for suggestion and diagnosis panels, improve date picker functionality, and update database schema to include queue number and ultrasound doctor ID. Revise report generation to accommodate new parameters for better patient management.

This commit is contained in:
Lê Thành Đạt committed 2025-07-24 19:45:08 +07:00
1 parent 5552ac6c73
commit c4fe96929e
13 files changed
+669 -139

No files matched your search

Binary file not shown.
@@ -41,6 +41,11 @@ import java.text.SimpleDateFormat;
import java.text.ParseException;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.imageio.ImageIO;
import javax.imageio.ImageWriter;
import javax.imageio.ImageWriteParam;
import javax.imageio.IIOImage;
import javax.imageio.stream.ImageOutputStream;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
@@ -119,6 +124,7 @@ import java.io.ByteArrayOutputStream;
import java.io.ByteArrayInputStream;
import java.io.OutputStream;
import java.io.InputStream;
import java.io.StringReader;
// --- JasperReports Imports ---
import net.sf.jasperreports.engine.JasperPrint;
@@ -169,8 +175,11 @@ public class CheckUpPage extends JPanel {
private JTextArea suggestionField, diagnosisField, conclusionField; // Changed symptomsField to suggestionField
private JTextPane notesField;
private JComboBox<String> doctorComboBox, statusComboBox, genderComboBox, provinceComboBox, districtComboBox, wardComboBox, checkupTypeComboBox, templateComboBox, orientationComboBox; // Added orientationComboBox
private JComboBox<String> ultrasoundDoctorComboBox;
private JCheckBox needRecheckupCheckbox; // Checkbox to indicate if re-checkup is needed
private JSpinner customerWeightSpinner, customerHeightSpinner, patientHeartRateSpinner, bloodPressureSystolicSpinner, bloodPressureDiastolicSpinner;
private JDatePickerImpl datePicker, dobPicker, recheckupDatePicker;
private JButton recheckupDatePickerButton;
private String[][] medicinePrescription = new String[0][0]; // Initialize to empty
private String[][] servicePrescription = new String[0][0]; // Initialize to empty
private String[] doctorOptions;
@@ -861,7 +870,7 @@ public class CheckUpPage extends JPanel {
// Top Row Panel (Doctor, Status, Type)
JPanel topRowPanel = new JPanel(new GridBagLayout());
GridBagConstraints gbcTop = new GridBagConstraints();
gbcTop.insets = new Insets(3, 5, 3, 5); // Reduced vertical insets from 5 to 3
gbcTop.insets = new Insets(1, 5, 1, 5); // Reduced vertical insets for density
gbcTop.fill = GridBagConstraints.HORIZONTAL;
// Initialize datePicker
@@ -878,43 +887,59 @@ public class CheckUpPage extends JPanel {
setupDateFieldForDirectInput(datePicker);
gbcTop.gridx = 0; gbcTop.gridy = 0;
JLabel doctorLabel = new JLabel("Bác Sĩ");
doctorLabel.setFont(labelFont);
topRowPanel.add(doctorLabel, gbcTop);
gbcTop.gridx = 1; gbcTop.weightx = 0.4;
doctorComboBox = new JComboBox<>(LocalStorage.doctorsName != null ? LocalStorage.doctorsName : new String[]{"Đang tải bác sĩ..."});
doctorComboBox.setFont(fieldFont);
topRowPanel.add(doctorComboBox, gbcTop);
gbcTop.gridx = 2; gbcTop.weightx = 0;
JLabel dateLabel = new JLabel("Đơn Ngày:");
dateLabel.setFont(labelFont);
topRowPanel.add(dateLabel, gbcTop);
gbcTop.gridx = 3; gbcTop.weightx = 0.3;
gbcTop.gridx = 1; gbcTop.weightx = 0.3;
topRowPanel.add(datePicker, gbcTop);
gbcTop.gridx = 4; gbcTop.weightx = 0;
gbcTop.gridx = 2; gbcTop.weightx = 0;
JLabel statusLabel = new JLabel("Trạng thái");
statusLabel.setFont(labelFont);
topRowPanel.add(statusLabel, gbcTop);
gbcTop.gridx = 5; gbcTop.weightx = 0.3;
gbcTop.gridx = 3; gbcTop.weightx = 0.3;
statusComboBox = new JComboBox<>(new String[]{"ĐANG KHÁM", "CHỜ KHÁM", "ĐÃ KHÁM"});
statusComboBox.setFont(fieldFont);
topRowPanel.add(statusComboBox, gbcTop);
gbcTop.gridx = 6; gbcTop.weightx = 0;
gbcTop.gridx = 4; gbcTop.weightx = 0;
JLabel typeLabel = new JLabel("Loại khám");
typeLabel.setFont(labelFont);
topRowPanel.add(typeLabel, gbcTop);
gbcTop.gridx = 7; gbcTop.weightx = 0.3;
gbcTop.gridx = 5; gbcTop.weightx = 0.3;
checkupTypeComboBox = new JComboBox<>(new String[]{"BỆNH", "THAI", "KHÁC"});
checkupTypeComboBox.setFont(fieldFont);
topRowPanel.add(checkupTypeComboBox, gbcTop);
// Doctor Selection Row
JPanel doctorPanel = new JPanel(new GridBagLayout());
GridBagConstraints gbcDoctor = new GridBagConstraints();
gbcDoctor.insets = new Insets(1, 5, 1, 5); // Reduced vertical insets for density
gbcDoctor.fill = GridBagConstraints.HORIZONTAL;
gbcDoctor.gridx = 0; gbcDoctor.gridy = 0;
JLabel doctorLabel = new JLabel("Bác sĩ chỉ định");
doctorLabel.setFont(labelFont);
doctorPanel.add(doctorLabel, gbcDoctor);
gbcDoctor.gridx = 1; gbcDoctor.weightx = 0.4;
doctorComboBox = new JComboBox<>(LocalStorage.doctorsName != null ? LocalStorage.doctorsName : new String[]{"Đang tải bác sĩ..."});
doctorComboBox.setFont(fieldFont);
doctorPanel.add(doctorComboBox, gbcDoctor);
gbcDoctor.gridx = 2; gbcDoctor.weightx = 0;
JLabel ultrasoundDoctorLabel = new JLabel("Bác sĩ siêu âm");
ultrasoundDoctorLabel.setFont(labelFont);
doctorPanel.add(ultrasoundDoctorLabel, gbcDoctor);
gbcDoctor.gridx = 3; gbcDoctor.weightx = 0.4;
ultrasoundDoctorComboBox = new JComboBox<>(LocalStorage.doctorsName != null ? LocalStorage.doctorsName : new String[]{"Đang tải bác sĩ..."});
ultrasoundDoctorComboBox.setFont(fieldFont);
doctorPanel.add(ultrasoundDoctorComboBox, gbcDoctor);
// Template Selection Row
JPanel templatePanel = new JPanel(new GridBagLayout());
GridBagConstraints gbcTemplate = new GridBagConstraints();
@@ -972,7 +997,7 @@ public class CheckUpPage extends JPanel {
templatePanel.add(orientationLabel, gbcTemplate);
gbcTemplate.gridx = 7;
orientationComboBox = new JComboBox<>(new String[]{"ngang", "dọc"});
orientationComboBox = new JComboBox<>(new String[]{"Ngang", "Dọc"});
orientationComboBox.setFont(fieldFont);
orientationComboBox.setPreferredSize(new Dimension(80, 25));
orientationComboBox.addActionListener(e -> {
@@ -1171,32 +1196,56 @@ public class CheckUpPage extends JPanel {
rightPanel.setMinimumSize(new Dimension(200, 0)); // Set minimum size to prevent it from shrinking too much
rightPanel.setMaximumSize(new Dimension(280, Integer.MAX_VALUE)); // Set maximum width to limit expansion
// Suggestion Panel
JPanel suggestionPanel = new JPanel(new BorderLayout(5, 5));
// Suggestion Panel - more compact
JPanel suggestionPanel = new JPanel(new BorderLayout(3, 3)); // Reduced spacing
suggestionPanel.setBorder(BorderFactory.createTitledBorder(
BorderFactory.createEtchedBorder(),
"Đề nghị",
TitledBorder.LEADING, TitledBorder.TOP,
new Font("Arial", Font.BOLD, 14),
new Font("Arial", Font.BOLD, 12), // Smaller font
new Color(50, 50, 50)
));
suggestionField = new JTextArea(5, 20); // Adjusted rows for better layout
suggestionField = new JTextArea(2, 10); // Further reduced to 2 rows
suggestionField.setFont(fieldFont);
suggestionField.setLineWrap(true);
suggestionField.setWrapStyleWord(true);
addSelectAllOnFocus(suggestionField);
JScrollPane suggestionScrollPane = new JScrollPane(suggestionField);
suggestionScrollPane.setPreferredSize(new Dimension(0, 200)); // Set fixed height
suggestionScrollPane.setPreferredSize(new Dimension(0, 50)); // Reduced height
suggestionPanel.add(suggestionScrollPane, BorderLayout.CENTER);
suggestionPanel.setMinimumSize(new Dimension(200, 200));
suggestionPanel.setPreferredSize(new Dimension(250, 200));
suggestionPanel.setMinimumSize(new Dimension(200, 90)); // Reduced height
suggestionPanel.setPreferredSize(new Dimension(280, 90)); // Reduced height
// Add Re-checkup date picker
JPanel recheckupPanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 5, 2));
// Add Re-checkup date picker - even more compact layout
JPanel recheckupPanel = new JPanel();
recheckupPanel.setLayout(new BoxLayout(recheckupPanel, BoxLayout.X_AXIS)); // More compact layout
recheckupPanel.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0)); // No border
recheckupPanel.setBackground(Color.WHITE);
JLabel recheckupLabel = new JLabel("Tái khám:");
recheckupLabel.setFont(labelFont);
recheckupLabel.setFont(new Font("Arial", Font.BOLD, 12)); // Even smaller font
recheckupPanel.add(recheckupLabel);
recheckupPanel.add(Box.createHorizontalStrut(2)); // Minimal spacing
// Add checkbox for re-checkup needed - ultra compact
needRecheckupCheckbox = new JCheckBox();
needRecheckupCheckbox.setFont(new Font("Arial", Font.PLAIN, 11)); // Even smaller font
needRecheckupCheckbox.setBackground(Color.WHITE);
needRecheckupCheckbox.setSelected(false);
needRecheckupCheckbox.setMargin(new Insets(0, 0, 0, 0)); // Remove margin
needRecheckupCheckbox.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0)); // No border
needRecheckupCheckbox.addActionListener(e -> {
boolean selected = needRecheckupCheckbox.isSelected();
recheckupDatePicker.setEnabled(selected);
recheckupDatePicker.getJFormattedTextField().setEditable(selected);
if(recheckupDatePickerButton != null) {
recheckupDatePickerButton.setEnabled(selected);
}
if (!selected) {
// Clear the date if checkbox is unchecked
recheckupDatePicker.getModel().setValue(null);
}
});
recheckupPanel.add(needRecheckupCheckbox);
UtilDateModel recheckupModel = new UtilDateModel();
Properties recheckupProps = new Properties();
@@ -1205,52 +1254,70 @@ public class CheckUpPage extends JPanel {
// Remove "text.today" since these dates shouldn't default to today
JDatePanelImpl recheckupDatePanel = new JDatePanelImpl(recheckupModel, recheckupProps);
recheckupDatePicker = new JDatePickerImpl(recheckupDatePanel, new DateLabelFormatter());
recheckupDatePicker.getJFormattedTextField().setFont(fieldFont);
// Find and store the button component
for (Component comp : recheckupDatePicker.getComponents()) {
if (comp instanceof JButton) {
recheckupDatePickerButton = (JButton) comp;
break;
}
}
recheckupDatePicker.getJFormattedTextField().setFont(new Font("Arial", Font.PLAIN, 12)); // Smaller font
recheckupDatePicker.getJFormattedTextField().setToolTipText("Nhập ngày theo định dạng dd/mm/yyyy");
setupDateFieldForDirectInput(recheckupDatePicker);
recheckupDatePicker.setPreferredSize(new Dimension(140, 30)); // Make it a bit smaller
recheckupDatePicker.setPreferredSize(new Dimension(120, 25)); // Even smaller dimensions
recheckupDatePicker.setEnabled(false); // Initially disabled until checkbox is checked
recheckupDatePicker.getJFormattedTextField().setEditable(false);
if (recheckupDatePickerButton != null) {
recheckupDatePickerButton.setEnabled(false);
}
recheckupPanel.add(recheckupDatePicker);
// Adjust the layout to make room for the new checkbox
suggestionPanel.setPreferredSize(new Dimension(280, 200)); // Increased width from 250 to 280
rightPanel.setPreferredSize(new Dimension(280, 0)); // Increased width from 250 to 280
rightPanel.setMinimumSize(new Dimension(230, 0)); // Increased minimum width from 200 to 230
suggestionPanel.add(recheckupPanel, BorderLayout.SOUTH);
suggestionPanel.setMinimumSize(new Dimension(200, 200));
suggestionPanel.setPreferredSize(new Dimension(250, 200));
// Diagnosis Panel
JPanel diagnosisPanel = new JPanel(new BorderLayout(5, 5));
// Diagnosis Panel - more compact
JPanel diagnosisPanel = new JPanel(new BorderLayout(3, 3)); // Reduced spacing
diagnosisPanel.setBorder(BorderFactory.createTitledBorder(
BorderFactory.createEtchedBorder(),
"Chẩn đoán",
TitledBorder.LEADING, TitledBorder.TOP,
new Font("Arial", Font.BOLD, 14),
new Font("Arial", Font.BOLD, 12), // Smaller font
new Color(50, 50, 50)
));
diagnosisField = new JTextArea(4, 20);
diagnosisField.setFont(fieldFont);
diagnosisField = new JTextArea(3, 20); // Reduced rows
diagnosisField.setFont(new Font("Arial", Font.PLAIN, 14)); // Slightly smaller font
diagnosisField.setLineWrap(true);
diagnosisField.setWrapStyleWord(true);
addSelectAllOnFocus(diagnosisField);
diagnosisPanel.add(new JScrollPane(diagnosisField), BorderLayout.CENTER);
// Conclusion Panel
JPanel conclusionPanel = new JPanel(new BorderLayout(5, 5));
// Conclusion Panel - more compact
JPanel conclusionPanel = new JPanel(new BorderLayout(3, 3)); // Reduced spacing
conclusionPanel.setBorder(BorderFactory.createTitledBorder(
BorderFactory.createEtchedBorder(),
"Kết luận",
TitledBorder.LEADING, TitledBorder.TOP,
new Font("Arial", Font.BOLD, 14),
new Font("Arial", Font.BOLD, 12), // Smaller font
new Color(50, 50, 50)
));
conclusionField = new JTextArea(4, 20);
conclusionField.setFont(fieldFont);
conclusionField = new JTextArea(3, 20); // Reduced rows
conclusionField.setFont(new Font("Arial", Font.PLAIN, 14)); // Slightly smaller font
conclusionField.setLineWrap(true);
conclusionField.setWrapStyleWord(true);
addSelectAllOnFocus(conclusionField);
conclusionPanel.add(new JScrollPane(conclusionField), BorderLayout.CENTER);
rightPanel.add(suggestionPanel);
rightPanel.add(Box.createRigidArea(new Dimension(0, 10)));
rightPanel.add(Box.createRigidArea(new Dimension(0, 5))); // Reduced from 10 to 5
rightPanel.add(diagnosisPanel);
rightPanel.add(Box.createRigidArea(new Dimension(0, 10)));
rightPanel.add(Box.createRigidArea(new Dimension(0, 5))); // Reduced from 10 to 5
rightPanel.add(conclusionPanel);
// Create split pane for left and right panels
@@ -1264,8 +1331,14 @@ public class CheckUpPage extends JPanel {
mainContentPanel.add(templatePanel, BorderLayout.NORTH);
mainContentPanel.add(contentSplitPane, BorderLayout.CENTER);
// Create a container panel to hold the top rows with vertical layout
JPanel topContainer = new JPanel();
topContainer.setLayout(new BoxLayout(topContainer, BoxLayout.Y_AXIS));
topContainer.add(topRowPanel);
topContainer.add(doctorPanel);
// Assemble checkup info panel
checkupInfoPanel.add(topRowPanel, BorderLayout.NORTH);
checkupInfoPanel.add(topContainer, BorderLayout.NORTH);
checkupInfoPanel.add(mainContentPanel, BorderLayout.CENTER);
// Create tabbed pane for patient info and checkup info
@@ -1465,6 +1538,65 @@ public class CheckUpPage extends JPanel {
// In the constructor, after creating notesField:
setupNotesPasteHandler();
setupShortcuts();
// Listen for CallPatientResponse to update the TV queue display
ClientHandler.addResponseListener(CallPatientResponse.class, response -> {
log.info("Received CallPatientResponse: PatientId={}, RoomId={}, Status={}, QueueNumber={}",
response.getPatientId(), response.getRoomId(), response.getStatus(), response.getQueueNumber());
if (tvQueueFrame != null && tvQueueFrame.isShowing()) {
// Find the full patient name and birth year from patient queue
String patientName = "";
String birthYear = "";
// Look up the patient in our patient queue by checkup ID
for (Patient patient : patientQueue) {
if (patient.getCheckupId().equals(String.valueOf(response.getPatientId()))) {
patientName = patient.getCustomerLastName() + " " + patient.getCustomerFirstName();
// Extract year from DOB
if (patient.getCustomerDob() != null && !patient.getCustomerDob().isEmpty()) {
int year = DateUtils.extractYearFromTimestamp(patient.getCustomerDob());
if (year != -1) {
birthYear = String.valueOf(year);
}
}
break;
}
}
String fullPatientInfo = patientName + " (" + birthYear + ")";
// Pass the QUEUE NUMBER to be displayed in the small room status box
tvQueueFrame.updateSpecificRoomStatus(
response.getRoomId(),
String.valueOf(response.getPatientId()),
response.getQueueNumber(), // Use the queue number here
fullPatientInfo, // Full info for the central display
response.getStatus()
);
}
});
// Listen for queue updates
ClientHandler.addResponseListener(GetCheckUpQueueUpdateResponse.class, response -> {
SwingUtilities.invokeLater(() -> {
log.info("Received checkup update queue");
this.rawQueueForTv = response.getQueue();
this.patientQueue.clear();
if (this.rawQueueForTv != null) {
for (String[] patientData : this.rawQueueForTv) {
this.patientQueue.add(new Patient(patientData));
}
}
if (queueManagementPage != null) {
queueManagementPage.updateQueueTable();
}
if (tvQueueFrame != null && tvQueueFrame.isVisible()) {
tvQueueFrame.updateQueueData(this.rawQueueForTv);
}
});
});
}
private void addSelectAllOnFocus(JTextComponent textComponent) {
@@ -1707,6 +1839,7 @@ public class CheckUpPage extends JPanel {
(String) genderComboBox.getSelectedItem(),
customerAddressField.getText() + ", " + (wardComboBox.getSelectedItem() != null ? wardComboBox.getSelectedItem().toString() : "") + ", " + (districtComboBox.getSelectedItem() != null ? districtComboBox.getSelectedItem().toString() : "") + ", " + (provinceComboBox.getSelectedItem() != null ? provinceComboBox.getSelectedItem().toString() : ""),
(String) doctorComboBox.getSelectedItem(),
(String) ultrasoundDoctorComboBox.getSelectedItem(),
datePicker.getJFormattedTextField().getText(),
TextUtils.scaleRtfFontSize(getRtfContentAsString()),
conclusionField.getText(),
@@ -1781,6 +1914,7 @@ public class CheckUpPage extends JPanel {
(String) genderComboBox.getSelectedItem(),
customerAddressField.getText() + ", " + (wardComboBox.getSelectedItem() != null ? wardComboBox.getSelectedItem().toString() : "") + ", " + (districtComboBox.getSelectedItem() != null ? districtComboBox.getSelectedItem().toString() : "") + ", " + (provinceComboBox.getSelectedItem() != null ? provinceComboBox.getSelectedItem().toString() : ""),
(String) doctorComboBox.getSelectedItem(),
(String) ultrasoundDoctorComboBox.getSelectedItem(),
datePicker.getJFormattedTextField().getText(),
TextUtils.scaleRtfFontSize(getRtfContentAsString()),
conclusionField.getText(),
@@ -1988,6 +2122,37 @@ public class CheckUpPage extends JPanel {
log.error("Invalid date format for checkup date: {}", selectedPatient.getCheckupDate());
JOptionPane.showMessageDialog(null, "Định dạng ngày hoặc dấu thời gian không hợp lệ: " + selectedPatient.getCheckupDate(), "Lỗi định dạng ngày", JOptionPane.ERROR_MESSAGE);
}
// Check if re-checkup date is present and valid
if (selectedPatient.getReCheckupDate() != null && !selectedPatient.getReCheckupDate().isEmpty() &&
!selectedPatient.getReCheckupDate().equals("0") && !selectedPatient.getReCheckupDate().equals("null")) {
needRecheckupCheckbox.setSelected(true);
recheckupDatePicker.setEnabled(true);
recheckupDatePicker.getJFormattedTextField().setEditable(true);
if (recheckupDatePickerButton != null) {
recheckupDatePickerButton.setEnabled(true);
}
// Parse and set the re-checkup date
Date recheckupDate = DateUtils.convertToDate(selectedPatient.getReCheckupDate());
if (recheckupDate != null) {
Calendar calendar = Calendar.getInstance();
calendar.setTime(recheckupDate);
recheckupDatePicker.getModel().setDate(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH), calendar.get(Calendar.DAY_OF_MONTH));
recheckupDatePicker.getModel().setSelected(true);
} else {
// If parsing fails, log it and keep the field clear
log.warn("Could not parse re-checkup date: {}", selectedPatient.getReCheckupDate());
recheckupDatePicker.getModel().setValue(null);
}
} else {
needRecheckupCheckbox.setSelected(false);
recheckupDatePicker.setEnabled(false);
recheckupDatePicker.getJFormattedTextField().setEditable(false);
if (recheckupDatePickerButton != null) {
recheckupDatePickerButton.setEnabled(false);
}
recheckupDatePicker.getModel().setValue(null);
}
// Set DOB using utility function
Date dobDate = DateUtils.convertToDate(selectedPatient.getCustomerDob());
@@ -2004,6 +2169,7 @@ public class CheckUpPage extends JPanel {
customerLastNameField.setText(selectedPatient.getCustomerLastName());
customerFirstNameField.setText(selectedPatient.getCustomerFirstName());
doctorComboBox.setSelectedItem(selectedPatient.getDoctorName());
ultrasoundDoctorComboBox.setSelectedItem(selectedPatient.getDoctorUltrasoundId());
suggestionField.setText(selectedPatient.getSuggestion()); // De nghi
diagnosisField.setText(selectedPatient.getDiagnosis()); // Chuan doan
conclusionField.setText(selectedPatient.getConclusion()); // Ket luan
@@ -2285,11 +2451,13 @@ public class CheckUpPage extends JPanel {
private void handleCallPatientResponse(CallPatientResponse response) {
SwingUtilities.invokeLater(() -> {
log.info("Received call patient response: Room {}, Patient ID {}, Status {}", response.getRoomId(), response.getPatientId(), response.getStatus());
log.info("Received call patient response: Room {}, Patient ID {}, Queue Number {}, Status {}",
response.getRoomId(), response.getPatientId(), response.getQueueNumber(), response.getStatus());
if (tvQueueFrame != null && tvQueueFrame.isVisible()) {
if (response.getStatus() == Status.PROCESSING) {
String patientIdToFind = String.valueOf(response.getPatientId());
String patientDisplayInfo = patientIdToFind;
String queueNumber = response.getQueueNumber();
String patientDisplayInfo = queueNumber; // Use queue number instead of patient ID
if (this.patientQueue != null) {
for (Patient patient : this.patientQueue) {
@@ -2316,7 +2484,7 @@ public class CheckUpPage extends JPanel {
}
}
}
tvQueueFrame.updateSpecificRoomStatus(response.getRoomId(), String.valueOf(response.getPatientId()), patientDisplayInfo, response.getStatus());
tvQueueFrame.updateSpecificRoomStatus(response.getRoomId(), String.valueOf(response.getPatientId()), queueNumber, patientDisplayInfo, response.getStatus());
} else if (response.getStatus() == Status.EMPTY) {
tvQueueFrame.markRoomAsFree(response.getRoomId());
}
@@ -2342,39 +2510,44 @@ public class CheckUpPage extends JPanel {
callingStatusLabel.setBackground(new Color(230, 255, 230));
JOptionPane.showMessageDialog(this, "Phòng " + selectedRoomName + " đã được đánh dấu là trống.", "Cập nhật trạng thái phòng", JOptionPane.INFORMATION_MESSAGE);
log.info("Room {} marked as free", selectedRoomName);
NetworkUtil.sendPacket(ClientHandler.ctx.channel(), new CallPatientRequest(roomId, -1, Status.EMPTY));
NetworkUtil.sendPacket(ClientHandler.ctx.channel(), new CallPatientRequest(roomId, -1, "", Status.EMPTY));
}
private void handleCallPatient() {
// Check if a patient is selected on the main CheckUpPage
if (selectedCheckupId == null || selectedCheckupId.isEmpty()) {
JOptionPane.showMessageDialog(this, "Vui lòng chọn một bệnh nhân từ danh sách để gọi.", "Chưa chọn bệnh nhân", JOptionPane.WARNING_MESSAGE);
if (selectedCheckupId == null) {
JOptionPane.showMessageDialog(this, "Vui lòng chọn một bệnh nhân từ danh sách chờ.", "Chưa chọn bệnh nhân", JOptionPane.WARNING_MESSAGE);
return;
}
// Find the selected patient by checkup ID
Patient selectedPatient = null;
for (Patient patient : patientQueue) {
if (patient.getCheckupId().equals(selectedCheckupId)) {
if (selectedCheckupId.equals(patient.getCheckupId())) {
selectedPatient = patient;
break;
}
}
if (selectedPatient == null) {
JOptionPane.showMessageDialog(this, "Không tìm thấy bệnh nhân đã chọn trong hàng đợi.", "Lỗi", JOptionPane.ERROR_MESSAGE);
JOptionPane.showMessageDialog(this, "Không tìm thấy thông tin chi tiết cho bệnh nhân đã chọn.", "Lỗi", JOptionPane.ERROR_MESSAGE);
return;
}
String maKhamBenh = selectedPatient.getCheckupId();
String patientName = selectedPatient.getCustomerLastName() + " " + selectedPatient.getCustomerFirstName();
int selectedRoom = callRoomComboBox.getSelectedIndex() + 1;
JOptionPane.showMessageDialog(this, "Đang gọi bệnh nhân " + patientName + " (Mã KB: " + maKhamBenh + ") đến " + callRoomComboBox.getSelectedItem().toString(), "Gọi bệnh nhân", JOptionPane.INFORMATION_MESSAGE);
NetworkUtil.sendPacket(ClientHandler.ctx.channel(), new CallPatientRequest(selectedRoom, Integer.parseInt(maKhamBenh), Status.PROCESSING));
log.info("Called patient {} (ID: {}) to room {}", patientName, maKhamBenh, selectedRoom);
String callingText = "<html><b>Đang gọi:</b> BN " + patientName + " (Mã KB: " + maKhamBenh + ") đến " + callRoomComboBox.getSelectedItem().toString() + "</html>";
callingStatusLabel.setText(callingText);
callingStatusLabel.setForeground(Color.WHITE);
callingStatusLabel.setBackground(new Color(217, 83, 79)); // Red background for calling
int roomId = callRoomComboBox.getSelectedIndex() + 1;
int patientId = Integer.parseInt(selectedCheckupId);
// Get queue number from patient DTO and format it to 2 digits with leading zero
String queueNumber = selectedPatient.getQueueNumber();
// Set status to PROCESSING when calling
statusComboBox.setSelectedItem("ĐANG KHÁM");
Status status = Status.PROCESSING;
callingStatusLabel.setText("Đang gọi bệnh nhân " + selectedPatient.getCustomerFirstName() + " (STT: " + queueNumber + ") vào phòng " + roomId);
callingStatusLabel.setForeground(Color.BLUE);
callingStatusLabel.setBackground(new Color(220, 230, 255));
CallPatientRequest request = new CallPatientRequest(roomId, patientId, queueNumber, status);
NetworkUtil.sendPacket(ClientHandler.ctx.channel(), request);
}
private void handleGetOrderInfoByCheckupResponse(GetOrderInfoByCheckupRes response) {
@@ -3276,9 +3449,26 @@ public class CheckUpPage extends JPanel {
private void uploadImageInBackground(String fileName, BufferedImage image) {
imageUploadExecutor.submit(() -> {
try {
// Compress the image to JPEG for smaller size
// Compress the image to JPEG with high quality (0.9) for better preservation
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ImageIO.write(image, "jpg", baos);
// Get JPEG writer and set high quality compression
ImageWriter jpegWriter = ImageIO.getImageWritersByFormatName("jpg").next();
ImageOutputStream ios = ImageIO.createImageOutputStream(baos);
jpegWriter.setOutput(ios);
// Set compression quality to 0.9 (90% quality)
ImageWriteParam writeParam = jpegWriter.getDefaultWriteParam();
writeParam.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
writeParam.setCompressionQuality(0.9f); // High quality compression
// Write the image with high quality
jpegWriter.write(null, new IIOImage(image, null, null), writeParam);
// Clean up
jpegWriter.dispose();
ios.close();
byte[] compressedImageData = baos.toByteArray();
// Create and send the request
@@ -4112,13 +4302,14 @@ public class CheckUpPage extends JPanel {
}
private int findRowByCheckupId(String checkupId) {
// Find the patient in the patientQueue
if (checkupId == null) return -1;
for (int i = 0; i < queueTableModel.getRowCount(); i++) {
if (checkupId.equals(queueTableModel.getValueAt(i, 0))) {
return i;
}
}
return -1;
return -1; // Not found
}
/**
@@ -4330,6 +4521,7 @@ public class CheckUpPage extends JPanel {
String customerWeight = customerWeightSpinner.getValue().toString();
String customerHeight = customerHeightSpinner.getValue().toString();
String doctorId = String.valueOf(doctorComboBox.getSelectedIndex() + 1);
String ultrasoundDoctorId = String.valueOf(ultrasoundDoctorComboBox.getSelectedIndex() + 1);
String suggestions = suggestionField.getText();
String diagnosis = diagnosisField.getText();
String conclusion = conclusionField.getText();
@@ -4352,6 +4544,7 @@ public class CheckUpPage extends JPanel {
log.info("customerWeight: {}", customerWeight);
log.info("customerHeight: {}", customerHeight);
log.info("doctorId: {}", doctorId);
log.info("ultrasoundDoctorId: {}", ultrasoundDoctorId);
log.info("suggestions: {}", suggestions);
log.info("diagnosis: {}", diagnosis);
log.info("conclusion: {}", conclusion);
@@ -4371,10 +4564,18 @@ public class CheckUpPage extends JPanel {
Long reCheckupDateLong = DateUtils.convertToDate(reCheckupDate).getTime();
Long checkupDateLong = DateUtils.convertToDate(checkupDate).getTime();
Integer heartBeat = (Integer) patientHeartRateSpinner.getValue();
Boolean needsRecheckup = needRecheckupCheckbox.isSelected();
// If re-checkup is not needed, clear the re-checkup date
if (!needsRecheckup) {
reCheckupDateLong = 0L; // Use 0 to indicate no re-checkup date
}
SaveCheckupRequest request = new SaveCheckupRequest(
Integer.parseInt(checkupId),
Integer.parseInt(customerId),
Integer.parseInt(doctorId),
Integer.parseInt(ultrasoundDoctorId),
checkupDateLong,
suggestions,
diagnosis,
@@ -4383,6 +4584,7 @@ public class CheckUpPage extends JPanel {
checkupType,
conclusion,
reCheckupDateLong,
needsRecheckup,
customerFirstName,
customerLastName,
customerDobLong,
@@ -4421,30 +4623,47 @@ public class CheckUpPage extends JPanel {
}
private void applyTemplate(Template template) {
diagnosisField.setText(template.getDiagnosis());
conclusionField.setText(template.getConclusion());
suggestionField.setText(template.getSuggestion());
if (template == null) return;
String rtfContent = template.getContent();
if (rtfContent != null && !rtfContent.isEmpty()) {
setRtfContentFromString(rtfContent);
} else {
setRtfContentFromString(""); // Clear if content is empty
// Set the print orientation from the template
if (template.getPrintType() != null) {
orientationComboBox.setSelectedItem(template.getPrintType());
}
// Set template print setting
photoNum = Integer.parseInt(template.getPhotoNum());
printType = template.getPrintType();
orientationComboBox.setSelectedItem(template.getPrintType()); // Update orientation dropdown
templateName = template.getTemplateName();
templateTitle = template.getTemplateTitle();
templateGender = template.getTemplateGender();
templateContent = template.getContent();
templateConclusion = template.getConclusion();
templateSuggestion = template.getSuggestion();
photoNum = Integer.parseInt(template.getPhotoNum());
// Update template info labels
imageCountValueLabel.setText(template.getPhotoNum());
genderValueLabel.setText(template.getTemplateGender());
// Use a try-catch for the RTF content to prevent application crashes
try {
RTFEditorKit rtfEditorKit = (RTFEditorKit) notesField.getEditorKit();
// First clear the document to ensure we're not appending content
notesField.getDocument().remove(0, notesField.getDocument().getLength());
if (template.getContent() != null && !template.getContent().isEmpty()) {
rtfEditorKit.read(new StringReader(template.getContent()), notesField.getDocument(), 0);
}
} catch (Exception e) {
log.error("Failed to apply RTF content from template '{}'", template.getTemplateName(), e);
// Fallback to plain text or show an error
notesField.setText("Lỗi khi tải nội dung mẫu.");
}
// Only set fields if they have content in the template
if (template.getDiagnosis() != null && !template.getDiagnosis().isEmpty()) {
diagnosisField.setText(template.getDiagnosis());
}
if (template.getConclusion() != null && !template.getConclusion().isEmpty()) {
conclusionField.setText(template.getConclusion());
}
if (template.getSuggestion() != null && !template.getSuggestion().isEmpty()) {
suggestionField.setText(template.getSuggestion());
}
callingStatusLabel.setText("Đã áp dụng mẫu '" + template.getTemplateName() + "'.");
callingStatusLabel.setBackground(new Color(220, 230, 255));
callingStatusLabel.setForeground(new Color(0, 0, 139));
}
private void handleGetAllTemplatesResponse(GetAllTemplatesRes response) {
@@ -4537,6 +4756,12 @@ public class CheckUpPage extends JPanel {
datePicker.getModel().setValue(null);
dobPicker.getModel().setValue(null);
recheckupDatePicker.getModel().setValue(null);
needRecheckupCheckbox.setSelected(false);
recheckupDatePicker.setEnabled(false);
recheckupDatePicker.getJFormattedTextField().setEditable(false);
if (recheckupDatePickerButton != null) {
recheckupDatePickerButton.setEnabled(false);
}
medicinePrescription = new String[0][0];
servicePrescription = new String[0][0];
@@ -4662,6 +4887,16 @@ public class CheckUpPage extends JPanel {
}
});
}
private int findRowByCheckupId(String checkupId) {
DefaultTableModel model = (DefaultTableModel) table.getModel();
for (int i = 0; i < model.getRowCount(); i++) {
if (model.getValueAt(i, 0).equals(checkupId)) {
return i;
}
}
return -1; // Not found
}
}
@@ -70,6 +70,7 @@ public class UltrasoundResult {
private final String patientGender;
private final String patientAddress;
private final String doctorName;
private final String ultrasoundDoctorName;
private final String checkupDate;
private final String rtfContent;
private final String conclusion;
@@ -89,32 +90,59 @@ public class UltrasoundResult {
private static final String PDF_PATH = "ultrasound_result.pdf";
public UltrasoundResult(String checkupId, String patientName, String patientDOB, String patientGender,
String patientAddress, String doctorName, String checkupDate,
String patientAddress, String doctorName, String ultrasoundDoctorName, String checkupDate,
String rtfContent, String conclusion, String suggestion,
String recheckupDate, List<File> selectedImages,
String printType, String templateTitle, String customerHeight,
String customerWeight, String heartRate, String bloodPressure, String driveUrl) {
// Defensive null checks to prevent JasperReports from crashing on null parameters
this.checkupId = checkupId != null ? checkupId : "";
this.patientName = patientName != null ? patientName : "";
this.patientDOB = patientDOB != null ? patientDOB : "";
this.patientGender = patientGender != null ? patientGender : "";
this.patientAddress = patientAddress != null ? patientAddress : "";
this.doctorName = doctorName != null ? doctorName : "";
this.checkupDate = checkupDate != null ? checkupDate : "";
this.rtfContent = rtfContent != null ? rtfContent : "";
this.conclusion = conclusion != null ? conclusion : "";
this.suggestion = suggestion != null ? suggestion : "";
this.recheckupDate = recheckupDate != null ? recheckupDate : "";
// Also handle "null" string values by converting them to empty strings
this.checkupId = convertNullToEmpty(checkupId);
this.patientName = convertNullToEmpty(patientName);
this.patientDOB = convertNullToEmpty(patientDOB);
this.patientGender = convertNullToEmpty(patientGender);
this.patientAddress = convertNullToEmpty(patientAddress);
this.doctorName = convertNullToEmpty(doctorName);
this.ultrasoundDoctorName = convertNullToEmpty(ultrasoundDoctorName);
this.checkupDate = convertNullToEmpty(checkupDate);
this.rtfContent = convertNullToEmpty(rtfContent);
this.conclusion = convertNullToEmpty(conclusion);
this.suggestion = convertNullToEmpty(suggestion);
this.recheckupDate = convertNullToEmpty(recheckupDate);
this.selectedImages = selectedImages != null ? selectedImages : new ArrayList<>();
this.printType = printType != null ? printType : "";
this.templateTitle = templateTitle != null ? templateTitle : "";
this.customerHeight = customerHeight != null ? customerHeight : "";
this.customerWeight = customerWeight != null ? customerWeight : "";
this.heartRate = heartRate != null ? heartRate : "";
this.bloodPressure = bloodPressure != null ? bloodPressure : "";
this.driveUrl = driveUrl != null ? driveUrl : ""; // Google Drive URL
this.printType = convertNullToEmpty(printType);
this.templateTitle = convertNullToEmpty(templateTitle);
this.customerHeight = convertNullToEmpty(customerHeight);
this.customerWeight = convertNullToEmpty(customerWeight);
this.heartRate = convertNullToEmpty(heartRate);
this.bloodPressure = convertNullToEmpty(bloodPressure);
this.driveUrl = convertNullToEmpty(driveUrl); // Google Drive URL
}
/**
* Helper method to convert null or "null" string values to empty strings
* @param value The string to check
* @return Empty string if value is null or equals "null", otherwise the original value
*/
private String convertNullToEmpty(String value) {
if (value == null || "null".equals(value)) {
return "";
}
return value;
}
/**
* Helper method to convert null or "null" string values to a default value
* @param value The string to check
* @param defaultValue The default value to use if value is null or "null"
* @return defaultValue if value is null or equals "null", otherwise the original value
*/
private String convertNullToEmpty(String value, String defaultValue) {
if (value == null || "null".equals(value)) {
return defaultValue;
}
return value;
}
public void showDirectJasperViewer() {
@@ -143,7 +171,15 @@ public class UltrasoundResult {
}
public JasperPrint createJasperPrint() throws JRException, IOException {
String jrxmlPath = System.getProperty("user.dir") + "/src/main/java/BsK/client/ui/component/CheckUpPage/PrintDialog/print_forms/ultrasoundresult.jrxml";
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";
} else {
jrxmlPath = System.getProperty("user.dir") + "/src/main/java/BsK/client/ui/component/CheckUpPage/PrintDialog/print_forms/ultrasoundresult.jrxml";
}
log.info("Using JRXML template: {}", jrxmlPath);
try (InputStream inputStream = new FileInputStream(new File(jrxmlPath))) {
Map<String, Object> parameters = new HashMap<>();
@@ -151,14 +187,15 @@ public class UltrasoundResult {
parameters.put(JRParameter.REPORT_LOCALE, new Locale("vi", "VN"));
// Populate all the string parameters
parameters.put("clinicName", LocalStorage.ClinicName != null ? LocalStorage.ClinicName : "Phòng khám BSK");
parameters.put("clinicAddress", LocalStorage.ClinicAddress != null ? LocalStorage.ClinicAddress : "Địa chỉ phòng khám");
parameters.put("clinicPhone", LocalStorage.ClinicPhone != null ? LocalStorage.ClinicPhone : "SĐT phòng khám");
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"));
parameters.put("patientName", this.patientName);
parameters.put("patientDOB", this.patientDOB);
parameters.put("patientGender", this.patientGender);
parameters.put("patientAddress", this.patientAddress);
parameters.put("doctorName", this.doctorName);
parameters.put("ultrasoundDoctorName", this.ultrasoundDoctorName);
parameters.put("checkupDate", this.checkupDate);
parameters.put("barcodeNumber", this.checkupId);
@@ -176,6 +213,14 @@ public class UltrasoundResult {
// Template title
parameters.put("templateTitle", this.templateTitle);
// Extra safety: Ensure no parameter is null or "null" string
for (String key : parameters.keySet()) {
Object value = parameters.get(key);
if (value instanceof String && ("null".equals(value) || value == null)) {
parameters.put(key, "");
}
}
// Handle images
int numberOfImages = this.selectedImages.size();
@@ -37,6 +37,7 @@
<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"/>
@@ -45,17 +46,17 @@
<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="-5" width="70" height="64">
<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="70" y="0" width="233" height="20" forecolor="#FF0905" fontName="Times New Roman" fontSize="14.0" bold="true">
<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="70" y="20" width="217" height="22" fontName="Times New Roman" fontSize="10.0">
<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="70" y="42" width="162" height="15" fontName="Times New Roman" fontSize="8.0">
<expression><![CDATA[$P{clinicPhone}]]></expression>
<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>
@@ -132,7 +133,7 @@
<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="352" y="19" width="40" height="37">
<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>
@@ -149,11 +150,11 @@
<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="247" y="442" width="96" height="15" fontName="Times New Roman" fontSize="12.0" bold="true" hTextAlign="Center">
<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{doctorName}]]></expression>
<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>
@@ -164,7 +165,7 @@
<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="-113" y="19" width="64" height="40">
<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>
@@ -259,7 +260,7 @@
<expression><![CDATA[$P{image1}]]></expression>
</element>
</element>
<element kind="staticText" uuid="8f35aa72-22a4-45f0-a35e-8e35e832404e" x="-55" y="54" 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="-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>
@@ -0,0 +1,198 @@
<!-- 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>
@@ -158,7 +158,7 @@ public class TemplateDialog extends JDialog {
diagnosisArea.setLineWrap(true);
diagnosisArea.setWrapStyleWord(true);
imageCountComboBox = new JComboBox<>(new String[]{"1", "2", "3", "4", "5", "6"});
imageCountComboBox = new JComboBox<>(new String[]{"1", "2", "3", "4"});
printTypeComboBox = new JComboBox<>(new String[]{"Ngang", "Dọc"});
sttField = new JTextField(10);
@@ -18,7 +18,7 @@ import java.util.List;
public class QueueViewPage extends JFrame {
private DefaultTableModel tvQueueTableModel;
private JTable tvQueueTable;
private final String[] tvQueueColumns = {"Mã khám bệnh", "Họ và Tên", "Năm sinh"};
private final String[] tvQueueColumns = {"STT", "Họ và Tên", "Năm sinh"};
private JLabel clinicNameLabel;
private JLabel clinicAddressLabel;
@@ -211,7 +211,7 @@ public class QueueViewPage extends JFrame {
}
}
public void updateSpecificRoomStatus(int roomId, String patientIdForRoomBox, String fullPatientInfoForCentralDisplay, BsK.common.entity.Status status) {
public void updateSpecificRoomStatus(int roomId, String patientIdForRoomBox, String queueNumberForRoomBox, String fullPatientInfoForCentralDisplay, BsK.common.entity.Status status) {
JLabel targetLabel;
JPanel targetPanel;
String roomName;
@@ -230,7 +230,7 @@ public class QueueViewPage extends JFrame {
}
if (status == BsK.common.entity.Status.PROCESSING) {
styleRoomLabel(targetLabel, targetPanel, Color.RED.darker(), "Mã BN: " + patientIdForRoomBox);
styleRoomLabel(targetLabel, targetPanel, Color.RED.darker(), "STT: " + queueNumberForRoomBox);
if (roomId == 1) {
room1PatientInfo = fullPatientInfoForCentralDisplay;
} else {
@@ -289,8 +289,8 @@ public class QueueViewPage extends JFrame {
SimpleDateFormat inputDateFormat = new SimpleDateFormat("dd/MM/yyyy");
for (String[] row : fullQueueData) {
if (row.length > 15) { // Changed from > 3 to > 15 to ensure we have DOB data
String maKhamBenh = row[0];
if (row.length > 24) { // Ensure we have all data including queue number
String queueNumber = row[24]; // Use the new queue number from index 24
String ho = row[2];
String ten = row[3];
String hoVaTen = ho + " " + ten;
@@ -316,7 +316,7 @@ public class QueueViewPage extends JFrame {
}
}
}
tvDataList.add(new Object[]{maKhamBenh, hoVaTen, namSinh});
tvDataList.add(new Object[]{queueNumber, hoVaTen, namSinh});
}
}
tvQueueTableModel.setDataVector(tvDataList.toArray(new Object[0][0]), tvQueueColumns);
+8 -2
View File
@@ -30,6 +30,8 @@ public class Patient {
private String heartBeat;
private String bloodPressure;
private String driveUrl;
private String doctorUltrasoundId;
private String queueNumber;
public Patient(String[][] array) {
this.checkupId = array[0][0];
@@ -55,12 +57,14 @@ public class Patient {
this.heartBeat = array[0][20];
this.bloodPressure = array[0][21];
this.driveUrl = array[0][22];
this.doctorUltrasoundId = array[0][23];
this.queueNumber = array[0][24];
}
// New constructor for a single patient data row
public Patient(String[] data) {
if (data.length < 23) {
throw new IllegalArgumentException("Patient data array must contain at least 23 elements to include a conclusion.");
if (data.length < 25) {
throw new IllegalArgumentException("Patient data array must contain at least 25 elements to include a conclusion.");
}
this.checkupId = data[0];
this.checkupDate = data[1];
@@ -85,5 +89,7 @@ public class Patient {
this.heartBeat = data[20];
this.bloodPressure = data[21];
this.driveUrl = data[22];
this.doctorUltrasoundId = data[23];
this.queueNumber = data[24];
}
}
@@ -10,5 +10,6 @@ import lombok.Data;
public class CallPatientRequest implements Packet {
int roomId;
int patientId;
String queueNumber;
Status status;
}
@@ -11,6 +11,7 @@ public class SaveCheckupRequest implements Packet {
Integer checkupId;
Integer customerId;
Integer doctorId;
Integer doctorUltrasoundId;
Long checkupDate;
// Checkup Details
@@ -21,6 +22,7 @@ public class SaveCheckupRequest implements Packet {
String checkupType;
String conclusion;
Long reCheckupDate;
Boolean needsRecheckup; // Flag to indicate if re-checkup is needed
// Patient Details
String customerFirstName;
@@ -10,5 +10,6 @@ import lombok.Data;
public class CallPatientResponse implements Packet {
int patientId;
int roomId;
String queueNumber;
Status status;
}
@@ -109,7 +109,7 @@ public class ServerHandler extends SimpleChannelInboundHandler<TextWebSocketFram
"select a.checkup_id, a.checkup_date, c.customer_last_name, c.customer_first_name,\n" +
"d.doctor_first_name, d.doctor_last_name, a.suggestion, a.diagnosis, a.notes, a.status, a.customer_id, \n" +
"c.customer_number, c.customer_address, a.customer_weight, a.customer_height, c.customer_gender, c.customer_dob,\n" +
"a.checkup_type, a.conclusion, a.reCheckupDate, c.cccd_ddcn, a.heart_beat, a.blood_pressure, c.drive_url\n" +
"a.checkup_type, a.conclusion, a.reCheckupDate, c.cccd_ddcn, a.heart_beat, a.blood_pressure, c.drive_url, a.doctor_ultrasound_id, a.queue_number\n" +
"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" +
@@ -151,6 +151,8 @@ public class ServerHandler extends SimpleChannelInboundHandler<TextWebSocketFram
String heartBeat = rs.getString("heart_beat");
String bloodPressure = rs.getString("blood_pressure");
String driveUrl = rs.getString("drive_url");
String doctorUltrasoundId = rs.getString("doctor_ultrasound_id");
String queueNumber = String.format("%02d", rs.getInt("queue_number"));
if (driveUrl == null) {
driveUrl = "";
}
@@ -159,7 +161,7 @@ public class ServerHandler extends SimpleChannelInboundHandler<TextWebSocketFram
doctorLastName + " " + doctorFirstName, suggestion,
diagnosis, notes, status, customerId, customerNumber, customerAddress, customerWeight, customerHeight,
customerGender, customerDob, checkupType, conclusion, reCheckupDate, cccdDdcn, heartBeat, bloodPressure,
driveUrl
driveUrl, doctorUltrasoundId, queueNumber
);
resultList.add(result);
@@ -184,7 +186,8 @@ public class ServerHandler extends SimpleChannelInboundHandler<TextWebSocketFram
ResultSet rs = statement.executeQuery(
"select a.checkup_id, a.checkup_date, c.customer_last_name, c.customer_first_name,\n" +
"d.doctor_first_name, d.doctor_last_name, a.suggestion, a.diagnosis, a.notes, a.status, a.customer_id, \n" +
"c.customer_number, c.customer_address, a.customer_weight, a.customer_height, c.customer_gender, c.customer_dob, a.checkup_type, a.conclusion, a.reCheckupDate, c.cccd_ddcn, a.heart_beat, a.blood_pressure, c.drive_url\n" +
"c.customer_number, c.customer_address, a.customer_weight, a.customer_height, c.customer_gender, c.customer_dob, \n" +
"a.checkup_type, a.conclusion, a.reCheckupDate, c.cccd_ddcn, a.heart_beat, a.blood_pressure, c.drive_url, a.doctor_ultrasound_id, a.queue_number\n" +
"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" +
@@ -230,6 +233,8 @@ public class ServerHandler extends SimpleChannelInboundHandler<TextWebSocketFram
String heartBeat = rs.getString("heart_beat");
String bloodPressure = rs.getString("blood_pressure");
String driveUrl = rs.getString("drive_url");
String doctorUltrasoundId = rs.getString("doctor_ultrasound_id");
String queueNumber = String.format("%02d", rs.getInt("queue_number"));
if (driveUrl == null) {
driveUrl = "";
}
@@ -238,7 +243,7 @@ public class ServerHandler extends SimpleChannelInboundHandler<TextWebSocketFram
doctorLastName + " " + doctorFirstName, suggestion,
diagnosis, notes, status, customerId, customerNumber, customerAddress, customerWeight, customerHeight,
customerGender, customerDob, checkupType, conclusion, reCheckupDate, cccdDdcn, heartBeat, bloodPressure,
driveUrl
driveUrl, doctorUltrasoundId, queueNumber
);
resultList.add(result);
@@ -676,13 +681,44 @@ public class ServerHandler extends SimpleChannelInboundHandler<TextWebSocketFram
// 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) VALUES (?, ?, ?, ?)");
"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
@@ -742,14 +778,15 @@ public class ServerHandler extends SimpleChannelInboundHandler<TextWebSocketFram
}
if (packet instanceof CallPatientRequest callPatientRequest) {
log.debug("Received CallPatientRequest to call patient{}", callPatientRequest.getPatientId());
int patientId = callPatientRequest.getPatientId();
log.debug("Received CallPatientRequest to call patient checkup_id: {}", callPatientRequest.getPatientId());
int checkupId = callPatientRequest.getPatientId(); // This is the checkup_id
int roomId = callPatientRequest.getRoomId();
Status status = callPatientRequest.getStatus();
// send to all clients
String queueNumber = callPatientRequest.getQueueNumber();
// send to all clients with the queue number included
int maxCurId = SessionManager.getMaxSessionId();
for (int sessionId = 1; sessionId <= maxCurId; sessionId++) {
UserUtil.sendPacket(sessionId, new CallPatientResponse(patientId, roomId, status));
UserUtil.sendPacket(sessionId, new CallPatientResponse(checkupId, roomId, queueNumber, status));
}
}
@@ -809,8 +846,9 @@ public class ServerHandler extends SimpleChannelInboundHandler<TextWebSocketFram
String checkupSql = """
INSERT INTO Checkup (
checkup_id, customer_id, doctor_id, checkup_date,
suggestion, diagnosis, prescription_id, notes, status, checkup_type, conclusion, reCheckupDate, customer_weight, customer_height, heart_beat, blood_pressure
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
suggestion, diagnosis, prescription_id, notes, status, checkup_type, conclusion, reCheckupDate, customer_weight, customer_height,
heart_beat, blood_pressure, doctor_ultrasound_id
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
ON CONFLICT(checkup_id) DO UPDATE SET
suggestion = excluded.suggestion,
diagnosis = excluded.diagnosis,
@@ -823,7 +861,9 @@ public class ServerHandler extends SimpleChannelInboundHandler<TextWebSocketFram
customer_weight = excluded.customer_weight,
customer_height = excluded.customer_height,
heart_beat = excluded.heart_beat,
blood_pressure = excluded.blood_pressure
blood_pressure = excluded.blood_pressure,
doctor_ultrasound_id = excluded.doctor_ultrasound_id,
doctor_id = excluded.doctor_id
""";
PreparedStatement checkupStmt = conn.prepareStatement(checkupSql);
@@ -843,6 +883,7 @@ public class ServerHandler extends SimpleChannelInboundHandler<TextWebSocketFram
checkupStmt.setDouble(14, saveCheckupRequest.getCustomerHeight());
checkupStmt.setInt(15, saveCheckupRequest.getHeartBeat());
checkupStmt.setString(16, saveCheckupRequest.getBloodPressure());
checkupStmt.setInt(17, saveCheckupRequest.getDoctorUltrasoundId());
checkupStmt.executeUpdate();
log.info("Prescription ID generated or edited: {}", prescriptionId);
log.info("Checkup saved successfully");
Binary file not shown.