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 3fcedf6..c11606a 100644 --- a/src/main/java/BsK/client/ui/component/CheckUpPage/CheckUpPage.java +++ b/src/main/java/BsK/client/ui/component/CheckUpPage/CheckUpPage.java @@ -10,11 +10,11 @@ import BsK.client.network.handler.ResponseListener; import BsK.client.ui.component.common.AddDialog.AddDialog; import BsK.client.ui.component.common.HistoryViewDialog.HistoryViewDialog; import BsK.client.ui.component.common.MedicineDialog.MedicineDialog; -import BsK.client.ui.component.common.PrintDialog.MedicineInvoice; -import BsK.client.ui.component.common.PrintDialog.UltrasoundResult; import BsK.client.ui.component.common.ServiceDialog.ServiceDialog; import BsK.client.ui.component.common.TemplateDialog.TemplateDialog; import BsK.client.ui.component.MainFrame; +import BsK.client.ui.component.CheckUpPage.PrintDialog.MedicineInvoice; +import BsK.client.ui.component.CheckUpPage.PrintDialog.UltrasoundResult; import BsK.client.ui.component.common.DateLabelFormatter; import BsK.client.ui.component.common.NavBar; import BsK.client.ui.component.common.RoundedPanel; @@ -1909,8 +1909,8 @@ public class CheckUpPage extends JPanel { ultrasoundDoctorNameForPrint, datePicker.getJFormattedTextField().getText(), TextUtils.scaleRtfFontSize(getRtfContentAsString()), - conclusionField.getText(), - suggestionField.getText(), + conclusionField.getText() == null ? "" : conclusionField.getText(), + suggestionField.getText() == null ? "" : suggestionField.getText(), recheckupDatePicker.getJFormattedTextField().getText(), selectedImagesForPrint, (String) orientationComboBox.getSelectedItem(), // Use selected orientation @@ -1941,7 +1941,7 @@ public class CheckUpPage extends JPanel { // } String statusToSavePrint = (String) statusComboBox.getSelectedItem(); handleSave(); - afterSaveActions(statusToSavePrint, "Đã lưu. Đang gửi lệnh in..."); + // Step 4: Finally, show print dialog with the pre-made object. try { @@ -1952,7 +1952,8 @@ public class CheckUpPage extends JPanel { } // Step 5: Upload PDF to backend after successful print dialog - uploadPdfToBackend(ultrasoundResultPrint, "ultrasound_result"); + uploadPdfToBackend(ultrasoundResultPrint, "ultrasound_result", checkupIdField.getText()); + afterSaveActions(statusToSavePrint, "Đã lưu. Đang gửi lệnh in..."); break; case "loupe": // This case now handles "Lưu & Xem" // Step 1: Validate conditions first. @@ -1990,8 +1991,8 @@ public class CheckUpPage extends JPanel { ultrasoundDoctorNameForView, datePicker.getJFormattedTextField().getText(), TextUtils.scaleRtfFontSize(getRtfContentAsString()), - conclusionField.getText(), - suggestionField.getText(), + conclusionField.getText() == null ? "" : conclusionField.getText(), + suggestionField.getText() == null ? "" : suggestionField.getText(), recheckupDatePicker.getJFormattedTextField().getText(), selectedImagesForPrint, (String) orientationComboBox.getSelectedItem(), // Use selected orientation @@ -2019,13 +2020,14 @@ public class CheckUpPage extends JPanel { // NO automatic status change for "Lưu & Xem" String statusToSaveView = (String) statusComboBox.getSelectedItem(); handleSave(); - afterSaveActions(statusToSaveView, "Đã lưu. Đang tạo bản xem trước..."); + // Step 4: Finally, show the viewer with the pre-made object. JasperViewer.viewReport(jasperPrintToView, false); // Step 5: Upload PDF to backend after successful view - uploadPdfToBackend(ultrasoundResultView, "ultrasound_result"); + uploadPdfToBackend(ultrasoundResultView, "ultrasound_result", checkupIdField.getText()); + afterSaveActions(statusToSaveView, "Đã lưu. Đang tạo bản xem trước..."); break; } } @@ -3692,11 +3694,7 @@ public class CheckUpPage extends JPanel { * @param ultrasoundResult The UltrasoundResult object to export as PDF * @param pdfType The type of PDF ("ultrasound_result" or "medserinvoice") */ - private void uploadPdfToBackend(UltrasoundResult ultrasoundResult, String pdfType) { - if (currentCheckupIdForMedia == null) { - log.warn("No current checkup ID for PDF upload"); - return; - } + private void uploadPdfToBackend(UltrasoundResult ultrasoundResult, String pdfType, String checkupId) { // Run PDF export and upload in background thread to avoid blocking UI CompletableFuture.runAsync(() -> { @@ -3709,17 +3707,17 @@ public class CheckUpPage extends JPanel { // Create and send upload request UploadCheckupPdfRequest request = new UploadCheckupPdfRequest( - currentCheckupIdForMedia, + checkupId, pdfBytes, fileName, pdfType ); NetworkUtil.sendPacket(ClientHandler.ctx.channel(), request); - log.info("Sent PDF upload request for checkup: {}, type: {}", currentCheckupIdForMedia, pdfType); + log.info("Sent PDF upload request for checkup: {}, type: {}", checkupId, pdfType); } catch (Exception e) { - log.error("Failed to export or upload PDF for checkup: {}", currentCheckupIdForMedia, e); + log.error("Failed to export or upload PDF for checkup: {}", checkupId, e); SwingUtilities.invokeLater(() -> { JOptionPane.showMessageDialog(this, "Lỗi khi tạo hoặc tải PDF: " + e.getMessage(), diff --git a/src/main/java/BsK/client/ui/component/common/PrintDialog/MedicineInvoice.java b/src/main/java/BsK/client/ui/component/CheckUpPage/PrintDialog/MedicineInvoice.java similarity index 99% rename from src/main/java/BsK/client/ui/component/common/PrintDialog/MedicineInvoice.java rename to src/main/java/BsK/client/ui/component/CheckUpPage/PrintDialog/MedicineInvoice.java index 8e6446d..dfa3ff5 100644 --- a/src/main/java/BsK/client/ui/component/common/PrintDialog/MedicineInvoice.java +++ b/src/main/java/BsK/client/ui/component/CheckUpPage/PrintDialog/MedicineInvoice.java @@ -1,8 +1,7 @@ -package BsK.client.ui.component.common.PrintDialog; +package BsK.client.ui.component.CheckUpPage.PrintDialog; import BsK.client.LocalStorage; -import BsK.client.ui.component.common.PrintDialog.print_forms.InvoiceItem; - +import BsK.client.ui.component.CheckUpPage.PrintDialog.print_forms.InvoiceItem; // JasperReports imports import net.sf.jasperreports.engine.*; import net.sf.jasperreports.engine.data.JRBeanCollectionDataSource; diff --git a/src/main/java/BsK/client/ui/component/common/PrintDialog/UltrasoundResult.java b/src/main/java/BsK/client/ui/component/CheckUpPage/PrintDialog/UltrasoundResult.java similarity index 99% rename from src/main/java/BsK/client/ui/component/common/PrintDialog/UltrasoundResult.java rename to src/main/java/BsK/client/ui/component/CheckUpPage/PrintDialog/UltrasoundResult.java index bd79768..59a263d 100644 --- a/src/main/java/BsK/client/ui/component/common/PrintDialog/UltrasoundResult.java +++ b/src/main/java/BsK/client/ui/component/CheckUpPage/PrintDialog/UltrasoundResult.java @@ -1,4 +1,4 @@ -package BsK.client.ui.component.common.PrintDialog; +package BsK.client.ui.component.CheckUpPage.PrintDialog; import BsK.client.LocalStorage; import com.itextpdf.io.font.constants.StandardFonts; diff --git a/src/main/java/BsK/client/ui/component/common/PrintDialog/print_forms/InvoiceItem.java b/src/main/java/BsK/client/ui/component/CheckUpPage/PrintDialog/print_forms/InvoiceItem.java similarity index 97% rename from src/main/java/BsK/client/ui/component/common/PrintDialog/print_forms/InvoiceItem.java rename to src/main/java/BsK/client/ui/component/CheckUpPage/PrintDialog/print_forms/InvoiceItem.java index 16329ab..bdc973b 100644 --- a/src/main/java/BsK/client/ui/component/common/PrintDialog/print_forms/InvoiceItem.java +++ b/src/main/java/BsK/client/ui/component/CheckUpPage/PrintDialog/print_forms/InvoiceItem.java @@ -1,4 +1,4 @@ -package BsK.client.ui.component.common.PrintDialog.print_forms; +package BsK.client.ui.component.CheckUpPage.PrintDialog.print_forms; /** * Represents a single item on the invoice, which can be a medicine, a service, or a supplement. diff --git a/src/main/java/BsK/client/ui/component/CheckUpPage/PrintDialog/print_forms/medserinvoice.jrxml b/src/main/java/BsK/client/ui/component/CheckUpPage/PrintDialog/print_forms/medserinvoice.jrxml new file mode 100644 index 0000000..861a71b Binary files /dev/null and b/src/main/java/BsK/client/ui/component/CheckUpPage/PrintDialog/print_forms/medserinvoice.jrxml differ diff --git a/src/main/java/BsK/client/ui/component/common/PrintDialog/print_forms/test_ultrasound_print.java b/src/main/java/BsK/client/ui/component/CheckUpPage/PrintDialog/print_forms/test_ultrasound_print.java similarity index 98% rename from src/main/java/BsK/client/ui/component/common/PrintDialog/print_forms/test_ultrasound_print.java rename to src/main/java/BsK/client/ui/component/CheckUpPage/PrintDialog/print_forms/test_ultrasound_print.java index 7ce72e8..4405d24 100644 --- a/src/main/java/BsK/client/ui/component/common/PrintDialog/print_forms/test_ultrasound_print.java +++ b/src/main/java/BsK/client/ui/component/CheckUpPage/PrintDialog/print_forms/test_ultrasound_print.java @@ -1,4 +1,4 @@ -package BsK.client.ui.component.common.PrintDialog.print_forms; +package BsK.client.ui.component.CheckUpPage.PrintDialog.print_forms; import net.sf.jasperreports.engine.JREmptyDataSource; import net.sf.jasperreports.engine.JasperReport; diff --git a/src/main/java/BsK/client/ui/component/common/PrintDialog/print_forms/ultrasoundresult.jrxml b/src/main/java/BsK/client/ui/component/CheckUpPage/PrintDialog/print_forms/ultrasoundresult.jrxml similarity index 100% rename from src/main/java/BsK/client/ui/component/common/PrintDialog/print_forms/ultrasoundresult.jrxml rename to src/main/java/BsK/client/ui/component/CheckUpPage/PrintDialog/print_forms/ultrasoundresult.jrxml diff --git a/src/main/java/BsK/client/ui/component/common/PrintDialog/print_forms/ultrasoundresult_potrait.jrxml b/src/main/java/BsK/client/ui/component/CheckUpPage/PrintDialog/print_forms/ultrasoundresult_potrait.jrxml similarity index 100% rename from src/main/java/BsK/client/ui/component/common/PrintDialog/print_forms/ultrasoundresult_potrait.jrxml rename to src/main/java/BsK/client/ui/component/CheckUpPage/PrintDialog/print_forms/ultrasoundresult_potrait.jrxml diff --git a/src/main/java/BsK/client/ui/component/DataDialog/MedicineManagementPanel.java b/src/main/java/BsK/client/ui/component/DataDialog/MedicineManagementPanel.java index ef613b2..fc8bd2c 100644 --- a/src/main/java/BsK/client/ui/component/DataDialog/MedicineManagementPanel.java +++ b/src/main/java/BsK/client/ui/component/DataDialog/MedicineManagementPanel.java @@ -3,6 +3,8 @@ package BsK.client.ui.component.DataDialog; import BsK.client.network.handler.ClientHandler; import BsK.client.network.handler.ResponseListener; import BsK.common.entity.Medicine; +import BsK.common.packet.req.AddMedicineRequest; +import BsK.common.packet.req.EditMedicineRequest; import BsK.common.packet.req.GetMedInfoRequest; import BsK.common.packet.res.GetMedInfoResponse; import BsK.common.util.network.NetworkUtil; @@ -14,7 +16,6 @@ import javax.swing.border.TitledBorder; import javax.swing.event.DocumentEvent; import javax.swing.event.DocumentListener; import javax.swing.table.DefaultTableModel; -import javax.swing.table.TableRowSorter; import java.awt.*; import java.util.ArrayList; import java.util.List; @@ -25,12 +26,12 @@ import java.util.List; */ public class MedicineManagementPanel extends JPanel { - // --- UI Components + // --- UI Components --- private JTable medicineTable; private DefaultTableModel medicineTableModel; private JTextField medicineSearchField; - // --- Input Fields + // --- Input Fields --- private JTextField medicineNameField; private JTextField medicineCompanyField; private JTextArea medicineDescriptionField; @@ -38,15 +39,17 @@ public class MedicineManagementPanel extends JPanel { private JTextField medicinePriceField; private JSpinner morningSpinner, noonSpinner, eveningSpinner; private JTextArea noteField; + private JCheckBox chkIsDeleted; // Checkbox for soft delete + private JCheckBox chkIsSupplement; // Checkbox for supplement status // --- Action Buttons --- - private JButton btnAdd, btnEdit, btnDelete, btnClear; + private JButton btnAdd, btnEdit, btnClear; - // --- Data & State + // --- Data & State --- private List allMedicines = new ArrayList<>(); private String selectedMedicineId = null; - // --- Networking + // --- Networking --- private final ResponseListener getMedInfoResponseListener = this::handleGetMedInfoResponse; public MedicineManagementPanel() { @@ -91,7 +94,7 @@ public class MedicineManagementPanel extends JPanel { TitledBorder.LEADING, TitledBorder.TOP, titleFont, new Color(50, 50, 50) )); - + GridBagConstraints gbc = new GridBagConstraints(); gbc.fill = GridBagConstraints.HORIZONTAL; gbc.anchor = GridBagConstraints.WEST; @@ -183,7 +186,7 @@ public class MedicineManagementPanel extends JPanel { medicinePriceField.setPreferredSize(textFieldSize); quantityPricePanel.add(medicinePriceField, gbc); gbc.weightx = 0.0; - + mainGbc.gridx = 0; mainGbc.gridy = 1; mainInputPanel.add(quantityPricePanel, mainGbc); @@ -230,7 +233,7 @@ public class MedicineManagementPanel extends JPanel { eveningSpinner.setPreferredSize(new Dimension(60,30)); dosagePanel.add(eveningSpinner, gbc); gbc.weightx = 0.0; - + mainGbc.gridx = 0; mainGbc.gridy = 2; mainInputPanel.add(dosagePanel, mainGbc); @@ -241,7 +244,7 @@ public class MedicineManagementPanel extends JPanel { TitledBorder.LEADING, TitledBorder.TOP, titleFont, new Color(50, 50, 50) )); - + gbc.gridy = 0; gbc.gridx = 0; JLabel noteLabel = new JLabel("Ghi chú:"); @@ -266,7 +269,7 @@ public class MedicineManagementPanel extends JPanel { mainGbc.gridx = 0; mainGbc.gridy = 3; mainInputPanel.add(notePanel, mainGbc); - + // --- Sub-Panel 5: Action Buttons --- mainGbc.gridx = 0; mainGbc.gridy = 4; mainGbc.fill = GridBagConstraints.HORIZONTAL; mainInputPanel.add(createMedicineButtonPanel(), mainGbc); @@ -283,60 +286,150 @@ public class MedicineManagementPanel extends JPanel { JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 10, 5)); btnAdd = new JButton("Thêm mới"); btnEdit = new JButton("Chỉnh sửa"); - btnDelete = new JButton("Xoá"); btnClear = new JButton("Làm mới"); + Font checkboxFont = new Font("Arial", Font.BOLD, 13); + chkIsSupplement = new JCheckBox("Thực phẩm bổ sung"); + chkIsSupplement.setFont(checkboxFont); + chkIsDeleted = new JCheckBox("Ẩn (Xoá)"); + chkIsDeleted.setFont(checkboxFont); + Dimension btnSize = new Dimension(100, 35); btnAdd.setPreferredSize(btnSize); btnEdit.setPreferredSize(btnSize); - btnDelete.setPreferredSize(btnSize); btnClear.setPreferredSize(btnSize); + // --- Component Order Changed Here --- + buttonPanel.add(chkIsSupplement); + buttonPanel.add(chkIsDeleted); buttonPanel.add(btnAdd); buttonPanel.add(btnEdit); - buttonPanel.add(btnDelete); buttonPanel.add(btnClear); // --- Button Actions --- btnClear.addActionListener(e -> clearMedicineFields()); + // --- ADD MEDICINE ACTION --- btnAdd.addActionListener(e -> { - String name = medicineNameField.getText(); - if (name.trim().isEmpty()) { + // 1. Validate required fields + String name = medicineNameField.getText().trim(); + if (name.isEmpty()) { JOptionPane.showMessageDialog(this, "Tên thuốc không được để trống.", "Lỗi", JOptionPane.ERROR_MESSAGE); + medicineNameField.requestFocusInWindow(); return; } - // TODO: Implement Add Medicine network request - JOptionPane.showMessageDialog(this, "Chức năng 'Thêm mới' cho thuốc '" + name + "' sẽ được thực hiện tại đây.", "Thông báo", JOptionPane.INFORMATION_MESSAGE); + + String priceText = medicinePriceField.getText().trim(); + if (priceText.isEmpty()) { + JOptionPane.showMessageDialog(this, "Giá thuốc không được để trống.", "Lỗi", JOptionPane.ERROR_MESSAGE); + medicinePriceField.requestFocusInWindow(); + return; + } + + // 2. Gather data from all other fields + String company = medicineCompanyField.getText().trim(); + String description = medicineDescriptionField.getText().trim(); + String unit = medicineUnitField.getText().trim(); + Boolean isSupplement = chkIsSupplement.isSelected(); + Boolean isDeleted = false; // New medicines are active by default + + // 3. Parse price and handle potential errors + double price; + try { + price = Double.parseDouble(priceText); + if (price < 0) { + JOptionPane.showMessageDialog(this, "Giá thuốc không được là số âm.", "Lỗi", JOptionPane.ERROR_MESSAGE); + medicinePriceField.requestFocusInWindow(); + return; + } + } catch (NumberFormatException nfe) { + JOptionPane.showMessageDialog(this, "Giá thuốc phải là một con số hợp lệ.", "Lỗi", JOptionPane.ERROR_MESSAGE); + medicinePriceField.requestFocusInWindow(); + return; + } + + // 4. Construct the special 'preferedNote' string + String preferedNote = morningSpinner.getValue().toString() + "," + + noonSpinner.getValue().toString() + "," + + eveningSpinner.getValue().toString() + "," + + noteField.getText().trim(); + + // 5. Create the request packet and send it to the server + // IMPORTANT: Assumes your AddMedicineRequest packet is updated to include 'supplement' + AddMedicineRequest request = new AddMedicineRequest(name, company, description, unit, price, preferedNote, isSupplement, isDeleted); + NetworkUtil.sendPacket(ClientHandler.ctx.channel(), request); + + // 6. Provide feedback and reset the form + JOptionPane.showMessageDialog(this, "Yêu cầu thêm thuốc '" + name + "' đã được gửi.", "Thành công", JOptionPane.INFORMATION_MESSAGE); + clearMedicineFields(); }); + // --- EDIT MEDICINE ACTION --- btnEdit.addActionListener(e -> { + // 1. Check if a medicine has been selected if (selectedMedicineId == null) { JOptionPane.showMessageDialog(this, "Vui lòng chọn một loại thuốc để chỉnh sửa.", "Chưa chọn thuốc", JOptionPane.WARNING_MESSAGE); return; } - // TODO: Implement Edit Medicine network request - String name = medicineNameField.getText(); - JOptionPane.showMessageDialog(this, "Chức năng 'Chỉnh sửa' cho thuốc ID: " + selectedMedicineId + " (" + name + ") sẽ được thực hiện tại đây.", "Thông báo", JOptionPane.INFORMATION_MESSAGE); - }); - btnDelete.addActionListener(e -> { - if (selectedMedicineId == null) { - JOptionPane.showMessageDialog(this, "Vui lòng chọn một loại thuốc để xóa.", "Chưa chọn thuốc", JOptionPane.WARNING_MESSAGE); + // 2. Validate required fields + String name = medicineNameField.getText().trim(); + if (name.isEmpty()) { + JOptionPane.showMessageDialog(this, "Tên thuốc không được để trống.", "Lỗi", JOptionPane.ERROR_MESSAGE); + medicineNameField.requestFocusInWindow(); return; } - int choice = JOptionPane.showConfirmDialog(this, - "Bạn có chắc chắn muốn xóa thuốc '" + medicineNameField.getText() + "' không?", - "Xác nhận xóa", JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE); - if (choice == JOptionPane.YES_OPTION) { - // TODO: Implement Delete Medicine network request - JOptionPane.showMessageDialog(this, "Chức năng 'Xoá' cho thuốc ID: " + selectedMedicineId + " sẽ được thực hiện tại đây.", "Thông báo", JOptionPane.INFORMATION_MESSAGE); + + String priceText = medicinePriceField.getText().trim(); + if (priceText.isEmpty()) { + JOptionPane.showMessageDialog(this, "Giá thuốc không được để trống.", "Lỗi", JOptionPane.ERROR_MESSAGE); + medicinePriceField.requestFocusInWindow(); + return; } + + // 3. Gather data from all fields + String id = selectedMedicineId; + String company = medicineCompanyField.getText().trim(); + String description = medicineDescriptionField.getText().trim(); + String unit = medicineUnitField.getText().trim(); + Boolean isSupplement = chkIsSupplement.isSelected(); + Boolean isDeleted = chkIsDeleted.isSelected(); + + // 4. Parse price and handle errors + Double price; + try { + price = Double.parseDouble(priceText); + if (price < 0) { + JOptionPane.showMessageDialog(this, "Giá thuốc không được là số âm.", "Lỗi", JOptionPane.ERROR_MESSAGE); + medicinePriceField.requestFocusInWindow(); + return; + } + } catch (NumberFormatException nfe) { + JOptionPane.showMessageDialog(this, "Giá thuốc phải là một con số hợp lệ.", "Lỗi", JOptionPane.ERROR_MESSAGE); + medicinePriceField.requestFocusInWindow(); + return; + } + + // 5. Construct the 'preferedNote' string + String preferedNote = morningSpinner.getValue().toString() + "," + + noonSpinner.getValue().toString() + "," + + eveningSpinner.getValue().toString() + "," + + noteField.getText().trim(); + + // 6. Create the request packet and send it + // IMPORTANT: Assumes your EditMedicineRequest packet is updated to include 'supplement' + EditMedicineRequest request = new EditMedicineRequest(id, name, company, description, unit, price, preferedNote, isSupplement, isDeleted); + NetworkUtil.sendPacket(ClientHandler.ctx.channel(), request); + + // 7. Provide user feedback and clear the form + JOptionPane.showMessageDialog(this, "Yêu cầu chỉnh sửa thuốc '" + name + "' đã được gửi.", "Thành công", JOptionPane.INFORMATION_MESSAGE); + clearMedicineFields(); }); // Initial button states btnEdit.setEnabled(false); - btnDelete.setEnabled(false); + chkIsSupplement.setEnabled(true); // Can set for new items + chkIsDeleted.setEnabled(false); // Can only set for existing items return buttonPanel; } @@ -348,7 +441,7 @@ public class MedicineManagementPanel extends JPanel { TitledBorder.LEFT, TitledBorder.TOP, new Font("Arial", Font.BOLD, 14))); // --- Table Setup --- - String[] medicineColumns = {"ID", "Tên thuốc", "Công ty", "Tồn kho", "ĐVT", "Đơn giá"}; + String[] medicineColumns = {"ID", "Tên thuốc", "Bổ sung", "Trạng thái"}; medicineTableModel = new DefaultTableModel(medicineColumns, 0) { @Override public boolean isCellEditable(int row, int column) { return false; } @@ -376,6 +469,7 @@ public class MedicineManagementPanel extends JPanel { JPanel searchPanel = new JPanel(new FlowLayout(FlowLayout.LEFT)); searchPanel.add(new JLabel("Tìm kiếm thuốc:")); medicineSearchField = new JTextField(25); + // FIX: Add the text field to the panel, not the panel to itself searchPanel.add(medicineSearchField); medicineSearchField.getDocument().addDocumentListener(new DocumentListener() { @@ -413,10 +507,15 @@ public class MedicineManagementPanel extends JPanel { medicineUnitField.setText(med.getUnit()); medicinePriceField.setText(med.getSellingPrice()); + // Set checkboxes based on the medicine's status + chkIsSupplement.setSelected("1".equals(med.getSupplement())); + chkIsDeleted.setSelected("1".equals(med.getDeleted())); + // Update button states btnAdd.setEnabled(false); btnEdit.setEnabled(true); - btnDelete.setEnabled(true); + chkIsSupplement.setEnabled(true); + chkIsDeleted.setEnabled(true); } private void clearMedicineFields() { @@ -426,13 +525,16 @@ public class MedicineManagementPanel extends JPanel { medicineDescriptionField.setText(""); medicineUnitField.setText(""); medicinePriceField.setText(""); + chkIsSupplement.setSelected(false); + chkIsDeleted.setSelected(false); medicineTable.clearSelection(); medicineNameField.requestFocusInWindow(); // Reset button states btnAdd.setEnabled(true); btnEdit.setEnabled(false); - btnDelete.setEnabled(false); + chkIsSupplement.setEnabled(true); + chkIsDeleted.setEnabled(false); } private void filterMedicineTable() { @@ -442,14 +544,19 @@ public class MedicineManagementPanel extends JPanel { medicineTableModel.setRowCount(0); // Clear the table before adding filtered results for (Medicine med : allMedicines) { - if (filterText.isEmpty() || TextUtils.removeAccents(med.getName().toLowerCase()).contains(lowerCaseFilterText)) { + // Check if name matches filter text + boolean nameMatches = filterText.isEmpty() || TextUtils.removeAccents(med.getName().toLowerCase()).contains(lowerCaseFilterText); + + if (nameMatches) { + // Determine the status text based on the flags + String supplementStatus = "1".equals(med.getSupplement()) ? "Có" : "Không"; + String deletedStatus = "0".equals(med.getDeleted()) ? "Đang bán" : "Đã ẩn"; + medicineTableModel.addRow(new Object[]{ med.getId(), med.getName(), - med.getCompany(), - med.getQuantity(), - med.getUnit(), - med.getSellingPrice() + supplementStatus, + deletedStatus }); } } diff --git a/src/main/java/BsK/client/ui/component/DataDialog/ServiceManagementPanel.java b/src/main/java/BsK/client/ui/component/DataDialog/ServiceManagementPanel.java index 66a4415..cd0fdfb 100644 --- a/src/main/java/BsK/client/ui/component/DataDialog/ServiceManagementPanel.java +++ b/src/main/java/BsK/client/ui/component/DataDialog/ServiceManagementPanel.java @@ -3,6 +3,8 @@ package BsK.client.ui.component.DataDialog; import BsK.client.network.handler.ClientHandler; import BsK.client.network.handler.ResponseListener; import BsK.common.entity.Service; +import BsK.common.packet.req.AddServiceRequest; +import BsK.common.packet.req.EditServiceRequest; import BsK.common.packet.req.GetSerInfoRequest; import BsK.common.packet.res.GetSerInfoResponse; import BsK.common.util.network.NetworkUtil; @@ -14,7 +16,6 @@ import javax.swing.border.TitledBorder; import javax.swing.event.DocumentEvent; import javax.swing.event.DocumentListener; import javax.swing.table.DefaultTableModel; -import javax.swing.table.TableRowSorter; import java.awt.*; import java.util.ArrayList; import java.util.List; @@ -33,9 +34,10 @@ public class ServiceManagementPanel extends JPanel { // --- Input Fields (Left Side) --- private JTextField serviceNameField; private JTextField priceField; - private JTextArea noteField; + private JCheckBox chkIsDeleted; // Checkbox for soft delete - private JButton btnAdd, btnEdit, btnDelete, btnClear; + // --- Action Buttons --- + private JButton btnAdd, btnEdit, btnClear; // --- Data & State --- private List allServices = new ArrayList<>(); @@ -88,20 +90,11 @@ public class ServiceManagementPanel extends JPanel { mainGbc.gridy = 0; mainInputPanel.add(serviceInfoPanel, mainGbc); - JPanel notePanel = new JPanel(new GridBagLayout()); - notePanel.setBorder(BorderFactory.createTitledBorder( - BorderFactory.createEtchedBorder(), "Ghi chú", - javax.swing.border.TitledBorder.LEADING, javax.swing.border.TitledBorder.TOP, - titleFont, new Color(50, 50, 50) - )); mainGbc.gridy = 1; - mainInputPanel.add(notePanel, mainGbc); - - mainGbc.gridy = 2; mainInputPanel.add(createServiceButtonPanel(), mainGbc); - mainGbc.gridy = 3; - mainGbc.weighty = 1.0; + mainGbc.gridy = 2; + mainGbc.weighty = 1.0; // Pushes content to the top mainInputPanel.add(new JPanel(), mainGbc); GridBagConstraints gbc = new GridBagConstraints(); @@ -119,91 +112,87 @@ public class ServiceManagementPanel extends JPanel { serviceInfoPanel.add(nameLabel, gbc); gbc.gridx = 1; - gbc.gridwidth = 3; gbc.weightx = 1.0; serviceNameField = new JTextField(20); serviceNameField.setFont(textFont); serviceNameField.setPreferredSize(textFieldSize); serviceInfoPanel.add(serviceNameField, gbc); - gbc.gridwidth = 1; - gbc.weightx = 0.0; // --- Đơn giá --- gbc.gridy++; gbc.gridx = 0; + gbc.weightx = 0.0; JLabel priceLabel = new JLabel("Đơn giá (VNĐ):"); priceLabel.setFont(labelFont); serviceInfoPanel.add(priceLabel, gbc); gbc.gridx = 1; - gbc.gridwidth = 3; gbc.weightx = 1.0; priceField = new JTextField(10); priceField.setFont(textFont); priceField.setPreferredSize(textFieldSize); serviceInfoPanel.add(priceField, gbc); - gbc.gridwidth = 1; - gbc.weightx = 0.0; - - // --- Ghi chú --- - gbc.gridy = 0; - gbc.gridx = 0; - gbc.anchor = GridBagConstraints.NORTHWEST; - JLabel noteLabel = new JLabel("Ghi chú:"); - noteLabel.setFont(labelFont); - notePanel.add(noteLabel, gbc); - gbc.anchor = GridBagConstraints.WEST; - - gbc.gridx = 1; - gbc.weightx = 1.0; - gbc.weighty = 1.0; - gbc.fill = GridBagConstraints.BOTH; - noteField = new JTextArea(3, 20); - noteField.setFont(textFont); - noteField.setLineWrap(true); - noteField.setWrapStyleWord(true); - JScrollPane noteScrollPane = new JScrollPane(noteField); - noteScrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED); - notePanel.add(noteScrollPane, gbc); - gbc.fill = GridBagConstraints.HORIZONTAL; - gbc.weightx = 0.0; - gbc.weighty = 0.0; return mainInputPanel; } /** - * Creates the panel containing the "Thêm", "Sửa", "Xóa", "Làm mới" buttons. + * Creates the panel containing the action buttons and checkboxes. */ private JPanel createServiceButtonPanel() { JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 10, 5)); btnAdd = new JButton("Thêm mới"); btnEdit = new JButton("Chỉnh sửa"); - btnDelete = new JButton("Xoá"); btnClear = new JButton("Làm mới"); + chkIsDeleted = new JCheckBox("Ẩn (Xoá)"); + chkIsDeleted.setFont(new Font("Arial", Font.BOLD, 13)); Dimension btnSize = new Dimension(100, 35); btnAdd.setPreferredSize(btnSize); btnEdit.setPreferredSize(btnSize); - btnDelete.setPreferredSize(btnSize); btnClear.setPreferredSize(btnSize); + // --- Component Order Changed Here --- + buttonPanel.add(chkIsDeleted); buttonPanel.add(btnAdd); buttonPanel.add(btnEdit); - buttonPanel.add(btnDelete); buttonPanel.add(btnClear); // Button Actions btnClear.addActionListener(e -> clearServiceFields()); btnAdd.addActionListener(e -> { - String name = serviceNameField.getText(); - if (name.trim().isEmpty()) { + String name = serviceNameField.getText().trim(); + if (name.isEmpty()) { JOptionPane.showMessageDialog(this, "Tên dịch vụ không được để trống.", "Lỗi", JOptionPane.ERROR_MESSAGE); + serviceNameField.requestFocusInWindow(); return; } - // TODO: Implement Add Service network request - JOptionPane.showMessageDialog(this, "Chức năng 'Thêm mới' cho dịch vụ '" + name + "' sẽ được thực hiện tại đây.", "Thông báo", JOptionPane.INFORMATION_MESSAGE); + String priceText = priceField.getText().trim(); + if (priceText.isEmpty()) { + JOptionPane.showMessageDialog(this, "Giá dịch vụ không được để trống.", "Lỗi", JOptionPane.ERROR_MESSAGE); + priceField.requestFocusInWindow(); + return; + } + + Double price; + try { + price = Double.parseDouble(priceText); + if (price < 0) { + JOptionPane.showMessageDialog(this, "Giá dịch vụ không được là số âm.", "Lỗi", JOptionPane.ERROR_MESSAGE); + return; + } + } catch (NumberFormatException nfe) { + JOptionPane.showMessageDialog(this, "Giá dịch vụ phải là một con số hợp lệ.", "Lỗi", JOptionPane.ERROR_MESSAGE); + return; + } + + Boolean deleted = false; // New services are active by default + AddServiceRequest request = new AddServiceRequest(name, price, deleted); + NetworkUtil.sendPacket(ClientHandler.ctx.channel(), request); + + JOptionPane.showMessageDialog(this, "Yêu cầu thêm dịch vụ '" + name + "' đã được gửi.", "Thành công", JOptionPane.INFORMATION_MESSAGE); + clearServiceFields(); }); btnEdit.addActionListener(e -> { @@ -211,28 +200,40 @@ public class ServiceManagementPanel extends JPanel { JOptionPane.showMessageDialog(this, "Vui lòng chọn một dịch vụ để chỉnh sửa.", "Chưa chọn dịch vụ", JOptionPane.WARNING_MESSAGE); return; } - // TODO: Implement Edit Service network request - String name = serviceNameField.getText(); - JOptionPane.showMessageDialog(this, "Chức năng 'Chỉnh sửa' cho dịch vụ ID: " + selectedServiceId + " (" + name + ") sẽ được thực hiện tại đây.", "Thông báo", JOptionPane.INFORMATION_MESSAGE); - }); - - btnDelete.addActionListener(e -> { - if (selectedServiceId == null) { - JOptionPane.showMessageDialog(this, "Vui lòng chọn một dịch vụ để xóa.", "Chưa chọn dịch vụ", JOptionPane.WARNING_MESSAGE); + String name = serviceNameField.getText().trim(); + if (name.isEmpty()) { + JOptionPane.showMessageDialog(this, "Tên dịch vụ không được để trống.", "Lỗi", JOptionPane.ERROR_MESSAGE); return; } - int choice = JOptionPane.showConfirmDialog(this, - "Bạn có chắc chắn muốn xóa dịch vụ '" + serviceNameField.getText() + "' không?", - "Xác nhận xóa", JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE); - if (choice == JOptionPane.YES_OPTION) { - // TODO: Implement Delete Service network request - JOptionPane.showMessageDialog(this, "Chức năng 'Xoá' cho dịch vụ ID: " + selectedServiceId + " sẽ được thực hiện tại đây.", "Thông báo", JOptionPane.INFORMATION_MESSAGE); + String priceText = priceField.getText().trim(); + if (priceText.isEmpty()) { + JOptionPane.showMessageDialog(this, "Giá dịch vụ không được để trống.", "Lỗi", JOptionPane.ERROR_MESSAGE); + return; } + + Double price; + try { + price = Double.parseDouble(priceText); + if (price < 0) { + JOptionPane.showMessageDialog(this, "Giá dịch vụ không được là số âm.", "Lỗi", JOptionPane.ERROR_MESSAGE); + return; + } + } catch (NumberFormatException nfe) { + JOptionPane.showMessageDialog(this, "Giá dịch vụ phải là một con số hợp lệ.", "Lỗi", JOptionPane.ERROR_MESSAGE); + return; + } + + Boolean deleted = chkIsDeleted.isSelected(); + EditServiceRequest request = new EditServiceRequest(selectedServiceId, name, price, deleted); + NetworkUtil.sendPacket(ClientHandler.ctx.channel(), request); + + JOptionPane.showMessageDialog(this, "Yêu cầu chỉnh sửa dịch vụ '" + name + "' đã được gửi.", "Thành công", JOptionPane.INFORMATION_MESSAGE); + clearServiceFields(); }); // Initial button states btnEdit.setEnabled(false); - btnDelete.setEnabled(false); + chkIsDeleted.setEnabled(false); return buttonPanel; } @@ -247,7 +248,7 @@ public class ServiceManagementPanel extends JPanel { TitledBorder.LEFT, TitledBorder.TOP, new Font("Arial", Font.BOLD, 14))); // Table - String[] serviceColumns = {"ID", "Tên dịch vụ", "Đơn giá (VNĐ)"}; + String[] serviceColumns = {"ID", "Tên dịch vụ", "Đơn giá (VNĐ)", "Trạng thái"}; serviceTableModel = new DefaultTableModel(serviceColumns, 0) { @Override public boolean isCellEditable(int row, int column) { return false; } @@ -261,10 +262,9 @@ public class ServiceManagementPanel extends JPanel { serviceTable.getSelectionModel().addListSelectionListener(e -> { if (!e.getValueIsAdjusting() && serviceTable.getSelectedRow() != -1) { - // IMPORTANT: We need to find the original index from the 'allServices' list int viewRow = serviceTable.getSelectedRow(); String serviceId = (String) serviceTableModel.getValueAt(viewRow, 0); - + allServices.stream() .filter(service -> service.getId().equals(serviceId)) .findFirst() @@ -309,26 +309,28 @@ public class ServiceManagementPanel extends JPanel { selectedServiceId = service.getId(); serviceNameField.setText(service.getName()); priceField.setText(service.getCost()); - noteField.setText(""); // Assuming notes are not stored in the main service entity + + // Update checkbox state + chkIsDeleted.setSelected("1".equals(service.getDeleted())); // Update button states btnAdd.setEnabled(false); btnEdit.setEnabled(true); - btnDelete.setEnabled(true); + chkIsDeleted.setEnabled(true); } private void clearServiceFields() { selectedServiceId = null; serviceNameField.setText(""); priceField.setText(""); - noteField.setText(""); + chkIsDeleted.setSelected(false); serviceTable.clearSelection(); serviceNameField.requestFocusInWindow(); // Reset button states btnAdd.setEnabled(true); btnEdit.setEnabled(false); - btnDelete.setEnabled(false); + chkIsDeleted.setEnabled(false); } private void filterServiceTable() { @@ -339,10 +341,12 @@ public class ServiceManagementPanel extends JPanel { for (Service service : allServices) { if (filterText.isEmpty() || TextUtils.removeAccents(service.getName().toLowerCase()).contains(lowerCaseFilterText)) { + String status = "0".equals(service.getDeleted()) ? "Đang bán" : "Đã ẩn"; serviceTableModel.addRow(new Object[]{ service.getId(), service.getName(), - service.getCost() + service.getCost(), + status }); } } diff --git a/src/main/java/BsK/client/ui/component/common/MedicineDialog/MedicineDialog.java b/src/main/java/BsK/client/ui/component/common/MedicineDialog/MedicineDialog.java index 1521cc8..8bb06d2 100644 --- a/src/main/java/BsK/client/ui/component/common/MedicineDialog/MedicineDialog.java +++ b/src/main/java/BsK/client/ui/component/common/MedicineDialog/MedicineDialog.java @@ -37,15 +37,14 @@ public class MedicineDialog extends JDialog { private JTextField medicineCompanyField; private JTextArea medicineDescriptionField; private JSpinner quantitySpinner; - private JTextField quantityLeftField; private JComboBox UnitComboBox; private JTextField priceField; private JTextField totalField; private JSpinner morningSpinner, noonSpinner, eveningSpinner; private JTextArea noteField; private DefaultTableModel tableModel, selectedTableModel; - private String[] medcineColumns = {"ID", "Tên thuốc", "Công ty", "Mô tả", "Tồn kho", "ĐVT", "Giá"}; - private String[] suggestionColumns = {"Tên thuốc", "Tồn kho", "ĐVT", "Giá", "Supplement"}; + private String[] medcineColumns = {"ID", "Tên thuốc", "Công ty", "Mô tả", "ĐVT", "Giá"}; + private String[] suggestionColumns = {"Tên thuốc", "ĐVT", "Giá", "Supplement"}; private String[][] medicineData; private final ResponseListener getMedInfoResponseListener = this::getMedInfoHandler; private TableColumnModel columnModel; @@ -280,18 +279,6 @@ public class MedicineDialog extends JDialog { gbc.gridx = 2; gbc.weightx = 0.0; - JLabel quantityLeftLabel = new JLabel("Còn lại:"); - quantityLeftLabel.setFont(labelFont); - quantityPricePanel.add(quantityLeftLabel, gbc); - - gbc.gridx = 3; - gbc.weightx = 0.5; - quantityLeftField = new JTextField(5); - quantityLeftField.setFont(textFont); - quantityLeftField.setPreferredSize(textFieldSize); - quantityLeftField.setEditable(false); - quantityPricePanel.add(quantityLeftField, gbc); - gbc.weightx = 0.0; gbc.gridy++; gbc.gridx = 0; @@ -417,7 +404,6 @@ public class MedicineDialog extends JDialog { suggestionPopup.add(suggestionScrollPane, BorderLayout.CENTER); suggestionPopup.setFocusable(false); - String[] selectedColumnNames = {"ID", "Tên thuốc", "SL", "ĐVT", "Sáng", "Trưa", "Chiều", "Đơn giá", "Thành tiền", "Ghi chú", "Supplement"}; selectedTableModel = new DefaultTableModel(new String[][]{}, selectedColumnNames) { @Override @@ -561,7 +547,7 @@ public class MedicineDialog extends JDialog { } else { if (e.getKeyCode() == KeyEvent.VK_ENTER) { handleExactMatch(); - } + } } } }); @@ -601,10 +587,10 @@ public class MedicineDialog extends JDialog { // If there are changes but no items selected, show a confirmation if (medicinePrescription == null || medicinePrescription.length == 0) { int choice = JOptionPane.showConfirmDialog(this, - "Bạn đã xóa tất cả thuốc khỏi đơn. Bạn có muốn lưu thay đổi này không?", - "Xác nhận", - JOptionPane.YES_NO_OPTION, - JOptionPane.QUESTION_MESSAGE); + "Bạn đã xóa tất cả thuốc khỏi đơn. Bạn có muốn lưu thay đổi này không?", + "Xác nhận", + JOptionPane.YES_NO_OPTION, + JOptionPane.QUESTION_MESSAGE); if (choice != JOptionPane.YES_OPTION) { return; } @@ -644,13 +630,15 @@ public class MedicineDialog extends JDialog { String lowerCaseFilterText = TextUtils.removeAccents(filterText.toLowerCase()); for (Medicine med : medicines) { - if (filterText.isEmpty() || TextUtils.removeAccents(med.getName().toLowerCase()).contains(lowerCaseFilterText)) { + // Check if the medicine is not deleted and matches the filter text + if ("0".equals(med.getDeleted()) && + (filterText.isEmpty() || TextUtils.removeAccents(med.getName().toLowerCase()).contains(lowerCaseFilterText))) { + filteredMedicines.add(med); // Show "Có" if supplement is "1", otherwise "Không" String isSupplementText = "1".equals(med.getSupplement()) ? "Có" : "Không"; filteredDisplayData.add(new String[]{ med.getName(), - med.getQuantity(), med.getUnit(), med.getSellingPrice(), isSupplementText @@ -677,17 +665,15 @@ public class MedicineDialog extends JDialog { medicineNameField.requestFocusInWindow(); } else { suggestionPopup.setVisible(false); - // clearInputFields(); // Don't clear fields if the user is typing } } private void resizeSuggestionTableColumns() { columnModel = suggestionTable.getColumnModel(); columnModel.getColumn(0).setPreferredWidth(180); // Tên thuốc - columnModel.getColumn(1).setPreferredWidth(50); // Tồn kho - columnModel.getColumn(2).setPreferredWidth(50); // ĐVT - columnModel.getColumn(3).setPreferredWidth(70); // Giá - columnModel.getColumn(4).setPreferredWidth(70); // Supplement + columnModel.getColumn(1).setPreferredWidth(60); // ĐVT + columnModel.getColumn(2).setPreferredWidth(70); // Giá + columnModel.getColumn(3).setPreferredWidth(70); // Supplement } private void handleMedicineTableRowSelection(int viewRow) { @@ -709,7 +695,8 @@ public class MedicineDialog extends JDialog { String normalizedSearchName = TextUtils.removeAccents(searchName.toLowerCase()); for (Medicine med : medicines) { - if (TextUtils.removeAccents(med.getName().toLowerCase()).equals(normalizedSearchName)) { + // Also check the deleted flag here for consistency + if ("0".equals(med.getDeleted()) && TextUtils.removeAccents(med.getName().toLowerCase()).equals(normalizedSearchName)) { foundMedicine = med; break; } @@ -733,7 +720,6 @@ public class MedicineDialog extends JDialog { medicineCompanyField.setText(medicine.getCompany()); medicineDescriptionField.setText(medicine.getDescription()); - quantityLeftField.setText(medicine.getQuantity()); UnitComboBox.setSelectedItem(medicine.getUnit()); priceField.setText(medicine.getSellingPrice()); @@ -771,7 +757,6 @@ public class MedicineDialog extends JDialog { // Don't clear the name field as the user is typing in it medicineCompanyField.setText(""); medicineDescriptionField.setText(""); - quantityLeftField.setText(""); UnitComboBox.setSelectedIndex(0); priceField.setText(""); totalField.setText(""); @@ -810,32 +795,27 @@ public class MedicineDialog extends JDialog { // Prioritize selection from the popup table if it's open and has a selection if (suggestionPopup.isVisible() && selectedRowInSuggestionTable != -1) { selectedMedicine = filteredMedicines.get(suggestionTable.convertRowIndexToModel(selectedRowInSuggestionTable)); - medicineId = selectedMedicine.getId(); - name = selectedMedicine.getName(); - unit = selectedMedicine.getUnit(); - currentPrice = selectedMedicine.getSellingPrice(); } else { // Otherwise, try to find an exact match from the text field String normalizedSearchName = TextUtils.removeAccents(searchName.toLowerCase()); - for (Medicine med : medicines) { - if (TextUtils.removeAccents(med.getName().toLowerCase()).equals(normalizedSearchName)) { + // Also check the deleted flag here + if ("0".equals(med.getDeleted()) && TextUtils.removeAccents(med.getName().toLowerCase()).equals(normalizedSearchName)) { selectedMedicine = med; break; } } - - if (selectedMedicine == null) { - JOptionPane.showMessageDialog(this, "Không tìm thấy thuốc khớp với: '" + searchName + "'. Vui lòng chọn từ danh sách gợi ý.", "Lỗi", JOptionPane.ERROR_MESSAGE); - return; - } - medicineId = selectedMedicine.getId(); - name = selectedMedicine.getName(); - unit = selectedMedicine.getUnit(); - currentPrice = selectedMedicine.getSellingPrice(); } - // Get supplement status + if (selectedMedicine == null) { + JOptionPane.showMessageDialog(this, "Không tìm thấy thuốc khớp với: '" + searchName + "'. Vui lòng chọn từ danh sách gợi ý.", "Lỗi", JOptionPane.ERROR_MESSAGE); + return; + } + + medicineId = selectedMedicine.getId(); + name = selectedMedicine.getName(); + unit = selectedMedicine.getUnit(); + currentPrice = selectedMedicine.getSellingPrice(); supplement = selectedMedicine.getSupplement(); int quantity = (Integer) quantitySpinner.getValue(); @@ -862,9 +842,9 @@ public class MedicineDialog extends JDialog { } private void removeSelectedMedicine() { - int selectedRow = chosenMedicineTable.getSelectedRow(); - if (selectedRow != -1) { - selectedTableModel.removeRow(selectedRow); + int selectedRow = chosenMedicineTable.getSelectedRow(); + if (selectedRow != -1) { + selectedTableModel.removeRow(selectedRow); } else { JOptionPane.showMessageDialog(this, "Vui lòng chọn một thuốc từ bảng dưới để xóa.", "Chưa chọn thuốc", JOptionPane.WARNING_MESSAGE); } @@ -972,4 +952,4 @@ public class MedicineDialog extends JDialog { frame.setVisible(true); }); } -} +} \ No newline at end of file diff --git a/src/main/java/BsK/client/ui/component/common/PrintDialog/print_forms/medserinvoice.jrxml b/src/main/java/BsK/client/ui/component/common/PrintDialog/print_forms/medserinvoice.jrxml deleted file mode 100644 index 48a416b..0000000 --- a/src/main/java/BsK/client/ui/component/common/PrintDialog/print_forms/medserinvoice.jrxml +++ /dev/null @@ -1,621 +0,0 @@ - - - - -