活动批次查询确认

This commit is contained in:
李子铭 2025-03-17 19:48:10 +08:00
parent 95dbc27dcc
commit 8ec8f2a980
9 changed files with 156 additions and 55 deletions

View File

@ -124,8 +124,10 @@ message CmbQueryProductReply {
string detail = 18 [json_name = "detail"]; string detail = 18 [json_name = "detail"];
// yyyy-mm-dd hh:mm:ss.sss // yyyy-mm-dd hh:mm:ss.sss
//
string saleStartTime = 19 [json_name = "saleStartTime"]; string saleStartTime = 19 [json_name = "saleStartTime"];
// yyyy-mm-dd hh:mm:ss.sss // yyyy-mm-dd hh:mm:ss.sss
//
string saleEndTime = 20 [json_name = "saleEndTime"]; string saleEndTime = 20 [json_name = "saleEndTime"];
// //

View File

@ -14,6 +14,8 @@ type ProductBo struct {
BatchNo string BatchNo string
MchId string MchId string
Channel vo.Channel Channel vo.Channel
AvailableType vo.AvailableType
AvailableDays uint32
CreateTime *time.Time CreateTime *time.Time
UpdateTime *time.Time UpdateTime *time.Time
} }

View File

@ -112,22 +112,6 @@ func (v *VoucherBiz) CmbProductQuery(ctx context.Context, productNo string) (rep
return err return err
} }
inputFormat := time.RFC3339
beginTime := ""
if wechatResp.AvailableBeginTime != nil {
// 解析开始时间
availableBeginTime, _ := time.Parse(inputFormat, *wechatResp.AvailableBeginTime)
beginTime = availableBeginTime.Format(time.DateTime)
}
endTime := ""
if wechatResp.AvailableEndTime != nil {
// 解析结束时间
availableEndTime, _ := time.Parse(inputFormat, *wechatResp.AvailableEndTime)
endTime = availableEndTime.Format(time.DateTime)
}
reps = &v1.CmbQueryProductReply{ reps = &v1.CmbQueryProductReply{
RespCode: vo.CmbResponseStatusSuccess.GetValue(), RespCode: vo.CmbResponseStatusSuccess.GetValue(),
RespMsg: "成功", RespMsg: "成功",
@ -137,28 +121,49 @@ func (v *VoucherBiz) CmbProductQuery(ctx context.Context, productNo string) (rep
MinAmount: "", MinAmount: "",
AvailableType: "", AvailableType: "",
AvailableDays: "", // 动态有效期天数 AvailableDays: "", // 动态有效期天数
StartTime: beginTime, StartTime: "",
EndTime: endTime, EndTime: "",
AvailableStock: "", AvailableStock: "",
Detail: *wechatResp.Description, Detail: *wechatResp.Description,
} }
inputFormat := time.RFC3339
if wechatResp.AvailableBeginTime != nil {
// 解析开始时间
availableBeginTime, _ := time.Parse(inputFormat, *wechatResp.AvailableBeginTime)
reps.StartTime = availableBeginTime.Format(time.DateTime)
}
if wechatResp.AvailableEndTime != nil {
// 解析结束时间
availableEndTime, _ := time.Parse(inputFormat, *wechatResp.AvailableEndTime)
reps.EndTime = availableEndTime.Format(time.DateTime)
}
if wechatResp.StartTime != nil {
s, _ := time.Parse(inputFormat, *wechatResp.StartTime)
reps.SaleStartTime = s.Format(time.DateTime)
}
if wechatResp.StopTime != nil {
e, _ := time.Parse(inputFormat, *wechatResp.StopTime)
reps.SaleEndTime = e.Format(time.DateTime)
}
reps.Amount = fmt.Sprintf("%d", *wechatResp.StockUseRule.FixedNormalCoupon.CouponAmount) reps.Amount = fmt.Sprintf("%d", *wechatResp.StockUseRule.FixedNormalCoupon.CouponAmount)
reps.MinAmount = fmt.Sprintf("%d", *wechatResp.StockUseRule.FixedNormalCoupon.TransactionMinimum) reps.MinAmount = fmt.Sprintf("%d", *wechatResp.StockUseRule.FixedNormalCoupon.TransactionMinimum)
availableStock := *wechatResp.StockUseRule.MaxCoupons - *wechatResp.DistributedCoupons availableStock := *wechatResp.StockUseRule.MaxCoupons - *wechatResp.DistributedCoupons
reps.AvailableStock = fmt.Sprintf("%d", availableStock) reps.AvailableStock = fmt.Sprintf("%d", availableStock)
if wechatResp.StartTime != nil { availableType, err := product.AvailableType.GetCmbAvailableType()
s, _ := time.Parse(inputFormat, *wechatResp.StartTime) if err != nil {
reps.SaleStartTime = s.Format(time.DateTime) return err
}
if wechatResp.StopTime != nil {
e, _ := time.Parse(inputFormat, *wechatResp.StopTime)
reps.SaleEndTime = e.Format(time.DateTime)
} }
reps.AvailableType = vo.CmbAvailableTypeFixed.GetValue() reps.AvailableType = availableType.GetValue()
reps.AvailableDays = fmt.Sprintf("%d", product.AvailableDays)
return nil return nil
}) })

