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

90 lines
2.9 KiB
Go
Raw Permalink 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 (
"encoding/json"
"fmt"
"net/http"
"time"
"bindbox-game/internal/code"
"bindbox-game/internal/pkg/core"
"bindbox-game/internal/pkg/validation"
"bindbox-game/internal/repository/mysql/model"
)
const (
shippingFeeThreshold = 5 // 低于此件数收运费
shippingFeeCents = 1000 // 运费金额10 元
shippingFeeSourceType = int32(5) // orders.source_type: 5 = 运费订单
)
type shippingFeePreorderRequest struct {
InventoryIDs []int64 `json:"inventory_ids"`
}
type shippingFeePreorderResponse struct {
OrderNo string `json:"order_no"`
}
// ShippingFeePreorder 创建运费订单
// @Summary 创建运费订单
// @Description 选中件数不满 5 件时,创建 10 元运费订单并返回 order_no前端再调用 /pay/wechat/jsapi/preorder 发起支付;满 5 件包邮无需调用
// @Tags APP端.用户
// @Accept json
// @Produce json
// @Security LoginVerifyToken
// @Param user_id path integer true "用户ID"
// @Param RequestBody body shippingFeePreorderRequest true "请求参数资产ID列表"
// @Success 200 {object} shippingFeePreorderResponse
// @Failure 400 {object} code.Failure
// @Router /api/app/users/{user_id}/inventory/shipping-fee/preorder [post]
func (h *handler) ShippingFeePreorder() core.HandlerFunc {
return func(ctx core.Context) {
req := new(shippingFeePreorderRequest)
rsp := new(shippingFeePreorderResponse)
if err := ctx.ShouldBindJSON(req); err != nil {
ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, validation.Error(err)))
return
}
if len(req.InventoryIDs) == 0 {
ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, "inventory_ids 不能为空"))
return
}
if len(req.InventoryIDs) >= shippingFeeThreshold {
ctx.AbortWithError(core.Error(http.StatusBadRequest, 150001, fmt.Sprintf("件数满 %d 件,无需支付运费", shippingFeeThreshold)))
return
}
userID := int64(ctx.SessionUserInfo().Id)
remarkBytes, _ := json.Marshal(req.InventoryIDs)
// 生成运费订单号SF + 时间戳 + 用户ID后6位保证唯一
now := time.Now()
orderNo := fmt.Sprintf("SF%s%06d", now.Format("20060102150405"), userID%1000000)
// 创建运费订单source_type=5 区分普通商品订单status=1 待支付)
order := &model.Orders{
UserID: userID,
OrderNo: orderNo,
SourceType: shippingFeeSourceType,
TotalAmount: shippingFeeCents,
DiscountAmount: 0,
PointsAmount: 0,
ActualAmount: shippingFeeCents,
Status: 1,
IsConsumed: 0,
Remark: string(remarkBytes),
}
if err := h.writeDB.Orders.WithContext(ctx.RequestContext()).
Omit(h.writeDB.Orders.PaidAt, h.writeDB.Orders.CancelledAt).
Create(order); err != nil {
ctx.AbortWithError(core.Error(http.StatusBadRequest, 150002, "创建运费订单失败: "+err.Error()))
return
}
rsp.OrderNo = orderNo
ctx.Payload(rsp)
}
}