From 8dac9f2a1b4ef0c72c0a45c837a86aed8545ee2d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=AA=20Th=C3=A0nh=20=C4=90=E1=BA=A1t?= <91755733+lds217@users.noreply.github.com> Date: Tue, 14 Oct 2025 15:40:40 -0400 Subject: [PATCH] [update] Introduce shift management in the application by adding currentShift variable in LocalStorage. Update various components including CheckUpPage, DashboardPage, and NavBar to utilize shift information for queue and counter requests. Modify database request handling in ServerHandler to accommodate shift-based queries and responses. Update binary files for database to reflect changes. --- database/BSK.db-shm | Bin 32768 -> 32768 bytes database/BSK.db-wal | Bin 3633872 -> 3942872 bytes src/main/java/BsK/client/LocalStorage.java | 1 + .../ui/component/CheckUpPage/CheckUpPage.java | 9 +- .../DashboardPage/DashboardPage.java | 9 +- .../ui/component/LoginPage/LoginPage.java | 23 +- .../component/common/AddDialog/AddDialog.java | 6 +- .../client/ui/component/common/NavBar.java | 75 ++++-- .../common/packet/req/AddCheckupRequest.java | 1 + .../packet/req/DeleteCheckupRequest.java | 4 +- .../packet/req/GetCheckUpQueueRequest.java | 8 +- .../req/GetCheckUpQueueUpdateRequest.java | 5 + .../common/packet/req/GetCounterRequest.java | 7 +- .../common/packet/req/SaveCheckupRequest.java | 1 + .../common/packet/req/SetCounterRequest.java | 1 + .../res/GetCheckUpQueueUpdateResponse.java | 1 + .../common/packet/res/GetCounterResponse.java | 1 + .../common/packet/res/SetCounterResponse.java | 1 + .../server/network/handler/ServerHandler.java | 242 +++++++++--------- 19 files changed, 237 insertions(+), 158 deletions(-) diff --git a/database/BSK.db-shm b/database/BSK.db-shm index 0194ae226950cf2aab4a718500a1c88a2c15c2de..4d7a7fc0dd344ed3d9fbc31ea705dcc0d4447b5c 100644 GIT binary patch delta 780 zcmb7;O-Phc6o&7)@07H#nJ~&|AtWIZQ7(!$f!dE@ATtZ0p-n^$ErP(Z(ro6_%D>8{ zzAUZm*P8rG$6IQqL5sjeQc&v_wTTGANLobNdx!aApf-K*+;h%*-gCa=INEV^Ece4& zWxu6FlnP8jsWK)r%irwWP#l^IzWNlb2=4k(xcl3|`L1>PfBmWDeC*!&j4!QgRh6uN zogL#Jm7mzSm24xcSZpL-?RoN<6r_7rvp#PB;~Ql@PHeRO?Zn$n!nAS(Hr*agb6KPP-LRT z5iRX*N%;zQu5_9IFsf09dbHp?x^S0z*wk&=r{#(%Deu&#cE^+~IfXXd#68?cFNW|0 zPuW{7{-dbHX*@t5k{H1_XIIKqw%+QjV>p2`=%&ZjMZg8{Z$0JCwhgc%)k- z$~0`+4n%zZBRGjBJj5dyjA4TIChfK!+AFu1zSP-yszp6lU(}4+j2OrA-1k-QaxNl) j9t>a*!+4BQJi{dIFT^xfulLC%=CfK{hF@APbE@(;NJ7AM delta 294 zcmZo@U}|V!s+V}A%K!pGK+MR%AW+22z~ByKyqh4M|M`nXbikPx0e%4y-vbyD1wP~- zR3%kC*l-{LGWS0cfQmCQIB#q`&%3#W|Chn$3H&CEo9i6Xm?l4Rm74s|NeoD5Y_4%m zVcOitKZ|K|mB$Ij&5QglF#%ORVA=d7unxphW8FL>Qh;sqBUdNJ&94&nFacSw7$;9i z6##1guz5n-5=I~+YI9#k8VgWr8q?&i{3M_;$C$X~89EvEF}z{;$Y4A9p{wHLdqr1( R23}#@+*WG90<_bM4FK#TZ5Y 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 BDS`k1 diff --git a/src/main/java/BsK/client/LocalStorage.java b/src/main/java/BsK/client/LocalStorage.java index e2481b4..fe59ab0 100644 --- a/src/main/java/BsK/client/LocalStorage.java +++ b/src/main/java/BsK/client/LocalStorage.java @@ -24,6 +24,7 @@ public class LocalStorage { public static String pathToProject = ""; public static int currentMaxQueueNumber = 0; + public static int currentShift = 0; // 0 for morning, 1 for afternoon public static String dataDialogSearchTerm = ""; public static Date dataDialogFromDate = new Date(); public static Date dataDialogToDate = new Date(); diff --git a/src/main/java/BsK/client/ui/component/CheckUpPage/CheckUpPage.java b/src/main/java/BsK/client/ui/component/CheckUpPage/CheckUpPage.java index b206df2..ea7ada4 100644 --- a/src/main/java/BsK/client/ui/component/CheckUpPage/CheckUpPage.java +++ b/src/main/java/BsK/client/ui/component/CheckUpPage/CheckUpPage.java @@ -291,7 +291,7 @@ public class CheckUpPage extends JPanel { public void updateQueue() { - NetworkUtil.sendPacket(ClientHandler.ctx.channel(), new GetCheckUpQueueRequest()); + NetworkUtil.sendPacket(ClientHandler.ctx.channel(), new GetCheckUpQueueRequest(LocalStorage.currentShift)); } @@ -300,7 +300,7 @@ public class CheckUpPage extends JPanel { } public void updateUpdateQueue() { - NetworkUtil.sendPacket(ClientHandler.ctx.channel(), new GetCheckUpQueueUpdateRequest()); + NetworkUtil.sendPacket(ClientHandler.ctx.channel(), new GetCheckUpQueueUpdateRequest(LocalStorage.currentShift)); } private String[][] preprocessPatientDataForTable(List patients) { @@ -602,8 +602,6 @@ public class CheckUpPage extends JPanel { driveButton.setBackground(new Color(26, 115, 232)); // Google Blue color driveButton.setForeground(Color.WHITE); driveButton.setFocusPainted(false); - driveButton.setCursor(new Cursor(Cursor.HAND_CURSOR)); - driveButton.setEnabled(false); // Disabled by default driveButton.setBorder(BorderFactory.createEmptyBorder(8, 15, 8, 15)); // Load and set the icon @@ -4851,7 +4849,8 @@ public class CheckUpPage extends JPanel { (Integer) patientHeartRateSpinner.getValue(), bloodPressureSystolicSpinner.getValue() + "/" + bloodPressureDiastolicSpinner.getValue(), medicinePrescription, - servicePrescription + servicePrescription, + LocalStorage.currentShift ); NetworkUtil.sendPacket(ClientHandler.ctx.channel(), request); saved = true; diff --git a/src/main/java/BsK/client/ui/component/DashboardPage/DashboardPage.java b/src/main/java/BsK/client/ui/component/DashboardPage/DashboardPage.java index 20abfbe..3066b5d 100644 --- a/src/main/java/BsK/client/ui/component/DashboardPage/DashboardPage.java +++ b/src/main/java/BsK/client/ui/component/DashboardPage/DashboardPage.java @@ -53,7 +53,12 @@ public class DashboardPage extends JPanel { private void handleGetCheckUpQueueUpdateResponse(GetCheckUpQueueUpdateResponse response) { SwingUtilities.invokeLater(() -> { - log.info("Received dashboard queue update from server."); + if (response.getShift() != LocalStorage.currentShift) { + log.info("Ignored dashboard queue update for different shift. Current: {}, Received: {}", LocalStorage.currentShift, response.getShift()); + return; + } + + log.info("Received dashboard queue update from server for shift {}.", response.getShift()); this.patientQueue.clear(); if (response.getQueue() != null) { for (String[] patientData : response.getQueue()) { @@ -128,7 +133,7 @@ public class DashboardPage extends JPanel { ClientHandler.addResponseListener(TodayPatientCountResponse.class, todayPatientCountListener); ClientHandler.addResponseListener(RecheckCountResponse.class, recheckCountListener); log.info("DashboardPage listeners registered. Requesting initial data."); - NetworkUtil.sendPacket(ClientHandler.ctx.channel(), new GetCheckUpQueueUpdateRequest()); + NetworkUtil.sendPacket(ClientHandler.ctx.channel(), new GetCheckUpQueueUpdateRequest(LocalStorage.currentShift)); } private void startRealTimeClock() { diff --git a/src/main/java/BsK/client/ui/component/LoginPage/LoginPage.java b/src/main/java/BsK/client/ui/component/LoginPage/LoginPage.java index 2eafcf2..a623921 100644 --- a/src/main/java/BsK/client/ui/component/LoginPage/LoginPage.java +++ b/src/main/java/BsK/client/ui/component/LoginPage/LoginPage.java @@ -78,6 +78,21 @@ public class LoginPage extends JPanel { gbc.anchor = GridBagConstraints.WEST; JPasswordField passwordField = new JPasswordField(20); formPanel.add(passwordField, gbc); + + gbc.gridx = 0; + gbc.gridy++; + gbc.anchor = GridBagConstraints.EAST; + JLabel shiftLabel = new JLabel("Chọn ca:"); + shiftLabel.setForeground(Color.WHITE); + shiftLabel.setFont(new Font("Arial", Font.PLAIN, 14)); + formPanel.add(shiftLabel, gbc); + + gbc.gridx = 1; + gbc.anchor = GridBagConstraints.WEST; + String[] shifts = {"Chọn ca", "Ca sáng", "Ca chiều"}; + JComboBox shiftComboBox = new JComboBox<>(shifts); + formPanel.add(shiftComboBox, gbc); + // --- BUTTON PANEL START --- gbc.gridx = 0; @@ -120,10 +135,15 @@ public class LoginPage extends JPanel { passwordField.addActionListener(e -> loginButton.doClick()); loginButton.addActionListener(e -> { + if (shiftComboBox.getSelectedIndex() == 0) { + JOptionPane.showMessageDialog(this, "Vui lòng chọn ca làm việc.", "Lỗi", JOptionPane.ERROR_MESSAGE); + return; + } char[] passwordChars = passwordField.getPassword(); String password = new String(passwordChars); String username = loginField.getText(); - var loginRequest = new LoginRequest(username, password); + int shift = shiftComboBox.getSelectedIndex() - 1; + var loginRequest = new LoginRequest(username, password, shift); NetworkUtil.sendPacket(ClientHandler.ctx.channel(), loginRequest); }); @@ -131,6 +151,7 @@ public class LoginPage extends JPanel { log.info("Login successful, UserId: {}, Role: {}", response.getUserId(), response.getRole()); LocalStorage.username = loginField.getText(); LocalStorage.userId = response.getUserId(); + LocalStorage.currentShift = shiftComboBox.getSelectedIndex() - 1; // 0 for morning, 1 for afternoon NetworkUtil.sendPacket(ClientHandler.ctx.channel(), new ClinicInfoRequest()); NetworkUtil.sendPacket(ClientHandler.ctx.channel(), new GetDoctorGeneralInfo()); NetworkUtil.sendPacket(ClientHandler.ctx.channel(), new GetProvinceRequest()); diff --git a/src/main/java/BsK/client/ui/component/common/AddDialog/AddDialog.java b/src/main/java/BsK/client/ui/component/common/AddDialog/AddDialog.java index 8c08044..1679b16 100644 --- a/src/main/java/BsK/client/ui/component/common/AddDialog/AddDialog.java +++ b/src/main/java/BsK/client/ui/component/common/AddDialog/AddDialog.java @@ -644,8 +644,8 @@ public class AddDialog extends JDialog { // Send -1 to let the server know to auto-increment the queue number queueNumber = -1; } - log.info("Sending AddCheckupRequest with queue number: {}", queueNumber); - NetworkUtil.sendPacket(ClientHandler.ctx.channel(), new AddCheckupRequest(patientId, doctorId, LocalStorage.userId, selectedCheckupType, "CHỜ KHÁM", queueNumber)); + log.info("Sending AddCheckupRequest with queue number: {} for shift {}", queueNumber, LocalStorage.currentShift); + NetworkUtil.sendPacket(ClientHandler.ctx.channel(), new AddCheckupRequest(patientId, doctorId, LocalStorage.userId, selectedCheckupType, "CHỜ KHÁM", queueNumber, LocalStorage.currentShift)); }); checkupInfoPanel.add(saveButton, gbc); @@ -1105,7 +1105,7 @@ private void setupDebounceSearch() { // Now that the JOptionPane is closed, the connection is still alive. // This packet will be sent successfully. - NetworkUtil.sendPacket(ClientHandler.ctx.channel(), new GetCheckUpQueueUpdateRequest()); + NetworkUtil.sendPacket(ClientHandler.ctx.channel(), new GetCheckUpQueueUpdateRequest(LocalStorage.currentShift)); patientIdField.setText(String.valueOf(response.getPatientId())); addPatientButton.setEnabled(false); // Disable add patient button diff --git a/src/main/java/BsK/client/ui/component/common/NavBar.java b/src/main/java/BsK/client/ui/component/common/NavBar.java index 1d26419..a8fd8fa 100644 --- a/src/main/java/BsK/client/ui/component/common/NavBar.java +++ b/src/main/java/BsK/client/ui/component/common/NavBar.java @@ -31,6 +31,7 @@ import java.awt.event.MouseEvent; import java.awt.event.ActionListener; import java.text.SimpleDateFormat; import java.util.Date; +import java.util.Calendar; @Slf4j public class NavBar extends JPanel { @@ -41,6 +42,7 @@ public class NavBar extends JPanel { private RoundedPanel messageButtonPanel; // NEW: Reference to message button panel for repainting private JSpinner counterSpinner; // NEW: Spinner for current number private boolean isUpdatingSpinner = false; // Flag to prevent recursive updates + private int currentShift = 0; // 0 for morning, 1 for afternoon // Listener for incoming emergency alerts private final ResponseListener emergencyResponseListener = this::handleEmergencyResponse; @@ -285,7 +287,9 @@ public class NavBar extends JPanel { this.add(Box.createHorizontalGlue()); this.add(userPanel); - NetworkUtil.sendPacket(ClientHandler.ctx.channel(), new GetCounterRequest()); + // Determine current shift and request counter + currentShift = LocalStorage.currentShift; + NetworkUtil.sendPacket(ClientHandler.ctx.channel(), new GetCounterRequest(currentShift)); } private int findNavItemIndex(String text, String[] items) { @@ -297,7 +301,7 @@ public class NavBar extends JPanel { // NEW: Create counter spinner component private Component createCounterSpinner() { - JPanel counterPanel = new JPanel(new BorderLayout(5, 0)); + JPanel counterPanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 5, 0)); counterPanel.setBackground(this.getBackground()); counterPanel.setAlignmentY(Component.CENTER_ALIGNMENT); @@ -309,7 +313,7 @@ public class NavBar extends JPanel { // Create spinner with initial value of 1, minimum 1, maximum 999, step 1 SpinnerNumberModel spinnerModel = new SpinnerNumberModel(1, 1, 999, 1); counterSpinner = new JSpinner(spinnerModel); - counterSpinner.setPreferredSize(new Dimension(80, 30)); + counterSpinner.setPreferredSize(new Dimension(60, 30)); counterSpinner.setFont(new Font("Arial", Font.BOLD, 14)); counterSpinner.setEnabled(false); // Style the spinner @@ -330,13 +334,21 @@ public class NavBar extends JPanel { log.info("Counter spinner changed to: {}", newValue); // Send SetCounterRequest to server - NetworkUtil.sendPacket(ClientHandler.ctx.channel(), new SetCounterRequest(newValue)); + NetworkUtil.sendPacket(ClientHandler.ctx.channel(), new SetCounterRequest(newValue, currentShift)); } } }); - counterPanel.add(counterLabel, BorderLayout.WEST); - counterPanel.add(counterSpinner, BorderLayout.EAST); + counterPanel.add(counterLabel); + counterPanel.add(counterSpinner); + + String shiftText = (LocalStorage.currentShift == 0) ? "Ca sáng" : "Ca chiều"; + JLabel shiftLabel = new JLabel(shiftText); + shiftLabel.setFont(new Font("Arial", Font.BOLD, 12)); + shiftLabel.setForeground(new Color(60, 60, 60)); + + counterPanel.add(new JLabel("Ca:")); + counterPanel.add(shiftLabel); return counterPanel; } @@ -344,16 +356,21 @@ public class NavBar extends JPanel { // NEW: Handle SetCounterResponse private void handleSetCounterResponse(SetCounterResponse response) { SwingUtilities.invokeLater(() -> { - log.info("Received SetCounterResponse with value: {}", response.getCounter()); - LocalStorage.currentMaxQueueNumber = response.getCounter(); - // Update spinner value without triggering change event - isUpdatingSpinner = true; - try { - counterSpinner.setValue(response.getCounter()); - } catch (Exception e) { - log.error("Error updating counter spinner: {}", e.getMessage()); - } finally { - isUpdatingSpinner = false; + // Only update if the response is for the currently selected shift + if (response.getShift() == currentShift) { + log.info("Received SetCounterResponse with value: {} for shift {}", response.getCounter(), response.getShift()); + LocalStorage.currentMaxQueueNumber = response.getCounter(); + // Update spinner value without triggering change event + isUpdatingSpinner = true; + try { + counterSpinner.setValue(response.getCounter()); + } catch (Exception e) { + log.error("Error updating counter spinner: {}", e.getMessage()); + } finally { + isUpdatingSpinner = false; + } + } else { + log.info("Ignored SetCounterResponse for different shift. Current: {}, Received: {}", currentShift, response.getShift()); } }); } @@ -705,17 +722,21 @@ public class NavBar extends JPanel { private void handleGetCounterResponse(GetCounterResponse response) { SwingUtilities.invokeLater(() -> { - log.info("Received GetCounterResponse with initial value: {}", response.getCounter()); - LocalStorage.currentMaxQueueNumber = response.getCounter(); - // Update spinner value without triggering change event - isUpdatingSpinner = true; - try { - counterSpinner.setValue(response.getCounter()); - log.info("Counter spinner initialized to: {}", response.getCounter()); - } catch (Exception e) { - log.error("Error initializing counter spinner: {}", e.getMessage()); - } finally { - isUpdatingSpinner = false; + if (response.getShift() == currentShift) { + log.info("Received GetCounterResponse with initial value: {} for shift {}", response.getCounter(), response.getShift()); + LocalStorage.currentMaxQueueNumber = response.getCounter(); + // Update spinner value without triggering change event + isUpdatingSpinner = true; + try { + counterSpinner.setValue(response.getCounter()); + log.info("Counter spinner initialized to: {} for shift {}", response.getCounter(), response.getShift()); + } catch (Exception e) { + log.error("Error initializing counter spinner: {}", e.getMessage()); + } finally { + isUpdatingSpinner = false; + } + } else { + log.info("Ignored GetCounterResponse for different shift. Current: {}, Received: {}", currentShift, response.getShift()); } }); } diff --git a/src/main/java/BsK/common/packet/req/AddCheckupRequest.java b/src/main/java/BsK/common/packet/req/AddCheckupRequest.java index 701cd67..920c558 100644 --- a/src/main/java/BsK/common/packet/req/AddCheckupRequest.java +++ b/src/main/java/BsK/common/packet/req/AddCheckupRequest.java @@ -14,4 +14,5 @@ public class AddCheckupRequest implements Packet { private String checkupType; private String status; private int queueNumber; + private int shift; // 0 for morning, 1 for afternoon } diff --git a/src/main/java/BsK/common/packet/req/DeleteCheckupRequest.java b/src/main/java/BsK/common/packet/req/DeleteCheckupRequest.java index c618ee5..d283093 100644 --- a/src/main/java/BsK/common/packet/req/DeleteCheckupRequest.java +++ b/src/main/java/BsK/common/packet/req/DeleteCheckupRequest.java @@ -6,9 +6,11 @@ import lombok.Data; @Data public class DeleteCheckupRequest implements Packet { private long checkupId; + private int shift; - public DeleteCheckupRequest(long checkupId) { + public DeleteCheckupRequest(long checkupId, int shift) { this.checkupId = checkupId; + this.shift = shift; } } diff --git a/src/main/java/BsK/common/packet/req/GetCheckUpQueueRequest.java b/src/main/java/BsK/common/packet/req/GetCheckUpQueueRequest.java index 38d365b..70c2881 100644 --- a/src/main/java/BsK/common/packet/req/GetCheckUpQueueRequest.java +++ b/src/main/java/BsK/common/packet/req/GetCheckUpQueueRequest.java @@ -1,5 +1,11 @@ package BsK.common.packet.req; import BsK.common.packet.Packet; +import lombok.AllArgsConstructor; +import lombok.Data; -public class GetCheckUpQueueRequest implements Packet {} +@AllArgsConstructor +@Data +public class GetCheckUpQueueRequest implements Packet { + private int shift; +} diff --git a/src/main/java/BsK/common/packet/req/GetCheckUpQueueUpdateRequest.java b/src/main/java/BsK/common/packet/req/GetCheckUpQueueUpdateRequest.java index 5bf5bf8..031db74 100644 --- a/src/main/java/BsK/common/packet/req/GetCheckUpQueueUpdateRequest.java +++ b/src/main/java/BsK/common/packet/req/GetCheckUpQueueUpdateRequest.java @@ -1,6 +1,11 @@ package BsK.common.packet.req; import BsK.common.packet.Packet; +import lombok.AllArgsConstructor; +import lombok.Getter; +@AllArgsConstructor +@Getter public class GetCheckUpQueueUpdateRequest implements Packet { + private int shift; } diff --git a/src/main/java/BsK/common/packet/req/GetCounterRequest.java b/src/main/java/BsK/common/packet/req/GetCounterRequest.java index 440e3e9..4f6eac0 100644 --- a/src/main/java/BsK/common/packet/req/GetCounterRequest.java +++ b/src/main/java/BsK/common/packet/req/GetCounterRequest.java @@ -2,7 +2,10 @@ package BsK.common.packet.req; import BsK.common.packet.Packet; import lombok.AllArgsConstructor; +import lombok.Getter; + @AllArgsConstructor -public class GetCounterRequest implements Packet{ - +@Getter +public class GetCounterRequest implements Packet { + private int shift; // 0 for morning, 1 for afternoon } diff --git a/src/main/java/BsK/common/packet/req/SaveCheckupRequest.java b/src/main/java/BsK/common/packet/req/SaveCheckupRequest.java index 7f5a408..b5780e0 100644 --- a/src/main/java/BsK/common/packet/req/SaveCheckupRequest.java +++ b/src/main/java/BsK/common/packet/req/SaveCheckupRequest.java @@ -40,4 +40,5 @@ public class SaveCheckupRequest implements Packet { // Prescriptions String[][] medicinePrescription; String[][] servicePrescription; + int shift; } \ No newline at end of file diff --git a/src/main/java/BsK/common/packet/req/SetCounterRequest.java b/src/main/java/BsK/common/packet/req/SetCounterRequest.java index f2e14c7..b30d47a 100644 --- a/src/main/java/BsK/common/packet/req/SetCounterRequest.java +++ b/src/main/java/BsK/common/packet/req/SetCounterRequest.java @@ -8,4 +8,5 @@ import lombok.Data; @AllArgsConstructor public class SetCounterRequest implements Packet { private int counter; + private int shift; // 0 for morning, 1 for afternoon } diff --git a/src/main/java/BsK/common/packet/res/GetCheckUpQueueUpdateResponse.java b/src/main/java/BsK/common/packet/res/GetCheckUpQueueUpdateResponse.java index e436195..0311b0c 100644 --- a/src/main/java/BsK/common/packet/res/GetCheckUpQueueUpdateResponse.java +++ b/src/main/java/BsK/common/packet/res/GetCheckUpQueueUpdateResponse.java @@ -8,4 +8,5 @@ import lombok.Data; @Data public class GetCheckUpQueueUpdateResponse implements Packet { private String[][] queue; + private int shift; } \ No newline at end of file diff --git a/src/main/java/BsK/common/packet/res/GetCounterResponse.java b/src/main/java/BsK/common/packet/res/GetCounterResponse.java index 0404e43..0d4e379 100644 --- a/src/main/java/BsK/common/packet/res/GetCounterResponse.java +++ b/src/main/java/BsK/common/packet/res/GetCounterResponse.java @@ -8,4 +8,5 @@ import lombok.Data; @Data public class GetCounterResponse implements Packet{ private int counter; + private int shift; } diff --git a/src/main/java/BsK/common/packet/res/SetCounterResponse.java b/src/main/java/BsK/common/packet/res/SetCounterResponse.java index d0e4723..f5ec2bb 100644 --- a/src/main/java/BsK/common/packet/res/SetCounterResponse.java +++ b/src/main/java/BsK/common/packet/res/SetCounterResponse.java @@ -8,4 +8,5 @@ import lombok.Data; @AllArgsConstructor public class SetCounterResponse implements Packet{ private int counter; + private int shift; // 0 for morning, 1 for afternoon } diff --git a/src/main/java/BsK/server/network/handler/ServerHandler.java b/src/main/java/BsK/server/network/handler/ServerHandler.java index 9fe88c1..f5ce101 100644 --- a/src/main/java/BsK/server/network/handler/ServerHandler.java +++ b/src/main/java/BsK/server/network/handler/ServerHandler.java @@ -119,9 +119,9 @@ public class ServerHandler extends SimpleChannelInboundHandler currentMax) { String upsertSql = """ - INSERT INTO DailyQueueCounter (date, current_count) - VALUES (date('now', 'localtime'), ?) - ON CONFLICT(date) DO UPDATE SET current_count = ? + INSERT INTO DailyQueueCounter (date, shift, current_count) + VALUES (date('now', 'localtime'), ?, ?) + ON CONFLICT(date, shift) DO UPDATE SET current_count = ? """; try (PreparedStatement stmt = conn.prepareStatement(upsertSql)) { - stmt.setInt(1, queueNumber); + stmt.setInt(1, shift); stmt.setInt(2, queueNumber); + stmt.setInt(3, queueNumber); stmt.executeUpdate(); } shouldBroadcastCounter = true; @@ -675,13 +681,14 @@ public class ServerHandler extends SimpleChannelInboundHandler currentMax) { String upsertSql = """ - INSERT INTO DailyQueueCounter (date, current_count) - VALUES (date('now', 'localtime'), ?) - ON CONFLICT(date) DO UPDATE SET current_count = ? + INSERT INTO DailyQueueCounter (date, shift, current_count) + VALUES (date('now', 'localtime'), ?, ?) + ON CONFLICT(date, shift) DO UPDATE SET current_count = ? """; try (PreparedStatement stmt = conn.prepareStatement(upsertSql)) { - stmt.setInt(1, newCounter); + stmt.setInt(1, shift); stmt.setInt(2, newCounter); + stmt.setInt(3, newCounter); stmt.executeUpdate(); } int maxCurId = SessionManager.getMaxSessionId(); for (int sessionId = 1; sessionId <= maxCurId; sessionId++) { - UserUtil.sendPacket(sessionId, new SetCounterResponse(newCounter)); + UserUtil.sendPacket(sessionId, new SetCounterResponse(newCounter, shift)); } } } catch (SQLException e) { @@ -791,13 +802,18 @@ public class ServerHandler extends SimpleChannelInboundHandler resultList = new ArrayList<>(); - while (rs.next()) { - String checkupId = rs.getString("checkup_id"); - String checkupDate = rs.getString("checkup_date"); - long checkupDateLong = Long.parseLong(checkupDate); - Timestamp timestamp = new Timestamp(checkupDateLong); - Date date = new Date(timestamp.getTime()); - SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy"); - checkupDate = sdf.format(date); - String customerLastName = rs.getString("customer_last_name"); - String customerFirstName = rs.getString("customer_first_name"); - String doctorFirstName = rs.getString("doctor_first_name"); - String doctorLastName = rs.getString("doctor_last_name"); - String suggestion = rs.getString("suggestion"); - String diagnosis = rs.getString("diagnosis"); - String notes = rs.getString("notes"); - String status = rs.getString("status"); - String customerId = rs.getString("customer_id"); - String customerNumber = rs.getString("customer_number"); - String customerAddress = rs.getString("customer_address"); - String customerWeight = rs.getString("customer_weight"); - String customerHeight = rs.getString("customer_height"); - String customerGender = rs.getString("customer_gender"); - String customerDob = rs.getString("customer_dob"); - String checkupType = rs.getString("checkup_type"); - String conclusion = rs.getString("conclusion"); - String reCheckupDate = rs.getString("reCheckupDate"); - String cccdDdcn = rs.getString("cccd_ddcn"); - 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 = ""; } - String result = String.join("|", checkupId, checkupDate, customerLastName, customerFirstName, - doctorLastName + " " + doctorFirstName, suggestion, diagnosis, notes, status, customerId, customerNumber, customerAddress, customerWeight, customerHeight, - customerGender, customerDob, checkupType, conclusion, reCheckupDate, cccdDdcn, heartBeat, bloodPressure, - driveUrl, doctorUltrasoundId, queueNumber - ); - resultList.add(result); - } - String[] resultString = resultList.toArray(new String[0]); - resultArray = new String[resultString.length][]; - for (int i = 0; i < resultString.length; i++) { - resultArray[i] = resultString[i].split("\\|"); + if (!rs.isBeforeFirst()) { + log.warn("No data found in the checkup table for today's shift {}.", shift); + resultArray = new String[0][0]; + } else { + // ... (rest of the logic is the same) + ArrayList resultList = new ArrayList<>(); + while (rs.next()) { + String checkupId = rs.getString("checkup_id"); + String checkupDate = rs.getString("checkup_date"); + long checkupDateLong = Long.parseLong(checkupDate); + Timestamp timestamp = new Timestamp(checkupDateLong); + Date date = new Date(timestamp.getTime()); + SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy"); + checkupDate = sdf.format(date); + String customerLastName = rs.getString("customer_last_name"); + String customerFirstName = rs.getString("customer_first_name"); + String doctorFirstName = rs.getString("doctor_first_name"); + String doctorLastName = rs.getString("doctor_last_name"); + String suggestion = rs.getString("suggestion"); + String diagnosis = rs.getString("diagnosis"); + String notes = rs.getString("notes"); + String status = rs.getString("status"); + String customerId = rs.getString("customer_id"); + String customerNumber = rs.getString("customer_number"); + String customerAddress = rs.getString("customer_address"); + String customerWeight = rs.getString("customer_weight"); + String customerHeight = rs.getString("customer_height"); + String customerGender = rs.getString("customer_gender"); + String customerDob = rs.getString("customer_dob"); + String checkupType = rs.getString("checkup_type"); + String conclusion = rs.getString("conclusion"); + String reCheckupDate = rs.getString("reCheckupDate"); + String cccdDdcn = rs.getString("cccd_ddcn"); + 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 = ""; } + String result = String.join("|", checkupId, checkupDate, customerLastName, customerFirstName, + doctorLastName + " " + doctorFirstName, suggestion, diagnosis, notes, status, customerId, customerNumber, customerAddress, customerWeight, customerHeight, + customerGender, customerDob, checkupType, conclusion, reCheckupDate, cccdDdcn, heartBeat, bloodPressure, + driveUrl, doctorUltrasoundId, queueNumber + ); + resultList.add(result); + } + String[] resultString = resultList.toArray(new String[0]); + resultArray = new String[resultString.length][]; + for (int i = 0; i < resultString.length; i++) { + resultArray[i] = resultString[i].split("\\|"); } } - + // --- LOGIC GỐC ĐẾM SỐ BỆNH NHÂN TRONG NGÀY --- ZoneId zoneId = ZoneId.of("Asia/Ho_Chi_Minh"); LocalDate today = LocalDate.now(zoneId); @@ -2733,7 +2747,6 @@ public class ServerHandler extends SimpleChannelInboundHandler