|  |  |  | @ -11,13 +11,16 @@ import model.OutboundRecord; | 
			
		
	
		
			
				
					|  |  |  |  | import model.DataManager; | 
			
		
	
		
			
				
					|  |  |  |  | import model.Goods; | 
			
		
	
		
			
				
					|  |  |  |  | import javafx.collections.FXCollections; | 
			
		
	
		
			
				
					|  |  |  |  | import model.InboundRecord; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | import java.util.List; | 
			
		
	
		
			
				
					|  |  |  |  | import java.util.stream.Collectors; | 
			
		
	
		
			
				
					|  |  |  |  | import java.sql.*; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | public class OutboundView extends BorderPane { | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     private TextField goodsField; | 
			
		
	
		
			
				
					|  |  |  |  |     private TextField customerField; | 
			
		
	
		
			
				
					|  |  |  |  |     private TextField supplierField; | 
			
		
	
		
			
				
					|  |  |  |  |     private TextField quantityField; | 
			
		
	
		
			
				
					|  |  |  |  |     private TextField remarkField; | 
			
		
	
		
			
				
					|  |  |  |  |     private TableView<OutboundRecord> tableView; | 
			
		
	
	
		
			
				
					|  |  |  | @ -25,6 +28,7 @@ public class OutboundView extends BorderPane { | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     public OutboundView() { | 
			
		
	
		
			
				
					|  |  |  |  |         initializeUI(); | 
			
		
	
		
			
				
					|  |  |  |  |         loadOutboundRecords(); | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     private void initializeUI() { | 
			
		
	
	
		
			
				
					|  |  |  | @ -54,11 +58,11 @@ public class OutboundView extends BorderPane { | 
			
		
	
		
			
				
					|  |  |  |  |         goodsField = new TextField(); | 
			
		
	
		
			
				
					|  |  |  |  |         goodsField.setPromptText("请输入货物名称"); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         Label customerLabel = new Label("客户:"); | 
			
		
	
		
			
				
					|  |  |  |  |         customerField = new TextField(); | 
			
		
	
		
			
				
					|  |  |  |  |         customerField.setPromptText("请输入客户"); | 
			
		
	
		
			
				
					|  |  |  |  |         Label supplierLabel = new Label("供应商:"); | 
			
		
	
		
			
				
					|  |  |  |  |         supplierField = new TextField(); | 
			
		
	
		
			
				
					|  |  |  |  |         supplierField.setPromptText("请输入供应商"); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         basicInfo.addRow(0, goodsLabel, goodsField, customerLabel, customerField); | 
			
		
	
		
			
				
					|  |  |  |  |         basicInfo.addRow(0, goodsLabel, goodsField, supplierLabel, supplierField); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         // 第二行:数量和备注
 | 
			
		
	
		
			
				
					|  |  |  |  |         Label quantityLabel = new Label("数量:"); | 
			
		
	
	
		
			
				
					|  |  |  | @ -103,7 +107,7 @@ public class OutboundView extends BorderPane { | 
			
		
	
		
			
				
					|  |  |  |  |     private TableView<OutboundRecord> createTableView() { | 
			
		
	
		
			
				
					|  |  |  |  |         TableView<OutboundRecord> table = new TableView<>(); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         TableColumn<OutboundRecord, String> idCol = new TableColumn<>("单号"); | 
			
		
	
		
			
				
					|  |  |  |  |         TableColumn<OutboundRecord, String> idCol = new TableColumn<>("出库单号"); | 
			
		
	
		
			
				
					|  |  |  |  |         idCol.setCellValueFactory(new PropertyValueFactory<>("id")); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         TableColumn<OutboundRecord, String> goodsCol = new TableColumn<>("货物名称"); | 
			
		
	
	
		
			
				
					|  |  |  | @ -112,11 +116,11 @@ public class OutboundView extends BorderPane { | 
			
		
	
		
			
				
					|  |  |  |  |         TableColumn<OutboundRecord, Integer> quantityCol = new TableColumn<>("数量"); | 
			
		
	
		
			
				
					|  |  |  |  |         quantityCol.setCellValueFactory(new PropertyValueFactory<>("quantity")); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         TableColumn<OutboundRecord, String> customerCol = new TableColumn<>("客户"); | 
			
		
	
		
			
				
					|  |  |  |  |         customerCol.setCellValueFactory(new PropertyValueFactory<>("customer")); | 
			
		
	
		
			
				
					|  |  |  |  |         TableColumn<OutboundRecord, String> supplierCol = new TableColumn<>("供应商"); | 
			
		
	
		
			
				
					|  |  |  |  |         supplierCol.setCellValueFactory(new PropertyValueFactory<>("supplier")); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         TableColumn<OutboundRecord, LocalDateTime> timeCol = new TableColumn<>("出库时间"); | 
			
		
	
		
			
				
					|  |  |  |  |         timeCol.setCellValueFactory(new PropertyValueFactory<>("outboundTime")); | 
			
		
	
		
			
				
					|  |  |  |  |         timeCol.setCellValueFactory(new PropertyValueFactory<>("inboundTime")); // 保持字段名不变,但实际表示出库时间
 | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         TableColumn<OutboundRecord, String> operatorCol = new TableColumn<>("操作员"); | 
			
		
	
		
			
				
					|  |  |  |  |         operatorCol.setCellValueFactory(new PropertyValueFactory<>("operator")); | 
			
		
	
	
		
			
				
					|  |  |  | @ -124,7 +128,7 @@ public class OutboundView extends BorderPane { | 
			
		
	
		
			
				
					|  |  |  |  |         TableColumn<OutboundRecord, String> remarkCol = new TableColumn<>("备注"); | 
			
		
	
		
			
				
					|  |  |  |  |         remarkCol.setCellValueFactory(new PropertyValueFactory<>("remark")); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         table.getColumns().addAll(idCol, goodsCol, quantityCol, customerCol, | 
			
		
	
		
			
				
					|  |  |  |  |         table.getColumns().addAll(idCol, goodsCol, quantityCol, supplierCol, | 
			
		
	
		
			
				
					|  |  |  |  |                 timeCol, operatorCol, remarkCol); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         table.getItems().addListener((javafx.collections.ListChangeListener.Change<? extends OutboundRecord> c) -> { | 
			
		
	
	
		
			
				
					|  |  |  | @ -157,12 +161,12 @@ public class OutboundView extends BorderPane { | 
			
		
	
		
			
				
					|  |  |  |  |     private void handleSave() { | 
			
		
	
		
			
				
					|  |  |  |  |         try { | 
			
		
	
		
			
				
					|  |  |  |  |             String goodsName = goodsField.getText().trim(); | 
			
		
	
		
			
				
					|  |  |  |  |             String customer = customerField.getText().trim(); | 
			
		
	
		
			
				
					|  |  |  |  |             String supplier = supplierField.getText().trim(); | 
			
		
	
		
			
				
					|  |  |  |  |             String quantityText = quantityField.getText().trim(); | 
			
		
	
		
			
				
					|  |  |  |  |             String remark = remarkField.getText().trim(); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |             // 输入验证
 | 
			
		
	
		
			
				
					|  |  |  |  |             if (goodsName.isEmpty() || customer.isEmpty() || quantityText.isEmpty()) { | 
			
		
	
		
			
				
					|  |  |  |  |             if (goodsName.isEmpty() || supplier.isEmpty() || quantityText.isEmpty()) { | 
			
		
	
		
			
				
					|  |  |  |  |                 showAlert("错误", "请填写完整的出库信息!"); | 
			
		
	
		
			
				
					|  |  |  |  |                 return; | 
			
		
	
		
			
				
					|  |  |  |  |             } | 
			
		
	
	
		
			
				
					|  |  |  | @ -179,14 +183,43 @@ public class OutboundView extends BorderPane { | 
			
		
	
		
			
				
					|  |  |  |  |                 return; | 
			
		
	
		
			
				
					|  |  |  |  |             } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |             // 检查库存是否足够
 | 
			
		
	
		
			
				
					|  |  |  |  |             if (!isStockSufficient(goodsName, quantity)) { | 
			
		
	
		
			
				
					|  |  |  |  |                 showAlert("错误", "库存不足!"); | 
			
		
	
		
			
				
					|  |  |  |  |                 return; | 
			
		
	
		
			
				
					|  |  |  |  |             } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |             // 创建出库记录
 | 
			
		
	
		
			
				
					|  |  |  |  |             String id = String.format("NO%014d", System.currentTimeMillis()); | 
			
		
	
		
			
				
					|  |  |  |  |             String id = "OUT" + System.currentTimeMillis(); | 
			
		
	
		
			
				
					|  |  |  |  |             LocalDateTime now = LocalDateTime.now(); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |             // 修改数据库连接为相对路径
 | 
			
		
	
		
			
				
					|  |  |  |  |             String url = "jdbc:sqlite:db/dbuml.db3"; | 
			
		
	
		
			
				
					|  |  |  |  |             try (Connection conn = DriverManager.getConnection(url)) { | 
			
		
	
		
			
				
					|  |  |  |  |                 String sql = "INSERT INTO warehouse (id, goods_id, quantity, supplier, inbound_time, operator, remark, type) " + | 
			
		
	
		
			
				
					|  |  |  |  |                         "VALUES (?, ?, ?, ?, ?, ?, ?, ?)"; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |                 try (PreparedStatement pstmt = conn.prepareStatement(sql)) { | 
			
		
	
		
			
				
					|  |  |  |  |                     pstmt.setString(1, id); | 
			
		
	
		
			
				
					|  |  |  |  |                     pstmt.setString(2, goodsName); | 
			
		
	
		
			
				
					|  |  |  |  |                     pstmt.setInt(3, quantity); | 
			
		
	
		
			
				
					|  |  |  |  |                     pstmt.setString(4, supplier); | 
			
		
	
		
			
				
					|  |  |  |  |                     pstmt.setString(5, now.toString()); | 
			
		
	
		
			
				
					|  |  |  |  |                     pstmt.setString(6, "当前用户"); | 
			
		
	
		
			
				
					|  |  |  |  |                     pstmt.setString(7, remark); | 
			
		
	
		
			
				
					|  |  |  |  |                     pstmt.setString(8, "OUT"); // 设置类型为出库
 | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |                     pstmt.executeUpdate(); | 
			
		
	
		
			
				
					|  |  |  |  |                 } | 
			
		
	
		
			
				
					|  |  |  |  |             } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |             // 创建记录对象并添加到表格
 | 
			
		
	
		
			
				
					|  |  |  |  |             OutboundRecord record = new OutboundRecord( | 
			
		
	
		
			
				
					|  |  |  |  |                     id, | 
			
		
	
		
			
				
					|  |  |  |  |                     goodsName, | 
			
		
	
		
			
				
					|  |  |  |  |                     quantity, | 
			
		
	
		
			
				
					|  |  |  |  |                     customer, | 
			
		
	
		
			
				
					|  |  |  |  |                     LocalDateTime.now(), | 
			
		
	
		
			
				
					|  |  |  |  |                     supplier, | 
			
		
	
		
			
				
					|  |  |  |  |                     now, | 
			
		
	
		
			
				
					|  |  |  |  |                     "当前用户", | 
			
		
	
		
			
				
					|  |  |  |  |                     remark | 
			
		
	
		
			
				
					|  |  |  |  |             ); | 
			
		
	
	
		
			
				
					|  |  |  | @ -200,24 +233,26 @@ public class OutboundView extends BorderPane { | 
			
		
	
		
			
				
					|  |  |  |  |             // 清空输入
 | 
			
		
	
		
			
				
					|  |  |  |  |             handleClear(); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |             showAlert("成功", "出库记录已保存!"); | 
			
		
	
		
			
				
					|  |  |  |  |             // 添加操作日志
 | 
			
		
	
		
			
				
					|  |  |  |  |             String details = String.format("出库货物:%s,数量:%d,供应商:%s", | 
			
		
	
		
			
				
					|  |  |  |  |                     goodsName, quantity, supplier); | 
			
		
	
		
			
				
					|  |  |  |  |             DataManager.getInstance().addOperationLog("出库", goodsName, "当前用户", details); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |             // 在handleSave方法中添加日志记录
 | 
			
		
	
		
			
				
					|  |  |  |  |             String details = String.format("出库货物:%s,数量:%d,客户:%s",  | 
			
		
	
		
			
				
					|  |  |  |  |                 goodsName, quantity, customer); | 
			
		
	
		
			
				
					|  |  |  |  |             DataManager.getInstance().addOperationLog("出库", goodsName, "当前<E5BD93><E5898D>户", details); | 
			
		
	
		
			
				
					|  |  |  |  |             showAlert("成功", "出库记录已保存!"); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         } catch (Exception e) { | 
			
		
	
		
			
				
					|  |  |  |  |             showAlert("错误", "保存失败:" + e.getMessage()); | 
			
		
	
		
			
				
					|  |  |  |  |             e.printStackTrace(); | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     private void handleClear() { | 
			
		
	
		
			
				
					|  |  |  |  |         goodsField.clear(); | 
			
		
	
		
			
				
					|  |  |  |  |         customerField.clear(); | 
			
		
	
		
			
				
					|  |  |  |  |         supplierField.clear(); | 
			
		
	
		
			
				
					|  |  |  |  |         quantityField.clear(); | 
			
		
	
		
			
				
					|  |  |  |  |         remarkField.clear(); | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     private void showAlert(String title, String content) { | 
			
		
	
		
			
				
					|  |  |  |  |         Alert alert = new Alert(Alert.AlertType.INFORMATION); | 
			
		
	
		
			
				
					|  |  |  |  |         alert.setTitle(title); | 
			
		
	
	
		
			
				
					|  |  |  | @ -225,4 +260,52 @@ public class OutboundView extends BorderPane { | 
			
		
	
		
			
				
					|  |  |  |  |         alert.setContentText(content); | 
			
		
	
		
			
				
					|  |  |  |  |         alert.showAndWait(); | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     // 添加加载数据的方法
 | 
			
		
	
		
			
				
					|  |  |  |  |     private void loadOutboundRecords() { | 
			
		
	
		
			
				
					|  |  |  |  |         String url = "jdbc:sqlite:db/dbuml.db3"; | 
			
		
	
		
			
				
					|  |  |  |  |         try (Connection conn = DriverManager.getConnection(url)) { | 
			
		
	
		
			
				
					|  |  |  |  |             String sql = "SELECT * FROM warehouse WHERE type = 'OUT' ORDER BY inbound_time DESC"; | 
			
		
	
		
			
				
					|  |  |  |  |             try (Statement stmt = conn.createStatement(); | 
			
		
	
		
			
				
					|  |  |  |  |                  ResultSet rs = stmt.executeQuery(sql)) { | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |                 while (rs.next()) { | 
			
		
	
		
			
				
					|  |  |  |  |                     OutboundRecord record = new OutboundRecord( | 
			
		
	
		
			
				
					|  |  |  |  |                             rs.getString("id"), | 
			
		
	
		
			
				
					|  |  |  |  |                             rs.getString("goods_id"), | 
			
		
	
		
			
				
					|  |  |  |  |                             rs.getInt("quantity"), | 
			
		
	
		
			
				
					|  |  |  |  |                             rs.getString("supplier"), | 
			
		
	
		
			
				
					|  |  |  |  |                             LocalDateTime.parse(rs.getString("inbound_time")), // 实际表示出库时间
 | 
			
		
	
		
			
				
					|  |  |  |  |                             rs.getString("operator"), | 
			
		
	
		
			
				
					|  |  |  |  |                             rs.getString("remark") | 
			
		
	
		
			
				
					|  |  |  |  |                     ); | 
			
		
	
		
			
				
					|  |  |  |  |                     tableView.getItems().add(record); | 
			
		
	
		
			
				
					|  |  |  |  |                 } | 
			
		
	
		
			
				
					|  |  |  |  |             } | 
			
		
	
		
			
				
					|  |  |  |  |         } catch (Exception e) { | 
			
		
	
		
			
				
					|  |  |  |  |             e.printStackTrace(); | 
			
		
	
		
			
				
					|  |  |  |  |             showAlert("错误", "加载出库记录失败:" + e.getMessage()); | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     // 查询库存是否足够
 | 
			
		
	
		
			
				
					|  |  |  |  |     private boolean isStockSufficient(String goodsName, int quantity) { | 
			
		
	
		
			
				
					|  |  |  |  |         String url = "jdbc:sqlite:db/dbuml.db3"; | 
			
		
	
		
			
				
					|  |  |  |  |         try (Connection conn = DriverManager.getConnection(url)) { | 
			
		
	
		
			
				
					|  |  |  |  |             String sql = "SELECT SUM(quantity) AS total_stock FROM warehouse WHERE goods_id = ? AND type = 'IN'"; | 
			
		
	
		
			
				
					|  |  |  |  |             try (PreparedStatement pstmt = conn.prepareStatement(sql)) { | 
			
		
	
		
			
				
					|  |  |  |  |                 pstmt.setString(1, goodsName); | 
			
		
	
		
			
				
					|  |  |  |  |                 try (ResultSet rs = pstmt.executeQuery()) { | 
			
		
	
		
			
				
					|  |  |  |  |                     if (rs.next()) { | 
			
		
	
		
			
				
					|  |  |  |  |                         int totalStock = rs.getInt("total_stock"); | 
			
		
	
		
			
				
					|  |  |  |  |                         return totalStock >= quantity; | 
			
		
	
		
			
				
					|  |  |  |  |                     } | 
			
		
	
		
			
				
					|  |  |  |  |                 } | 
			
		
	
		
			
				
					|  |  |  |  |             } | 
			
		
	
		
			
				
					|  |  |  |  |         } catch (SQLException e) { | 
			
		
	
		
			
				
					|  |  |  |  |             e.printStackTrace(); | 
			
		
	
		
			
				
					|  |  |  |  |             showAlert("错误", "查询库存失败:" + e.getMessage()); | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  |         return false; // 默认返回false,防止未知错误导致库存检查失败
 | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  | } |