解耦订单和申诉模块外部依赖
This commit is contained in:
@@ -204,24 +204,27 @@ type flowServices struct {
|
|||||||
|
|
||||||
func newFlowServices(db *gorm.DB) flowServices {
|
func newFlowServices(db *gorm.DB) flowServices {
|
||||||
listingRepo := listing.NewRepository(db)
|
listingRepo := listing.NewRepository(db)
|
||||||
orderRepo := order.NewRepository(db)
|
|
||||||
walletRepo := wallet.NewRepository(db)
|
walletRepo := wallet.NewRepository(db)
|
||||||
configRepo := paymentconfig.NewRepository(db, &paymentconfig.MockEncryptor{})
|
configRepo := paymentconfig.NewRepository(db, &paymentconfig.MockEncryptor{})
|
||||||
paymentRepo := payment.NewRepository(db, configRepo, orderRepo, walletRepo)
|
var paymentRepo *payment.Repository
|
||||||
disputeRepo := dispute.NewRepository(db)
|
orderRepo := order.NewRepository(db, order.Dependencies{
|
||||||
orderRepo.SetRefundFunc(func(ctx context.Context, orderID uint64, refundAmountCent int64, bizType string, remark string) (string, error) {
|
RefundStarter: order.RefundStarterFunc(func(ctx context.Context, orderID uint64, refundAmountCent int64, bizType string, remark string) (string, error) {
|
||||||
refund, err := paymentRepo.StartRefund(ctx, orderID, refundAmountCent, bizType, remark)
|
refund, err := paymentRepo.StartRefund(ctx, orderID, refundAmountCent, bizType, remark)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
return refund.Status, nil
|
return refund.Status, nil
|
||||||
|
}),
|
||||||
})
|
})
|
||||||
disputeRepo.SetRefundFunc(func(ctx context.Context, orderID uint64, refundAmountCent int64, bizType string, remark string) (string, error) {
|
paymentRepo = payment.NewRepository(db, configRepo, orderRepo, walletRepo)
|
||||||
refund, err := paymentRepo.StartRefund(ctx, orderID, refundAmountCent, bizType, remark)
|
disputeRepo := dispute.NewRepository(db, dispute.Dependencies{
|
||||||
if err != nil {
|
RefundStarter: dispute.RefundStarterFunc(func(ctx context.Context, orderID uint64, refundAmountCent int64, bizType string, remark string) (string, error) {
|
||||||
return "", err
|
refund, err := paymentRepo.StartRefund(ctx, orderID, refundAmountCent, bizType, remark)
|
||||||
}
|
if err != nil {
|
||||||
return refund.Status, nil
|
return "", err
|
||||||
|
}
|
||||||
|
return refund.Status, nil
|
||||||
|
}),
|
||||||
})
|
})
|
||||||
|
|
||||||
return flowServices{
|
return flowServices{
|
||||||
|
|||||||
@@ -256,7 +256,7 @@ func (r *Repository) prepareRefund(order *model.RentalOrder, amountCent int64, b
|
|||||||
if amountCent <= 0 {
|
if amountCent <= 0 {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
if r.refundFunc == nil {
|
if r.refundStarter == nil {
|
||||||
return nil, ErrDependencyUnavailable
|
return nil, ErrDependencyUnavailable
|
||||||
}
|
}
|
||||||
order.RefundStatus = "pending"
|
order.RefundStatus = "pending"
|
||||||
@@ -271,10 +271,10 @@ func (r *Repository) prepareRefund(order *model.RentalOrder, amountCent int64, b
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r *Repository) startRefundBestEffort(ctx context.Context, action *refundAction) {
|
func (r *Repository) startRefundBestEffort(ctx context.Context, action *refundAction) {
|
||||||
if action == nil || r.refundFunc == nil {
|
if action == nil || r.refundStarter == nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
_, _ = r.refundFunc(ctx, action.OrderID, action.RefundAmountCent, action.BizType, action.Remark)
|
_, _ = r.refundStarter.StartRefund(ctx, action.OrderID, action.RefundAmountCent, action.BizType, action.Remark)
|
||||||
}
|
}
|
||||||
|
|
||||||
func renterFrozenBalance(tx *gorm.DB, renterID uint64) (int64, error) {
|
func renterFrozenBalance(tx *gorm.DB, renterID uint64) (int64, error) {
|
||||||
|
|||||||
@@ -8,14 +8,24 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type Repository struct {
|
type Repository struct {
|
||||||
db *gorm.DB
|
db *gorm.DB
|
||||||
refundFunc RefundFunc
|
refundStarter RefundStarter
|
||||||
}
|
}
|
||||||
|
|
||||||
// RefundFunc 由 payment 模块注入,避免 dispute 与 payment 形成循环依赖。
|
// RefundStarter 由支付模块适配实现,避免 dispute 直接依赖 payment。
|
||||||
|
type RefundStarter interface {
|
||||||
|
StartRefund(ctx context.Context, orderID uint64, refundAmountCent int64, bizType string, remark string) (status string, err error)
|
||||||
|
}
|
||||||
|
|
||||||
// RefundFunc 由 payment 模块注入,避免 dispute 与 payment 形成循环依赖。
|
type RefundStarterFunc func(ctx context.Context, orderID uint64, refundAmountCent int64, bizType string, remark string) (status string, err error)
|
||||||
type RefundFunc func(ctx context.Context, orderID uint64, refundAmountCent int64, bizType string, remark string) (status string, err error)
|
|
||||||
|
func (fn RefundStarterFunc) StartRefund(ctx context.Context, orderID uint64, refundAmountCent int64, bizType string, remark string) (string, error) {
|
||||||
|
return fn(ctx, orderID, refundAmountCent, bizType, remark)
|
||||||
|
}
|
||||||
|
|
||||||
|
type Dependencies struct {
|
||||||
|
RefundStarter RefundStarter
|
||||||
|
}
|
||||||
|
|
||||||
type refundAction struct {
|
type refundAction struct {
|
||||||
OrderID uint64
|
OrderID uint64
|
||||||
@@ -24,12 +34,12 @@ type refundAction struct {
|
|||||||
Remark string
|
Remark string
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewRepository(db *gorm.DB) *Repository {
|
func NewRepository(db *gorm.DB, deps ...Dependencies) *Repository {
|
||||||
return &Repository{db: db}
|
repo := &Repository{db: db}
|
||||||
}
|
if len(deps) > 0 {
|
||||||
|
repo.refundStarter = deps[0].RefundStarter
|
||||||
func (r *Repository) SetRefundFunc(fn RefundFunc) {
|
}
|
||||||
r.refundFunc = fn
|
return repo
|
||||||
}
|
}
|
||||||
|
|
||||||
func IsNotFound(err error) bool {
|
func IsNotFound(err error) bool {
|
||||||
|
|||||||
@@ -172,14 +172,14 @@ func (r *Repository) AdminRefund(ctx context.Context, orderID uint64) (*RefundSt
|
|||||||
if order.RefundStatus == refundStatusRefunded {
|
if order.RefundStatus == refundStatusRefunded {
|
||||||
return r.buildRefundStatusDTO(&order), nil
|
return r.buildRefundStatusDTO(&order), nil
|
||||||
}
|
}
|
||||||
if r.refundFunc == nil {
|
if r.refundStarter == nil {
|
||||||
return nil, ErrDependencyUnavailable
|
return nil, ErrDependencyUnavailable
|
||||||
}
|
}
|
||||||
totalCent := order.RentAmountCent + order.DepositAmountCent
|
totalCent := order.RentAmountCent + order.DepositAmountCent
|
||||||
if totalCent <= 0 {
|
if totalCent <= 0 {
|
||||||
return nil, ErrInvalidCheckoutAmount
|
return nil, ErrInvalidCheckoutAmount
|
||||||
}
|
}
|
||||||
status, err := r.refundFunc(ctx, orderID, totalCent, refundBizAdmin, "后台人工退款")
|
status, err := r.refundStarter.StartRefund(ctx, orderID, totalCent, refundBizAdmin, "后台人工退款")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -195,8 +195,8 @@ func (r *Repository) ConfirmPaidFromChannel(ctx context.Context, orderID uint64,
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if newConvID > 0 && r.chatRepo != nil {
|
if newConvID > 0 && r.chatNotifier != nil {
|
||||||
r.chatRepo.NotifyNewConversation(newConvID)
|
r.chatNotifier.NotifyNewConversation(newConvID)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ func (r *Repository) prepareRefund(order *model.RentalOrder, amountCent int64, b
|
|||||||
if amountCent <= 0 {
|
if amountCent <= 0 {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
if r.refundFunc == nil {
|
if r.refundStarter == nil {
|
||||||
return nil, ErrDependencyUnavailable
|
return nil, ErrDependencyUnavailable
|
||||||
}
|
}
|
||||||
order.RefundStatus = refundStatusPending
|
order.RefundStatus = refundStatusPending
|
||||||
@@ -26,10 +26,10 @@ func (r *Repository) prepareRefund(order *model.RentalOrder, amountCent int64, b
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r *Repository) startRefundBestEffort(ctx context.Context, action *refundAction) {
|
func (r *Repository) startRefundBestEffort(ctx context.Context, action *refundAction) {
|
||||||
if action == nil || r.refundFunc == nil {
|
if action == nil || r.refundStarter == nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if _, err := r.refundFunc(ctx, action.OrderID, action.RefundAmountCent, action.BizType, action.Remark); err != nil {
|
if _, err := r.refundStarter.StartRefund(ctx, action.OrderID, action.RefundAmountCent, action.BizType, action.Remark); err != nil {
|
||||||
log.Printf("[order] start refund failed order_id=%d biz_type=%s amount_cent=%d err=%v", action.OrderID, action.BizType, action.RefundAmountCent, err)
|
log.Printf("[order] start refund failed order_id=%d biz_type=%s amount_cent=%d err=%v", action.OrderID, action.BizType, action.RefundAmountCent, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,13 +3,29 @@ package order
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
"hfb_sys/backend/internal/modules/chat"
|
|
||||||
|
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
)
|
)
|
||||||
|
|
||||||
// RefundFunc 由 payment 模块注入,避免 order 与 payment 形成循环依赖。
|
// RefundStarter 由支付模块适配实现,避免 order 直接依赖 payment。
|
||||||
type RefundFunc func(ctx context.Context, orderID uint64, refundAmountCent int64, bizType string, remark string) (status string, err error)
|
type RefundStarter interface {
|
||||||
|
StartRefund(ctx context.Context, orderID uint64, refundAmountCent int64, bizType string, remark string) (status string, err error)
|
||||||
|
}
|
||||||
|
|
||||||
|
type RefundStarterFunc func(ctx context.Context, orderID uint64, refundAmountCent int64, bizType string, remark string) (status string, err error)
|
||||||
|
|
||||||
|
func (fn RefundStarterFunc) StartRefund(ctx context.Context, orderID uint64, refundAmountCent int64, bizType string, remark string) (string, error) {
|
||||||
|
return fn(ctx, orderID, refundAmountCent, bizType, remark)
|
||||||
|
}
|
||||||
|
|
||||||
|
type OrderChatNotifier interface {
|
||||||
|
NotifyNewConversation(conversationID uint64)
|
||||||
|
}
|
||||||
|
|
||||||
|
type Dependencies struct {
|
||||||
|
ChatNotifier OrderChatNotifier
|
||||||
|
RefundStarter RefundStarter
|
||||||
|
}
|
||||||
|
|
||||||
type refundAction struct {
|
type refundAction struct {
|
||||||
OrderID uint64
|
OrderID uint64
|
||||||
RefundAmountCent int64
|
RefundAmountCent int64
|
||||||
@@ -18,21 +34,18 @@ type refundAction struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type Repository struct {
|
type Repository struct {
|
||||||
db *gorm.DB
|
db *gorm.DB
|
||||||
chatRepo *chat.Repository
|
chatNotifier OrderChatNotifier
|
||||||
refundFunc RefundFunc
|
refundStarter RefundStarter
|
||||||
}
|
}
|
||||||
|
|
||||||
const defaultPendingPaymentTimeoutMinutes = 15
|
const defaultPendingPaymentTimeoutMinutes = 15
|
||||||
|
|
||||||
func NewRepository(db *gorm.DB) *Repository {
|
func NewRepository(db *gorm.DB, deps ...Dependencies) *Repository {
|
||||||
return &Repository{db: db}
|
repo := &Repository{db: db}
|
||||||
}
|
if len(deps) > 0 {
|
||||||
|
repo.chatNotifier = deps[0].ChatNotifier
|
||||||
func (r *Repository) SetChatRepo(cr *chat.Repository) {
|
repo.refundStarter = deps[0].RefundStarter
|
||||||
r.chatRepo = cr
|
}
|
||||||
}
|
return repo
|
||||||
|
|
||||||
func (r *Repository) SetRefundFunc(fn RefundFunc) {
|
|
||||||
r.refundFunc = fn
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -109,9 +109,30 @@ func New(cfg config.Config, deps Dependencies, logger *zap.Logger) *gin.Engine {
|
|||||||
if deps.DB != nil {
|
if deps.DB != nil {
|
||||||
listingRepo = listing.NewRepository(deps.DB)
|
listingRepo = listing.NewRepository(deps.DB)
|
||||||
}
|
}
|
||||||
|
var chatHub *chathub.Hub
|
||||||
|
if deps.DB != nil {
|
||||||
|
chatHub = chathub.NewHub(deps.DB)
|
||||||
|
}
|
||||||
|
var chatRepo *chat.Repository
|
||||||
|
if deps.DB != nil {
|
||||||
|
chatRepo = chat.NewRepository(deps.DB, chatHub)
|
||||||
|
}
|
||||||
|
var paymentRepo *payment.Repository
|
||||||
var orderRepo *order.Repository
|
var orderRepo *order.Repository
|
||||||
if deps.DB != nil {
|
if deps.DB != nil {
|
||||||
orderRepo = order.NewRepository(deps.DB)
|
orderRepo = order.NewRepository(deps.DB, order.Dependencies{
|
||||||
|
ChatNotifier: chatRepo,
|
||||||
|
RefundStarter: order.RefundStarterFunc(func(ctx context.Context, orderID uint64, refundAmountCent int64, bizType string, remark string) (string, error) {
|
||||||
|
if paymentRepo == nil {
|
||||||
|
return "", order.ErrDependencyUnavailable
|
||||||
|
}
|
||||||
|
dto, err := paymentRepo.StartRefund(ctx, orderID, refundAmountCent, bizType, remark)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return dto.Status, nil
|
||||||
|
}),
|
||||||
|
})
|
||||||
}
|
}
|
||||||
orderService := order.NewService(orderRepo)
|
orderService := order.NewService(orderRepo)
|
||||||
orderHandler := order.NewHandler(orderService)
|
orderHandler := order.NewHandler(orderService)
|
||||||
@@ -156,56 +177,36 @@ func New(cfg config.Config, deps Dependencies, logger *zap.Logger) *gin.Engine {
|
|||||||
paymentConfigHandler = paymentconfig.NewHandler(paymentConfigService)
|
paymentConfigHandler = paymentconfig.NewHandler(paymentConfigService)
|
||||||
}
|
}
|
||||||
|
|
||||||
var paymentRepo *payment.Repository
|
|
||||||
if deps.DB != nil {
|
if deps.DB != nil {
|
||||||
paymentRepo = payment.NewRepository(deps.DB, paymentConfigRepo, orderRepo, walletRepo)
|
paymentRepo = payment.NewRepository(deps.DB, paymentConfigRepo, orderRepo, walletRepo)
|
||||||
}
|
}
|
||||||
paymentService := payment.NewService(paymentRepo, cfg.AppEnv)
|
paymentService := payment.NewService(paymentRepo, cfg.AppEnv)
|
||||||
paymentHandler := payment.NewHandler(paymentService)
|
paymentHandler := payment.NewHandler(paymentService)
|
||||||
// Inject refund function into order repo to avoid circular dependency
|
|
||||||
if orderRepo != nil && paymentRepo != nil {
|
|
||||||
orderRepo.SetRefundFunc(func(ctx context.Context, orderID uint64, refundAmountCent int64, bizType string, remark string) (string, error) {
|
|
||||||
dto, err := paymentRepo.StartRefund(ctx, orderID, refundAmountCent, bizType, remark)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
return dto.Status, nil
|
|
||||||
})
|
|
||||||
}
|
|
||||||
var notificationRepo *notification.Repository
|
var notificationRepo *notification.Repository
|
||||||
if deps.DB != nil {
|
if deps.DB != nil {
|
||||||
notificationRepo = notification.NewRepository(deps.DB)
|
notificationRepo = notification.NewRepository(deps.DB)
|
||||||
}
|
}
|
||||||
notificationService := notification.NewService(notificationRepo)
|
notificationService := notification.NewService(notificationRepo)
|
||||||
notificationHandler := notification.NewHandler(notificationService)
|
notificationHandler := notification.NewHandler(notificationService)
|
||||||
var chatHub *chathub.Hub
|
|
||||||
if deps.DB != nil {
|
|
||||||
chatHub = chathub.NewHub(deps.DB)
|
|
||||||
}
|
|
||||||
var chatRepo *chat.Repository
|
|
||||||
if deps.DB != nil {
|
|
||||||
chatRepo = chat.NewRepository(deps.DB, chatHub)
|
|
||||||
}
|
|
||||||
chatService := chat.NewService(chatRepo)
|
chatService := chat.NewService(chatRepo)
|
||||||
chatHandler := chat.NewHandler(chatService)
|
chatHandler := chat.NewHandler(chatService)
|
||||||
var chatHubHandler *chathub.Handler
|
var chatHubHandler *chathub.Handler
|
||||||
if chatHub != nil {
|
if chatHub != nil {
|
||||||
chatHubHandler = chathub.NewHandler(chatHub)
|
chatHubHandler = chathub.NewHandler(chatHub)
|
||||||
}
|
}
|
||||||
if orderRepo != nil && chatRepo != nil {
|
|
||||||
orderRepo.SetChatRepo(chatRepo)
|
|
||||||
}
|
|
||||||
var disputeRepo *dispute.Repository
|
var disputeRepo *dispute.Repository
|
||||||
if deps.DB != nil {
|
if deps.DB != nil {
|
||||||
disputeRepo = dispute.NewRepository(deps.DB)
|
disputeRepo = dispute.NewRepository(deps.DB, dispute.Dependencies{
|
||||||
}
|
RefundStarter: dispute.RefundStarterFunc(func(ctx context.Context, orderID uint64, refundAmountCent int64, bizType string, remark string) (string, error) {
|
||||||
if disputeRepo != nil && paymentRepo != nil {
|
if paymentRepo == nil {
|
||||||
disputeRepo.SetRefundFunc(func(ctx context.Context, orderID uint64, refundAmountCent int64, bizType string, remark string) (string, error) {
|
return "", dispute.ErrDependencyUnavailable
|
||||||
dto, err := paymentRepo.StartRefund(ctx, orderID, refundAmountCent, bizType, remark)
|
}
|
||||||
if err != nil {
|
dto, err := paymentRepo.StartRefund(ctx, orderID, refundAmountCent, bizType, remark)
|
||||||
return "", err
|
if err != nil {
|
||||||
}
|
return "", err
|
||||||
return dto.Status, nil
|
}
|
||||||
|
return dto.Status, nil
|
||||||
|
}),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
disputeService := dispute.NewService(disputeRepo)
|
disputeService := dispute.NewService(disputeRepo)
|
||||||
|
|||||||
Reference in New Issue
Block a user