出库功能

master
王城 7 months ago
parent a52cac0ee0
commit e41a3a5f00

@ -1,9 +1,8 @@
<component name="libraryTable">
<library name="junit-4.12" type="repository">
<properties maven-id="junit:junit:4.13.1" />
<library name="junit-4.12">
<CLASSES>
<root url="jar://$USER_HOME$/.m2/repository/junit/junit/4.13.1/junit-4.13.1.jar!/" />
<root url="jar://$USER_HOME$/.m2/repository/org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3.jar!/" />
<root url="jar://$APPLICATION_HOME_DIR$/lib/junit-4.12.jar!/" />
<root url="jar://$APPLICATION_HOME_DIR$/lib/hamcrest-core-1.3.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />

Binary file not shown.

@ -69,7 +69,7 @@ public class DML {
try (Connection conn = DriverManager.getConnection(URL);
Statement stmt = conn.createStatement()) {
String sql = "DELETE FROM operation_logs";
String sql = "DELETE FROM warehouse";
int result = stmt.executeUpdate(sql);
System.out.println("已清空数据表,删除了 " + result + " 条记录");
@ -93,4 +93,96 @@ public class DML {
e.printStackTrace();
}
} //删除指定数据表
@Test
public void showCurrentStock() {
try (Connection conn = DriverManager.getConnection(URL);
Statement stmt = conn.createStatement()) {
// 查询每个商品的当前库存(入库减去出库)
String sql = "SELECT goods_id, SUM(quantity) as current_stock " +
"FROM warehouse " +
"GROUP BY goods_id";
ResultSet rs = stmt.executeQuery(sql);
// 打印表头
System.out.println("===================== 当前库存状态 =====================");
System.out.printf("%-20s %-15s%n", "货物名称", "当前库存");
System.out.println("===================================================");
// 打印数据
while (rs.next()) {
System.out.printf("%-20s %-15d%n",
rs.getString("goods_id"),
rs.getInt("current_stock")
);
}
System.out.println("===================================================");
} catch (SQLException e) {
e.printStackTrace();
}
}
@Test
public void showAllTransactions() {
try (Connection conn = DriverManager.getConnection(URL);
Statement stmt = conn.createStatement()) {
// 查询所有出入库记录
String sql = "SELECT *, " +
"CASE WHEN quantity > 0 THEN '入库' ELSE '出库' END as type " +
"FROM warehouse " +
"ORDER BY inbound_time DESC";
ResultSet rs = stmt.executeQuery(sql);
// 打印表头
System.out.println("===================== 出入库记录 =====================");
System.out.printf("%-15s %-15s %-8s %-8s %-15s %-25s%n",
"单号", "货物名称", "数量", "类型", "供应商", "时间");
System.out.println("===================================================");
// 打印数据
while (rs.next()) {
System.out.printf("%-15s %-15s %-8d %-8s %-15s %-25s%n",
rs.getString("id"),
rs.getString("goods_id"),
Math.abs(rs.getInt("quantity")),
rs.getString("type"),
rs.getString("supplier"),
rs.getString("inbound_time")
);
}
System.out.println("===================================================");
} catch (SQLException e) {
e.printStackTrace();
}
}
@Test
public void deleteOutboundRecord() {
try (Connection conn = DriverManager.getConnection(URL);
Statement stmt = conn.createStatement()) {
// 删除出库记录的SQL语句
String sql = "DELETE FROM warehouse WHERE id = ?";
try (PreparedStatement pstmt = conn.prepareStatement(sql)) {
// 这里可以设置要删除的记录ID
pstmt.setString(1, "要删除的记录ID");
int result = pstmt.executeUpdate();
if (result > 0) {
System.out.println("出库记录删除成功");
} else {
System.out.println("未找到要删除的记录");
}
}
} catch (SQLException e) {
e.printStackTrace();
System.out.println("删除出库记录失败:" + e.getMessage());
}
}
}

