voucher/internal/data/repoimpl/order.go

539 lines
12 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package repoimpl
import (
"context"
"errors"
"fmt"
"gorm.io/gorm"
"time"
"unicode/utf8"
err2 "voucher/api/err"
"voucher/internal/biz/bo"
"voucher/internal/biz/do"
"voucher/internal/biz/repo"
"voucher/internal/biz/vo"
"voucher/internal/data"
"voucher/internal/data/model"
)
// OrderRepoImpl .
type OrderRepoImpl struct {
Base[model.Order, bo.OrderBo]
db *data.Db
}
// NewOrderRepoImpl .
func NewOrderRepoImpl(db *data.Db) repo.OrderRepo {
return &OrderRepoImpl{db: db}
}
func (p *OrderRepoImpl) DB(ctx context.Context) *gorm.DB {
return p.db.DB(ctx).Model(model.Order{})
}
func (p *OrderRepoImpl) SpecifyFindInBatches(ctx context.Context, req *bo.FindInBatchesBo, fun func(ctx context.Context, rows []*bo.OrderBo) error) error {
tx := p.DB(ctx).Where("activity_id = ''")
if req.ProductNo != "" {
tx = tx.Where("product_no = ?", req.ProductNo)
}
if req.StartTime != "" && req.EndTime != "" {
tx = tx.Where("receive_success_time BETWEEN ? AND ?", req.StartTime, req.EndTime)
}
if req.OrderNos != nil {
tx = tx.Where("order_no IN (?)", req.OrderNos)
}
if req.OutBizNos != nil {
tx = tx.Where("out_biz_no IN (?)", req.OutBizNos)
}
if req.VoucherNos != nil {
tx = tx.Where("voucher_no IN (?)", req.VoucherNos)
}
tx.Order("receive_success_time asc") // 显式清除排序,移除默认的 ORDER BY
var results = make([]*model.Order, 0)
result := tx.FindInBatches(&results, 100, func(tx *gorm.DB, batch int) error {
return fun(ctx, p.ToBos(results))
})
if result.Error != nil {
return result.Error
}
return nil
}
func (p *OrderRepoImpl) FinSucByStockIdInBatches(ctx context.Context, req *do.WechatQuery, fun func(ctx context.Context, rows []*bo.OrderBo) error) error {
tx := p.DB(ctx).
Where("`status` in (?)", []uint8{vo.OrderStatusSuccess.GetValue(), vo.OrderStatusUse.GetValue(), vo.OrderStatusExpired.GetValue()}).
Where("activity_id = ''")
if req.ProductNo != "" {
tx = tx.Where("product_no = ?", req.ProductNo)
}
if req.BatchNo != "" {
tx = tx.Where("batch_no = ?", req.BatchNo)
}
if req.StartTime != "" {
tx = tx.Where("receive_success_time > ?", req.StartTime)
}
if req.EndTime != "" {
tx = tx.Where("receive_success_time <= ?", req.EndTime)
}
if req.OrderNo != "" {
tx = tx.Where("order_no = ?", req.OrderNo)
}
var results = make([]*model.Order, 0)
tx.Order("receive_success_time asc") // 显式清除排序,移除默认的 ORDER BY
result := tx.FindInBatches(&results, 1000, func(tx *gorm.DB, batch int) error {
return fun(ctx, p.ToBos(results))
})
if result.Error != nil {
return result.Error
}
return nil
}
func (p *OrderRepoImpl) FinUsedInBatches(ctx context.Context, req *do.WechatUsedQuery, fun func(ctx context.Context, rows []*bo.OrderBo) error) error {
var results = make([]*model.Order, 0)
tx := p.DB(ctx).
Where("`status` = ?", vo.OrderStatusUse.GetValue()).
Where("activity_id = ''")
if req.StartTime != "" {
tx = tx.Where("last_use_time > ?", req.StartTime)
}
if req.EndTime != "" {
tx = tx.Where("last_use_time <= ?", req.EndTime)
}
if req.ProductNo != "" {
tx = tx.Where("product_no = ?", req.ProductNo)
}
if req.BatchNo != "" {
tx = tx.Where("batch_no = ?", req.ProductNo)
}
if req.OrderNo != "" {
tx = tx.Where("order_no = ?", req.OrderNo)
}
// 显式清除排序,移除默认的 ORDER BY
result := tx.Order("last_use_time asc").FindInBatches(&results, 500, func(tx *gorm.DB, batch int) error {
return fun(ctx, p.ToBos(results))
})
if result.Error != nil {
return result.Error
}
return nil
}
func (p *OrderRepoImpl) FinFailByStockIdInBatches(ctx context.Context, batchNo string, fun func(ctx context.Context, rows []*bo.OrderBo) error) error {
var results = make([]*model.Order, 0)
result := p.DB(ctx).
Where("batch_no = ?", batchNo).
Where("`status` = ?", vo.OrderStatusFail.GetValue()).
Order("receive_success_time asc"). // 显式清除排序,移除默认的 ORDER BY
FindInBatches(&results, 200, func(tx *gorm.DB, batch int) error {
return fun(ctx, p.ToBos(results))
})
if result.Error != nil {
return result.Error
}
return nil
}
func (p *OrderRepoImpl) FindIngInBatches(ctx context.Context, fun func(ctx context.Context, rows []*bo.OrderBo) error) error {
var results = make([]*model.Order, 0)
result := p.DB(ctx).
Where("`status` = ?", vo.OrderStatusIng.GetValue()).
Limit(20).
Order("receive_success_time asc"). // 显式清除排序,移除默认的 ORDER BY
FindInBatches(&results, 10, func(tx *gorm.DB, batch int) error {
return fun(ctx, p.ToBos(results))
})
if result.Error != nil {
return result.Error
}
return nil
}
func (p *OrderRepoImpl) FindInBatches(ctx context.Context, req *bo.FindInBatchesUseBo, fun func(ctx context.Context, rows []*bo.OrderBo) error) error {
var results = make([]*model.Order, 0)
result := p.DB(ctx).
Where("activity_id = ''").
Where("`status` IN (?)", []uint8{vo.OrderStatusSuccess.GetValue(), vo.OrderStatusUse.GetValue()}).
Where("receive_success_time BETWEEN ? AND ?", req.StartTime, req.EndTime).
Order("receive_success_time asc"). // 显式清除排序,移除默认的 ORDER BY
FindInBatches(&results, 1000, func(tx *gorm.DB, batch int) error {
// tx.RowsAffected 提供当前批处理中记录的计数the count of records in the current batch
// 'batch' 变量表示当前批号the current batch number
// 返回 error 将阻止更多的批处理
return fun(ctx, p.ToBos(results))
})
if result.Error != nil {
return result.Error
}
return nil
}
func (p *OrderRepoImpl) Create(ctx context.Context, req *bo.OrderBo) (*bo.OrderBo, error) {
now := time.Now()
info := &model.Order{
OrderNo: req.OrderNo,
OutBizNo: req.OutBizNo,
ProductNo: req.ProductNo,
BatchNo: req.BatchNo,
Account: req.Account,
AccountType: req.AccountType.GetValue(),
Status: req.Status.GetValue(),
Type: req.Type.GetValue(),
AppID: req.AppID,
MerchantNo: req.MerchantNo,
Channel: req.Channel.GetValue(),
NotifyUrl: req.NotifyUrl,
Attach: req.Attach,
CreateTime: &now,
UpdateTime: &now,
ActivityId: req.ActivityId,
}
tx := p.DB(ctx).Create(info)
if tx.Error != nil {
return nil, fmt.Errorf("create db fail %w", tx.Error)
}
return p.ToBo(info), nil
}
func (p *OrderRepoImpl) GetByOutBizNo(ctx context.Context, t vo.OrderType, outBizNo string) (*bo.OrderBo, error) {
info := &model.Order{}
tx := p.DB(ctx).Where(model.Order{Type: t.GetValue(), OutBizNo: outBizNo}).First(&info)
if tx.Error != nil {
if errors.Is(tx.Error, gorm.ErrRecordNotFound) {
return nil, err2.ErrorDbNotFound("订单数据不存在")
}
return nil, fmt.Errorf("order db fail %w", tx.Error)
}
if tx.RowsAffected == 0 {
return nil, err2.ErrorDbNotFound("订单数据不存在")
}
return p.ToBo(info), nil
}
func (p *OrderRepoImpl) GetByID(ctx context.Context, id uint64) (*bo.OrderBo, error) {
info := &model.Order{}
tx := p.DB(ctx).Where(model.Order{ID: id}).First(&info)
if tx.Error != nil {
if errors.Is(tx.Error, gorm.ErrRecordNotFound) {
return nil, err2.ErrorDbNotFound("订单数据不存在")
}
return nil, fmt.Errorf("order db fail %w", tx.Error)
}
if tx.RowsAffected == 0 {
return nil, err2.ErrorDbNotFound("订单数据不存在")
}
return p.ToBo(info), nil
}
func (p *OrderRepoImpl) GetByOrderNo(ctx context.Context, orderNo string) (*bo.OrderBo, error) {
info := &model.Order{}
tx := p.DB(ctx).Where(model.Order{OrderNo: orderNo}).First(&info)
if tx.Error != nil {
if errors.Is(tx.Error, gorm.ErrRecordNotFound) {
return nil, err2.ErrorDbNotFound("订单数据不存在")
}
return nil, fmt.Errorf("order db fail %w", tx.Error)
}
if tx.RowsAffected == 0 {
return nil, err2.ErrorDbNotFound("订单数据不存在")
}
return p.ToBo(info), nil
}
func (p *OrderRepoImpl) GetByCouponId(ctx context.Context, merchantNo, batchNo, voucherNo string) (*bo.OrderBo, error) {
info := &model.Order{}
tx := p.DB(ctx).Where(model.Order{MerchantNo: merchantNo, BatchNo: batchNo, VoucherNo: voucherNo}).First(&info)
if tx.Error != nil {
return nil, tx.Error
}
if tx.RowsAffected == 0 {
return nil, gorm.ErrRecordNotFound
}
return p.ToBo(info), nil
}
func (this *OrderRepoImpl) GetByTransactionId(ctx context.Context, stockCreatorMchId, stockID, transactionId string) (*bo.OrderBo, error) {
row := &model.Order{}
tx := this.DB(ctx).Where(model.Order{MerchantNo: stockCreatorMchId, BatchNo: stockID, TransactionId: transactionId}).First(&row)
if tx.Error != nil {
return nil, tx.Error
}
if tx.RowsAffected == 0 {
return nil, gorm.ErrRecordNotFound
}
return this.ToBo(row), nil
}
func (p *OrderRepoImpl) Ing(ctx context.Context, id uint64) error {
now := time.Now()
tx := p.DB(ctx).
Where(model.Order{
ID: id,
Status: vo.OrderStatusWait.GetValue(),
}).
Updates(model.Order{
Status: vo.OrderStatusIng.GetValue(),
UpdateTime: &now,
})
if tx.Error != nil {
return fmt.Errorf("db fail %w", tx.Error)
}
return nil
}
func (p *OrderRepoImpl) Success(ctx context.Context, id uint64, voucherNo string) error {
now := time.Now()
tx := p.DB(ctx).
Where(model.Order{
ID: id,
}).
Updates(model.Order{
Status: vo.OrderStatusSuccess.GetValue(),
VoucherNo: voucherNo,
Remark: "成功",
ReceiveSuccessTime: &now,
UpdateTime: &now,
})
if tx.Error != nil {
return fmt.Errorf("update db fail %w", tx.Error)
}
if tx.RowsAffected == 0 {
return fmt.Errorf("no rows affected")
}
return nil
}
func (p *OrderRepoImpl) Available(ctx context.Context, id uint64) error {
now := time.Now()
tx := p.DB(ctx).
Where(model.Order{
ID: id,
Status: vo.OrderStatusUse.GetValue(),
}).
Updates(model.Order{
Status: vo.OrderStatusSuccess.GetValue(),
Remark: "重置为成功,领取成功时间重置",
ReceiveSuccessTime: &now, // 领取成功时间重置
UpdateTime: &now,
})
if tx.Error != nil {
return fmt.Errorf("update db fail %w", tx.Error)
}
return nil
}
func (p *OrderRepoImpl) Fail(ctx context.Context, id uint64, remark string) error {
now := time.Now()
if utf8.RuneCountInString(remark) > 100 {
runes := []rune(remark)
if len(runes) > 100 {
remark = string(runes[:100])
}
}
tx := p.DB(ctx).
Where(model.Order{
ID: id,
}).
Updates(model.Order{
Status: vo.OrderStatusFail.GetValue(),
Remark: remark,
UpdateTime: &now,
})
if tx.Error != nil {
return fmt.Errorf("update db fail %w", tx.Error)
}
if tx.RowsAffected == 0 {
return fmt.Errorf("no rows affected")
}
return nil
}
func (p *OrderRepoImpl) Used(ctx context.Context, id uint64) error {
now := time.Now()
tx := p.DB(ctx).
Where(model.Order{
ID: id,
}).
Updates(model.Order{
Status: vo.OrderStatusUse.GetValue(),
Remark: "核销",
LastUseTime: &now,
UpdateTime: &now,
})
if tx.Error != nil {
return fmt.Errorf("update db fail %w", tx.Error)
}
return nil
}
func (p *OrderRepoImpl) MultiLastUsed(ctx context.Context, id uint64, lastUseTime time.Time) error {
now := time.Now()
tx := p.DB(ctx).
Where(model.Order{
ID: id,
}).
Updates(model.Order{
Remark: "核销",
Status: vo.OrderStatusSuccess.GetValue(),
LastUseTime: &lastUseTime,
UpdateTime: &now,
})
if tx.Error != nil {
return fmt.Errorf("update db fail %w", tx.Error)
}
return nil
}
func (p *OrderRepoImpl) MultiOverUsed(ctx context.Context, id uint64, lastUseTime time.Time, remark string) error {
now := time.Now()
tx := p.DB(ctx).
Where(model.Order{
ID: id,
}).
Updates(model.Order{
Status: vo.OrderStatusUse.GetValue(),
Remark: remark,
LastUseTime: &lastUseTime,
UpdateTime: &now,
})
if tx.Error != nil {
return fmt.Errorf("update db fail %w", tx.Error)
}
return nil
}
func (p *OrderRepoImpl) NotifyUsed(ctx context.Context, id uint64, transactionId string) error {
now := time.Now()
tx := p.DB(ctx).
Where(model.Order{
ID: id,
}).
Updates(model.Order{
Status: vo.OrderStatusUse.GetValue(),
TransactionId: transactionId,
Remark: "微信回调核销",
LastUseTime: &now,
UpdateTime: &now,
})
if tx.Error != nil {
return fmt.Errorf("update db fail %w", tx.Error)
}
return nil
}
func (p *OrderRepoImpl) Expired(ctx context.Context, id uint64) error {
now := time.Now()
tx := p.DB(ctx).
Where(model.Order{
ID: id,
}).
Updates(model.Order{
Status: vo.OrderStatusExpired.GetValue(),
Remark: "过期",
UpdateTime: &now,
})
if tx.Error != nil {
return fmt.Errorf("update db fail %w", tx.Error)
}
return nil
}