bindbox-game/internal/api/user/request_shipping_batch_app.go
Zuncle 4353b0f053 fix(shipping): 反转运费规则为不满5件收运费,满5件包邮
- 运费预下单接口:< 5 件允许创建运费订单,>= 5 件拒绝
- 批量发货接口:< 5 件时强制校验已支付运费订单
- 单件发货接口:同样强制校验已支付运费订单
- 运费订单 remark 存入 inventory_ids JSON 用于关联
2026-03-31 21:08:33 +08:00

80 lines
2.8 KiB
Go
Executable File
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 app
import (
"bindbox-game/internal/code"
"bindbox-game/internal/pkg/core"
"bindbox-game/internal/pkg/validation"
"net/http"
)
type requestShippingBatchRequest struct {
InventoryIDs []int64 `json:"inventory_ids"`
AddressID *int64 `json:"address_id"`
}
type requestShippingBatchResponse struct {
AddressID int64 `json:"address_id"`
BatchNo string `json:"batch_no"`
SuccessIDs []int64 `json:"success_ids"`
Skipped []map[string]any `json:"skipped"`
Failed []map[string]any `json:"failed"`
}
// RequestShippingBatch 批量申请发货(使用默认地址或指定地址)
// @Summary 批量申请发货
// @Description 为多个资产申请发货,校验所有权与状态;不满 5 件需先支付运费;幂等:已申请的资产跳过
// @Tags APP端.用户
// @Accept json
// @Produce json
// @Security LoginVerifyToken
// @Param user_id path integer true "用户ID"
// @Param RequestBody body requestShippingBatchRequest true "请求参数资产ID列表与可选地址ID"
// @Success 200 {object} requestShippingBatchResponse
// @Failure 400 {object} code.Failure
// @Router /api/app/users/{user_id}/inventory/request-shipping-batch [post]
func (h *handler) RequestShippingBatch() core.HandlerFunc {
return func(ctx core.Context) {
req := new(requestShippingBatchRequest)
rsp := new(requestShippingBatchResponse)
if err := ctx.ShouldBindJSON(req); err != nil {
ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, validation.Error(err)))
return
}
if len(req.InventoryIDs) == 0 || len(req.InventoryIDs) > 100 {
ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, "invalid inventory_ids"))
return
}
userID := int64(ctx.SessionUserInfo().Id)
// 运费校验:不满 5 件须已支付运费订单
if len(req.InventoryIDs) < shippingFeeThreshold {
paid, _ := h.readDB.Orders.WithContext(ctx.RequestContext()).
Where(
h.readDB.Orders.UserID.Eq(userID),
h.readDB.Orders.SourceType.Eq(shippingFeeSourceType),
h.readDB.Orders.Status.Eq(2),
).Count()
if paid == 0 {
ctx.AbortWithError(core.Error(http.StatusBadRequest, 150003, "不满5件需先支付运费"))
return
}
}
addrID, batchNo, success, skipped, failed, err := h.user.RequestShippings(ctx.RequestContext(), userID, req.InventoryIDs, req.AddressID)
if err != nil {
ctx.AbortWithError(core.Error(http.StatusBadRequest, 10023, err.Error()))
return
}
rsp.AddressID = addrID
rsp.BatchNo = batchNo
rsp.SuccessIDs = success
for _, s := range skipped {
rsp.Skipped = append(rsp.Skipped, map[string]any{"id": s.ID, "reason": s.Reason})
}
for _, f := range failed {
rsp.Failed = append(rsp.Failed, map[string]any{"id": f.ID, "reason": f.Reason})
}
ctx.Payload(rsp)
}
}