@ -1,3 +1,4 @@
package model;
import java.time.LocalDateTime;
@ -6,35 +7,76 @@ public class OutboundRecord {
private String id;
private String goodsId;
private int quantity;
private String supplier;
private LocalDateTime inboundTime;
private String customer;
private LocalDateTime outboundTime;
private String operator;
private String remark;
public OutboundRecord(String id, String goodsId, int quantity, String supplier,
LocalDateTime inboundTime, String operator, String remark) {
public OutboundRecord(String id, String goodsId, int quantity, String customer,
LocalDateTime outboundTime, String operator, String remark) {
this.id = id;
this.goodsId = goodsId;
this.quantity = quantity;
this.supplier = supplier;
this.inboundTime = inboundTime;
this.customer = customer;
this.outboundTime = outboundTime;
this.operator = operator;
this.remark = remark;
}
// Getters and Setters
public String getId() { return id; }
public void setId(String id) { this.id = id; }
public String getGoodsId() { return goodsId; }
public void setGoodsId(String goodsId) { this.goodsId = goodsId; }
public int getQuantity() { return quantity; }
public void setQuantity(int quantity) { this.quantity = quantity; }
public String getSupplier() { return supplier; }
public void setSupplier(String supplier) { this.supplier = supplier; }
public LocalDateTime getInboundTime() { return inboundTime; }
public void setInboundTime(LocalDateTime inboundTime) { this.inboundTime = inboundTime; }
public String getOperator() { return operator; }
public void setOperator(String operator) { this.operator = operator; }
public String getRemark() { return remark; }
public void setRemark(String remark) { this.remark = remark; }
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getGoodsId() {
return goodsId;
}
public void setGoodsId(String goodsId) {
this.goodsId = goodsId;
}
public int getQuantity() {
return quantity;
}
public void setQuantity(int quantity) {
this.quantity = quantity;
}
public String getCustomer() {
return customer;
}
public void setCustomer(String customer) {
this.customer = customer;
}
public LocalDateTime getOutboundTime() {
return outboundTime;
}
public void setOutboundTime(LocalDateTime outboundTime) {
this.outboundTime = outboundTime;
}
public String getOperator() {
return operator;
}
public void setOperator(String operator) {
this.operator = operator;
}
public String getRemark() {
return remark;
}
public void setRemark(String remark) {
this.remark = remark;
}
}

@ -11,7 +11,6 @@ import model.Goods;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Statement;
import java.time.LocalDateTime;
@ -146,14 +145,17 @@ public class GoodsManagementView extends BorderPane {
String url = "jdbc:sqlite:db/dbuml.db3";
List<Goods> goodsList = new ArrayList<>();
try (Connection conn = DriverManager.getConnection(url)) {
String sql = "SELECT * FROM warehouse ORDER BY inbound_time DESC";
String sql = "SELECT id, goods_id as name, quantity, " +
"supplier, inbound_time, operator, remark " +
"FROM warehouse " +
"ORDER BY id"; // 不再使用GROUP BY直接显示所有记录
try (Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery(sql)) {
while (rs.next()) {
Goods goods = new Goods(
rs.getString("id"),
rs.getString("goods_id"),
rs.getString("name"),
rs.getInt("quantity"),
rs.getString("remark")
);
@ -196,41 +198,33 @@ public class GoodsManagementView extends BorderPane {
return;
}
// 检查是否存在该记录
String url = "jdbc:sqlite:db/dbuml.db3";
try (Connection conn = DriverManager.getConnection(url)) {
String checkSql = "SELECT * FROM warehouse WHERE id = ?";
try (PreparedStatement pstmt = conn.prepareStatement(checkSql)) {
pstmt.setString(1, id);
ResultSet rs = pstmt.executeQuery();
if (rs.next()) {
// 记录存在,执行更新操作
String updateSql = "UPDATE warehouse SET goods_id = ?, quantity = ?, " +
"supplier = ?, remark = ? WHERE id = ?";
try (PreparedStatement updateStmt = conn.prepareStatement(updateSql)) {
updateStmt.setString(1, name);
updateStmt.setInt(2, quantity);
updateStmt.setString(3, supplier);
updateStmt.setString(4, remark);
updateStmt.setString(5, id);
updateStmt.executeUpdate();
showAlert("成功", "货物信息已更新!");
}
// 查找货物对象
Goods existingGoods = DataManager.getInstance().getGoods(id);
if (existingGoods == null) {
// 插入新货物
Goods newGoods = new Goods(String.format("NO%014d", System.currentTimeMillis()),
name, quantity, remark);
newGoods.setInboundTime(LocalDateTime.now());
newGoods.setOperator("当前用户");
newGoods.setSupplier(supplier);
DataManager.getInstance().addGoodsToDatabase(newGoods);
} else {
showAlert("错误", "未找到指定ID的货物记录");
return;
}
}
// 更新现有货物
existingGoods.setName(name);
existingGoods.setQuantity(quantity);
existingGoods.setSupplier(supplier);
existingGoods.setRemark(remark);
DataManager.getInstance().updateGoodsInDatabase(existingGoods);
}
// 更新表格显示
// 更新表格
loadGoodsData();
// 清空输入
handleClear();
showAlert("成功", "货物信息已更新!");
} catch (Exception e) {
showAlert("错误", "保存失败:" + e.getMessage());
e.printStackTrace();

@ -182,14 +182,15 @@ public class InboundView extends BorderPane {
}
// 创建入库记录
String id = "IN" + System.currentTimeMillis();
String id = String.format("NO%014d", 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 (?, ?, ?, ?, ?, ?, ?, ?)";
String sql = "INSERT INTO warehouse (id, goods_id, quantity, supplier, inbound_time, operator, remark) " +
"VALUES (?, ?, ?, ?, ?, ?, ?)";
try (PreparedStatement pstmt = conn.prepareStatement(sql)) {
pstmt.setString(1, id);
pstmt.setString(2, goodsName);
@ -198,7 +199,6 @@ public class InboundView extends BorderPane {
pstmt.setString(5, now.toString());
pstmt.setString(6, "当前用户");
pstmt.setString(7, remark);
pstmt.setString(8, "IN"); // 设置类型为入库
pstmt.executeUpdate();
}
@ -256,7 +256,7 @@ public class InboundView extends BorderPane {
private void loadInboundRecords() {
String url = "jdbc:sqlite:db/dbuml.db3";
try (Connection conn = DriverManager.getConnection(url)) {
String sql = "SELECT * FROM warehouse WHERE type = 'IN' ORDER BY inbound_time DESC";
String sql = "SELECT * FROM warehouse ORDER BY inbound_time DESC";
try (Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery(sql)) {

@ -11,8 +11,6 @@ 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.*;
@ -20,7 +18,7 @@ import java.sql.*;
public class OutboundView extends BorderPane {
private TextField goodsField;
private TextField supplierField;
private TextField customerField;
private TextField quantityField;
private TextField remarkField;
private TableView<OutboundRecord> tableView;
@ -49,20 +47,21 @@ public class OutboundView extends BorderPane {
VBox topArea = new VBox(10);
topArea.setPadding(new Insets(10));
// 第一行:基本信息
// 基本信息
GridPane basicInfo = new GridPane();
basicInfo.setHgap(10);
basicInfo.setVgap(10);
// 第一行:货物名称和供应商
Label goodsLabel = new Label("货物名称:");
goodsField = new TextField();
goodsField.setPromptText("请输入货物名称");
Label supplierLabel = new Label("供应商:");
supplierField = new TextField();
supplierField.setPromptText("请输入供应商");
customerField = new TextField();
customerField.setPromptText("请输入供应商");
basicInfo.addRow(0, goodsLabel, goodsField, supplierLabel, supplierField);
basicInfo.addRow(0, goodsLabel, goodsField, supplierLabel, customerField);
// 第二行:数量和备注
Label quantityLabel = new Label("数量:");
@ -92,7 +91,7 @@ public class OutboundView extends BorderPane {
buttonBox.setAlignment(Pos.CENTER_RIGHT);
buttonBox.setPadding(new Insets(10, 0, 0, 0));
Button saveButton = new Button("保存");
Button saveButton = new Button("出库");
saveButton.setOnAction(e -> handleSave());
Button clearButton = new Button("清空");
@ -107,32 +106,57 @@ 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"));
idCol.setPrefWidth(150);
TableColumn<OutboundRecord, String> goodsCol = new TableColumn<>("货物名称");
goodsCol.setCellValueFactory(new PropertyValueFactory<>("goodsId"));
goodsCol.setPrefWidth(120);
TableColumn<OutboundRecord, Integer> quantityCol = new TableColumn<>("数量");
quantityCol.setCellValueFactory(new PropertyValueFactory<>("quantity"));
quantityCol.setPrefWidth(80);
TableColumn<OutboundRecord, String> supplierCol = new TableColumn<>("供应商");
supplierCol.setCellValueFactory(new PropertyValueFactory<>("supplier"));
TableColumn<OutboundRecord, String> customerCol = new TableColumn<>("供应商");
customerCol.setCellValueFactory(new PropertyValueFactory<>("customer"));
customerCol.setPrefWidth(120);
TableColumn<OutboundRecord, LocalDateTime> timeCol = new TableColumn<>("出库时间");
timeCol.setCellValueFactory(new PropertyValueFactory<>("inboundTime")); // 保持字段名不变,但实际表示出库时间
timeCol.setCellValueFactory(new PropertyValueFactory<>("outboundTime"));
timeCol.setPrefWidth(180);
timeCol.setCellFactory(column -> new TableCell<OutboundRecord, LocalDateTime>() {
private final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
@Override
protected void updateItem(LocalDateTime item, boolean empty) {
super.updateItem(item, empty);
if (empty || item == null) {
setText(null);
} else {
setText(formatter.format(item));
}
}
});
TableColumn<OutboundRecord, String> operatorCol = new TableColumn<>("操作员");
operatorCol.setCellValueFactory(new PropertyValueFactory<>("operator"));
operatorCol.setPrefWidth(100);
TableColumn<OutboundRecord, String> remarkCol = new TableColumn<>("备注");
remarkCol.setCellValueFactory(new PropertyValueFactory<>("remark"));
remarkCol.setPrefWidth(150);
table.getColumns().addAll(idCol, goodsCol, quantityCol, supplierCol,
table.getColumns().addAll(idCol, goodsCol, quantityCol, customerCol,
timeCol, operatorCol, remarkCol);
table.getItems().addListener((javafx.collections.ListChangeListener.Change<? extends OutboundRecord> c) -> {
updateTotal();
// 添加双击事件处理
table.setOnMouseClicked(event -> {
if (event.getClickCount() == 2) {
OutboundRecord selectedRecord = table.getSelectionModel().getSelectedItem();
if (selectedRecord != null) {
fillFields(selectedRecord);
}
}
});
return table;
@ -161,98 +185,89 @@ public class OutboundView extends BorderPane {
private void handleSave() {
try {
String goodsName = goodsField.getText().trim();
String supplier = supplierField.getText().trim();
String customer = customerField.getText().trim();
String quantityText = quantityField.getText().trim();
String remark = remarkField.getText().trim();
// 输入验证
if (goodsName.isEmpty() || supplier.isEmpty() || quantityText.isEmpty()) {
if (goodsName.isEmpty() || customer.isEmpty() || quantityText.isEmpty()) {
showAlert("错误", "请填写完整的出库信息!");
return;
}
int quantity;
try {
quantity = Integer.parseInt(quantityText);
int quantity = Integer.parseInt(quantityText);
if (quantity <= 0) {
showAlert("错误", "数量必须大于0");
return;
}
} catch (NumberFormatException e) {
showAlert("错误", "请输入有效的数量!");
return;
}
// 检查库存是否足够
if (!isStockSufficient(goodsName, quantity)) {
showAlert("错误", "库存不足!");
String url = "jdbc:sqlite:db/dbuml.db3";
try (Connection conn = DriverManager.getConnection(url)) {
// 首先查询当前库存
String checkSql = "SELECT id, quantity FROM warehouse WHERE goods_id = ?";
try (PreparedStatement checkStmt = conn.prepareStatement(checkSql)) {
checkStmt.setString(1, goodsName);
ResultSet rs = checkStmt.executeQuery();
if (rs.next()) {
int currentStock = rs.getInt("quantity");
String recordId = rs.getString("id");
if (currentStock < quantity) {
showAlert("错误", "库存不足!当前库存: " + currentStock);
return;
}
// 创建出库记录
String id = "OUT" + System.currentTimeMillis();
LocalDateTime now = LocalDateTime.now();
int remainingStock = currentStock - quantity;
// 修改数据库连接为相对路径
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();
if (remainingStock == 0) {
// 如果全部出库,删除记录
String deleteSql = "DELETE FROM warehouse WHERE id = ?";
try (PreparedStatement deleteStmt = conn.prepareStatement(deleteSql)) {
deleteStmt.setString(1, recordId);
deleteStmt.executeUpdate();
}
} else {
// 更新剩余库存
String updateSql = "UPDATE warehouse SET quantity = ? WHERE id = ?";
try (PreparedStatement updateStmt = conn.prepareStatement(updateSql)) {
updateStmt.setInt(1, remainingStock);
updateStmt.setString(2, recordId);
updateStmt.executeUpdate();
}
}
// 创建记录对象并添加到表格
OutboundRecord record = new OutboundRecord(
id,
goodsName,
quantity,
supplier,
now,
"当前用户",
remark
);
// 添加到表格
tableView.getItems().add(record);
// 更新总计
updateTotal();
// 刷新表格显示
loadOutboundRecords();
// 清空输入
handleClear();
// 添加操作日志
String details = String.format("出库货物:%s数量%d供应商%s",
goodsName, quantity, supplier);
goodsName, quantity, customer);
DataManager.getInstance().addOperationLog("出库", goodsName, "当前用户", details);
showAlert("成功", "出库记录已保存!");
} else {
showAlert("错误", "未找到该货物的库存记录!");
}
}
}
} catch (NumberFormatException e) {
showAlert("错误", "请输入有效的数量!");
} catch (Exception e) {
showAlert("错误", "保存失败:" + e.getMessage());
e.printStackTrace();
showAlert("错误", "保存失败:" + e.getMessage());
}
}
private void handleClear() {
goodsField.clear();
supplierField.clear();
customerField.clear();
quantityField.clear();
remarkField.clear();
}
private void showAlert(String title, String content) {
Alert alert = new Alert(Alert.AlertType.INFORMATION);
alert.setTitle(title);
@ -261,26 +276,42 @@ public class OutboundView extends BorderPane {
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";
String sql = "SELECT * FROM warehouse ORDER BY inbound_time DESC";
try (Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery(sql)) {
tableView.getItems().clear();
while (rs.next()) {
try {
String id = rs.getString("id");
String goodsId = rs.getString("goods_id");
int quantity = rs.getInt("quantity");
String supplier = rs.getString("supplier");
String timeStr = rs.getString("inbound_time");
String operator = rs.getString("operator");
String remark = rs.getString("remark");
LocalDateTime dateTime = LocalDateTime.parse(timeStr);
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")
id,
goodsId,
quantity,
supplier,
dateTime,
operator,
remark
);
tableView.getItems().add(record);
} catch (Exception e) {
e.printStackTrace();
}
}
updateTotal();
}
} catch (Exception e) {
e.printStackTrace();
@ -288,24 +319,11 @@ public class OutboundView extends BorderPane {
}
}
// 查询库存是否足够
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防止未知错误导致库存检查失败
// <20><>加填充字段的方法
private void fillFields(OutboundRecord record) {
goodsField.setText(record.getGoodsId());
customerField.setText(record.getCustomer());
quantityField.setText(String.valueOf(record.getQuantity()));
remarkField.setText(record.getRemark());
}
}
Loading…
Cancel
Save