102 lines
2.9 KiB
Go
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
|
|
}
|