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) 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) } 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 = ?", vo.OrderStatusSuccess.GetValue()) 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) 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) 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()). 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) 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). 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("status IN (?)", []uint8{vo.OrderStatusSuccess.GetValue(), vo.OrderStatusUse.GetValue()}). Where("receive_success_time BETWEEN ? AND ?", req.StartTime, req.EndTime). FindInBatches(&results, 100, 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, } 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) } 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) } 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) 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 }