fix(shipping): 使用资产价值快照价格确保发货与分解价格一致
修复改价后发货价格与分解价格不一致的问题: - 发货时优先使用 user_inventory.value_cents 快照价格 - 后台发货列表使用 shipping_records.price 存储的快照价格 - 确保盈亏统计时价格数据准确一致
This commit is contained in:
parent
a29669ccf6
commit
2aa7cdbd61
@ -216,11 +216,46 @@ func (h *handler) ListShippingOrders() core.HandlerFunc {
|
||||
}
|
||||
}
|
||||
|
||||
// 获取商品信息(去重并计数)
|
||||
pidCounts := make(map[int64]int64)
|
||||
for _, pid := range a.pid {
|
||||
pidCounts[pid]++
|
||||
// 获取商品信息(去重并计数,使用发货记录中的价格快照)
|
||||
// 按商品ID聚合价格和数量
|
||||
type productInfo struct {
|
||||
Name string
|
||||
Image string
|
||||
Price int64 // 使用发货记录中的快照价格
|
||||
Count int64
|
||||
}
|
||||
productMap := make(map[int64]*productInfo)
|
||||
|
||||
// 查询发货记录获取每个商品的快照价格
|
||||
if len(a.recordIDs) > 0 {
|
||||
records, _ := h.readDB.ShippingRecords.WithContext(ctx.RequestContext()).ReadDB().
|
||||
Where(h.readDB.ShippingRecords.ID.In(a.recordIDs...)).
|
||||
Find()
|
||||
|
||||
for _, r := range records {
|
||||
if r.ProductID <= 0 {
|
||||
continue
|
||||
}
|
||||
if info, ok := productMap[r.ProductID]; ok {
|
||||
info.Count++
|
||||
} else {
|
||||
// 查询商品名称和图片
|
||||
var prodName, prodImage string
|
||||
if prod, _ := h.readDB.Products.WithContext(ctx.RequestContext()).ReadDB().
|
||||
Where(h.readDB.Products.ID.Eq(r.ProductID)).First(); prod != nil {
|
||||
prodName = prod.Name
|
||||
prodImage = prod.ImagesJSON
|
||||
}
|
||||
productMap[r.ProductID] = &productInfo{
|
||||
Name: prodName,
|
||||
Image: prodImage,
|
||||
Price: r.Price, // 使用发货记录中的快照价格
|
||||
Count: 1,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var products []struct {
|
||||
ID int64 `json:"id"`
|
||||
Name string `json:"name"`
|
||||
@ -228,22 +263,20 @@ func (h *handler) ListShippingOrders() core.HandlerFunc {
|
||||
Price int64 `json:"price"`
|
||||
Count int64 `json:"count"`
|
||||
}
|
||||
for pid, count := range pidCounts {
|
||||
if prod, _ := h.readDB.Products.WithContext(ctx.RequestContext()).ReadDB().Where(h.readDB.Products.ID.Eq(pid)).First(); prod != nil {
|
||||
products = append(products, struct {
|
||||
ID int64 `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Image string `json:"image"`
|
||||
Price int64 `json:"price"`
|
||||
Count int64 `json:"count"`
|
||||
}{
|
||||
ID: prod.ID,
|
||||
Name: prod.Name,
|
||||
Image: prod.ImagesJSON, // 商品图片JSON
|
||||
Price: prod.Price,
|
||||
Count: count,
|
||||
})
|
||||
}
|
||||
for pid, info := range productMap {
|
||||
products = append(products, struct {
|
||||
ID int64 `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Image string `json:"image"`
|
||||
Price int64 `json:"price"`
|
||||
Count int64 `json:"count"`
|
||||
}{
|
||||
ID: pid,
|
||||
Name: info.Name,
|
||||
Image: info.Image,
|
||||
Price: info.Price, // 使用快照价格
|
||||
Count: info.Count,
|
||||
})
|
||||
}
|
||||
|
||||
items = append(items, &ShippingOrderGroup{
|
||||
|
||||
@ -200,11 +200,19 @@ func (s *service) SubmitAddressShare(ctx context.Context, shareToken string, nam
|
||||
}
|
||||
|
||||
// c. 创建发货记录 (归属于 targetUserID)
|
||||
var price int64
|
||||
if inv.ProductID > 0 {
|
||||
// 使用资产价值快照,确保价格与分解时一致
|
||||
price := inv.ValueCents
|
||||
if price <= 0 && inv.ProductID > 0 {
|
||||
// 如果没有快照价格,回退到商品当前价格并记录快照
|
||||
var p model.Products
|
||||
if err := tx.Table("products").Where("id = ?", inv.ProductID).First(&p).Error; err == nil {
|
||||
price = p.Price
|
||||
// 回写资产价值快照
|
||||
tx.Table("user_inventory").Where("id = ?", inv.ID).Updates(map[string]interface{}{
|
||||
"value_cents": price,
|
||||
"value_source": 2,
|
||||
"value_snapshot_at": time.Now(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@ -265,10 +273,15 @@ func (s *service) RequestShippingWithBatch(ctx context.Context, userID int64, in
|
||||
addrID = addr.ID
|
||||
}
|
||||
|
||||
var price int64
|
||||
if inv.ProductID > 0 {
|
||||
// 使用资产价值快照,确保价格与分解时一致
|
||||
price := inv.ValueCents
|
||||
if price <= 0 && inv.ProductID > 0 {
|
||||
// 如果没有快照价格,回退到商品当前价格并记录快照
|
||||
if p, e := s.readDB.Products.WithContext(ctx).Where(s.readDB.Products.ID.Eq(inv.ProductID)).First(); e == nil && p != nil {
|
||||
price = p.Price
|
||||
// 回写资产价值快照
|
||||
s.repo.GetDbW().Exec("UPDATE user_inventory SET value_cents=?, value_source=?, value_snapshot_at=NOW(3) WHERE id=? AND user_id=?",
|
||||
price, 2, inventoryID, userID)
|
||||
}
|
||||
}
|
||||
|
||||
@ -443,8 +456,26 @@ func (s *service) RequestShippings(ctx context.Context, userID int64, inventoryI
|
||||
return addrID, batchNo, success, skipped, failed, nil
|
||||
}
|
||||
|
||||
// 7. 批量查询products获取价格(一次查询替代N次)
|
||||
// 7. 批量查询products获取价格(用于没有快照价格的资产)
|
||||
productMap := make(map[int64]int64) // productID -> price
|
||||
// 收集需要回写快照的资产
|
||||
type valueFix struct {
|
||||
ID int64
|
||||
ValueCents int64
|
||||
ValueSource int32
|
||||
}
|
||||
valueFixes := make([]valueFix, 0)
|
||||
|
||||
// 先检查哪些资产没有快照价格
|
||||
for _, inv := range validInvs {
|
||||
if inv.ValueCents <= 0 && inv.ProductID > 0 {
|
||||
if _, ok := productIDSet[inv.ProductID]; !ok {
|
||||
productIDSet[inv.ProductID] = struct{}{}
|
||||
productIDs = append(productIDs, inv.ProductID)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if len(productIDs) > 0 {
|
||||
prods, _ := s.readDB.Products.WithContext(ctx).Where(s.readDB.Products.ID.In(productIDs...)).Find()
|
||||
for _, p := range prods {
|
||||
@ -455,9 +486,22 @@ func (s *service) RequestShippings(ctx context.Context, userID int64, inventoryI
|
||||
// 8. 单事务批量处理
|
||||
validIDs := make([]int64, 0, len(validInvs))
|
||||
err = s.repo.GetDbW().Transaction(func(tx *gorm.DB) error {
|
||||
// 批量插入shipping_records
|
||||
// 批量插入shipping_records(使用资产价值快照)
|
||||
for _, inv := range validInvs {
|
||||
price := productMap[inv.ProductID]
|
||||
// 优先使用资产价值快照,确保与分解价格一致
|
||||
price := inv.ValueCents
|
||||
valueSource := inv.ValueSource
|
||||
if price <= 0 && inv.ProductID > 0 {
|
||||
// 如果没有快照价格,回退到商品当前价格
|
||||
price = productMap[inv.ProductID]
|
||||
valueSource = 2
|
||||
// 记录需要回写快照的资产
|
||||
valueFixes = append(valueFixes, valueFix{
|
||||
ID: inv.ID,
|
||||
ValueCents: price,
|
||||
ValueSource: valueSource,
|
||||
})
|
||||
}
|
||||
if errExec := tx.Exec(
|
||||
"INSERT INTO shipping_records (user_id, order_id, order_item_id, inventory_id, product_id, quantity, price, address_id, status, batch_no, remark) VALUES (?,?,?,?,?,?,?,?,?,?,?)",
|
||||
userID, inv.OrderID, 0, inv.ID, inv.ProductID, 1, price, addrID, 1, batchNo, "batch_request_shipping",
|
||||
@ -467,6 +511,16 @@ func (s *service) RequestShippings(ctx context.Context, userID int64, inventoryI
|
||||
validIDs = append(validIDs, inv.ID)
|
||||
}
|
||||
|
||||
// 回写资产价值快照(用于之前没有快照的资产)
|
||||
for _, fix := range valueFixes {
|
||||
if err := tx.Exec(
|
||||
"UPDATE user_inventory SET value_cents=?, value_source=?, value_snapshot_at=NOW(3) WHERE id=? AND user_id=?",
|
||||
fix.ValueCents, fix.ValueSource, fix.ID, userID,
|
||||
).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// 批量更新inventory状态(一次UPDATE替代N次)
|
||||
if len(validIDs) > 0 {
|
||||
if errExec := tx.Exec(
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user