diff --git a/CHANGELOG-server.md b/CHANGELOG-server.md index bfca1d6..e46daf1 100644 --- a/CHANGELOG-server.md +++ b/CHANGELOG-server.md @@ -5,6 +5,11 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [1.0.76] - 2026-06-22 + +### 修复 +- 修复「编辑入库单草稿后合计金额变成 0」的问题:此前每次编辑草稿会把单据合计金额错误清零(明细的单价/金额正常,仅单据头合计未重算),现已按明细正确重算。 + ## [1.0.75] - 2026-06-22 ### 新功能 diff --git a/backend/internal/handler/stock_in.go b/backend/internal/handler/stock_in.go index 860a16f..6416762 100644 --- a/backend/internal/handler/stock_in.go +++ b/backend/internal/handler/stock_in.go @@ -172,6 +172,7 @@ func (h *StockInHandler) Update(c *gin.Context) { it.ProductID = prod.ID it.ProductCode = prod.Code it.TotalPrice = it.Quantity * it.UnitPrice + total += it.TotalPrice } updates := map[string]interface{}{ "warehouse_id": req.WarehouseID, diff --git a/backend/internal/handler/stock_in_test.go b/backend/internal/handler/stock_in_test.go index 77cc4fb..eb869e7 100644 --- a/backend/internal/handler/stock_in_test.go +++ b/backend/internal/handler/stock_in_test.go @@ -272,6 +272,44 @@ func TestStockInHandler_TotalAmount(t *testing.T) { assert.Equal(t, float64(110), data["total_amount"]) } +// 回归:编辑草稿入库单后 total_amount 必须按新明细重算(此前 Update 漏了累加,编辑后被清成 0)。 +func TestStockInHandler_UpdateRecomputesTotal(t *testing.T) { + db := testutil.SetupTestDB() + shop := testutil.CreateTestShop(db, "SI_UPD") + user := testutil.CreateTestUser(db, shop.ID, "admin", "pass", "admin") + warehouse := testutil.CreateTestWarehouse(db, shop.ID, "Warehouse") + token := getAuthToken(user.ID, shop.ID, "admin") + r := setupProtectedRouter(db) + + // 建草稿:1 行 10×5 = 50 + w := makeRequest(r, "POST", "/api/v1/stock-in/orders", token, map[string]interface{}{ + "warehouse_id": warehouse.ID, + "order_date": time.Now().Format(time.RFC3339), + "items": []map[string]interface{}{ + {"product_name": "茅台", "series": "飞天", "spec": "500ml", "quantity": 10.0, "unit_price": 5.0}, + }, + }) + require.Equal(t, http.StatusCreated, w.Code) + orderID := extractID(w) + + // 编辑:改成 2 行 12×3100 + 1×4500 = 41700 + w = makeRequest(r, "PUT", fmt.Sprintf("/api/v1/stock-in/orders/%d", orderID), token, map[string]interface{}{ + "warehouse_id": warehouse.ID, + "order_date": time.Now().Format(time.RFC3339), + "items": []map[string]interface{}{ + {"product_name": "茅台2009", "series": "大件", "spec": "500ml", "quantity": 12.0, "unit_price": 3100.0}, + {"product_name": "茅台十五年", "series": "大件", "spec": "500ml", "quantity": 1.0, "unit_price": 4500.0}, + }, + }) + require.Equal(t, http.StatusOK, w.Code) + + // 取详情核对 total_amount 已重算(不是 0) + w = makeRequest(r, "GET", fmt.Sprintf("/api/v1/stock-in/orders/%d", orderID), token, nil) + require.Equal(t, http.StatusOK, w.Code) + data := parseResponse(w)["data"].(map[string]interface{}) + assert.Equal(t, float64(41700), data["total_amount"], "编辑后金额应按新明细重算") +} + func TestStockInHandler_NoAuth(t *testing.T) { db := testutil.SetupTestDB() r := setupProtectedRouter(db) diff --git a/backend/internal/handler/testhelper_test.go b/backend/internal/handler/testhelper_test.go index a48b0de..25f2c58 100644 --- a/backend/internal/handler/testhelper_test.go +++ b/backend/internal/handler/testhelper_test.go @@ -60,6 +60,7 @@ func setupProtectedRouter(db *gorm.DB) *gin.Engine { stockIn.GET("/orders", stockInH.List) stockIn.GET("/orders/:id", stockInH.Get) stockIn.POST("/orders", stockInH.Create) + stockIn.PUT("/orders/:id", stockInH.Update) stockIn.PUT("/orders/:id/submit", stockInH.Submit) stockIn.PUT("/orders/:id/approve", stockInH.Approve) stockIn.PUT("/orders/:id/reject", stockInH.Reject) @@ -71,6 +72,7 @@ func setupProtectedRouter(db *gorm.DB) *gin.Engine { stockOut.GET("/orders", stockOutH.List) stockOut.GET("/orders/:id", stockOutH.Get) stockOut.POST("/orders", stockOutH.Create) + stockOut.PUT("/orders/:id", stockOutH.Update) stockOut.PUT("/orders/:id/submit", stockOutH.Submit) stockOut.PUT("/orders/:id/approve", stockOutH.Approve) stockOut.PUT("/orders/:id/reject", stockOutH.Reject)