出库售价(应收按售价) + 库存选择器分页上限修复 + seed 改为序列号模型 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YZ4DskSRKsSiheQonFtQvx
This commit is contained in:
@@ -54,9 +54,13 @@ func (h *InventoryHandler) List(c *gin.Context) {
|
||||
if page < 1 {
|
||||
page = 1
|
||||
}
|
||||
if pageSize < 1 || pageSize > 500 {
|
||||
if pageSize < 1 {
|
||||
pageSize = 20
|
||||
}
|
||||
// 超出上限钳到上限(此前是回退默认 20,导致出库选货请求大 page_size 被打回只剩 20 条)
|
||||
if pageSize > 5000 {
|
||||
pageSize = 5000
|
||||
}
|
||||
|
||||
baseWhere := "inv.shop_id = ? AND inv.deleted_at IS NULL"
|
||||
args := []interface{}{shopID}
|
||||
|
||||
@@ -110,8 +110,9 @@ func (h *StockOutHandler) Create(c *gin.Context) {
|
||||
var total float64
|
||||
for i := range req.Items {
|
||||
req.Items[i].ShopID = shopID
|
||||
// TotalPrice 记成本小计;应收(TotalAmount)按售价×数量
|
||||
req.Items[i].TotalPrice = req.Items[i].Quantity * req.Items[i].UnitPrice
|
||||
total += req.Items[i].TotalPrice
|
||||
total += req.Items[i].Quantity * req.Items[i].SalePrice
|
||||
}
|
||||
req.TotalAmount = total
|
||||
|
||||
@@ -147,8 +148,9 @@ func (h *StockOutHandler) Update(c *gin.Context) {
|
||||
for i := range req.Items {
|
||||
req.Items[i].ShopID = shopID
|
||||
req.Items[i].OrderID = order.ID
|
||||
// TotalPrice 记成本小计;应收(TotalAmount)按售价×数量
|
||||
req.Items[i].TotalPrice = req.Items[i].Quantity * req.Items[i].UnitPrice
|
||||
total += req.Items[i].TotalPrice
|
||||
total += req.Items[i].Quantity * req.Items[i].SalePrice
|
||||
}
|
||||
updates := map[string]interface{}{
|
||||
"warehouse_id": req.WarehouseID,
|
||||
|
||||
@@ -27,13 +27,21 @@ func TestStockReturn_StockOut_OwnAllowed(t *testing.T) {
|
||||
// 操作员建出库单(本人) → 提交 → 审核
|
||||
w := makeRequest(r, "POST", "/api/v1/stock-out/orders", opToken, map[string]interface{}{
|
||||
"warehouse_id": wh.ID, "order_date": time.Now().Format(time.RFC3339),
|
||||
"items": []map[string]interface{}{{"product_id": prod.ID, "quantity": 15.0, "unit_price": 20.0}},
|
||||
"items": []map[string]interface{}{{"product_id": prod.ID, "quantity": 15.0, "unit_price": 20.0, "sale_price": 25.0}},
|
||||
})
|
||||
require.Equal(t, http.StatusCreated, w.Code)
|
||||
orderID := extractID(w)
|
||||
makeRequest(r, "PUT", fmt.Sprintf("/api/v1/stock-out/orders/%d/submit", orderID), opToken, nil)
|
||||
makeRequest(r, "PUT", fmt.Sprintf("/api/v1/stock-out/orders/%d/approve", orderID), opToken, nil)
|
||||
|
||||
// 应收按售价口径:TotalAmount = 15 × 25 = 375(不是成本 15×20)
|
||||
var soOrder model.StockOutOrder
|
||||
require.NoError(t, db.First(&soOrder, orderID).Error)
|
||||
assert.Equal(t, float64(375), soOrder.TotalAmount)
|
||||
var recv model.FinanceRecord
|
||||
require.NoError(t, db.Where("shop_id = ? AND type = 'receivable' AND ref_type = 'stock_out'", shop.ID).First(&recv).Error)
|
||||
assert.Equal(t, float64(375), recv.Amount, "应收应按售价×数量")
|
||||
|
||||
var item model.StockOutItem
|
||||
require.NoError(t, db.Where("order_id = ?", orderID).First(&item).Error)
|
||||
|
||||
@@ -75,12 +83,11 @@ func TestStockReturn_StockOut_OwnAllowed(t *testing.T) {
|
||||
db.First(&order, orderID)
|
||||
assert.Equal(t, "full", order.ReturnState)
|
||||
|
||||
// 应收冲减:存在一条负向 receivable
|
||||
var neg int64
|
||||
db.Model(&model.FinanceRecord{}).
|
||||
Where("shop_id = ? AND type = 'receivable' AND amount < 0 AND ref_type = 'stock_out_return'", shop.ID).
|
||||
Count(&neg)
|
||||
assert.Equal(t, int64(1), neg)
|
||||
// 应收冲减:存在一条负向 receivable,金额按售价口径 = -375
|
||||
var negRec model.FinanceRecord
|
||||
require.NoError(t, db.Where("shop_id = ? AND type = 'receivable' AND amount < 0 AND ref_type = 'stock_out_return'", shop.ID).
|
||||
First(&negRec).Error)
|
||||
assert.Equal(t, float64(-375), negRec.Amount, "退单冲应收应按售价×数量")
|
||||
}
|
||||
|
||||
func TestStockReturn_StockIn_AdminOnly_AndRemovesInventory(t *testing.T) {
|
||||
|
||||
@@ -94,6 +94,8 @@ type StockOutItem struct {
|
||||
Spec string `gorm:"size:100" json:"spec"`
|
||||
Quantity float64 `gorm:"type:decimal(12,3);not null" json:"quantity"`
|
||||
UnitPrice float64 `gorm:"type:decimal(16,2);default:0" json:"unit_price"`
|
||||
// 售价:出库实际销售单价(可编辑),应收账款按 售价×数量 计;与 UnitPrice(入库成本) 区分
|
||||
SalePrice float64 `gorm:"type:decimal(16,2);default:0" json:"sale_price"`
|
||||
TotalPrice float64 `gorm:"type:decimal(16,2);default:0" json:"total_price"`
|
||||
// 已退数量:0=未退,=Quantity 表示整行已退单
|
||||
ReturnedQuantity float64 `gorm:"type:decimal(12,3);default:0" json:"returned_quantity"`
|
||||
|
||||
@@ -416,7 +416,8 @@ func (s *StockService) ReturnStockOut(shopID, orderID, userID uint64, role strin
|
||||
return err
|
||||
}
|
||||
it.ReturnedQuantity = it.Quantity
|
||||
returnedAmount += it.TotalPrice
|
||||
// 冲应收按售价口径(与审核建应收 TotalAmount=Σ售价×数量 一致)
|
||||
returnedAmount += it.Quantity * it.SalePrice
|
||||
}
|
||||
|
||||
// 冲减应收(负向调整记录)
|
||||
|
||||
Reference in New Issue
Block a user