mirror of
https://github.com/tiennm99/BSK-All-in-One-Clinic-Management-System.git
synced 2026-10-11 12:11:43 +00:00
[update] Revise medical invoice format with updated patient information and service details. Enhance CheckUpPage by integrating patient history retrieval, updating field names for clarity, and improving window behavior for better user experience. Implement modal behavior for dialogs to maintain application state during interactions.
This commit is contained in:
1 parent
606e3abe0f
commit
6a00da57af
22 files changed
+919
-93
No files matched your search
Generated
+10
@@ -0,0 +1,10 @@
|
||||
<configuration name="BSK Client" type="Application" factoryName="Application">
|
||||
<option name="MAIN_CLASS_NAME" value="BsK.client.Client" />
|
||||
<module name="BSK-All-in-One-Clinic-Management-System" />
|
||||
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$" />
|
||||
<option name="ALLOW_RUNNING_IN_PARALLEL" value="true" />
|
||||
<option name="SINGLE_INSTANCE_ONLY" value="false" />
|
||||
<method v="2">
|
||||
<option name="Make" enabled="true" />
|
||||
</method>
|
||||
</configuration>
|
||||
Generated
+10
@@ -0,0 +1,10 @@
|
||||
<configuration name="BSK Server" type="Application" factoryName="Application" singleton="true">
|
||||
<option name="MAIN_CLASS_NAME" value="BsK.server.Server" />
|
||||
<module name="BSK-All-in-One-Clinic-Management-System" />
|
||||
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$" />
|
||||
<option name="ALLOW_RUNNING_IN_PARALLEL" value="false" />
|
||||
<option name="SINGLE_INSTANCE_ONLY" value="true" />
|
||||
<method v="2">
|
||||
<option name="Make" enabled="true" />
|
||||
</method>
|
||||
</configuration>
|
||||
Vendored
+72
@@ -0,0 +1,72 @@
|
||||
{
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"type": "java",
|
||||
"name": "Client",
|
||||
"request": "launch",
|
||||
"mainClass": "BsK.client.Client",
|
||||
"projectName": "ldS_BsK"
|
||||
},
|
||||
{
|
||||
"type": "java",
|
||||
"name": "Server",
|
||||
"request": "launch",
|
||||
"mainClass": "BsK.server.Server",
|
||||
"projectName": "ldS_BsK"
|
||||
},
|
||||
{
|
||||
"type": "java",
|
||||
"name": "BSK Server",
|
||||
"request": "launch",
|
||||
"mainClass": "BsK.server.Server",
|
||||
"projectName": "BSK-All-in-One-Clinic-Management-System",
|
||||
"cwd": "${workspaceFolder}",
|
||||
"console": "internalConsole",
|
||||
"internalConsoleOptions": "openOnSessionStart",
|
||||
"args": [],
|
||||
"vmArgs": [],
|
||||
"env": {},
|
||||
"preLaunchTask": "${command:java.clean.workspace}"
|
||||
},
|
||||
{
|
||||
"type": "java",
|
||||
"name": "BSK Client",
|
||||
"request": "launch",
|
||||
"mainClass": "BsK.client.Client",
|
||||
"projectName": "BSK-All-in-One-Clinic-Management-System",
|
||||
"cwd": "${workspaceFolder}",
|
||||
"console": "internalConsole",
|
||||
"internalConsoleOptions": "openOnSessionStart",
|
||||
"args": [],
|
||||
"vmArgs": [],
|
||||
"env": {}
|
||||
},
|
||||
{
|
||||
"type": "java",
|
||||
"name": "BSK Client (Instance 2)",
|
||||
"request": "launch",
|
||||
"mainClass": "BsK.client.Client",
|
||||
"projectName": "BSK-All-in-One-Clinic-Management-System",
|
||||
"cwd": "${workspaceFolder}",
|
||||
"console": "internalConsole",
|
||||
"internalConsoleOptions": "openOnSessionStart",
|
||||
"args": [],
|
||||
"vmArgs": [],
|
||||
"env": {}
|
||||
},
|
||||
{
|
||||
"type": "java",
|
||||
"name": "BSK Client (Instance 3)",
|
||||
"request": "launch",
|
||||
"mainClass": "BsK.client.Client",
|
||||
"projectName": "BSK-All-in-One-Clinic-Management-System",
|
||||
"cwd": "${workspaceFolder}",
|
||||
"console": "internalConsole",
|
||||
"internalConsoleOptions": "openOnSessionStart",
|
||||
"args": [],
|
||||
"vmArgs": [],
|
||||
"env": {}
|
||||
}
|
||||
]
|
||||
}
|
||||
Binary file not shown.
@@ -173,9 +173,30 @@ public class AddDialog extends JDialog {
|
||||
|
||||
// Set size of the dialog
|
||||
setSize(1000, 400);
|
||||
// Put in the middle
|
||||
setLocationRelativeTo(null);
|
||||
// Put in the middle of parent window
|
||||
setLocationRelativeTo(parent);
|
||||
setResizable(true);
|
||||
|
||||
// Ensure modal behavior and proper parent relationship
|
||||
setModalityType(Dialog.ModalityType.APPLICATION_MODAL);
|
||||
setAlwaysOnTop(false); // Don't force always on top, let modal behavior handle this
|
||||
|
||||
// Add window listener to handle minimize/restore events with parent
|
||||
addWindowListener(new WindowAdapter() {
|
||||
@Override
|
||||
public void windowIconified(WindowEvent e) {
|
||||
if (parent != null) {
|
||||
parent.setState(Frame.ICONIFIED);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void windowDeiconified(WindowEvent e) {
|
||||
if (parent != null && parent.getState() == Frame.ICONIFIED) {
|
||||
parent.setState(Frame.NORMAL);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Send request to get the latest 20 patients in the database
|
||||
sendGetRecentPatientRequest();
|
||||
|
||||
@@ -38,6 +38,8 @@ import java.awt.event.ActionListener;
|
||||
import java.awt.event.MouseAdapter;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.awt.event.WindowAdapter;
|
||||
import java.awt.event.WindowEvent;
|
||||
import java.awt.datatransfer.*;
|
||||
import java.text.DecimalFormat;
|
||||
import java.text.ParseException;
|
||||
@@ -95,6 +97,11 @@ import java.io.ByteArrayInputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.InputStream;
|
||||
|
||||
// Add new imports
|
||||
import BsK.common.entity.PatientHistory;
|
||||
import BsK.common.packet.req.GetPatientHistoryRequest;
|
||||
import BsK.common.packet.res.GetPatientHistoryResponse;
|
||||
|
||||
@Slf4j
|
||||
public class CheckUpPage extends JPanel {
|
||||
private MainFrame mainFrame;
|
||||
@@ -105,7 +112,7 @@ public class CheckUpPage extends JPanel {
|
||||
private JTable historyTable;
|
||||
private final ResponseListener<GetCheckUpQueueUpdateResponse> checkUpQueueUpdateListener = this::handleGetCheckUpQueueUpdateResponse;
|
||||
private final ResponseListener<GetCheckUpQueueResponse> checkUpQueueListener = this::handleGetCheckUpQueueResponse;
|
||||
private final ResponseListener<GetCustomerHistoryResponse> customerHistoryListener = this::handleGetCustomerHistoryResponse;
|
||||
private final ResponseListener<GetPatientHistoryResponse> patientHistoryListener = this::handleGetPatientHistoryResponse;
|
||||
private final ResponseListener<GetDistrictResponse> districtResponseListener = this::handleGetDistrictResponse;
|
||||
private final ResponseListener<GetWardResponse> wardResponseListener = this::handleGetWardResponse;
|
||||
private final ResponseListener<CallPatientResponse> callPatientResponseListener = this::handleCallPatientResponse;
|
||||
@@ -264,7 +271,7 @@ public class CheckUpPage extends JPanel {
|
||||
|
||||
ClientHandler.addResponseListener(GetCheckUpQueueResponse.class, checkUpQueueListener);
|
||||
ClientHandler.addResponseListener(GetCheckUpQueueUpdateResponse.class, checkUpQueueUpdateListener);
|
||||
ClientHandler.addResponseListener(GetCustomerHistoryResponse.class, customerHistoryListener);
|
||||
ClientHandler.addResponseListener(GetPatientHistoryResponse.class, patientHistoryListener);
|
||||
ClientHandler.addResponseListener(GetDistrictResponse.class, districtResponseListener);
|
||||
ClientHandler.addResponseListener(GetWardResponse.class, wardResponseListener);
|
||||
ClientHandler.addResponseListener(CallPatientResponse.class, callPatientResponseListener);
|
||||
@@ -1047,7 +1054,8 @@ public class CheckUpPage extends JPanel {
|
||||
public void mouseClicked(MouseEvent e) {
|
||||
if (e.getClickCount() == 1) {
|
||||
int selectedRow = historyTable.getSelectedRow();
|
||||
// if (selectedRow != -1) { System.out.println("Clicked on history row: " + selectedRow); }
|
||||
// send getPatientInfoByCheckupIdReq
|
||||
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -1436,9 +1444,9 @@ public class CheckUpPage extends JPanel {
|
||||
customerLastNameField.setText(selectedPatient.getCustomerLastName());
|
||||
customerFirstNameField.setText(selectedPatient.getCustomerFirstName());
|
||||
doctorComboBox.setSelectedItem(selectedPatient.getDoctorName());
|
||||
suggestionField.setText(selectedPatient.getSymptoms());
|
||||
diagnosisField.setText(selectedPatient.getDiagnosis());
|
||||
conclusionField.setText(""); // Clear conclusion field for now
|
||||
suggestionField.setText(selectedPatient.getSuggestion()); // De nghi
|
||||
diagnosisField.setText(selectedPatient.getDiagnosis()); // Chuan doan
|
||||
conclusionField.setText(selectedPatient.getConclusion()); // Ket luan
|
||||
|
||||
// Handle RTF notes content
|
||||
String notes = selectedPatient.getNotes();
|
||||
@@ -1469,7 +1477,7 @@ public class CheckUpPage extends JPanel {
|
||||
genderComboBox.setSelectedItem(selectedPatient.getCustomerGender());
|
||||
checkupTypeComboBox.setSelectedItem(selectedPatient.getCheckupType());
|
||||
|
||||
NetworkUtil.sendPacket(ClientHandler.ctx.channel(), new GetCustomerHistoryRequest(Integer.parseInt(selectedPatient.getCustomerId())));
|
||||
NetworkUtil.sendPacket(ClientHandler.ctx.channel(), new GetPatientHistoryRequest(Integer.parseInt(selectedPatient.getCustomerId())));
|
||||
|
||||
String fullAddress = selectedPatient.getCustomerAddress();
|
||||
String[] addressParts = fullAddress.split(", ");
|
||||
@@ -1578,9 +1586,13 @@ public class CheckUpPage extends JPanel {
|
||||
}
|
||||
}
|
||||
|
||||
private void handleGetCustomerHistoryResponse(GetCustomerHistoryResponse response) {
|
||||
log.info("Received customer history");
|
||||
private void handleGetPatientHistoryResponse(GetPatientHistoryResponse response) {
|
||||
log.info("Received patient history");
|
||||
this.history = response.getHistory();
|
||||
|
||||
// Access PatientHistory objects if needed
|
||||
List<PatientHistory> patientHistories = response.getPatientHistoryList();
|
||||
|
||||
historyModel.setDataVector(this.history, new String[]{"Ngày Tháng","Mã khám bệnh", "Triệu chứng", "Chẩn đoán", "Ghi chú"});
|
||||
}
|
||||
|
||||
@@ -2400,6 +2412,29 @@ public class CheckUpPage extends JPanel {
|
||||
setIconImage(new ImageIcon("src/main/java/BsK/client/ui/assets/icon/database.png").getImage());
|
||||
setSize(800, 600);
|
||||
setLayout(new BorderLayout());
|
||||
|
||||
// Add window listener to handle minimize/restore events with parent
|
||||
addWindowListener(new WindowAdapter() {
|
||||
@Override
|
||||
public void windowIconified(WindowEvent e) {
|
||||
if (mainFrame != null) {
|
||||
mainFrame.setState(java.awt.Frame.ICONIFIED);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void windowDeiconified(WindowEvent e) {
|
||||
if (mainFrame != null && mainFrame.getState() == java.awt.Frame.ICONIFIED) {
|
||||
mainFrame.setState(java.awt.Frame.NORMAL);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void windowClosing(WindowEvent e) {
|
||||
// Hide instead of closing to maintain state
|
||||
setVisible(false);
|
||||
}
|
||||
});
|
||||
|
||||
String[] columns = {"Mã khám bệnh", "Ngày sinh", "Họ", "Tên", "Bác Sĩ", "Loại khám"};
|
||||
queueTableModel = new DefaultTableModel(preprocessPatientDataForTable(patientQueue), columns) {
|
||||
@@ -2622,7 +2657,7 @@ public class CheckUpPage extends JPanel {
|
||||
String customerNumber = customerPhoneField.getText();
|
||||
String customerWeight = customerWeightSpinner.getValue().toString();
|
||||
String customerHeight = customerHeightSpinner.getValue().toString();
|
||||
String doctorName = (String) doctorComboBox.getSelectedItem();
|
||||
String doctorId = String.valueOf(doctorComboBox.getSelectedIndex() + 1);
|
||||
String suggestions = suggestionField.getText();
|
||||
String diagnosis = diagnosisField.getText();
|
||||
String conclusion = conclusionField.getText();
|
||||
@@ -2642,7 +2677,7 @@ public class CheckUpPage extends JPanel {
|
||||
log.info("customerNumber: {}", customerNumber);
|
||||
log.info("customerWeight: {}", customerWeight);
|
||||
log.info("customerHeight: {}", customerHeight);
|
||||
log.info("doctorName: {}", doctorName);
|
||||
log.info("doctorId: {}", doctorId);
|
||||
log.info("suggestions: {}", suggestions);
|
||||
log.info("diagnosis: {}", diagnosis);
|
||||
log.info("conclusion: {}", conclusion);
|
||||
@@ -2653,7 +2688,7 @@ public class CheckUpPage extends JPanel {
|
||||
log.info("servicePrescription: {}", (Object) servicePrescription);
|
||||
log.info("=== End SaveCheckupRequest Data ===");
|
||||
|
||||
// Create and send the save request
|
||||
|
||||
SaveCheckupRequest request = new SaveCheckupRequest(
|
||||
checkupId,
|
||||
checkupDate,
|
||||
@@ -2666,12 +2701,13 @@ public class CheckUpPage extends JPanel {
|
||||
customerNumber,
|
||||
customerWeight,
|
||||
customerHeight,
|
||||
doctorName,
|
||||
suggestions,
|
||||
diagnosis,
|
||||
doctorId,
|
||||
suggestions, // De nghi
|
||||
diagnosis, // Chuan doan
|
||||
rtfContent, // Send RTF content as notes
|
||||
status,
|
||||
checkupType,
|
||||
conclusion, // Ket luan
|
||||
medicinePrescription,
|
||||
servicePrescription
|
||||
);
|
||||
|
||||
+70
-14
@@ -8,6 +8,7 @@ import javax.swing.table.TableColumnModel;
|
||||
|
||||
import BsK.client.network.handler.ClientHandler;
|
||||
import BsK.client.network.handler.ResponseListener;
|
||||
import BsK.common.entity.Medicine;
|
||||
import BsK.common.packet.req.GetMedInfoRequest;
|
||||
import BsK.common.packet.res.GetMedInfoResponse;
|
||||
import BsK.common.util.network.NetworkUtil;
|
||||
@@ -21,6 +22,8 @@ import java.awt.event.KeyAdapter;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.awt.event.MouseAdapter;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.awt.event.WindowAdapter;
|
||||
import java.awt.event.WindowEvent;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
@@ -47,6 +50,7 @@ public class MedicineDialog extends JDialog {
|
||||
private JTable selectedTable;
|
||||
private boolean isProgrammaticallySettingMedicineNameField = false;
|
||||
|
||||
private List<Medicine> medicines = new ArrayList<>();
|
||||
private String[][] medicinePrescription;
|
||||
private static final Logger logger = LoggerFactory.getLogger(MedicineDialog.class);
|
||||
|
||||
@@ -57,6 +61,11 @@ public class MedicineDialog extends JDialog {
|
||||
void getMedInfoHandler(GetMedInfoResponse response) {
|
||||
logger.info("Received medicine data");
|
||||
medicineData = response.getMedInfo();
|
||||
|
||||
// Get Medicine objects from the response
|
||||
medicines = response.getMedicines();
|
||||
|
||||
// Set the data vector with the raw string arrays for backward compatibility
|
||||
tableModel.setDataVector(medicineData, medcineColumns);
|
||||
|
||||
// resize column width
|
||||
@@ -81,6 +90,27 @@ public class MedicineDialog extends JDialog {
|
||||
setSize(1100, 600);
|
||||
setLocationRelativeTo(parent);
|
||||
setResizable(true);
|
||||
|
||||
// Ensure modal behavior and proper parent relationship
|
||||
setModalityType(Dialog.ModalityType.APPLICATION_MODAL);
|
||||
setAlwaysOnTop(false); // Don't force always on top, let modal behavior handle this
|
||||
|
||||
// Add window listener to handle minimize/restore events with parent
|
||||
addWindowListener(new WindowAdapter() {
|
||||
@Override
|
||||
public void windowIconified(WindowEvent e) {
|
||||
if (parent != null) {
|
||||
parent.setState(Frame.ICONIFIED);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void windowDeiconified(WindowEvent e) {
|
||||
if (parent != null && parent.getState() == Frame.ICONIFIED) {
|
||||
parent.setState(Frame.NORMAL);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Initialize medicinePrescription as empty array
|
||||
medicinePrescription = new String[0][0];
|
||||
@@ -325,12 +355,29 @@ public class MedicineDialog extends JDialog {
|
||||
JButton removeMedicineButton = new JButton("Xóa thuốc đã chọn");
|
||||
removeButtonPanel.add(removeMedicineButton);
|
||||
|
||||
// Create titled panels for right side sections
|
||||
JPanel availableMedicinesPanel = new JPanel(new BorderLayout());
|
||||
availableMedicinesPanel.setBorder(BorderFactory.createTitledBorder(
|
||||
BorderFactory.createEtchedBorder(), "Thuốc trong kho",
|
||||
javax.swing.border.TitledBorder.LEADING, javax.swing.border.TitledBorder.TOP,
|
||||
new Font("Arial", Font.BOLD, 14), new Color(63, 81, 181)
|
||||
));
|
||||
availableMedicinesPanel.add(medicineTableScrollPane, BorderLayout.CENTER);
|
||||
|
||||
JPanel chosenMedicinesPanel = new JPanel(new BorderLayout());
|
||||
chosenMedicinesPanel.setBorder(BorderFactory.createTitledBorder(
|
||||
BorderFactory.createEtchedBorder(), "Thuốc đã chọn",
|
||||
javax.swing.border.TitledBorder.LEADING, javax.swing.border.TitledBorder.TOP,
|
||||
new Font("Arial", Font.BOLD, 14), new Color(220, 20, 60)
|
||||
));
|
||||
chosenMedicinesPanel.setBackground(new Color(255, 240, 240)); // Light red background
|
||||
selectedTableScrollPane.setBackground(new Color(255, 240, 240)); // Light red background
|
||||
chosenMedicinesPanel.add(selectedTableScrollPane, BorderLayout.CENTER);
|
||||
chosenMedicinesPanel.add(removeButtonPanel, BorderLayout.SOUTH);
|
||||
|
||||
JPanel rightPanel = new JPanel(new BorderLayout(0, 5));
|
||||
rightPanel.add(medicineTableScrollPane, BorderLayout.CENTER);
|
||||
JPanel bottomRightsPanel = new JPanel(new BorderLayout(0,5));
|
||||
bottomRightsPanel.add(selectedTableScrollPane, BorderLayout.CENTER);
|
||||
bottomRightsPanel.add(removeButtonPanel, BorderLayout.SOUTH);
|
||||
rightPanel.add(bottomRightsPanel, BorderLayout.SOUTH);
|
||||
rightPanel.add(availableMedicinesPanel, BorderLayout.CENTER);
|
||||
rightPanel.add(chosenMedicinesPanel, BorderLayout.SOUTH);
|
||||
|
||||
JScrollPane mainInputScrollPane = new JScrollPane(mainInputPanel);
|
||||
mainInputScrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
|
||||
@@ -439,12 +486,16 @@ public class MedicineDialog extends JDialog {
|
||||
medicineTable.clearSelection();
|
||||
} else {
|
||||
List<String[]> filteredData = new ArrayList<>();
|
||||
List<Medicine> filteredMedicines = new ArrayList<>();
|
||||
String lowerCaseFilterText = TextUtils.removeAccents(filterText.toLowerCase());
|
||||
for (String[] row : medicineData) {
|
||||
if (row.length > 1 && row[1] != null && TextUtils.removeAccents(row[1].toLowerCase()).contains(lowerCaseFilterText)) {
|
||||
filteredData.add(row);
|
||||
|
||||
for (Medicine med : medicines) {
|
||||
if (TextUtils.removeAccents(med.getName().toLowerCase()).contains(lowerCaseFilterText)) {
|
||||
filteredMedicines.add(med);
|
||||
filteredData.add(med.toStringArray());
|
||||
}
|
||||
}
|
||||
|
||||
tableModel.setDataVector(filteredData.toArray(new String[0][0]), medcineColumns);
|
||||
resizeMedicineTableColumns();
|
||||
if (!filteredData.isEmpty()) {
|
||||
@@ -534,18 +585,23 @@ public class MedicineDialog extends JDialog {
|
||||
currentPrice = tableModel.getValueAt(modelRow, 6).toString();
|
||||
} else {
|
||||
String searchName = medicineNameField.getText().trim();
|
||||
String foundId = null, foundUnit = null, foundPrice = null, actualName = null;
|
||||
for (String[] med : medicineData) {
|
||||
if (TextUtils.removeAccents(med[1].toLowerCase()).equals(TextUtils.removeAccents(searchName.toLowerCase()))) {
|
||||
foundId = med[0]; actualName = med[1]; foundUnit = med[5]; foundPrice = med[6];
|
||||
Medicine foundMedicine = null;
|
||||
|
||||
for (Medicine med : medicines) {
|
||||
if (TextUtils.removeAccents(med.getName().toLowerCase()).equals(TextUtils.removeAccents(searchName.toLowerCase()))) {
|
||||
foundMedicine = med;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (foundId == null) {
|
||||
|
||||
if (foundMedicine == null) {
|
||||
JOptionPane.showMessageDialog(this, "Không tìm thấy ID cho thuốc: " + searchName + ". Vui lòng chọn từ bảng.", "Lỗi", JOptionPane.ERROR_MESSAGE);
|
||||
return;
|
||||
}
|
||||
medicineId = foundId; name = actualName; unit = foundUnit; currentPrice = foundPrice;
|
||||
medicineId = foundMedicine.getId();
|
||||
name = foundMedicine.getName();
|
||||
unit = foundMedicine.getUnit();
|
||||
currentPrice = foundMedicine.getSellingPrice();
|
||||
}
|
||||
|
||||
int quantity = (Integer) quantitySpinner.getValue();
|
||||
|
||||
@@ -32,6 +32,8 @@ import java.util.ArrayList;
|
||||
import java.time.LocalDate;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.text.DecimalFormat;
|
||||
import java.awt.event.WindowAdapter;
|
||||
import java.awt.event.WindowEvent;
|
||||
|
||||
public class MedicineInvoice{
|
||||
|
||||
@@ -107,6 +109,27 @@ public class MedicineInvoice{
|
||||
dialog.setResizable(true);
|
||||
dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
|
||||
dialog.setLayout(new BorderLayout());
|
||||
|
||||
// Ensure modal behavior and proper parent relationship
|
||||
dialog.setModalityType(Dialog.ModalityType.APPLICATION_MODAL);
|
||||
dialog.setAlwaysOnTop(false); // Don't force always on top, let modal behavior handle this
|
||||
|
||||
// Add window listener to handle minimize/restore events with parent
|
||||
dialog.addWindowListener(new WindowAdapter() {
|
||||
@Override
|
||||
public void windowIconified(WindowEvent e) {
|
||||
if (parent != null) {
|
||||
parent.setState(Frame.ICONIFIED);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void windowDeiconified(WindowEvent e) {
|
||||
if (parent != null && parent.getState() == Frame.ICONIFIED) {
|
||||
parent.setState(Frame.NORMAL);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
JPanel buttonPanel = new JPanel(new GridLayout(1, 2));
|
||||
JButton saveButton = new JButton("Save PDF");
|
||||
|
||||
+73
-32
@@ -8,6 +8,7 @@ import javax.swing.table.TableColumnModel;
|
||||
|
||||
import BsK.client.network.handler.ClientHandler;
|
||||
import BsK.client.network.handler.ResponseListener;
|
||||
import BsK.common.entity.Service;
|
||||
import BsK.common.packet.req.GetSerInfoRequest;
|
||||
import BsK.common.packet.res.GetSerInfoResponse;
|
||||
import BsK.common.util.network.NetworkUtil;
|
||||
@@ -21,6 +22,8 @@ import java.awt.event.KeyAdapter;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.awt.event.MouseAdapter;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.awt.event.WindowAdapter;
|
||||
import java.awt.event.WindowEvent;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
@@ -41,6 +44,7 @@ public class ServiceDialog extends JDialog {
|
||||
private JTable selectedTable;
|
||||
private boolean isProgrammaticallySettingNameField = false;
|
||||
|
||||
private List<Service> services = new ArrayList<>();
|
||||
private String[][] servicePrescription;
|
||||
private static final Logger logger = LoggerFactory.getLogger(ServiceDialog.class);
|
||||
|
||||
@@ -51,6 +55,11 @@ public class ServiceDialog extends JDialog {
|
||||
void getSerInfoHandler(GetSerInfoResponse response) {
|
||||
logger.info("Received service data");
|
||||
serviceData = response.getSerInfo();
|
||||
|
||||
// Get Service objects from the response
|
||||
services = response.getServices();
|
||||
|
||||
// Set the data vector with the raw string arrays for backward compatibility
|
||||
tableModel.setDataVector(serviceData, serviceColumns);
|
||||
resizeServiceTableColumns();
|
||||
}
|
||||
@@ -66,6 +75,27 @@ public class ServiceDialog extends JDialog {
|
||||
setSize(1100, 600);
|
||||
setLocationRelativeTo(parent);
|
||||
setResizable(true);
|
||||
|
||||
// Ensure modal behavior and proper parent relationship
|
||||
setModalityType(Dialog.ModalityType.APPLICATION_MODAL);
|
||||
setAlwaysOnTop(false); // Don't force always on top, let modal behavior handle this
|
||||
|
||||
// Add window listener to handle minimize/restore events with parent
|
||||
addWindowListener(new WindowAdapter() {
|
||||
@Override
|
||||
public void windowIconified(WindowEvent e) {
|
||||
if (parent != null) {
|
||||
parent.setState(Frame.ICONIFIED);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void windowDeiconified(WindowEvent e) {
|
||||
if (parent != null && parent.getState() == Frame.ICONIFIED) {
|
||||
parent.setState(Frame.NORMAL);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Initialize servicePrescription as empty array
|
||||
servicePrescription = new String[0][0];
|
||||
@@ -217,12 +247,29 @@ public class ServiceDialog extends JDialog {
|
||||
JButton removeServiceButton = new JButton("Xóa dịch vụ đã chọn");
|
||||
removeServiceButtonPanel.add(removeServiceButton);
|
||||
|
||||
// Create titled panels for right side sections
|
||||
JPanel availableServicesPanel = new JPanel(new BorderLayout());
|
||||
availableServicesPanel.setBorder(BorderFactory.createTitledBorder(
|
||||
BorderFactory.createEtchedBorder(), "Dịch vụ có",
|
||||
javax.swing.border.TitledBorder.LEADING, javax.swing.border.TitledBorder.TOP,
|
||||
new Font("Arial", Font.BOLD, 14), new Color(63, 81, 181)
|
||||
));
|
||||
availableServicesPanel.add(serviceTableScrollPane, BorderLayout.CENTER);
|
||||
|
||||
JPanel chosenServicesPanel = new JPanel(new BorderLayout());
|
||||
chosenServicesPanel.setBorder(BorderFactory.createTitledBorder(
|
||||
BorderFactory.createEtchedBorder(), "Dịch vụ đã chọn",
|
||||
javax.swing.border.TitledBorder.LEADING, javax.swing.border.TitledBorder.TOP,
|
||||
new Font("Arial", Font.BOLD, 14), new Color(220, 20, 60)
|
||||
));
|
||||
chosenServicesPanel.setBackground(new Color(255, 240, 240)); // Light red background
|
||||
selectedTableScrollPane.setBackground(new Color(255, 240, 240)); // Light red background
|
||||
chosenServicesPanel.add(selectedTableScrollPane, BorderLayout.CENTER);
|
||||
chosenServicesPanel.add(removeServiceButtonPanel, BorderLayout.SOUTH);
|
||||
|
||||
JPanel rightPanel = new JPanel(new BorderLayout(0,5));
|
||||
rightPanel.add(serviceTableScrollPane, BorderLayout.CENTER);
|
||||
JPanel bottomRightPanel = new JPanel(new BorderLayout(0,5));
|
||||
bottomRightPanel.add(selectedTableScrollPane, BorderLayout.CENTER);
|
||||
bottomRightPanel.add(removeServiceButtonPanel, BorderLayout.SOUTH);
|
||||
rightPanel.add(bottomRightPanel, BorderLayout.SOUTH);
|
||||
rightPanel.add(availableServicesPanel, BorderLayout.CENTER);
|
||||
rightPanel.add(chosenServicesPanel, BorderLayout.SOUTH);
|
||||
|
||||
JScrollPane mainInputScrollPane = new JScrollPane(mainInputPanel);
|
||||
mainInputScrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
|
||||
@@ -333,30 +380,30 @@ public class ServiceDialog extends JDialog {
|
||||
private void filterServiceTable() {
|
||||
String filterText = serviceNameField.getText().trim();
|
||||
if (serviceData == null) return;
|
||||
|
||||
if (filterText.isEmpty()) {
|
||||
tableModel.setDataVector(serviceData, serviceColumns);
|
||||
resizeServiceTableColumns();
|
||||
serviceTable.clearSelection();
|
||||
} else {
|
||||
List<String[]> filteredData = new ArrayList<>();
|
||||
List<Service> filteredServices = new ArrayList<>();
|
||||
String lowerCaseFilterText = TextUtils.removeAccents(filterText.toLowerCase());
|
||||
for (String[] row : serviceData) {
|
||||
if (row.length > 1 && row[1] != null) {
|
||||
String cellValue = TextUtils.removeAccents(row[1].toLowerCase());
|
||||
if (cellValue.contains(lowerCaseFilterText)) {
|
||||
filteredData.add(row);
|
||||
}
|
||||
|
||||
for (Service service : services) {
|
||||
if (TextUtils.removeAccents(service.getName().toLowerCase()).contains(lowerCaseFilterText)) {
|
||||
filteredServices.add(service);
|
||||
filteredData.add(service.toStringArray());
|
||||
}
|
||||
}
|
||||
|
||||
tableModel.setDataVector(filteredData.toArray(new String[0][0]), serviceColumns);
|
||||
resizeServiceTableColumns();
|
||||
if (!filteredData.isEmpty()) {
|
||||
if (!filteredData.isEmpty()) {
|
||||
serviceTable.setRowSelectionInterval(0,0);
|
||||
handleServiceTableRowSelection(0);
|
||||
} else {
|
||||
clearInputFields();
|
||||
}
|
||||
clearInputFields();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -416,9 +463,7 @@ public class ServiceDialog extends JDialog {
|
||||
return;
|
||||
}
|
||||
|
||||
String serviceId;
|
||||
String name;
|
||||
String currentPrice;
|
||||
String serviceId, name, currentPrice;
|
||||
|
||||
if (selectedRowInServiceTable != -1) {
|
||||
int modelRow = serviceTable.convertRowIndexToModel(selectedRowInServiceTable);
|
||||
@@ -427,26 +472,22 @@ public class ServiceDialog extends JDialog {
|
||||
currentPrice = tableModel.getValueAt(modelRow, 2).toString();
|
||||
} else {
|
||||
String searchName = serviceNameField.getText().trim();
|
||||
String foundId = null;
|
||||
String foundPrice = null;
|
||||
String actualName = null;
|
||||
|
||||
for (String[] serv : serviceData) {
|
||||
if (TextUtils.removeAccents(serv[1].toLowerCase()).equals(TextUtils.removeAccents(searchName.toLowerCase()))) {
|
||||
foundId = serv[0];
|
||||
actualName = serv[1];
|
||||
foundPrice = serv[2];
|
||||
Service foundService = null;
|
||||
|
||||
for (Service service : services) {
|
||||
if (TextUtils.removeAccents(service.getName().toLowerCase()).equals(TextUtils.removeAccents(searchName.toLowerCase()))) {
|
||||
foundService = service;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (foundId == null) {
|
||||
|
||||
if (foundService == null) {
|
||||
JOptionPane.showMessageDialog(this, "Không tìm thấy ID cho dịch vụ: " + searchName + ". Vui lòng chọn từ bảng.", "Lỗi", JOptionPane.ERROR_MESSAGE);
|
||||
return;
|
||||
}
|
||||
serviceId = foundId;
|
||||
name = actualName;
|
||||
currentPrice = foundPrice;
|
||||
serviceId = foundService.getId();
|
||||
name = foundService.getName();
|
||||
currentPrice = foundService.getCost();
|
||||
}
|
||||
|
||||
int quantity = (Integer) quantitySpinner.getValue();
|
||||
|
||||
@@ -14,6 +14,8 @@ import javax.swing.text.StyleConstants;
|
||||
import java.awt.*;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.WindowAdapter;
|
||||
import java.awt.event.WindowEvent;
|
||||
|
||||
@Slf4j
|
||||
public class TemplateDialog extends JDialog {
|
||||
@@ -46,6 +48,27 @@ public class TemplateDialog extends JDialog {
|
||||
super(mainFrame, "Quản lý mẫu", true);
|
||||
this.mainFrame = mainFrame;
|
||||
|
||||
// Ensure modal behavior and proper parent relationship
|
||||
setModalityType(Dialog.ModalityType.APPLICATION_MODAL);
|
||||
setAlwaysOnTop(false); // Don't force always on top, let modal behavior handle this
|
||||
|
||||
// Add window listener to handle minimize/restore events with parent
|
||||
addWindowListener(new WindowAdapter() {
|
||||
@Override
|
||||
public void windowIconified(WindowEvent e) {
|
||||
if (mainFrame != null) {
|
||||
mainFrame.setState(Frame.ICONIFIED);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void windowDeiconified(WindowEvent e) {
|
||||
if (mainFrame != null && mainFrame.getState() == Frame.ICONIFIED) {
|
||||
mainFrame.setState(Frame.NORMAL);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
initializeComponents();
|
||||
setupLayout();
|
||||
setupListeners();
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
package BsK.common.entity;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* Entity class for Medicine
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class Medicine {
|
||||
private String id;
|
||||
private String name;
|
||||
private String company;
|
||||
private String description;
|
||||
private String quantity;
|
||||
private String unit;
|
||||
private String sellingPrice;
|
||||
|
||||
/**
|
||||
* Constructor to create Medicine from array data
|
||||
* @param data Array of medicine data from backend
|
||||
*/
|
||||
public Medicine(String[] data) {
|
||||
if (data.length < 7) {
|
||||
throw new IllegalArgumentException("Medicine data array must contain at least 7 elements");
|
||||
}
|
||||
this.id = data[0];
|
||||
this.name = data[1];
|
||||
this.company = data[2];
|
||||
this.description = data[3];
|
||||
this.quantity = data[4];
|
||||
this.unit = data[5];
|
||||
this.sellingPrice = data[6];
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the Medicine entity to a String array
|
||||
* @return String array representation of Medicine
|
||||
*/
|
||||
public String[] toStringArray() {
|
||||
return new String[]{id, name, company, description, quantity, unit, sellingPrice};
|
||||
}
|
||||
}
|
||||
@@ -12,7 +12,7 @@ public class Patient {
|
||||
private String customerLastName;
|
||||
private String customerFirstName;
|
||||
private String doctorName;
|
||||
private String symptoms;
|
||||
private String suggestion;
|
||||
private String diagnosis;
|
||||
private String notes;
|
||||
private String status;
|
||||
@@ -24,6 +24,7 @@ public class Patient {
|
||||
private String customerGender;
|
||||
private String customerDob;
|
||||
private String checkupType;
|
||||
private String conclusion;
|
||||
|
||||
public Patient(String[][] array) {
|
||||
this.checkupId = array[0][0];
|
||||
@@ -31,7 +32,7 @@ public class Patient {
|
||||
this.customerLastName = array[0][2];
|
||||
this.customerFirstName = array[0][3];
|
||||
this.doctorName = array[0][4];
|
||||
this.symptoms = array[0][5];
|
||||
this.suggestion = array[0][5];
|
||||
this.diagnosis = array[0][6];
|
||||
this.notes = array[0][7];
|
||||
this.status = array[0][8];
|
||||
@@ -43,6 +44,7 @@ public class Patient {
|
||||
this.customerGender = array[0][14];
|
||||
this.customerDob = array[0][15];
|
||||
this.checkupType = array[0][16];
|
||||
this.conclusion = array[0][17];
|
||||
}
|
||||
|
||||
// New constructor for a single patient data row
|
||||
@@ -55,7 +57,7 @@ public class Patient {
|
||||
this.customerLastName = data[2];
|
||||
this.customerFirstName = data[3];
|
||||
this.doctorName = data[4];
|
||||
this.symptoms = data[5];
|
||||
this.suggestion = data[5];
|
||||
this.diagnosis = data[6];
|
||||
this.notes = data[7];
|
||||
this.status = data[8];
|
||||
@@ -67,5 +69,6 @@ public class Patient {
|
||||
this.customerGender = data[14];
|
||||
this.customerDob = data[15];
|
||||
this.checkupType = data[16];
|
||||
this.conclusion = data[17];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
package BsK.common.entity;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* Entity class for Patient History
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class PatientHistory {
|
||||
private String checkupDate;
|
||||
private String checkupId;
|
||||
private String suggestion;
|
||||
private String diagnosis;
|
||||
private String prescriptionId;
|
||||
private String notes;
|
||||
|
||||
/**
|
||||
* Constructor to create PatientHistory from array data
|
||||
* @param data Array of patient history data from backend
|
||||
*/
|
||||
public PatientHistory(String[] data) {
|
||||
if (data.length < 6) {
|
||||
throw new IllegalArgumentException("PatientHistory data array must contain at least 6 elements");
|
||||
}
|
||||
this.checkupDate = data[0];
|
||||
this.checkupId = data[1];
|
||||
this.suggestion = data[2];
|
||||
this.diagnosis = data[3];
|
||||
this.prescriptionId = data[4];
|
||||
this.notes = data[5];
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the PatientHistory entity to a String array
|
||||
* @return String array representation of PatientHistory
|
||||
*/
|
||||
public String[] toStringArray() {
|
||||
return new String[]{checkupDate, checkupId, suggestion, diagnosis, prescriptionId, notes};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package BsK.common.entity;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* Entity class for Service
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class Service {
|
||||
private String id;
|
||||
private String name;
|
||||
private String cost;
|
||||
|
||||
/**
|
||||
* Constructor to create Service from array data
|
||||
* @param data Array of service data from backend
|
||||
*/
|
||||
public Service(String[] data) {
|
||||
if (data.length < 3) {
|
||||
throw new IllegalArgumentException("Service data array must contain at least 3 elements");
|
||||
}
|
||||
this.id = data[0];
|
||||
this.name = data[1];
|
||||
this.cost = data[2];
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the Service entity to a String array
|
||||
* @return String array representation of Service
|
||||
*/
|
||||
public String[] toStringArray() {
|
||||
return new String[]{id, name, cost};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package BsK.common.packet.req;
|
||||
|
||||
import BsK.common.packet.Packet;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
|
||||
@Slf4j
|
||||
@AllArgsConstructor
|
||||
@Data
|
||||
public class GetPatientHistoryRequest implements Packet {
|
||||
int patientId;
|
||||
}
|
||||
@@ -20,12 +20,13 @@ public class SaveCheckupRequest implements Packet {
|
||||
private String customerNumber; // Phone number
|
||||
private String customerWeight;
|
||||
private String customerHeight;
|
||||
private String doctorName; // Or doctorId if preferred for backend processing
|
||||
private String symptoms;
|
||||
private String doctorId; // Or doctorId if preferred for backend processing
|
||||
private String suggestions;
|
||||
private String diagnosis;
|
||||
private String notes;
|
||||
private String status;
|
||||
private String checkupType;
|
||||
private String conclusion;
|
||||
private String[][] medicinePrescription; // Structure: [med_id, name, quantity, unit, dose_morning, dose_noon, dose_evening, unit_price, total_price, notes]
|
||||
private String[][] servicePrescription; // Structure: [ser_id, name, quantity, unit_price, total_price, notes]
|
||||
}
|
||||
@@ -1,13 +1,51 @@
|
||||
package BsK.common.packet.res;
|
||||
|
||||
import BsK.common.entity.Medicine;
|
||||
import BsK.common.packet.Packet;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Slf4j
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
public class GetMedInfoResponse implements Packet {
|
||||
private String[][] medInfo;
|
||||
private transient List<Medicine> medicines;
|
||||
|
||||
public GetMedInfoResponse(String[][] medInfo) {
|
||||
this.medInfo = medInfo;
|
||||
this.medicines = convertToMedicineList(medInfo);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the raw string array data to a list of Medicine objects
|
||||
* @param medInfo Raw medicine data as string arrays
|
||||
* @return List of Medicine objects
|
||||
*/
|
||||
private List<Medicine> convertToMedicineList(String[][] medInfo) {
|
||||
List<Medicine> result = new ArrayList<>();
|
||||
if (medInfo != null) {
|
||||
for (String[] data : medInfo) {
|
||||
if (data.length >= 7) {
|
||||
result.add(new Medicine(data));
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the medicine list, converting from raw data if needed
|
||||
* @return List of Medicine objects
|
||||
*/
|
||||
public List<Medicine> getMedicines() {
|
||||
if (medicines == null && medInfo != null) {
|
||||
medicines = convertToMedicineList(medInfo);
|
||||
}
|
||||
return medicines;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package BsK.common.packet.res;
|
||||
|
||||
import BsK.common.entity.PatientHistory;
|
||||
import BsK.common.packet.Packet;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@Slf4j
|
||||
public class GetPatientHistoryResponse implements Packet {
|
||||
private String[][] history;
|
||||
private transient List<PatientHistory> patientHistoryList;
|
||||
|
||||
public GetPatientHistoryResponse(String[][] history) {
|
||||
this.history = history;
|
||||
this.patientHistoryList = convertToPatientHistoryList(history);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the raw string array data to a list of PatientHistory objects
|
||||
* @param history Raw patient history data as string arrays
|
||||
* @return List of PatientHistory objects
|
||||
*/
|
||||
private List<PatientHistory> convertToPatientHistoryList(String[][] history) {
|
||||
List<PatientHistory> result = new ArrayList<>();
|
||||
if (history != null) {
|
||||
for (String[] data : history) {
|
||||
if (data.length >= 6) {
|
||||
result.add(new PatientHistory(data));
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the patient history list, converting from raw data if needed
|
||||
* @return List of PatientHistory objects
|
||||
*/
|
||||
public List<PatientHistory> getPatientHistoryList() {
|
||||
if (patientHistoryList == null && history != null) {
|
||||
patientHistoryList = convertToPatientHistoryList(history);
|
||||
}
|
||||
return patientHistoryList;
|
||||
}
|
||||
}
|
||||
@@ -1,13 +1,51 @@
|
||||
package BsK.common.packet.res;
|
||||
|
||||
import BsK.common.entity.Service;
|
||||
import BsK.common.packet.Packet;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Slf4j
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
public class GetSerInfoResponse implements Packet {
|
||||
private String[][] serInfo;
|
||||
private transient List<Service> services;
|
||||
|
||||
public GetSerInfoResponse(String[][] serInfo) {
|
||||
this.serInfo = serInfo;
|
||||
this.services = convertToServiceList(serInfo);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the raw string array data to a list of Service objects
|
||||
* @param serInfo Raw service data as string arrays
|
||||
* @return List of Service objects
|
||||
*/
|
||||
private List<Service> convertToServiceList(String[][] serInfo) {
|
||||
List<Service> result = new ArrayList<>();
|
||||
if (serInfo != null) {
|
||||
for (String[] data : serInfo) {
|
||||
if (data.length >= 3) {
|
||||
result.add(new Service(data));
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the service list, converting from raw data if needed
|
||||
* @return List of Service objects
|
||||
*/
|
||||
public List<Service> getServices() {
|
||||
if (services == null && serInfo != null) {
|
||||
services = convertToServiceList(serInfo);
|
||||
}
|
||||
return services;
|
||||
}
|
||||
}
|
||||
@@ -19,6 +19,7 @@ import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler.Han
|
||||
import io.netty.handler.timeout.IdleState;
|
||||
import io.netty.handler.timeout.IdleStateEvent;
|
||||
import java.io.IOException;
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
@@ -30,6 +31,9 @@ import java.util.HashMap;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import BsK.common.entity.Medicine;
|
||||
import BsK.common.entity.Service;
|
||||
import BsK.common.entity.PatientHistory;
|
||||
|
||||
import static BsK.server.Server.statement;
|
||||
|
||||
@@ -94,8 +98,8 @@ public class ServerHandler extends SimpleChannelInboundHandler<TextWebSocketFram
|
||||
try {
|
||||
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.symptoms, a.diagnosis, a.notes, a.status, a.customer_id, \n" +
|
||||
"c.customer_number, c.customer_address, c.customer_weight, c.customer_height, c.customer_gender, c.customer_dob, a.checkup_type\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, c.customer_weight, c.customer_height, c.customer_gender, c.customer_dob, a.checkup_type, a.conclusion\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" +
|
||||
@@ -119,7 +123,7 @@ public class ServerHandler extends SimpleChannelInboundHandler<TextWebSocketFram
|
||||
String customerFirstName = rs.getString("customer_first_name");
|
||||
String doctorFirstName = rs.getString("doctor_first_name");
|
||||
String doctorLastName = rs.getString("doctor_last_name");
|
||||
String symptoms = rs.getString("symptoms");
|
||||
String suggestion = rs.getString("suggestion");
|
||||
String diagnosis = rs.getString("diagnosis");
|
||||
String notes = rs.getString("notes");
|
||||
String status = rs.getString("status");
|
||||
@@ -131,13 +135,13 @@ public class ServerHandler extends SimpleChannelInboundHandler<TextWebSocketFram
|
||||
String customerGender = rs.getString("customer_gender");
|
||||
String customerDob = rs.getString("customer_dob");
|
||||
String checkupType = rs.getString("checkup_type");
|
||||
|
||||
String conclusion = rs.getString("conclusion");
|
||||
|
||||
String result = String.join("|", checkupId,
|
||||
checkupDate, customerLastName, customerFirstName,
|
||||
doctorLastName + " " + doctorFirstName, symptoms,
|
||||
doctorLastName + " " + doctorFirstName, suggestion,
|
||||
diagnosis, notes, status, customerId, customerNumber, customerAddress, customerWeight, customerHeight,
|
||||
customerGender, customerDob, checkupType
|
||||
customerGender, customerDob, checkupType, conclusion
|
||||
);
|
||||
|
||||
resultList.add(result);
|
||||
@@ -161,7 +165,7 @@ public class ServerHandler extends SimpleChannelInboundHandler<TextWebSocketFram
|
||||
try {
|
||||
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.symptoms, a.diagnosis, a.notes, a.status, a.customer_id, \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, c.customer_weight, c.customer_height, c.customer_gender, c.customer_dob, a.checkup_type\n" +
|
||||
"from checkup as a\n" +
|
||||
"join customer as c on a.customer_id = c.customer_id\n" +
|
||||
@@ -186,7 +190,7 @@ public class ServerHandler extends SimpleChannelInboundHandler<TextWebSocketFram
|
||||
String customerFirstName = rs.getString("customer_first_name");
|
||||
String doctorFirstName = rs.getString("doctor_first_name");
|
||||
String doctorLastName = rs.getString("doctor_last_name");
|
||||
String symptoms = rs.getString("symptoms");
|
||||
String suggestion = rs.getString("suggestion");
|
||||
String diagnosis = rs.getString("diagnosis");
|
||||
String notes = rs.getString("notes");
|
||||
String status = rs.getString("status");
|
||||
@@ -202,7 +206,7 @@ public class ServerHandler extends SimpleChannelInboundHandler<TextWebSocketFram
|
||||
|
||||
String result = String.join("|", checkupId,
|
||||
checkupDate, customerLastName, customerFirstName,
|
||||
doctorLastName + " " + doctorFirstName, symptoms,
|
||||
doctorLastName + " " + doctorFirstName, suggestion,
|
||||
diagnosis, notes, status, customerId, customerNumber, customerAddress, customerWeight, customerHeight,
|
||||
customerGender, customerDob, checkupType
|
||||
);
|
||||
@@ -255,21 +259,21 @@ public class ServerHandler extends SimpleChannelInboundHandler<TextWebSocketFram
|
||||
}
|
||||
}
|
||||
|
||||
if (packet instanceof GetCustomerHistoryRequest getCustomerHistoryRequest) {
|
||||
log.debug("Received GetCustomerHistoryRequest");
|
||||
if (packet instanceof GetPatientHistoryRequest getPatientHistoryRequest) {
|
||||
log.debug("Received GetPatientHistoryRequest");
|
||||
try {
|
||||
ResultSet rs = statement.executeQuery(
|
||||
"select Checkup.checkup_date, Checkup.checkup_id, Checkup.symptoms, Checkup.diagnosis, Checkup.prescription_id, Checkup.notes\n" +
|
||||
"select Checkup.checkup_date, Checkup.checkup_id, Checkup.suggestion, Checkup.diagnosis, Checkup.prescription_id, Checkup.notes\n" +
|
||||
"from Customer\n" +
|
||||
"join Checkup on Customer.customer_id = Checkup.customer_id\n" +
|
||||
"where Checkup.status = \"DONE\" and Customer.customer_id = " +
|
||||
getCustomerHistoryRequest.getCustomerId() +
|
||||
getPatientHistoryRequest.getPatientId() +
|
||||
" order by checkup_date"
|
||||
);
|
||||
|
||||
if (!rs.isBeforeFirst()) {
|
||||
System.out.println("No history data found in the checkup table.");
|
||||
UserUtil.sendPacket(currentUser.getSessionId(), new GetCustomerHistoryResponse(new String[0][7]));
|
||||
UserUtil.sendPacket(currentUser.getSessionId(), new GetPatientHistoryResponse(new String[0][0]));
|
||||
} else {
|
||||
ArrayList<String> resultList = new ArrayList<>();
|
||||
while (rs.next()) {
|
||||
@@ -280,11 +284,11 @@ public class ServerHandler extends SimpleChannelInboundHandler<TextWebSocketFram
|
||||
SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
|
||||
checkupDate = sdf.format(date);
|
||||
String checkupId = rs.getString("checkup_id");
|
||||
String symptoms = rs.getString("symptoms");
|
||||
String suggestion = rs.getString("suggestion");
|
||||
String diagnosis = rs.getString("diagnosis");
|
||||
String prescriptionId = rs.getString("prescription_id");
|
||||
String notes = rs.getString("notes");
|
||||
String result = String.join("|", checkupDate, checkupId, symptoms, diagnosis, prescriptionId, notes);
|
||||
String result = String.join("|", checkupDate, checkupId, suggestion, diagnosis, prescriptionId, notes);
|
||||
resultList.add(result);
|
||||
// log.info(result);
|
||||
}
|
||||
@@ -295,7 +299,7 @@ public class ServerHandler extends SimpleChannelInboundHandler<TextWebSocketFram
|
||||
resultArray[i] = resultString[i].split("\\|");
|
||||
}
|
||||
|
||||
UserUtil.sendPacket(currentUser.getSessionId(), new GetCustomerHistoryResponse(resultArray));
|
||||
UserUtil.sendPacket(currentUser.getSessionId(), new GetPatientHistoryResponse(resultArray));
|
||||
}
|
||||
|
||||
} catch (SQLException e) {
|
||||
@@ -549,8 +553,12 @@ public class ServerHandler extends SimpleChannelInboundHandler<TextWebSocketFram
|
||||
if (packet instanceof AddPatientRequest addPatientRequest) {
|
||||
log.debug("Received AddPatientRequest");
|
||||
try {
|
||||
// Disable auto-commit for transaction
|
||||
Server.connection.setAutoCommit(false);
|
||||
|
||||
PreparedStatement preparedStatement = Server.connection.prepareStatement(
|
||||
"INSERT INTO Customer (customer_last_name, customer_first_name, customer_dob, customer_number, customer_address, customer_gender) VALUES (?, ?, ?, ?, ?, ?)"
|
||||
"INSERT INTO Customer (customer_last_name, customer_first_name, customer_dob, customer_number, customer_address, customer_gender) VALUES (?, ?, ?, ?, ?, ?)",
|
||||
PreparedStatement.RETURN_GENERATED_KEYS // Use this instead of separate query
|
||||
);
|
||||
preparedStatement.setString(1, addPatientRequest.getPatientLastName());
|
||||
preparedStatement.setString(2, addPatientRequest.getPatientFirstName());
|
||||
@@ -560,19 +568,40 @@ public class ServerHandler extends SimpleChannelInboundHandler<TextWebSocketFram
|
||||
preparedStatement.setString(6, addPatientRequest.getPatientGender());
|
||||
preparedStatement.executeUpdate();
|
||||
|
||||
// Get the last inserted ID
|
||||
PreparedStatement getIdStmt = Server.connection.prepareStatement("SELECT last_insert_rowid()");
|
||||
ResultSet rs = getIdStmt.executeQuery();
|
||||
// Get the generated key safely
|
||||
int customerId = 0;
|
||||
if (rs.next()) {
|
||||
customerId = rs.getInt(1);
|
||||
try (ResultSet generatedKeys = preparedStatement.getGeneratedKeys()) {
|
||||
if (generatedKeys.next()) {
|
||||
customerId = generatedKeys.getInt(1);
|
||||
} else {
|
||||
throw new SQLException("Creating patient failed, no ID obtained.");
|
||||
}
|
||||
}
|
||||
|
||||
// Commit the transaction
|
||||
Server.connection.commit();
|
||||
|
||||
// Close resources
|
||||
preparedStatement.close();
|
||||
|
||||
UserUtil.sendPacket(currentUser.getSessionId(), new AddPatientResponse(true, customerId, "Thêm bệnh nhân thành công"));
|
||||
} 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 AddPatientResponse(false,-1, "Lỗi: " + errorMessage));
|
||||
throw new RuntimeException(e);
|
||||
UserUtil.sendPacket(currentUser.getSessionId(), new AddPatientResponse(false, -1, "Lỗi: " + errorMessage));
|
||||
log.error("Error adding patient", e);
|
||||
} finally {
|
||||
try {
|
||||
// Reset auto-commit
|
||||
Server.connection.setAutoCommit(true);
|
||||
} catch (SQLException e) {
|
||||
log.error("Error resetting auto-commit", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -641,6 +670,238 @@ public class ServerHandler extends SimpleChannelInboundHandler<TextWebSocketFram
|
||||
UserUtil.sendPacket(sessionId, new CallPatientResponse(patientId, roomId, status));
|
||||
}
|
||||
}
|
||||
|
||||
if (packet instanceof SaveCheckupRequest saveCheckupRequest) {
|
||||
log.debug("Received SaveCheckupRequest to save checkup {}", saveCheckupRequest.getCheckupId());
|
||||
|
||||
Connection conn = null;
|
||||
try {
|
||||
conn = Server.connection;
|
||||
// Start transaction
|
||||
conn.setAutoCommit(false);
|
||||
|
||||
// 1. Insert/Update Customer
|
||||
String customerSql = """
|
||||
INSERT INTO Customer (
|
||||
customer_id, customer_first_name, customer_last_name, customer_dob,
|
||||
customer_gender, customer_address, customer_number,
|
||||
customer_weight, customer_height
|
||||
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||
ON CONFLICT(customer_id) DO UPDATE SET
|
||||
customer_first_name = excluded.customer_first_name,
|
||||
customer_last_name = excluded.customer_last_name,
|
||||
customer_dob = excluded.customer_dob,
|
||||
customer_gender = excluded.customer_gender,
|
||||
customer_address = excluded.customer_address,
|
||||
customer_number = excluded.customer_number,
|
||||
customer_weight = excluded.customer_weight,
|
||||
customer_height = excluded.customer_height
|
||||
""";
|
||||
|
||||
PreparedStatement customerStmt = conn.prepareStatement(customerSql);
|
||||
customerStmt.setString(1, saveCheckupRequest.getCustomerId());
|
||||
customerStmt.setString(2, saveCheckupRequest.getCustomerFirstName());
|
||||
customerStmt.setString(3, saveCheckupRequest.getCustomerLastName());
|
||||
customerStmt.setString(4, saveCheckupRequest.getCustomerDob());
|
||||
customerStmt.setString(5, saveCheckupRequest.getCustomerGender());
|
||||
customerStmt.setString(6, saveCheckupRequest.getCustomerAddress());
|
||||
customerStmt.setString(7, saveCheckupRequest.getCustomerNumber());
|
||||
customerStmt.setString(8, saveCheckupRequest.getCustomerWeight());
|
||||
customerStmt.setString(9, saveCheckupRequest.getCustomerHeight());
|
||||
customerStmt.executeUpdate();
|
||||
log.info("Customer saved successfully");
|
||||
// 2. Generate prescription_id if we have medicine prescriptions
|
||||
String prescriptionId = null;
|
||||
if (saveCheckupRequest.getMedicinePrescription() != null &&
|
||||
saveCheckupRequest.getMedicinePrescription().length > 0) {
|
||||
|
||||
// Get next prescription_id
|
||||
String getNextIdSql = "SELECT COALESCE(MAX(prescription_id), 0) + 1 as next_id FROM MedicineOrder";
|
||||
PreparedStatement nextIdStmt = conn.prepareStatement(getNextIdSql);
|
||||
ResultSet rs = nextIdStmt.executeQuery();
|
||||
if (rs.next()) {
|
||||
prescriptionId = rs.getString("next_id");
|
||||
}
|
||||
rs.close();
|
||||
nextIdStmt.close();
|
||||
}
|
||||
|
||||
// 3. Insert/Update Checkup
|
||||
String checkupSql = """
|
||||
INSERT INTO Checkup (
|
||||
checkup_id, customer_id, doctor_id, checkup_date,
|
||||
suggestion, diagnosis, prescription_id, notes, status, checkup_type, conclusion
|
||||
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||
ON CONFLICT(checkup_id) DO UPDATE SET
|
||||
suggestion = excluded.suggestion,
|
||||
diagnosis = excluded.diagnosis,
|
||||
prescription_id = excluded.prescription_id,
|
||||
notes = excluded.notes,
|
||||
status = excluded.status,
|
||||
checkup_type = excluded.checkup_type,
|
||||
conclusion = excluded.conclusion
|
||||
""";
|
||||
|
||||
PreparedStatement checkupStmt = conn.prepareStatement(checkupSql);
|
||||
checkupStmt.setString(1, saveCheckupRequest.getCheckupId());
|
||||
checkupStmt.setString(2, saveCheckupRequest.getCustomerId());
|
||||
checkupStmt.setString(3, saveCheckupRequest.getDoctorId());
|
||||
checkupStmt.setString(4, saveCheckupRequest.getCheckupDate());
|
||||
checkupStmt.setString(5, saveCheckupRequest.getSuggestions());
|
||||
checkupStmt.setString(6, saveCheckupRequest.getDiagnosis());
|
||||
checkupStmt.setString(7, prescriptionId);
|
||||
checkupStmt.setString(8, saveCheckupRequest.getNotes());
|
||||
checkupStmt.setString(9, saveCheckupRequest.getStatus());
|
||||
checkupStmt.setString(10, saveCheckupRequest.getCheckupType());
|
||||
checkupStmt.setString(11, saveCheckupRequest.getConclusion());
|
||||
checkupStmt.executeUpdate();
|
||||
log.info("Prescription ID generated or edited: {}", prescriptionId);
|
||||
log.info("Checkup saved successfully");
|
||||
// 4. Handle Medicine Prescriptions
|
||||
if (saveCheckupRequest.getMedicinePrescription() != null &&
|
||||
saveCheckupRequest.getMedicinePrescription().length > 0 && prescriptionId != null) {
|
||||
|
||||
// Calculate total amount for medicine order
|
||||
double totalMedicineAmount = 0;
|
||||
for (String[] medicine : saveCheckupRequest.getMedicinePrescription()) {
|
||||
if (medicine.length > 8) {
|
||||
try {
|
||||
totalMedicineAmount += Double.parseDouble(medicine[8]); // total_price
|
||||
} catch (NumberFormatException e) {
|
||||
log.warn("Invalid medicine total price: {}", medicine[8]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Insert/Update MedicineOrder
|
||||
String medicineOrderSql = """
|
||||
INSERT INTO MedicineOrder (
|
||||
prescription_id, checkup_id, customer_id,
|
||||
total_amount, payment_method, status,
|
||||
payment_status, processed_by, notes, datetime
|
||||
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, CURRENT_DATE)
|
||||
ON CONFLICT(prescription_id, checkup_id) DO UPDATE SET
|
||||
customer_id = excluded.customer_id,
|
||||
total_amount = excluded.total_amount,
|
||||
payment_method = excluded.payment_method,
|
||||
status = excluded.status,
|
||||
payment_status = excluded.payment_status,
|
||||
processed_by = excluded.processed_by,
|
||||
notes = excluded.notes,
|
||||
datetime = CURRENT_DATE
|
||||
""";
|
||||
|
||||
PreparedStatement medicineOrderStmt = conn.prepareStatement(medicineOrderSql);
|
||||
medicineOrderStmt.setString(1, prescriptionId);
|
||||
medicineOrderStmt.setString(2, saveCheckupRequest.getCheckupId());
|
||||
medicineOrderStmt.setString(3, saveCheckupRequest.getCustomerId());
|
||||
medicineOrderStmt.setDouble(4, totalMedicineAmount);
|
||||
medicineOrderStmt.setString(5, ""); // payment_method
|
||||
medicineOrderStmt.setString(6, "Pending"); // status
|
||||
medicineOrderStmt.setString(7, "Unpaid"); // payment_status
|
||||
medicineOrderStmt.setString(8, ""); // processed_by
|
||||
medicineOrderStmt.setString(9, ""); // notes
|
||||
medicineOrderStmt.executeUpdate();
|
||||
log.info("MedicineOrder saved successfully");
|
||||
// Insert OrderItems
|
||||
String orderItemSql = """
|
||||
INSERT INTO OrderItem (
|
||||
prescription_id, med_id, quantity_ordered,
|
||||
dosage, duration, price_per_unit, total_price, checkup_id, notes
|
||||
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||
ON CONFLICT(order_item_id) DO UPDATE SET
|
||||
quantity_ordered = excluded.quantity_ordered,
|
||||
dosage = excluded.dosage,
|
||||
duration = excluded.duration,
|
||||
price_per_unit = excluded.price_per_unit,
|
||||
total_price = excluded.total_price,
|
||||
checkup_id = excluded.checkup_id,
|
||||
notes = excluded.notes
|
||||
""";
|
||||
log.info("OrderItem saved successfully");
|
||||
PreparedStatement orderItemStmt = conn.prepareStatement(orderItemSql);
|
||||
|
||||
for (String[] medicine : saveCheckupRequest.getMedicinePrescription()) {
|
||||
if (medicine.length >= 10) {
|
||||
orderItemStmt.setString(1, prescriptionId);
|
||||
orderItemStmt.setString(2, medicine[0]); // med_id
|
||||
orderItemStmt.setString(3, medicine[2]); // quantity
|
||||
|
||||
// Build dosage string from morning, noon, evening
|
||||
String dosage = String.format("Sáng %s, Trưa %s, Chiều %s",
|
||||
medicine[4], medicine[5], medicine[6]);
|
||||
orderItemStmt.setString(4, dosage);
|
||||
orderItemStmt.setString(5, ""); // duration - could be calculated or added to request
|
||||
orderItemStmt.setString(6, medicine[7]); // unit_price
|
||||
orderItemStmt.setString(7, medicine[8]); // total_price
|
||||
orderItemStmt.setString(8, saveCheckupRequest.getCheckupId());
|
||||
orderItemStmt.setString(9, medicine[9]); // notes
|
||||
orderItemStmt.addBatch();
|
||||
}
|
||||
}
|
||||
orderItemStmt.executeBatch();
|
||||
}
|
||||
log.info("Medicine prescriptions saved successfully");
|
||||
// 5. Handle Service Prescriptions
|
||||
if (saveCheckupRequest.getServicePrescription() != null &&
|
||||
saveCheckupRequest.getServicePrescription().length > 0) {
|
||||
|
||||
String serviceSql = """
|
||||
INSERT INTO CheckupService (
|
||||
checkup_id, service_id, quantity,
|
||||
total_cost, status, checkup_date
|
||||
) VALUES (?, ?, ?, ?, ?, CURRENT_DATE)
|
||||
ON CONFLICT(order_id) DO UPDATE SET
|
||||
quantity = excluded.quantity,
|
||||
total_cost = excluded.total_cost,
|
||||
status = excluded.status
|
||||
""";
|
||||
|
||||
PreparedStatement serviceStmt = conn.prepareStatement(serviceSql);
|
||||
|
||||
for (String[] service : saveCheckupRequest.getServicePrescription()) {
|
||||
if (service.length >= 6) {
|
||||
serviceStmt.setString(1, saveCheckupRequest.getCheckupId());
|
||||
serviceStmt.setString(2, service[0]); // service_id
|
||||
serviceStmt.setString(3, service[2]); // quantity
|
||||
serviceStmt.setString(4, service[4]); // total_cost
|
||||
serviceStmt.setString(5, "PENDING"); // status
|
||||
|
||||
serviceStmt.addBatch();
|
||||
}
|
||||
}
|
||||
serviceStmt.executeBatch();
|
||||
}
|
||||
log.info("Service prescriptions saved successfully");
|
||||
// Commit transaction
|
||||
conn.commit();
|
||||
log.info("Successfully saved checkup {} with all related data", saveCheckupRequest.getCheckupId());
|
||||
|
||||
UserUtil.sendPacket(currentUser.getSessionId(), new AddCheckupResponse(true, "Checkup saved successfully"));
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("Error saving checkup transaction", e);
|
||||
// Rollback transaction on error
|
||||
if (conn != null) {
|
||||
try {
|
||||
conn.rollback();
|
||||
log.info("Transaction rolled back due to error");
|
||||
} catch (SQLException rollbackEx) {
|
||||
log.error("Error rolling back transaction", rollbackEx);
|
||||
}
|
||||
}
|
||||
UserUtil.sendPacket(currentUser.getSessionId(), new ErrorResponse(Error.SQL_EXCEPTION));
|
||||
} finally {
|
||||
// Restore auto-commit
|
||||
if (conn != null) {
|
||||
try {
|
||||
conn.setAutoCommit(true);
|
||||
} catch (SQLException e) {
|
||||
log.error("Error restoring auto-commit", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Binary file not shown.
Binary file not shown.
|
Before Width: | Height: | Size: 72 KiB |
Reference in new issue
Block a user