micro-bundle/internal/logic/orderGateLogic.go
2026-06-09 13:51:25 +08:00

102 lines
2.9 KiB
Go

package logic
import (
"micro-bundle/internal/dao"
"micro-bundle/internal/model"
"micro-bundle/pb/bundle"
"time"
)
// CheckOrderEligibility 下单前置校验。
// 规则:
// 1. 套餐订单:存在先用后付逾期未支付 或 普通订单未支付 → 拦截下单
// 2. 增值服务:必须有套餐订单且该套餐是(普通已支付 或 先用后付未逾期)→ 才能下单
// 3. 套餐订单有效期内只允许存在一笔
func CheckOrderEligibility(req *bundle.CheckOrderEligibilityRequest) (*bundle.CheckOrderEligibilityResponse, error) {
res := &bundle.CheckOrderEligibilityResponse{Allow: true}
if req == nil || req.CustomerID == "" {
res.Allow = false
res.Reason = "INVALID_PARAM"
res.Msg = "customerID 必填"
return res, nil
}
// 套餐下单校验
if req.OrderKind == model.OrderKindBundle {
// 1. 先用后付逾期未付 → 拦截
overdue, err := dao.ExistsOverduePayLaterBundle(req.CustomerID)
if err != nil {
return res, err
}
if overdue {
res.Allow = false
res.Reason = model.OrderGateReasonPayLaterBundleOverdue
res.Msg = "您有过期的先用后付订单,无法再次体验"
return res, nil
}
// 2. 普通订单未支付 → 拦截
unpaid, err := dao.ExistsUnpaidNormalBundle(req.CustomerID)
if err != nil {
return res, err
}
if unpaid {
res.Allow = false
res.Reason = "NORMAL_BUNDLE_UNPAID"
res.Msg = "当前已存在未支付订单,请先完成支付"
return res, nil
}
// 3. 有效期内已存在套餐订单 → 保证套餐有效期内只存在一笔
exists, err := dao.ExistsActiveBundle(req.CustomerID)
if err != nil {
return res, err
}
if exists {
res.Allow = false
res.Reason = model.OrderGateReasonBundleActiveExists
res.Msg = "有效期内已存在套餐订单"
return res, nil
}
} else if req.OrderKind == model.OrderKindValueAdd {
// 增值服务下单校验:必须有有效的套餐订单
hasValid, err := dao.ExistsValidBundleForValueAdd(req.CustomerID)
if err != nil {
return res, err
}
if !hasValid {
res.Allow = false
res.Reason = "NO_VALID_BUNDLE"
res.Msg = "请先购买套餐订单后再购买增值服务"
return res, nil
}
}
return res, nil
}
// MarkOverdueOrders 扫描到期订单(套餐 → 冻结;增值 → 余量作废)
func MarkOverdueOrders(req *bundle.MarkOverdueOrdersRequest) (*bundle.MarkOverdueOrdersResponse, error) {
res := &bundle.MarkOverdueOrdersResponse{}
now := time.Now()
if req != nil && req.Now != "" {
if t, err := time.ParseInLocation("2006-01-02 15:04:05", req.Now, time.Local); err == nil {
now = t
}
}
if n, err := dao.MarkBundleOverdue(now); err != nil {
res.Msg = err.Error()
return res, err
} else {
res.BundleOverdueCount = int32(n)
}
if n, err := dao.MarkValueAddExpiredByDue(now); err != nil {
res.Msg = err.Error()
return res, err
} else {
res.ValueAddExpiredCount = int32(n)
}
res.Msg = "ok"
return res, nil
}