bindbox-game/internal/service/user/shipping_groups.go

136 lines
3.5 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package user
import (
"context"
"strconv"
"time"
)
// ProductInfo 商品简要信息
type ProductInfo struct {
ID int64 `json:"id"`
Name string `json:"name"`
Image string `json:"image"`
Price int64 `json:"price"`
}
type ShipmentGroup struct {
ExpressCode string `json:"express_code"`
ExpressNo string `json:"express_no"`
BatchNo string `json:"batch_no"`
Status int32 `json:"status"`
Count int64 `json:"count"`
ShippedAt *time.Time `json:"shipped_at,omitempty"`
ReceivedAt *time.Time `json:"received_at,omitempty"`
InventoryIDs []int64 `json:"inventory_ids"`
ProductIDs []int64 `json:"product_ids"`
Products []ProductInfo `json:"products"`
}
func (s *service) ListUserShipmentGroups(ctx context.Context, userID int64, page, pageSize int) (items []*ShipmentGroup, total int64, err error) {
q := s.readDB.ShippingRecords.WithContext(ctx).ReadDB().Where(
s.readDB.ShippingRecords.UserID.Eq(userID),
s.readDB.ShippingRecords.Status.Neq(5), // Exclude cancelled records
)
total, err = q.Count()
if err != nil {
return nil, 0, err
}
if page <= 0 {
page = 1
}
if pageSize <= 0 {
pageSize = 20
}
if pageSize > 100 {
pageSize = 100
}
rows, err := q.Order(s.readDB.ShippingRecords.UpdatedAt.Desc(), s.readDB.ShippingRecords.ID.Desc()).Offset((page - 1) * pageSize).Limit(pageSize).Find()
if err != nil {
return nil, 0, err
}
type acc struct {
status int32
shippedAt *time.Time
receivedAt *time.Time
inv []int64
pid []int64
}
m := make(map[string]*acc)
meta := make(map[string]struct{ code, no, batch string })
order := make([]string, 0) // 保持顺序
for _, r := range rows {
// 分组优先级:运单号 > 批次号 > 记录ID
key := ""
if r.ExpressNo != "" {
// 有运单号,按运单号分组
key = "E|" + r.ExpressCode + "|" + r.ExpressNo
} else if r.BatchNo != "" {
// 无运单号但有批次号,按批次号分组
key = "B|" + r.BatchNo
} else {
// 无运单号也无批次号按记录ID独立
key = "_" + strconv.FormatInt(r.ID, 10)
}
if _, ok := m[key]; !ok {
m[key] = &acc{}
meta[key] = struct{ code, no, batch string }{r.ExpressCode, r.ExpressNo, r.BatchNo}
order = append(order, key)
}
a := m[key]
if a.status == 0 || r.Status >= a.status {
a.status = r.Status
}
if !r.ShippedAt.IsZero() {
t := r.ShippedAt
a.shippedAt = &t
}
if !r.ReceivedAt.IsZero() {
t := r.ReceivedAt
a.receivedAt = &t
}
a.inv = append(a.inv, r.InventoryID)
if r.ProductID > 0 {
a.pid = append(a.pid, r.ProductID)
}
}
items = make([]*ShipmentGroup, 0, len(m))
for _, k := range order {
a := m[k]
md := meta[k]
c := int64(len(a.inv))
// 获取商品详情(去重)
pidSet := make(map[int64]struct{})
for _, pid := range a.pid {
pidSet[pid] = struct{}{}
}
products := make([]ProductInfo, 0, len(pidSet))
for pid := range pidSet {
if prod, _ := s.readDB.Products.WithContext(ctx).ReadDB().Where(s.readDB.Products.ID.Eq(pid)).First(); prod != nil {
products = append(products, ProductInfo{
ID: prod.ID,
Name: prod.Name,
Image: prod.ImagesJSON,
Price: prod.Price,
})
}
}
items = append(items, &ShipmentGroup{
ExpressCode: md.code,
ExpressNo: md.no,
BatchNo: md.batch,
Status: a.status,
Count: c,
ShippedAt: a.shippedAt,
ReceivedAt: a.receivedAt,
InventoryIDs: a.inv,
ProductIDs: a.pid,
Products: products,
})
}
return items, total, nil
}