View File

@ -2,11 +2,10 @@ package biz
import ( import (
"context" "context"
"errors"
"fmt" "fmt"
"github.com/go-kratos/kratos/v2/log" "github.com/go-kratos/kratos/v2/log"
"github.com/redis/go-redis/v9" "github.com/redis/go-redis/v9"
"gorm.io/gorm" err2 "voucher/api/err"
"voucher/internal/biz/bo" "voucher/internal/biz/bo"
"voucher/internal/biz/vo" "voucher/internal/biz/vo"
"voucher/internal/pkg/lock" "voucher/internal/pkg/lock"
@ -34,8 +33,8 @@ func (v *VoucherBiz) order(ctx context.Context, req *bo.OrderCreateReqBo, produc
// 真实发放 // 真实发放
voucherNo, err = v.WechatCpnRepo.Order(ctx, order) voucherNo, err = v.WechatCpnRepo.Order(ctx, order)
if err != nil { if err != nil {
if err2 := v.fail(ctx, order, err.Error()); err2 != nil { if err3 := v.fail(ctx, order, err.Error()); err3 != nil {
return nil, err2 return nil, err3
} }
return nil, err return nil, err
} }
@ -118,7 +117,7 @@ func (v *VoucherBiz) registerNotifyTag(ctx context.Context, stockCreatorMchID, s
} }
wechatNotifyTag, err := v.WechatNotifyRegisterTagRepo.GetByStockIdAndMchId(ctx, stockCreatorMchID, stockID) wechatNotifyTag, err := v.WechatNotifyRegisterTagRepo.GetByStockIdAndMchId(ctx, stockCreatorMchID, stockID)
if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) { if err != nil && !err2.IsDbNotFound(err) {
return err return err
} }

View File

@ -0,0 +1,46 @@
package vo
import "errors"
type AvailableType uint8
const (
AvailableTypeFixed AvailableType = iota + 1
AvailableTypeDynamic
)
var AvailableTypeMap = map[AvailableType]string{
AvailableTypeFixed: "固定有效期",
AvailableTypeDynamic: "动态有效期",
}
func (s AvailableType) GetText() string {
if t, ok := AvailableTypeMap[s]; ok {
return t
}
return "未知券领取类型"
}
func (s AvailableType) GetValue() uint8 {
return uint8(s)
}
func (s AvailableType) IsFixed() bool {
return s == AvailableTypeFixed
}
func (s AvailableType) IsDynamic() bool {
return s == AvailableTypeDynamic
}
var AvailableCmbTypeMap = map[AvailableType]CmbAvailableType{
AvailableTypeFixed: CmbAvailableTypeFixed,
AvailableTypeDynamic: CmbAvailableTypeDynamic,
}
func (s AvailableType) GetCmbAvailableType() (CmbAvailableType, error) {
if t, ok := AvailableCmbTypeMap[s]; ok {
return t, nil
}
return "", errors.New("未知券领取类型")
}

View File

@ -16,8 +16,8 @@ func (s CmbFuncName) GetValue() string {
type CmbStatus string type CmbStatus string
const ( const (
CmbStatusSuccess CmbStatus = "0" CmbStatusSuccess CmbStatus = "0" // 券可用
CmbStatusUse CmbStatus = "1" CmbStatusUse CmbStatus = "1" // 券使用
CmbStatusExpired CmbStatus = "2" // 券过期-待确认是否通知 CmbStatusExpired CmbStatus = "2" // 券过期-待确认是否通知
) )
@ -29,8 +29,8 @@ func (s CmbStatus) GetValue() string {
type CmbResponseStatus string type CmbResponseStatus string
const ( const (
CmbResponseStatusSuccess CmbResponseStatus = "1000" CmbResponseStatusSuccess CmbResponseStatus = "1000" // 响应成功
CmbResponseStatusFail CmbResponseStatus = "1001" CmbResponseStatusFail CmbResponseStatus = "1001" // 响应失败
) )
func (s CmbResponseStatus) GetValue() string { func (s CmbResponseStatus) GetValue() string {
@ -41,8 +41,8 @@ func (s CmbResponseStatus) GetValue() string {
type CmbAvailableType string type CmbAvailableType string
const ( const (
CmbAvailableTypeFixed CmbAvailableType = "0" CmbAvailableTypeFixed CmbAvailableType = "0" // 固定有效期
CmbAvailableTypeDynamic CmbAvailableType = "1" CmbAvailableTypeDynamic CmbAvailableType = "1" // 动态有效期
) )
func (s CmbAvailableType) GetValue() string { func (s CmbAvailableType) GetValue() string {

View File

@ -19,6 +19,8 @@ type Product struct {
BatchNo string `gorm:"column:batch_no;not null;comment:立减金批次号" json:"batch_no"` // 立减金批次号 BatchNo string `gorm:"column:batch_no;not null;comment:立减金批次号" json:"batch_no"` // 立减金批次号
MchId string `gorm:"column:mch_id;not null;comment:商户号,创建批次的商户号" json:"mch_id"` // 商户号,创建批次的商户号 MchId string `gorm:"column:mch_id;not null;comment:商户号,创建批次的商户号" json:"mch_id"` // 商户号,创建批次的商户号
Channel uint8 `gorm:"column:channel;not null;comment:1:微信 2:支付宝" json:"channel"` // 1:微信 2:支付宝 Channel uint8 `gorm:"column:channel;not null;comment:1:微信 2:支付宝" json:"channel"` // 1:微信 2:支付宝
AvailableType uint8 `gorm:"column:available_type;not null;comment:1:固定有效期 2:动态有效期" json:"available_type"`
AvailableDays uint32 `gorm:"column:available_days;not null;comment:领取后多少天内" json:"available_days"`
CreateTime *time.Time `gorm:"column:create_time;not null" json:"create_time"` CreateTime *time.Time `gorm:"column:create_time;not null" json:"create_time"`
UpdateTime *time.Time `gorm:"column:update_time" json:"update_time"` UpdateTime *time.Time `gorm:"column:update_time" json:"update_time"`
} }

View File

@ -257,3 +257,17 @@ func IsInSameNaturalMonth(startTime, endTime time.Time) bool {
expectedEndTime.Minute() == endTime.Minute() && expectedEndTime.Minute() == endTime.Minute() &&
expectedEndTime.Second() == endTime.Second() expectedEndTime.Second() == endTime.Second()
} }
func DaysBetween(start, end time.Time) (int, error) {
// 2. 统一到同一天的 0 点(避免时分秒干扰)
startDay := start.Truncate(24 * time.Hour)
endDay := end.Truncate(24 * time.Hour)
// 3. 计算天数(含结束日)
days := int(endDay.Sub(startDay).Hours() / 24)
if end.After(endDay) { // 结束时间非 0 点,加 1 天
days++
}
return days, nil
}

View File

@ -101,3 +101,34 @@ func TestRFC3339(t *testing.T) {
fmt.Printf("格式化后的开始时间: %s\n", formattedBeginTime) fmt.Printf("格式化后的开始时间: %s\n", formattedBeginTime)
fmt.Printf("格式化后的结束时间: %s\n", formattedEndTime) fmt.Printf("格式化后的结束时间: %s\n", formattedEndTime)
} }
func TestDaysBetween(t *testing.T) {
// 输入的时间字符串
availableBeginTimeStr := "2025-03-07T00:00:00+08:00"
availableEndTimeStr := "2025-06-05T23:59:59+08:00"
// 定义输入时间字符串的格式
inputFormat := time.RFC3339
// 解析开始时间
availableBeginTime, err := time.Parse(inputFormat, availableBeginTimeStr)
if err != nil {
fmt.Printf("解析开始时间出错: %v\n", err)
return
}
// 解析结束时间
availableEndTime, err := time.Parse(inputFormat, availableEndTimeStr)
if err != nil {
fmt.Printf("解析结束时间出错: %v\n", err)
return
}
days, err := DaysBetween(availableBeginTime, availableEndTime)
if err != nil {
fmt.Printf("解析结束时间出错: %v\n", err)
return
}
t.Log(days)
}