micro-bundle/internal/logic/orderGateLogic.go
2026-06-08 17:08:04 +08:00

90 lines
2.7 KiB
Go

package logic
import (
"micro-bundle/internal/dao"
"micro-bundle/internal/model"
"micro-bundle/pb/bundle"
"time"
)
// CheckOrderEligibility 下单前置校验(先用后付)。
// 规则:
// 4. 套餐订单 + 先用后付 + 到期未付:禁止所有套餐下单
// 5. 套餐到期未付不影响增值下单(无限续杯)
// 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. 已存在先用后付且未支付(待付款)的套餐订单 → 提示去支付。
pending, err := dao.ExistsPendingPayLaterBundle(req.CustomerID)
if err != nil {
return res, err
}
if pending {
res.Allow = false
res.Reason = model.OrderGateReasonPayLaterBundlePending
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
}
}
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
}