Files
yml2213 e024319860 feat(distribution): 分销站点消息中心与钱包提现多租户独立分支隔离
- 新增 000070 数据库迁移:支持 chat_conversations、wallet_accounts、wallet_ledger、withdrawal_requests 按 distribution_site_id 隔离
- 消息中心:会话列表、未读数统计、站点专属客服及订单群聊与主站实现双向完全隔离
- 资金账户与提现:独立按 (user_id, distribution_site_id) 建账,分销订单自动结算至对应分站钱包,提现与流水相互独立
- 前台界面:Axios 自动透传 X-Distribution-Site-Code,钱包、提现与消息页面呈现分站专属标牌与独立说明
2026-09-07 18:11:27 +08:00

115 lines
3.2 KiB
Go
Raw Permalink 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 withdrawal
import (
"context"
"errors"
)
var (
ErrDependencyUnavailable = errors.New("dependency unavailable")
ErrWithdrawalNotFound = errors.New("withdrawal not found")
ErrInvalidAmount = errors.New("invalid amount")
ErrInsufficientBalance = errors.New("insufficient balance")
ErrMinWithdrawalAmount = errors.New("amount below minimum withdrawal")
ErrMaxWithdrawalAmount = errors.New("amount exceeds maximum withdrawal")
ErrWithdrawalLocked = errors.New("withdrawal status locked")
ErrInvalidReviewAction = errors.New("invalid review action")
ErrUnauthorized = errors.New("unauthorized")
)
const (
MinWithdrawalAmountCent = 1000 // 最低提现金额:10元 = 1000分
MaxWithdrawalAmountCent = 500000 // 单笔最高提现金额:5000元 = 500000分
WithdrawalFeeRate = 0.0 // 手续费率(暂时0%)
)
type Service struct {
repo *Repository
}
func NewService(repo *Repository) *Service {
return &Service{repo: repo}
}
// 用户端方法
func (s *Service) Create(ctx context.Context, userID uint64, req CreateWithdrawalRequest, siteCode ...string) (*WithdrawalDTO, error) {
if s.repo == nil {
return nil, ErrDependencyUnavailable
}
// 验证金额
if req.AmountCent < MinWithdrawalAmountCent {
return nil, ErrMinWithdrawalAmount
}
if req.AmountCent > MaxWithdrawalAmountCent {
return nil, ErrMaxWithdrawalAmount
}
return s.repo.Create(ctx, userID, req, siteCode...)
}
func (s *Service) List(ctx context.Context, userID uint64, page, pageSize int, siteCode ...string) (*PaginatedResult, error) {
if s.repo == nil {
return nil, ErrDependencyUnavailable
}
if page < 1 {
page = 1
}
if pageSize < 1 || pageSize > 100 {
pageSize = 20
}
return s.repo.List(ctx, userID, page, pageSize, siteCode...)
}
func (s *Service) FindByID(ctx context.Context, userID, id uint64) (*WithdrawalDTO, error) {
if s.repo == nil {
return nil, ErrDependencyUnavailable
}
return s.repo.FindByID(ctx, userID, id)
}
func (s *Service) Cancel(ctx context.Context, userID, id uint64) error {
if s.repo == nil {
return ErrDependencyUnavailable
}
return s.repo.Cancel(ctx, userID, id)
}
// 管理员端方法
func (s *Service) AdminList(ctx context.Context, query AdminListQuery) (*AdminPaginatedResult, error) {
if s.repo == nil {
return nil, ErrDependencyUnavailable
}
if query.Page < 1 {
query.Page = 1
}
if query.Size < 1 || query.Size > 100 {
query.Size = 20
}
return s.repo.AdminList(ctx, query)
}
func (s *Service) AdminFindByID(ctx context.Context, id uint64) (*WithdrawalDetailDTO, error) {
if s.repo == nil {
return nil, ErrDependencyUnavailable
}
return s.repo.AdminFindByID(ctx, id)
}
func (s *Service) Review(ctx context.Context, adminID, id uint64, req ReviewWithdrawalRequest) (*WithdrawalDetailDTO, error) {
if s.repo == nil {
return nil, ErrDependencyUnavailable
}
if req.Approved == nil {
return nil, ErrInvalidReviewAction
}
return s.repo.Review(ctx, adminID, id, req)
}
func (s *Service) ConfirmPayment(ctx context.Context, adminID, id uint64, req ConfirmPaymentRequest) (*WithdrawalDetailDTO, error) {
if s.repo == nil {
return nil, ErrDependencyUnavailable
}
return s.repo.ConfirmPayment(ctx, adminID, id, req)
}