package repository import ( "context" "errors" "time" "gorm.io/gorm" "pay-bridge/internal/model" ) // PaymentMatchRepository 收款匹配数据访问 type PaymentMatchRepository struct { db *gorm.DB } func NewPaymentMatchRepository(db *gorm.DB) *PaymentMatchRepository { return &PaymentMatchRepository{db: db} } // GetAccountByNo 按账号查询子商户收款账户 func (r *PaymentMatchRepository) GetAccountByNo(ctx context.Context, accountNo string) (*model.SubMerchantAccount, error) { var acc model.SubMerchantAccount err := r.db.WithContext(ctx).Where("account_no = ? AND status = 1", accountNo).First(&acc).Error if errors.Is(err, gorm.ErrRecordNotFound) { return nil, nil } return &acc, err } // GetAccountByID 按 id 查询 func (r *PaymentMatchRepository) GetAccountByID(ctx context.Context, id uint64) (*model.SubMerchantAccount, error) { var acc model.SubMerchantAccount err := r.db.WithContext(ctx).Where("id = ?", id).First(&acc).Error if errors.Is(err, gorm.ErrRecordNotFound) { return nil, nil } return &acc, err } // ListAccountsByApp 查询应用下所有收款账户 func (r *PaymentMatchRepository) ListAccountsByApp(ctx context.Context, appID string) ([]*model.SubMerchantAccount, error) { var accs []*model.SubMerchantAccount err := r.db.WithContext(ctx).Where("app_id = ? AND status = 1", appID).Find(&accs).Error return accs, err } // CreateAccount 创建收款账户 func (r *PaymentMatchRepository) CreateAccount(ctx context.Context, acc *model.SubMerchantAccount) error { return r.db.WithContext(ctx).Create(acc).Error } // CreateMatchLog 创建匹配记录 func (r *PaymentMatchRepository) CreateMatchLog(ctx context.Context, log *model.PaymentMatchLog) error { return r.db.WithContext(ctx).Create(log).Error } // GetMatchLogByBillNo 按渠道流水号查询(幂等检查) func (r *PaymentMatchRepository) GetMatchLogByBillNo(ctx context.Context, channelBillNo string) (*model.PaymentMatchLog, error) { var log model.PaymentMatchLog err := r.db.WithContext(ctx).Where("channel_bill_no = ?", channelBillNo).First(&log).Error if errors.Is(err, gorm.ErrRecordNotFound) { return nil, nil } return &log, err } // UpdateMatchLog 更新匹配记录 func (r *PaymentMatchRepository) UpdateMatchLog(ctx context.Context, id uint64, updates map[string]any) error { return r.db.WithContext(ctx).Model(&model.PaymentMatchLog{}).Where("id = ?", id).Updates(updates).Error } // ListPendingManual 查询待人工确认的记录 func (r *PaymentMatchRepository) ListPendingManual(ctx context.Context, appID string, limit, offset int) ([]*model.PaymentMatchLog, error) { var logs []*model.PaymentMatchLog err := r.db.WithContext(ctx). Joins("JOIN sub_merchant_account ON sub_merchant_account.id = payment_match_log.account_id"). Where("sub_merchant_account.app_id = ? AND payment_match_log.match_status = ?", appID, model.MatchStatusPendingManual). Order("payment_match_log.created_at DESC"). Limit(limit).Offset(offset). Find(&logs).Error return logs, err } // ListPayingByAmount 按金额查询指定时间窗口内的待支付订单(用于收款匹配降级) func (r *PaymentMatchRepository) ListPayingByAmount(ctx context.Context, appID string, amount int64, window time.Duration) ([]*model.TradeOrder, error) { var orders []*model.TradeOrder since := time.Now().Add(-window) err := r.db.WithContext(ctx). Where("app_id = ? AND amount = ? AND status = ? AND created_at >= ?", appID, amount, model.TradeStatusPaying, since). Find(&orders).Error return orders, err }