fix version 1

This commit is contained in:
2026-09-22 21:15:34 +08:00
parent 9f86366638
commit d63d7e8b3a
277 changed files with 9959 additions and 1514 deletions

View File

@@ -2,6 +2,7 @@ package summary
import (
"context"
"time"
"bsm/full/module/ec/order/internal/impl"
"bsm/full/module/ec/order/internal/models"
@@ -15,7 +16,7 @@ import (
// 确认订单,物流,优惠卷等其它信息
func Confirm(ctx context.Context, in *pb.ConfirmRequest) (reply *pb.ConfirmReply, err error) {
// parse authorization meta.
_, err = service.ParseMetaCtx(ctx, nil)
auth, err := service.ParseMetaCtx(ctx, nil)
if err != nil {
return nil, err
}
@@ -54,27 +55,56 @@ func Confirm(ctx context.Context, in *pb.ConfirmRequest) (reply *pb.ConfirmReply
if in.CouponIdentity != "" {
err = impl.DBService.Where("identity=?", in.CouponIdentity).First(&coupon).Error
if err == nil {
if coupon.Status == 2 {
impl.DBService.Model(&models.OrderCoupon{}).Where("identity=?", in.CouponIdentity).Update("status", 3)
couponAmount = coupon.Amount
} else {
printer.Error(err.Error())
return nil, errcode.ErrUnavailable
}
} else {
if err != nil {
printer.Error(err.Error())
return nil, errcode.ErrRecordNotFound
}
// 校验优惠券归属passport_id 或 passport_identity 命中调用者才算本人所有。
if coupon.PassportIdentity != auth.Identity && coupon.PassportID != auth.ID {
return nil, errcode.ErrPermissionDenied
}
// 校验使用状态仅可用的优惠券status=2可使用。
if coupon.Status != 2 {
return nil, errcode.ErrUnavailable
}
// 校验有效期started/expired 为字符串,格式可解析时强制校验,无法解析时跳过。
now := time.Now()
if started, ok := parseCouponTime(coupon.Started); ok && now.Before(started) {
return nil, errcode.ErrUnavailable
}
if expired, ok := parseCouponTime(coupon.Expired); ok && now.After(expired) {
return nil, errcode.ErrUnavailable
}
// 核销优惠券:带状态条件更新并检查影响行数,避免重复使用同一张券。
result := impl.DBService.Model(&models.OrderCoupon{}).Where("identity = ? AND status = 2", in.CouponIdentity).Update("status", 3)
if result.Error != nil {
printer.Error(result.Error.Error())
return nil, errcode.ErrDB
}
if result.RowsAffected == 0 {
return nil, errcode.ErrUnavailable
}
couponAmount = coupon.Amount
}
if couponAmount > 0 {
summary.TotalPrice = summary.TotalPrice + couponAmount
// 优惠券为减免项,抵扣后总额不得为负:抵扣额不超过订单金额。
if couponAmount >= summary.TotalPrice {
summary.TotalPrice = 0
} else {
summary.TotalPrice = summary.TotalPrice - couponAmount
}
// 回写所用券与其抵扣额,供取消订单时退券使用。
summary.CouponIdentity = in.CouponIdentity
summary.CouponAmount = couponAmount
}
summary.Status = 1
err = impl.DBService.Where("order_no = ?", in.OrderNo).Updates(summary).Error
// 显式指定需落库的列,保证总额抵扣为 0 时也能写入。
err = impl.DBService.Where("order_no = ?", in.OrderNo).
Select("total_price", "coupon_identity", "coupon_amount", "status").
Updates(summary).Error
if err != nil {
printer.Error(err.Error())
return nil, errcode.ErrDB
@@ -84,3 +114,17 @@ func Confirm(ctx context.Context, in *pb.ConfirmRequest) (reply *pb.ConfirmReply
TotalPrice: summary.TotalPrice,
}, nil
}
// parseCouponTime 解析优惠券 started/expired 时间字段,兼容"2006-01-02 15:04:05"与"2006-01-02"两种格式;
// 无法解析时返回 ok=false由调用方跳过该项校验。
func parseCouponTime(v string) (time.Time, bool) {
if v == "" {
return time.Time{}, false
}
for _, layout := range []string{"2006-01-02 15:04:05", "2006-01-02"} {
if t, err := time.ParseInLocation(layout, v, time.Local); err == nil {
return t, true
}
}
return time.Time{}, false
}