完成剩余模块 Context 超时控制改造
This commit is contained in:
@@ -197,7 +197,7 @@ func (r *Repository) loadRolesAndPerms(ctx context.Context, dto *AdminDTO) {
|
||||
for _, role := range roles {
|
||||
if role.Code == "super_admin" {
|
||||
dto.Permissions = []string{"*"}
|
||||
cachePermissions(r, dto.ID, dto.Permissions)
|
||||
cachePermissions(ctx, r, dto.ID, dto.Permissions)
|
||||
return
|
||||
}
|
||||
}
|
||||
@@ -212,14 +212,13 @@ func (r *Repository) loadRolesAndPerms(ctx context.Context, dto *AdminDTO) {
|
||||
dto.Permissions = permCodes
|
||||
|
||||
// 缓存权限到 Redis
|
||||
cachePermissions(r, dto.ID, permCodes)
|
||||
cachePermissions(ctx, r, dto.ID, permCodes)
|
||||
}
|
||||
|
||||
func cachePermissions(r *Repository, adminID uint64, permCodes []string) {
|
||||
func cachePermissions(ctx context.Context, r *Repository, adminID uint64, permCodes []string) {
|
||||
if r.redis == nil || len(permCodes) == 0 {
|
||||
return
|
||||
}
|
||||
ctx := context.Background()
|
||||
key := fmt.Sprintf("admin:perms:%d", adminID)
|
||||
raw, _ := json.Marshal(permCodes)
|
||||
r.redis.Set(ctx, key, string(raw), 2*time.Hour)
|
||||
|
||||
@@ -18,7 +18,7 @@ func NewHandler(service *Service) *Handler {
|
||||
}
|
||||
|
||||
func (h *Handler) Summary(c *gin.Context) {
|
||||
item, err := h.service.Summary()
|
||||
item, err := h.service.Summary(c.Request.Context())
|
||||
if err != nil {
|
||||
writeDashboardError(c, err)
|
||||
return
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package admindashboard
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"hfb_sys/backend/internal/model"
|
||||
@@ -16,56 +17,57 @@ func NewRepository(db *gorm.DB) *Repository {
|
||||
return &Repository{db: db}
|
||||
}
|
||||
|
||||
func (r *Repository) Summary() (*DashboardDTO, error) {
|
||||
func (r *Repository) Summary(ctx context.Context) (*DashboardDTO, error) {
|
||||
db := r.db.WithContext(ctx)
|
||||
now := time.Now()
|
||||
today := time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, now.Location())
|
||||
metrics := MetricsDTO{}
|
||||
pending := PendingDTO{}
|
||||
|
||||
if err := r.db.Model(&model.User{}).Count(&metrics.TotalUsers).Error; err != nil {
|
||||
if err := db.Model(&model.User{}).Count(&metrics.TotalUsers).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := r.db.Model(&model.User{}).Where("realname_status = ?", "verified").Count(&metrics.VerifiedUsers).Error; err != nil {
|
||||
if err := db.Model(&model.User{}).Where("realname_status = ?", "verified").Count(&metrics.VerifiedUsers).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := r.db.Model(&model.RentalListing{}).Count(&metrics.TotalListings).Error; err != nil {
|
||||
if err := db.Model(&model.RentalListing{}).Count(&metrics.TotalListings).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := r.db.Model(&model.RentalListing{}).Where("status = ? AND review_status = ?", "published", "approved").Count(&metrics.PublishedListings).Error; err != nil {
|
||||
if err := db.Model(&model.RentalListing{}).Where("status = ? AND review_status = ?", "published", "approved").Count(&metrics.PublishedListings).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := r.db.Model(&model.RentalOrder{}).Count(&metrics.TotalOrders).Error; err != nil {
|
||||
if err := db.Model(&model.RentalOrder{}).Count(&metrics.TotalOrders).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := r.db.Model(&model.RentalOrder{}).Where("status = ?", "renting").Count(&metrics.RentingOrders).Error; err != nil {
|
||||
if err := db.Model(&model.RentalOrder{}).Where("status = ?", "renting").Count(&metrics.RentingOrders).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := r.db.Model(&model.RentalOrder{}).Where("created_at >= ?", today).Count(&metrics.TodayOrders).Error; err != nil {
|
||||
if err := db.Model(&model.RentalOrder{}).Where("created_at >= ?", today).Count(&metrics.TodayOrders).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := r.db.Model(&model.WalletLedger{}).
|
||||
if err := db.Model(&model.WalletLedger{}).
|
||||
Select("COALESCE(SUM(amount_cent), 0)").
|
||||
Where("created_at >= ?", today).
|
||||
Scan(&metrics.TodayLedgerAmountCent).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := r.db.Model(&model.RentalListing{}).Where("review_status = ?", "pending").Count(&pending.ListingReviews).Error; err != nil {
|
||||
if err := db.Model(&model.RentalListing{}).Where("review_status = ?", "pending").Count(&pending.ListingReviews).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := r.db.Model(&model.Dispute{}).Where("status IN ?", []string{"open", "processing"}).Count(&pending.Disputes).Error; err != nil {
|
||||
if err := db.Model(&model.Dispute{}).Where("status IN ?", []string{"open", "processing"}).Count(&pending.Disputes).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := r.db.Model(&model.RentalOrder{}).Where("status = ? AND handoff_status IN ?", "pending_handoff", []string{"pending_owner", "pending_renter_confirm"}).Count(&pending.PendingHandoffs).Error; err != nil {
|
||||
if err := db.Model(&model.RentalOrder{}).Where("status = ? AND handoff_status IN ?", "pending_handoff", []string{"pending_owner", "pending_renter_confirm"}).Count(&pending.PendingHandoffs).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := r.db.Model(&model.RentalOrder{}).Where("status IN ?", []string{"pending_checkout_confirm", "pending_checkout_accept"}).Count(&pending.PendingReturnConfirms).Error; err != nil {
|
||||
if err := db.Model(&model.RentalOrder{}).Where("status IN ?", []string{"pending_checkout_confirm", "pending_checkout_accept"}).Count(&pending.PendingReturnConfirms).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
recentOrders, err := r.recentOrders()
|
||||
recentOrders, err := r.recentOrders(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
recentDisputes, err := r.recentDisputes()
|
||||
recentDisputes, err := r.recentDisputes(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -78,9 +80,9 @@ func (r *Repository) Summary() (*DashboardDTO, error) {
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (r *Repository) recentOrders() ([]RecentOrderDTO, error) {
|
||||
func (r *Repository) recentOrders(ctx context.Context) ([]RecentOrderDTO, error) {
|
||||
rows := make([]RecentOrderDTO, 0)
|
||||
err := r.db.Table("rental_orders AS o").
|
||||
err := r.db.WithContext(ctx).Table("rental_orders AS o").
|
||||
Select("o.id, o.order_no, a.title, o.renter_id, o.owner_id, o.status, o.rent_amount_cent, o.deposit_amount_cent, o.created_at").
|
||||
Joins("JOIN game_accounts AS a ON a.id = o.account_id").
|
||||
Order("o.id DESC").
|
||||
@@ -89,9 +91,9 @@ func (r *Repository) recentOrders() ([]RecentOrderDTO, error) {
|
||||
return rows, err
|
||||
}
|
||||
|
||||
func (r *Repository) recentDisputes() ([]RecentDisputeDTO, error) {
|
||||
func (r *Repository) recentDisputes(ctx context.Context) ([]RecentDisputeDTO, error) {
|
||||
rows := make([]RecentDisputeDTO, 0)
|
||||
err := r.db.Table("disputes AS d").
|
||||
err := r.db.WithContext(ctx).Table("disputes AS d").
|
||||
Select("d.id, d.order_id, o.order_no, a.title, d.type, d.status, d.initiator_id, d.created_at").
|
||||
Joins("JOIN rental_orders AS o ON o.id = d.order_id").
|
||||
Joins("JOIN game_accounts AS a ON a.id = o.account_id").
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
package admindashboard
|
||||
|
||||
import "errors"
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
)
|
||||
|
||||
var ErrDependencyUnavailable = errors.New("dependency unavailable")
|
||||
|
||||
@@ -12,9 +15,9 @@ func NewService(repo *Repository) *Service {
|
||||
return &Service{repo: repo}
|
||||
}
|
||||
|
||||
func (s *Service) Summary() (*DashboardDTO, error) {
|
||||
func (s *Service) Summary(ctx context.Context) (*DashboardDTO, error) {
|
||||
if s.repo == nil {
|
||||
return nil, ErrDependencyUnavailable
|
||||
}
|
||||
return s.repo.Summary()
|
||||
return s.repo.Summary(ctx)
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ func (h *Handler) Dashboard(c *gin.Context) {
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
item, err := h.service.Dashboard(query)
|
||||
item, err := h.service.Dashboard(c.Request.Context(), query)
|
||||
if err != nil {
|
||||
writeFinanceError(c, err)
|
||||
return
|
||||
@@ -38,7 +38,7 @@ func (h *Handler) Details(c *gin.Context) {
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
result, err := h.service.Details(query)
|
||||
result, err := h.service.Details(c.Request.Context(), query)
|
||||
if err != nil {
|
||||
writeFinanceError(c, err)
|
||||
return
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package adminfinance
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"hfb_sys/backend/internal/timeutil"
|
||||
@@ -16,12 +17,12 @@ func NewRepository(db *gorm.DB) *Repository {
|
||||
return &Repository{db: db}
|
||||
}
|
||||
|
||||
func (r *Repository) Dashboard(query DashboardQuery) (*DashboardDTO, error) {
|
||||
dailyItems, err := r.dailyItems(query)
|
||||
func (r *Repository) Dashboard(ctx context.Context, query DashboardQuery) (*DashboardDTO, error) {
|
||||
dailyItems, err := r.dailyItems(ctx, query)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
summary, err := r.summary(query)
|
||||
summary, err := r.summary(ctx, query)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -32,10 +33,11 @@ func (r *Repository) Dashboard(query DashboardQuery) (*DashboardDTO, error) {
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (r *Repository) Details(query DetailQuery) (*PaginatedResult, error) {
|
||||
db := r.financeDetailBaseQuery(query)
|
||||
func (r *Repository) Details(ctx context.Context, query DetailQuery) (*PaginatedResult, error) {
|
||||
baseDB := r.db.WithContext(ctx)
|
||||
db := r.financeDetailBaseQuery(ctx, query)
|
||||
var total int64
|
||||
countDB := r.db.Table("(?) AS finance_rows", db)
|
||||
countDB := baseDB.Table("(?) AS finance_rows", db)
|
||||
if err := countDB.Count(&total).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -52,9 +54,10 @@ func (r *Repository) Details(query DetailQuery) (*PaginatedResult, error) {
|
||||
return &PaginatedResult{Items: items, Total: total, Page: query.Page, PageSize: query.PageSize}, nil
|
||||
}
|
||||
|
||||
func (r *Repository) summary(query DashboardQuery) (*FinanceSummaryDTO, error) {
|
||||
func (r *Repository) summary(ctx context.Context, query DashboardQuery) (*FinanceSummaryDTO, error) {
|
||||
db := r.db.WithContext(ctx)
|
||||
var payment paymentSummaryRow
|
||||
if err := r.db.Table("payment_orders").
|
||||
if err := db.Table("payment_orders").
|
||||
Select(`COALESCE(SUM(CASE WHEN biz_type IN ('order_pay', 'wallet_recharge') AND status = 'paid' THEN amount_cent ELSE 0 END), 0) AS total_flow_amount_cent,
|
||||
COALESCE(SUM(CASE WHEN biz_type IN ? AND status = 'refunded' THEN amount_cent ELSE 0 END), 0) AS total_refund_amount_cent,
|
||||
COALESCE(SUM(CASE WHEN biz_type IN ? AND status = 'refunding' THEN amount_cent ELSE 0 END), 0) AS pending_refund_amount_cent,
|
||||
@@ -68,20 +71,20 @@ func (r *Repository) summary(query DashboardQuery) (*FinanceSummaryDTO, error) {
|
||||
}
|
||||
|
||||
var settlement settlementSummaryRow
|
||||
if err := r.db.Table("rental_orders AS ro").
|
||||
if err := db.Table("rental_orders AS ro").
|
||||
Select(`COALESCE(SUM(oc.platform_fee_cent), 0) AS platform_income_amount_cent,
|
||||
COALESCE(SUM(oc.owner_income_amount_cent), 0) AS owner_should_income_amount_cent,
|
||||
COALESCE(SUM(COALESCE(w.owner_wallet_income_amount_cent, 0)), 0) AS owner_wallet_income_amount_cent,
|
||||
COUNT(ro.id) AS settled_order_count`).
|
||||
Joins("JOIN order_checkouts AS oc ON oc.order_id = ro.id AND oc.status = 'accepted'").
|
||||
Joins("LEFT JOIN (?) AS w ON w.order_id = ro.id", ownerWalletIncomeSubquery(r.db)).
|
||||
Joins("LEFT JOIN (?) AS w ON w.order_id = ro.id", ownerWalletIncomeSubquery(db)).
|
||||
Where("ro.settled_at >= ? AND ro.settled_at <= ?", query.StartDate, query.EndDate).
|
||||
Scan(&settlement).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var exceptionCount int64
|
||||
if err := r.db.Table("(?) AS d", r.financeDetailBaseQuery(DetailQuery{
|
||||
if err := db.Table("(?) AS d", r.financeDetailBaseQuery(ctx, DetailQuery{
|
||||
DateType: "settled",
|
||||
StartDate: query.StartDate,
|
||||
EndDate: query.EndDate,
|
||||
@@ -108,9 +111,10 @@ func (r *Repository) summary(query DashboardQuery) (*FinanceSummaryDTO, error) {
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (r *Repository) dailyItems(query DashboardQuery) ([]FinanceDailyDTO, error) {
|
||||
func (r *Repository) dailyItems(ctx context.Context, query DashboardQuery) ([]FinanceDailyDTO, error) {
|
||||
db := r.db.WithContext(ctx)
|
||||
payments := make([]dailyPaymentRow, 0)
|
||||
if err := r.db.Table("payment_orders").
|
||||
if err := db.Table("payment_orders").
|
||||
Select(`DATE(created_at) AS date,
|
||||
COALESCE(SUM(CASE WHEN biz_type IN ('order_pay', 'wallet_recharge') AND status = 'paid' THEN amount_cent ELSE 0 END), 0) AS total_flow_amount_cent,
|
||||
COALESCE(SUM(CASE WHEN biz_type IN ? AND status = 'refunded' THEN amount_cent ELSE 0 END), 0) AS total_refund_amount_cent,
|
||||
@@ -126,14 +130,14 @@ func (r *Repository) dailyItems(query DashboardQuery) ([]FinanceDailyDTO, error)
|
||||
}
|
||||
|
||||
settlements := make([]dailySettlementRow, 0)
|
||||
if err := r.db.Table("rental_orders AS ro").
|
||||
if err := db.Table("rental_orders AS ro").
|
||||
Select(`DATE(ro.settled_at) AS date,
|
||||
COALESCE(SUM(oc.platform_fee_cent), 0) AS platform_income_amount_cent,
|
||||
COALESCE(SUM(oc.owner_income_amount_cent), 0) AS owner_should_income_amount_cent,
|
||||
COALESCE(SUM(COALESCE(w.owner_wallet_income_amount_cent, 0)), 0) AS owner_wallet_income_amount_cent,
|
||||
COUNT(ro.id) AS settled_order_count`).
|
||||
Joins("JOIN order_checkouts AS oc ON oc.order_id = ro.id AND oc.status = 'accepted'").
|
||||
Joins("LEFT JOIN (?) AS w ON w.order_id = ro.id", ownerWalletIncomeSubquery(r.db)).
|
||||
Joins("LEFT JOIN (?) AS w ON w.order_id = ro.id", ownerWalletIncomeSubquery(db)).
|
||||
Where("ro.settled_at >= ? AND ro.settled_at <= ?", query.StartDate, query.EndDate).
|
||||
Group("DATE(ro.settled_at)").
|
||||
Scan(&settlements).Error; err != nil {
|
||||
@@ -175,8 +179,8 @@ func (r *Repository) dailyItems(query DashboardQuery) ([]FinanceDailyDTO, error)
|
||||
return items, nil
|
||||
}
|
||||
|
||||
func (r *Repository) financeDetailBaseQuery(query DetailQuery) *gorm.DB {
|
||||
db := r.db.Table("rental_orders AS ro").
|
||||
func (r *Repository) financeDetailBaseQuery(ctx context.Context, query DetailQuery) *gorm.DB {
|
||||
db := r.db.WithContext(ctx).Table("rental_orders AS ro").
|
||||
Select(`ro.id AS order_id, ro.order_no, ro.status AS order_status, ro.settlement_status, ro.refund_status,
|
||||
ro.renter_id, COALESCE(ru.phone, '') AS renter_phone, COALESCE(ru.nickname, '') AS renter_nickname,
|
||||
ro.owner_id, COALESCE(ou.phone, '') AS owner_phone, COALESCE(ou.nickname, '') AS owner_nickname,
|
||||
@@ -202,9 +206,9 @@ func (r *Repository) financeDetailBaseQuery(query DetailQuery) *gorm.DB {
|
||||
ro.created_at, ro.settled_at`).
|
||||
Joins("LEFT JOIN users AS ru ON ru.id = ro.renter_id").
|
||||
Joins("LEFT JOIN users AS ou ON ou.id = ro.owner_id").
|
||||
Joins("LEFT JOIN (?) AS oc ON oc.order_id = ro.id", acceptedCheckoutSubquery(r.db)).
|
||||
Joins("LEFT JOIN (?) AS p ON p.order_id = ro.id", orderPaymentSubquery(r.db)).
|
||||
Joins("LEFT JOIN (?) AS w ON w.order_id = ro.id", ownerWalletIncomeSubquery(r.db))
|
||||
Joins("LEFT JOIN (?) AS oc ON oc.order_id = ro.id", acceptedCheckoutSubquery(r.db.WithContext(ctx))).
|
||||
Joins("LEFT JOIN (?) AS p ON p.order_id = ro.id", orderPaymentSubquery(r.db.WithContext(ctx))).
|
||||
Joins("LEFT JOIN (?) AS w ON w.order_id = ro.id", ownerWalletIncomeSubquery(r.db.WithContext(ctx)))
|
||||
|
||||
if query.OrderNo != "" {
|
||||
db = db.Where("ro.order_no = ?", query.OrderNo)
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
package adminfinance
|
||||
|
||||
import "errors"
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
)
|
||||
|
||||
var ErrDependencyUnavailable = errors.New("dependency unavailable")
|
||||
|
||||
@@ -12,14 +15,14 @@ func NewService(repo *Repository) *Service {
|
||||
return &Service{repo: repo}
|
||||
}
|
||||
|
||||
func (s *Service) Dashboard(query DashboardQuery) (*DashboardDTO, error) {
|
||||
func (s *Service) Dashboard(ctx context.Context, query DashboardQuery) (*DashboardDTO, error) {
|
||||
if s.repo == nil {
|
||||
return nil, ErrDependencyUnavailable
|
||||
}
|
||||
return s.repo.Dashboard(query)
|
||||
return s.repo.Dashboard(ctx, query)
|
||||
}
|
||||
|
||||
func (s *Service) Details(query DetailQuery) (*PaginatedResult, error) {
|
||||
func (s *Service) Details(ctx context.Context, query DetailQuery) (*PaginatedResult, error) {
|
||||
if s.repo == nil {
|
||||
return nil, ErrDependencyUnavailable
|
||||
}
|
||||
@@ -32,5 +35,5 @@ func (s *Service) Details(query DetailQuery) (*PaginatedResult, error) {
|
||||
if query.PageSize > 100 {
|
||||
query.PageSize = 100
|
||||
}
|
||||
return s.repo.Details(query)
|
||||
return s.repo.Details(ctx, query)
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ func NewHandler(service *Service) *Handler {
|
||||
func (h *Handler) List(c *gin.Context) {
|
||||
page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
|
||||
pageSize, _ := strconv.Atoi(c.DefaultQuery("page_size", "20"))
|
||||
result, err := h.service.List(page, pageSize)
|
||||
result, err := h.service.List(c.Request.Context(), page, pageSize)
|
||||
if err != nil {
|
||||
writeError(c, err)
|
||||
return
|
||||
@@ -35,7 +35,7 @@ func (h *Handler) FindByID(c *gin.Context) {
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
item, err := h.service.FindByID(id)
|
||||
item, err := h.service.FindByID(c.Request.Context(), id)
|
||||
if err != nil {
|
||||
writeError(c, err)
|
||||
return
|
||||
@@ -49,7 +49,7 @@ func (h *Handler) Create(c *gin.Context) {
|
||||
response.BadRequest(c, "用户名和密码不能为空")
|
||||
return
|
||||
}
|
||||
item, err := h.service.Create(req)
|
||||
item, err := h.service.Create(c.Request.Context(), req)
|
||||
if err != nil {
|
||||
writeError(c, err)
|
||||
return
|
||||
@@ -67,7 +67,7 @@ func (h *Handler) Update(c *gin.Context) {
|
||||
response.BadRequest(c, "请求格式不正确")
|
||||
return
|
||||
}
|
||||
item, err := h.service.Update(id, req)
|
||||
item, err := h.service.Update(c.Request.Context(), id, req)
|
||||
if err != nil {
|
||||
writeError(c, err)
|
||||
return
|
||||
@@ -81,7 +81,7 @@ func (h *Handler) Delete(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
currentAdminID, _ := c.Get(middleware.ContextAdminID)
|
||||
if err := h.service.Delete(id, currentAdminID.(uint64)); err != nil {
|
||||
if err := h.service.Delete(c.Request.Context(), id, currentAdminID.(uint64)); err != nil {
|
||||
writeError(c, err)
|
||||
return
|
||||
}
|
||||
@@ -98,7 +98,7 @@ func (h *Handler) AssignRoles(c *gin.Context) {
|
||||
response.BadRequest(c, "请求格式不正确")
|
||||
return
|
||||
}
|
||||
if err := h.service.AssignRoles(id, req); err != nil {
|
||||
if err := h.service.AssignRoles(c.Request.Context(), id, req); err != nil {
|
||||
writeError(c, err)
|
||||
return
|
||||
}
|
||||
@@ -115,7 +115,7 @@ func (h *Handler) ChangePassword(c *gin.Context) {
|
||||
response.BadRequest(c, "密码不能为空")
|
||||
return
|
||||
}
|
||||
if err := h.service.ChangePassword(id, req); err != nil {
|
||||
if err := h.service.ChangePassword(c.Request.Context(), id, req); err != nil {
|
||||
writeError(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -23,19 +23,20 @@ func NewRepository(db *gorm.DB, redis *redis.Client) *Repository {
|
||||
return &Repository{db: db, redis: redis}
|
||||
}
|
||||
|
||||
func (r *Repository) List(page, pageSize int) (*PaginatedResult, error) {
|
||||
func (r *Repository) List(ctx context.Context, page, pageSize int) (*PaginatedResult, error) {
|
||||
db := r.db.WithContext(ctx)
|
||||
var total int64
|
||||
if err := r.db.Model(&model.AdminUser{}).Count(&total).Error; err != nil {
|
||||
if err := db.Model(&model.AdminUser{}).Count(&total).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
offset := (page - 1) * pageSize
|
||||
var admins []model.AdminUser
|
||||
if err := r.db.Order("id DESC").Offset(offset).Limit(pageSize).Find(&admins).Error; err != nil {
|
||||
if err := db.Order("id DESC").Offset(offset).Limit(pageSize).Find(&admins).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items := make([]AdminUserDTO, 0, len(admins))
|
||||
for _, admin := range admins {
|
||||
roles, _ := r.getAdminRoles(admin.ID)
|
||||
roles, _ := r.getAdminRoles(ctx, admin.ID)
|
||||
items = append(items, AdminUserDTO{
|
||||
ID: admin.ID,
|
||||
Username: admin.Username,
|
||||
@@ -50,12 +51,12 @@ func (r *Repository) List(page, pageSize int) (*PaginatedResult, error) {
|
||||
return &PaginatedResult{Items: items, Total: total, Page: page, PageSize: pageSize}, nil
|
||||
}
|
||||
|
||||
func (r *Repository) FindByID(id uint64) (*AdminUserDTO, error) {
|
||||
func (r *Repository) FindByID(ctx context.Context, id uint64) (*AdminUserDTO, error) {
|
||||
var admin model.AdminUser
|
||||
if err := r.db.First(&admin, id).Error; err != nil {
|
||||
if err := r.db.WithContext(ctx).First(&admin, id).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
roles, _ := r.getAdminRoles(admin.ID)
|
||||
roles, _ := r.getAdminRoles(ctx, admin.ID)
|
||||
dto := AdminUserDTO{
|
||||
ID: admin.ID,
|
||||
Username: admin.Username,
|
||||
@@ -69,7 +70,7 @@ func (r *Repository) FindByID(id uint64) (*AdminUserDTO, error) {
|
||||
return &dto, nil
|
||||
}
|
||||
|
||||
func (r *Repository) Create(req CreateAdminRequest) (*AdminUserDTO, error) {
|
||||
func (r *Repository) Create(ctx context.Context, req CreateAdminRequest) (*AdminUserDTO, error) {
|
||||
hash, err := bcrypt.GenerateFromPassword([]byte(req.Password), bcrypt.DefaultCost)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -80,15 +81,16 @@ func (r *Repository) Create(req CreateAdminRequest) (*AdminUserDTO, error) {
|
||||
Nickname: req.Nickname,
|
||||
Status: "active",
|
||||
}
|
||||
if err := r.db.Create(&admin).Error; err != nil {
|
||||
if err := r.db.WithContext(ctx).Create(&admin).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return r.FindByID(admin.ID)
|
||||
return r.FindByID(ctx, admin.ID)
|
||||
}
|
||||
|
||||
func (r *Repository) Update(id uint64, req UpdateAdminRequest) (*AdminUserDTO, error) {
|
||||
func (r *Repository) Update(ctx context.Context, id uint64, req UpdateAdminRequest) (*AdminUserDTO, error) {
|
||||
db := r.db.WithContext(ctx)
|
||||
var admin model.AdminUser
|
||||
if err := r.db.First(&admin, id).Error; err != nil {
|
||||
if err := db.First(&admin, id).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if req.Nickname != "" {
|
||||
@@ -97,46 +99,48 @@ func (r *Repository) Update(id uint64, req UpdateAdminRequest) (*AdminUserDTO, e
|
||||
if req.Status != "" {
|
||||
admin.Status = req.Status
|
||||
}
|
||||
if err := r.db.Save(&admin).Error; err != nil {
|
||||
if err := db.Save(&admin).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return r.FindByID(id)
|
||||
return r.FindByID(ctx, id)
|
||||
}
|
||||
|
||||
func (r *Repository) Delete(id uint64, currentAdminID uint64) error {
|
||||
func (r *Repository) Delete(ctx context.Context, id uint64, currentAdminID uint64) error {
|
||||
if id == currentAdminID {
|
||||
return ErrCannotDeleteSelf
|
||||
}
|
||||
db := r.db.WithContext(ctx)
|
||||
var admin model.AdminUser
|
||||
if err := r.db.First(&admin, id).Error; err != nil {
|
||||
if err := db.First(&admin, id).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
// 检查是否是最后一个 super_admin
|
||||
isLastSuper, err := r.isLastSuperAdmin(id)
|
||||
isLastSuper, err := r.isLastSuperAdmin(ctx, id)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if isLastSuper {
|
||||
return ErrLastSuperAdmin
|
||||
}
|
||||
return r.db.Transaction(func(tx *gorm.DB) error {
|
||||
return db.Transaction(func(tx *gorm.DB) error {
|
||||
if err := tx.Where("admin_user_id = ?", id).Delete(&model.AdminUserRole{}).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
if err := tx.Delete(&model.AdminUser{}, id).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
r.invalidatePermCache(id)
|
||||
r.invalidatePermCache(ctx, id)
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func (r *Repository) AssignRoles(adminID uint64, roleIDs []uint64) error {
|
||||
func (r *Repository) AssignRoles(ctx context.Context, adminID uint64, roleIDs []uint64) error {
|
||||
db := r.db.WithContext(ctx)
|
||||
var admin model.AdminUser
|
||||
if err := r.db.First(&admin, adminID).Error; err != nil {
|
||||
if err := db.First(&admin, adminID).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
err := r.db.Transaction(func(tx *gorm.DB) error {
|
||||
err := db.Transaction(func(tx *gorm.DB) error {
|
||||
if err := tx.Where("admin_user_id = ?", adminID).Delete(&model.AdminUserRole{}).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -151,13 +155,13 @@ func (r *Repository) AssignRoles(adminID uint64, roleIDs []uint64) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
r.invalidatePermCache(adminID)
|
||||
r.invalidatePermCache(ctx, adminID)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *Repository) ChangePassword(id uint64, oldPwd, newPwd string) error {
|
||||
func (r *Repository) ChangePassword(ctx context.Context, id uint64, oldPwd, newPwd string) error {
|
||||
var admin model.AdminUser
|
||||
if err := r.db.First(&admin, id).Error; err != nil {
|
||||
if err := r.db.WithContext(ctx).First(&admin, id).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
if err := bcrypt.CompareHashAndPassword([]byte(admin.PasswordHash), []byte(oldPwd)); err != nil {
|
||||
@@ -167,12 +171,12 @@ func (r *Repository) ChangePassword(id uint64, oldPwd, newPwd string) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return r.db.Model(&admin).Update("password_hash", string(hash)).Error
|
||||
return r.db.WithContext(ctx).Model(&admin).Update("password_hash", string(hash)).Error
|
||||
}
|
||||
|
||||
func (r *Repository) GetPermissionCodes(adminID uint64) ([]string, error) {
|
||||
func (r *Repository) GetPermissionCodes(ctx context.Context, adminID uint64) ([]string, error) {
|
||||
var codes []string
|
||||
err := r.db.Table("admin_user_roles aur").
|
||||
err := r.db.WithContext(ctx).Table("admin_user_roles aur").
|
||||
Select("DISTINCT p.code").
|
||||
Joins("JOIN role_permissions rp ON rp.role_id = aur.role_id").
|
||||
Joins("JOIN permissions p ON p.id = rp.permission_id").
|
||||
@@ -181,9 +185,9 @@ func (r *Repository) GetPermissionCodes(adminID uint64) ([]string, error) {
|
||||
return codes, err
|
||||
}
|
||||
|
||||
func (r *Repository) getAdminRoles(adminID uint64) ([]adminrole.RoleDTO, error) {
|
||||
func (r *Repository) getAdminRoles(ctx context.Context, adminID uint64) ([]adminrole.RoleDTO, error) {
|
||||
var roles []model.Role
|
||||
err := r.db.Table("roles").
|
||||
err := r.db.WithContext(ctx).Table("roles").
|
||||
Joins("JOIN admin_user_roles aur ON aur.role_id = roles.id").
|
||||
Where("aur.admin_user_id = ?", adminID).
|
||||
Find(&roles).Error
|
||||
@@ -199,23 +203,23 @@ func (r *Repository) getAdminRoles(adminID uint64) ([]adminrole.RoleDTO, error)
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (r *Repository) isLastSuperAdmin(adminID uint64) (bool, error) {
|
||||
func (r *Repository) isLastSuperAdmin(ctx context.Context, adminID uint64) (bool, error) {
|
||||
var superRole model.Role
|
||||
if err := r.db.Where("code = ?", "super_admin").First(&superRole).Error; err != nil {
|
||||
db := r.db.WithContext(ctx)
|
||||
if err := db.Where("code = ?", "super_admin").First(&superRole).Error; err != nil {
|
||||
return false, nil // 没有 super_admin 角色,不限制
|
||||
}
|
||||
var count int64
|
||||
err := r.db.Model(&model.AdminUserRole{}).
|
||||
err := db.Model(&model.AdminUserRole{}).
|
||||
Where("role_id = ? AND admin_user_id != ?", superRole.ID, adminID).
|
||||
Count(&count).Error
|
||||
return count == 0, err
|
||||
}
|
||||
|
||||
func (r *Repository) invalidatePermCache(adminID uint64) {
|
||||
func (r *Repository) invalidatePermCache(ctx context.Context, adminID uint64) {
|
||||
if r.redis == nil {
|
||||
return
|
||||
}
|
||||
ctx := context.Background()
|
||||
r.redis.Del(ctx, permCacheKey(adminID))
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
package adminmgr
|
||||
|
||||
import "errors"
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
)
|
||||
|
||||
var ErrDependencyUnavailable = errors.New("dependency unavailable")
|
||||
|
||||
@@ -12,7 +15,7 @@ func NewService(repo *Repository) *Service {
|
||||
return &Service{repo: repo}
|
||||
}
|
||||
|
||||
func (s *Service) List(page, pageSize int) (*PaginatedResult, error) {
|
||||
func (s *Service) List(ctx context.Context, page, pageSize int) (*PaginatedResult, error) {
|
||||
if s.repo == nil {
|
||||
return nil, ErrDependencyUnavailable
|
||||
}
|
||||
@@ -22,53 +25,53 @@ func (s *Service) List(page, pageSize int) (*PaginatedResult, error) {
|
||||
if pageSize < 1 || pageSize > 100 {
|
||||
pageSize = 20
|
||||
}
|
||||
return s.repo.List(page, pageSize)
|
||||
return s.repo.List(ctx, page, pageSize)
|
||||
}
|
||||
|
||||
func (s *Service) FindByID(id uint64) (*AdminUserDTO, error) {
|
||||
func (s *Service) FindByID(ctx context.Context, id uint64) (*AdminUserDTO, error) {
|
||||
if s.repo == nil {
|
||||
return nil, ErrDependencyUnavailable
|
||||
}
|
||||
return s.repo.FindByID(id)
|
||||
return s.repo.FindByID(ctx, id)
|
||||
}
|
||||
|
||||
func (s *Service) Create(req CreateAdminRequest) (*AdminUserDTO, error) {
|
||||
func (s *Service) Create(ctx context.Context, req CreateAdminRequest) (*AdminUserDTO, error) {
|
||||
if s.repo == nil {
|
||||
return nil, ErrDependencyUnavailable
|
||||
}
|
||||
if len(req.Password) < 6 {
|
||||
return nil, errors.New("password too short")
|
||||
}
|
||||
return s.repo.Create(req)
|
||||
return s.repo.Create(ctx, req)
|
||||
}
|
||||
|
||||
func (s *Service) Update(id uint64, req UpdateAdminRequest) (*AdminUserDTO, error) {
|
||||
func (s *Service) Update(ctx context.Context, id uint64, req UpdateAdminRequest) (*AdminUserDTO, error) {
|
||||
if s.repo == nil {
|
||||
return nil, ErrDependencyUnavailable
|
||||
}
|
||||
return s.repo.Update(id, req)
|
||||
return s.repo.Update(ctx, id, req)
|
||||
}
|
||||
|
||||
func (s *Service) Delete(id uint64, currentAdminID uint64) error {
|
||||
func (s *Service) Delete(ctx context.Context, id uint64, currentAdminID uint64) error {
|
||||
if s.repo == nil {
|
||||
return ErrDependencyUnavailable
|
||||
}
|
||||
return s.repo.Delete(id, currentAdminID)
|
||||
return s.repo.Delete(ctx, id, currentAdminID)
|
||||
}
|
||||
|
||||
func (s *Service) AssignRoles(adminID uint64, req AssignRolesRequest) error {
|
||||
func (s *Service) AssignRoles(ctx context.Context, adminID uint64, req AssignRolesRequest) error {
|
||||
if s.repo == nil {
|
||||
return ErrDependencyUnavailable
|
||||
}
|
||||
return s.repo.AssignRoles(adminID, req.RoleIDs)
|
||||
return s.repo.AssignRoles(ctx, adminID, req.RoleIDs)
|
||||
}
|
||||
|
||||
func (s *Service) ChangePassword(id uint64, req ChangePasswordRequest) error {
|
||||
func (s *Service) ChangePassword(ctx context.Context, id uint64, req ChangePasswordRequest) error {
|
||||
if s.repo == nil {
|
||||
return ErrDependencyUnavailable
|
||||
}
|
||||
if len(req.NewPassword) < 6 {
|
||||
return errors.New("new password too short")
|
||||
}
|
||||
return s.repo.ChangePassword(id, req.OldPassword, req.NewPassword)
|
||||
return s.repo.ChangePassword(ctx, id, req.OldPassword, req.NewPassword)
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ func NewHandler(service *Service) *Handler {
|
||||
}
|
||||
|
||||
func (h *Handler) List(c *gin.Context) {
|
||||
items, err := h.service.List()
|
||||
items, err := h.service.List(c.Request.Context())
|
||||
if err != nil {
|
||||
writeError(c, err)
|
||||
return
|
||||
@@ -32,7 +32,7 @@ func (h *Handler) FindByID(c *gin.Context) {
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
item, err := h.service.FindByID(id)
|
||||
item, err := h.service.FindByID(c.Request.Context(), id)
|
||||
if err != nil {
|
||||
writeError(c, err)
|
||||
return
|
||||
@@ -46,7 +46,7 @@ func (h *Handler) Create(c *gin.Context) {
|
||||
response.BadRequest(c, "角色编码和名称不能为空")
|
||||
return
|
||||
}
|
||||
item, err := h.service.Create(req)
|
||||
item, err := h.service.Create(c.Request.Context(), req)
|
||||
if err != nil {
|
||||
writeError(c, err)
|
||||
return
|
||||
@@ -64,7 +64,7 @@ func (h *Handler) Update(c *gin.Context) {
|
||||
response.BadRequest(c, "角色名称不能为空")
|
||||
return
|
||||
}
|
||||
item, err := h.service.Update(id, req)
|
||||
item, err := h.service.Update(c.Request.Context(), id, req)
|
||||
if err != nil {
|
||||
writeError(c, err)
|
||||
return
|
||||
@@ -77,7 +77,7 @@ func (h *Handler) Delete(c *gin.Context) {
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
if err := h.service.Delete(id); err != nil {
|
||||
if err := h.service.Delete(c.Request.Context(), id); err != nil {
|
||||
writeError(c, err)
|
||||
return
|
||||
}
|
||||
@@ -94,7 +94,7 @@ func (h *Handler) AssignPermissions(c *gin.Context) {
|
||||
response.BadRequest(c, "请求格式不正确")
|
||||
return
|
||||
}
|
||||
if err := h.service.AssignPermissions(id, req); err != nil {
|
||||
if err := h.service.AssignPermissions(c.Request.Context(), id, req); err != nil {
|
||||
writeError(c, err)
|
||||
return
|
||||
}
|
||||
@@ -102,7 +102,7 @@ func (h *Handler) AssignPermissions(c *gin.Context) {
|
||||
}
|
||||
|
||||
func (h *Handler) ListPermissions(c *gin.Context) {
|
||||
items, err := h.service.ListPermissions()
|
||||
items, err := h.service.ListPermissions(c.Request.Context())
|
||||
if err != nil {
|
||||
writeError(c, err)
|
||||
return
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package adminrole
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
|
||||
"hfb_sys/backend/internal/model"
|
||||
@@ -17,18 +18,19 @@ func NewRepository(db *gorm.DB) *Repository {
|
||||
return &Repository{db: db}
|
||||
}
|
||||
|
||||
func (r *Repository) List() ([]RoleDTO, error) {
|
||||
func (r *Repository) List(ctx context.Context) ([]RoleDTO, error) {
|
||||
db := r.db.WithContext(ctx)
|
||||
var roles []model.Role
|
||||
if err := r.db.Order("id ASC").Find(&roles).Error; err != nil {
|
||||
if err := db.Order("id ASC").Find(&roles).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
result := make([]RoleDTO, 0, len(roles))
|
||||
for _, role := range roles {
|
||||
var count int64
|
||||
if role.Code == "super_admin" {
|
||||
r.db.Model(&model.Permission{}).Count(&count)
|
||||
db.Model(&model.Permission{}).Count(&count)
|
||||
} else {
|
||||
r.db.Model(&model.RolePermission{}).Where("role_id = ?", role.ID).Count(&count)
|
||||
db.Model(&model.RolePermission{}).Where("role_id = ?", role.ID).Count(&count)
|
||||
}
|
||||
result = append(result, RoleDTO{
|
||||
ID: role.ID,
|
||||
@@ -43,17 +45,17 @@ func (r *Repository) List() ([]RoleDTO, error) {
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (r *Repository) FindByID(id uint64) (*RoleDTO, error) {
|
||||
func (r *Repository) FindByID(ctx context.Context, id uint64) (*RoleDTO, error) {
|
||||
var role model.Role
|
||||
if err := r.db.First(&role, id).Error; err != nil {
|
||||
if err := r.db.WithContext(ctx).First(&role, id).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var perms []PermissionDTO
|
||||
var err error
|
||||
if role.Code == "super_admin" {
|
||||
perms, err = r.ListPermissions()
|
||||
perms, err = r.ListPermissions(ctx)
|
||||
} else {
|
||||
perms, err = r.getRolePermissions(id)
|
||||
perms, err = r.getRolePermissions(ctx, id)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -71,40 +73,42 @@ func (r *Repository) FindByID(id uint64) (*RoleDTO, error) {
|
||||
return &dto, nil
|
||||
}
|
||||
|
||||
func (r *Repository) Create(req CreateRoleRequest) (*RoleDTO, error) {
|
||||
func (r *Repository) Create(ctx context.Context, req CreateRoleRequest) (*RoleDTO, error) {
|
||||
role := model.Role{
|
||||
Code: req.Code,
|
||||
Name: req.Name,
|
||||
Description: req.Description,
|
||||
}
|
||||
if err := r.db.Create(&role).Error; err != nil {
|
||||
if err := r.db.WithContext(ctx).Create(&role).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return r.FindByID(role.ID)
|
||||
return r.FindByID(ctx, role.ID)
|
||||
}
|
||||
|
||||
func (r *Repository) Update(id uint64, req UpdateRoleRequest) (*RoleDTO, error) {
|
||||
func (r *Repository) Update(ctx context.Context, id uint64, req UpdateRoleRequest) (*RoleDTO, error) {
|
||||
db := r.db.WithContext(ctx)
|
||||
var role model.Role
|
||||
if err := r.db.First(&role, id).Error; err != nil {
|
||||
if err := db.First(&role, id).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
role.Name = req.Name
|
||||
role.Description = req.Description
|
||||
if err := r.db.Save(&role).Error; err != nil {
|
||||
if err := db.Save(&role).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return r.FindByID(id)
|
||||
return r.FindByID(ctx, id)
|
||||
}
|
||||
|
||||
func (r *Repository) Delete(id uint64) error {
|
||||
func (r *Repository) Delete(ctx context.Context, id uint64) error {
|
||||
db := r.db.WithContext(ctx)
|
||||
var role model.Role
|
||||
if err := r.db.First(&role, id).Error; err != nil {
|
||||
if err := db.First(&role, id).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
if role.Code == "super_admin" {
|
||||
return ErrProtectedRole
|
||||
}
|
||||
return r.db.Transaction(func(tx *gorm.DB) error {
|
||||
return db.Transaction(func(tx *gorm.DB) error {
|
||||
if err := tx.Where("role_id = ?", id).Delete(&model.RolePermission{}).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -115,12 +119,13 @@ func (r *Repository) Delete(id uint64) error {
|
||||
})
|
||||
}
|
||||
|
||||
func (r *Repository) AssignPermissions(roleID uint64, permIDs []uint64) error {
|
||||
func (r *Repository) AssignPermissions(ctx context.Context, roleID uint64, permIDs []uint64) error {
|
||||
db := r.db.WithContext(ctx)
|
||||
var role model.Role
|
||||
if err := r.db.First(&role, roleID).Error; err != nil {
|
||||
if err := db.First(&role, roleID).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
return r.db.Transaction(func(tx *gorm.DB) error {
|
||||
return db.Transaction(func(tx *gorm.DB) error {
|
||||
if role.Code == "super_admin" {
|
||||
var allPermIDs []uint64
|
||||
if err := tx.Model(&model.Permission{}).Pluck("id", &allPermIDs).Error; err != nil {
|
||||
@@ -141,9 +146,9 @@ func (r *Repository) AssignPermissions(roleID uint64, permIDs []uint64) error {
|
||||
})
|
||||
}
|
||||
|
||||
func (r *Repository) ListPermissions() ([]PermissionDTO, error) {
|
||||
func (r *Repository) ListPermissions(ctx context.Context) ([]PermissionDTO, error) {
|
||||
var perms []model.Permission
|
||||
if err := r.db.Order("resource ASC, action ASC").Find(&perms).Error; err != nil {
|
||||
if err := r.db.WithContext(ctx).Order("resource ASC, action ASC").Find(&perms).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
result := make([]PermissionDTO, 0, len(perms))
|
||||
@@ -155,9 +160,10 @@ func (r *Repository) ListPermissions() ([]PermissionDTO, error) {
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (r *Repository) getRolePermissions(roleID uint64) ([]PermissionDTO, error) {
|
||||
func (r *Repository) getRolePermissions(ctx context.Context, roleID uint64) ([]PermissionDTO, error) {
|
||||
db := r.db.WithContext(ctx)
|
||||
var rps []model.RolePermission
|
||||
if err := r.db.Where("role_id = ?", roleID).Find(&rps).Error; err != nil {
|
||||
if err := db.Where("role_id = ?", roleID).Find(&rps).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(rps) == 0 {
|
||||
@@ -168,7 +174,7 @@ func (r *Repository) getRolePermissions(roleID uint64) ([]PermissionDTO, error)
|
||||
ids = append(ids, rp.PermissionID)
|
||||
}
|
||||
var perms []model.Permission
|
||||
if err := r.db.Where("id IN ?", ids).Find(&perms).Error; err != nil {
|
||||
if err := db.Where("id IN ?", ids).Find(&perms).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
result := make([]PermissionDTO, 0, len(perms))
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
package adminrole
|
||||
|
||||
import "errors"
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
)
|
||||
|
||||
var ErrDependencyUnavailable = errors.New("dependency unavailable")
|
||||
|
||||
@@ -12,54 +15,54 @@ func NewService(repo *Repository) *Service {
|
||||
return &Service{repo: repo}
|
||||
}
|
||||
|
||||
func (s *Service) List() ([]RoleDTO, error) {
|
||||
func (s *Service) List(ctx context.Context) ([]RoleDTO, error) {
|
||||
if s.repo == nil {
|
||||
return nil, ErrDependencyUnavailable
|
||||
}
|
||||
return s.repo.List()
|
||||
return s.repo.List(ctx)
|
||||
}
|
||||
|
||||
func (s *Service) FindByID(id uint64) (*RoleDTO, error) {
|
||||
func (s *Service) FindByID(ctx context.Context, id uint64) (*RoleDTO, error) {
|
||||
if s.repo == nil {
|
||||
return nil, ErrDependencyUnavailable
|
||||
}
|
||||
return s.repo.FindByID(id)
|
||||
return s.repo.FindByID(ctx, id)
|
||||
}
|
||||
|
||||
func (s *Service) Create(req CreateRoleRequest) (*RoleDTO, error) {
|
||||
func (s *Service) Create(ctx context.Context, req CreateRoleRequest) (*RoleDTO, error) {
|
||||
if s.repo == nil {
|
||||
return nil, ErrDependencyUnavailable
|
||||
}
|
||||
if req.Code == "" || req.Name == "" {
|
||||
return nil, errors.New("code and name are required")
|
||||
}
|
||||
return s.repo.Create(req)
|
||||
return s.repo.Create(ctx, req)
|
||||
}
|
||||
|
||||
func (s *Service) Update(id uint64, req UpdateRoleRequest) (*RoleDTO, error) {
|
||||
func (s *Service) Update(ctx context.Context, id uint64, req UpdateRoleRequest) (*RoleDTO, error) {
|
||||
if s.repo == nil {
|
||||
return nil, ErrDependencyUnavailable
|
||||
}
|
||||
return s.repo.Update(id, req)
|
||||
return s.repo.Update(ctx, id, req)
|
||||
}
|
||||
|
||||
func (s *Service) Delete(id uint64) error {
|
||||
func (s *Service) Delete(ctx context.Context, id uint64) error {
|
||||
if s.repo == nil {
|
||||
return ErrDependencyUnavailable
|
||||
}
|
||||
return s.repo.Delete(id)
|
||||
return s.repo.Delete(ctx, id)
|
||||
}
|
||||
|
||||
func (s *Service) AssignPermissions(roleID uint64, req AssignPermissionsRequest) error {
|
||||
func (s *Service) AssignPermissions(ctx context.Context, roleID uint64, req AssignPermissionsRequest) error {
|
||||
if s.repo == nil {
|
||||
return ErrDependencyUnavailable
|
||||
}
|
||||
return s.repo.AssignPermissions(roleID, req.PermissionIDs)
|
||||
return s.repo.AssignPermissions(ctx, roleID, req.PermissionIDs)
|
||||
}
|
||||
|
||||
func (s *Service) ListPermissions() ([]PermissionDTO, error) {
|
||||
func (s *Service) ListPermissions(ctx context.Context) ([]PermissionDTO, error) {
|
||||
if s.repo == nil {
|
||||
return nil, ErrDependencyUnavailable
|
||||
}
|
||||
return s.repo.ListPermissions()
|
||||
return s.repo.ListPermissions(ctx)
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ func (h *Handler) List(c *gin.Context) {
|
||||
}
|
||||
query.Page, query.PageSize = parsePagination(c)
|
||||
|
||||
result, err := h.service.List(query)
|
||||
result, err := h.service.List(c.Request.Context(), query)
|
||||
if err != nil {
|
||||
response.InternalServerError(c, "获取公告列表失败")
|
||||
return
|
||||
@@ -44,7 +44,7 @@ func (h *Handler) GetByID(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
announcement, err := h.service.GetByID(id)
|
||||
announcement, err := h.service.GetByID(c.Request.Context(), id)
|
||||
if err != nil {
|
||||
if errors.Is(err, ErrNotFound) {
|
||||
response.NotFound(c, "公告不存在")
|
||||
@@ -65,7 +65,7 @@ func (h *Handler) AdminList(c *gin.Context) {
|
||||
}
|
||||
query.Page, query.PageSize = parsePagination(c)
|
||||
|
||||
result, err := h.service.AdminList(query)
|
||||
result, err := h.service.AdminList(c.Request.Context(), query)
|
||||
if err != nil {
|
||||
response.InternalServerError(c, "获取公告列表失败")
|
||||
return
|
||||
@@ -82,7 +82,7 @@ func (h *Handler) AdminGetByID(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
announcement, err := h.service.AdminGetByID(id)
|
||||
announcement, err := h.service.AdminGetByID(c.Request.Context(), id)
|
||||
if err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
response.NotFound(c, "公告不存在")
|
||||
@@ -109,7 +109,7 @@ func (h *Handler) Create(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
announcement, err := h.service.Create(req, adminID)
|
||||
announcement, err := h.service.Create(c.Request.Context(), req, adminID)
|
||||
if err != nil {
|
||||
response.InternalServerError(c, "创建公告失败")
|
||||
return
|
||||
@@ -132,7 +132,7 @@ func (h *Handler) Update(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
announcement, err := h.service.Update(id, req)
|
||||
announcement, err := h.service.Update(c.Request.Context(), id, req)
|
||||
if err != nil {
|
||||
response.InternalServerError(c, "更新公告失败")
|
||||
return
|
||||
@@ -149,7 +149,7 @@ func (h *Handler) Publish(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
if err := h.service.Publish(id); err != nil {
|
||||
if err := h.service.Publish(c.Request.Context(), id); err != nil {
|
||||
response.InternalServerError(c, "发布公告失败")
|
||||
return
|
||||
}
|
||||
@@ -165,7 +165,7 @@ func (h *Handler) Archive(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
if err := h.service.Archive(id); err != nil {
|
||||
if err := h.service.Archive(c.Request.Context(), id); err != nil {
|
||||
response.InternalServerError(c, "归档公告失败")
|
||||
return
|
||||
}
|
||||
@@ -181,7 +181,7 @@ func (h *Handler) Delete(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
if err := h.service.Delete(id); err != nil {
|
||||
if err := h.service.Delete(c.Request.Context(), id); err != nil {
|
||||
response.InternalServerError(c, "删除公告失败")
|
||||
return
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package announcement
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"hfb_sys/backend/internal/model"
|
||||
@@ -17,9 +18,9 @@ func NewRepository(db *gorm.DB) *Repository {
|
||||
}
|
||||
|
||||
// List 获取公告列表(前台用户)
|
||||
func (r *Repository) List(query AnnouncementListQuery) (*PaginatedResult, error) {
|
||||
func (r *Repository) List(ctx context.Context, query AnnouncementListQuery) (*PaginatedResult, error) {
|
||||
var total int64
|
||||
tx := r.db.Model(&model.Announcement{}).Where("status = ?", "published")
|
||||
tx := r.db.WithContext(ctx).Model(&model.Announcement{}).Where("status = ?", "published")
|
||||
|
||||
if query.Category != "" {
|
||||
tx = tx.Where("category = ?", query.Category)
|
||||
@@ -52,23 +53,24 @@ func (r *Repository) List(query AnnouncementListQuery) (*PaginatedResult, error)
|
||||
}
|
||||
|
||||
// GetByID 获取公告详情
|
||||
func (r *Repository) GetByID(id uint64) (*AnnouncementDTO, error) {
|
||||
func (r *Repository) GetByID(ctx context.Context, id uint64) (*AnnouncementDTO, error) {
|
||||
var announcement model.Announcement
|
||||
if err := r.db.Where("id = ? AND status = ?", id, "published").First(&announcement).Error; err != nil {
|
||||
db := r.db.WithContext(ctx)
|
||||
if err := db.Where("id = ? AND status = ?", id, "published").First(&announcement).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 增加查看次数
|
||||
r.db.Model(&model.Announcement{}).Where("id = ?", id).UpdateColumn("view_count", gorm.Expr("view_count + ?", 1))
|
||||
db.Model(&model.Announcement{}).Where("id = ?", id).UpdateColumn("view_count", gorm.Expr("view_count + ?", 1))
|
||||
|
||||
dto := toAnnouncementDTO(announcement)
|
||||
return &dto, nil
|
||||
}
|
||||
|
||||
// AdminList 管理员获取公告列表
|
||||
func (r *Repository) AdminList(query AnnouncementListQuery) (*PaginatedResult, error) {
|
||||
func (r *Repository) AdminList(ctx context.Context, query AnnouncementListQuery) (*PaginatedResult, error) {
|
||||
var total int64
|
||||
tx := r.db.Model(&model.Announcement{})
|
||||
tx := r.db.WithContext(ctx).Model(&model.Announcement{})
|
||||
|
||||
if query.Status != "" {
|
||||
tx = tx.Where("status = ?", query.Status)
|
||||
@@ -104,9 +106,9 @@ func (r *Repository) AdminList(query AnnouncementListQuery) (*PaginatedResult, e
|
||||
}
|
||||
|
||||
// AdminGetByID 管理员获取公告详情
|
||||
func (r *Repository) AdminGetByID(id uint64) (*AnnouncementDTO, error) {
|
||||
func (r *Repository) AdminGetByID(ctx context.Context, id uint64) (*AnnouncementDTO, error) {
|
||||
var announcement model.Announcement
|
||||
if err := r.db.Where("id = ?", id).First(&announcement).Error; err != nil {
|
||||
if err := r.db.WithContext(ctx).Where("id = ?", id).First(&announcement).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -115,7 +117,7 @@ func (r *Repository) AdminGetByID(id uint64) (*AnnouncementDTO, error) {
|
||||
}
|
||||
|
||||
// Create 创建公告
|
||||
func (r *Repository) Create(req CreateAnnouncementRequest, createdBy uint64) (*AnnouncementDTO, error) {
|
||||
func (r *Repository) Create(ctx context.Context, req CreateAnnouncementRequest, createdBy uint64) (*AnnouncementDTO, error) {
|
||||
announcement := model.Announcement{
|
||||
Title: req.Title,
|
||||
Content: req.Content,
|
||||
@@ -127,7 +129,7 @@ func (r *Repository) Create(req CreateAnnouncementRequest, createdBy uint64) (*A
|
||||
CreatedBy: &createdBy,
|
||||
}
|
||||
|
||||
if err := r.db.Create(&announcement).Error; err != nil {
|
||||
if err := r.db.WithContext(ctx).Create(&announcement).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -136,7 +138,7 @@ func (r *Repository) Create(req CreateAnnouncementRequest, createdBy uint64) (*A
|
||||
}
|
||||
|
||||
// Update 更新公告
|
||||
func (r *Repository) Update(id uint64, req UpdateAnnouncementRequest) (*AnnouncementDTO, error) {
|
||||
func (r *Repository) Update(ctx context.Context, id uint64, req UpdateAnnouncementRequest) (*AnnouncementDTO, error) {
|
||||
updates := make(map[string]interface{})
|
||||
|
||||
if req.Title != "" {
|
||||
@@ -152,17 +154,17 @@ func (r *Repository) Update(id uint64, req UpdateAnnouncementRequest) (*Announce
|
||||
updates["is_pinned"] = req.IsPinned
|
||||
updates["is_important"] = req.IsImportant
|
||||
|
||||
if err := r.db.Model(&model.Announcement{}).Where("id = ?", id).Updates(updates).Error; err != nil {
|
||||
if err := r.db.WithContext(ctx).Model(&model.Announcement{}).Where("id = ?", id).Updates(updates).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return r.AdminGetByID(id)
|
||||
return r.AdminGetByID(ctx, id)
|
||||
}
|
||||
|
||||
// Publish 发布公告
|
||||
func (r *Repository) Publish(id uint64) error {
|
||||
func (r *Repository) Publish(ctx context.Context, id uint64) error {
|
||||
now := time.Now()
|
||||
return r.db.Model(&model.Announcement{}).
|
||||
return r.db.WithContext(ctx).Model(&model.Announcement{}).
|
||||
Where("id = ?", id).
|
||||
Updates(map[string]interface{}{
|
||||
"status": "published",
|
||||
@@ -171,15 +173,15 @@ func (r *Repository) Publish(id uint64) error {
|
||||
}
|
||||
|
||||
// Archive 归档公告
|
||||
func (r *Repository) Archive(id uint64) error {
|
||||
return r.db.Model(&model.Announcement{}).
|
||||
func (r *Repository) Archive(ctx context.Context, id uint64) error {
|
||||
return r.db.WithContext(ctx).Model(&model.Announcement{}).
|
||||
Where("id = ?", id).
|
||||
Update("status", "archived").Error
|
||||
}
|
||||
|
||||
// Delete 删除公告
|
||||
func (r *Repository) Delete(id uint64) error {
|
||||
return r.db.Where("id = ?", id).Delete(&model.Announcement{}).Error
|
||||
func (r *Repository) Delete(ctx context.Context, id uint64) error {
|
||||
return r.db.WithContext(ctx).Where("id = ?", id).Delete(&model.Announcement{}).Error
|
||||
}
|
||||
|
||||
func toAnnouncementDTO(a model.Announcement) AnnouncementDTO {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package announcement
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
|
||||
"gorm.io/gorm"
|
||||
@@ -15,13 +16,13 @@ func NewService(repo *Repository) *Service {
|
||||
}
|
||||
|
||||
var (
|
||||
ErrNotFound = errors.New("公告不存在")
|
||||
ErrInvalidRequest = errors.New("请求参数不正确")
|
||||
ErrUnauthorized = errors.New("未授权")
|
||||
ErrNotFound = errors.New("公告不存在")
|
||||
ErrInvalidRequest = errors.New("请求参数不正确")
|
||||
ErrUnauthorized = errors.New("未授权")
|
||||
)
|
||||
|
||||
// List 获取公告列表(前台用户)
|
||||
func (s *Service) List(query AnnouncementListQuery) (*PaginatedResult, error) {
|
||||
func (s *Service) List(ctx context.Context, query AnnouncementListQuery) (*PaginatedResult, error) {
|
||||
if query.Page < 1 {
|
||||
query.Page = 1
|
||||
}
|
||||
@@ -32,12 +33,12 @@ func (s *Service) List(query AnnouncementListQuery) (*PaginatedResult, error) {
|
||||
query.PageSize = 100
|
||||
}
|
||||
|
||||
return s.repo.List(query)
|
||||
return s.repo.List(ctx, query)
|
||||
}
|
||||
|
||||
// GetByID 获取公告详情
|
||||
func (s *Service) GetByID(id uint64) (*AnnouncementDTO, error) {
|
||||
dto, err := s.repo.GetByID(id)
|
||||
func (s *Service) GetByID(ctx context.Context, id uint64) (*AnnouncementDTO, error) {
|
||||
dto, err := s.repo.GetByID(ctx, id)
|
||||
if err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return nil, ErrNotFound
|
||||
@@ -48,7 +49,7 @@ func (s *Service) GetByID(id uint64) (*AnnouncementDTO, error) {
|
||||
}
|
||||
|
||||
// AdminList 管理员获取公告列表
|
||||
func (s *Service) AdminList(query AnnouncementListQuery) (*PaginatedResult, error) {
|
||||
func (s *Service) AdminList(ctx context.Context, query AnnouncementListQuery) (*PaginatedResult, error) {
|
||||
if query.Page < 1 {
|
||||
query.Page = 1
|
||||
}
|
||||
@@ -59,12 +60,12 @@ func (s *Service) AdminList(query AnnouncementListQuery) (*PaginatedResult, erro
|
||||
query.PageSize = 100
|
||||
}
|
||||
|
||||
return s.repo.AdminList(query)
|
||||
return s.repo.AdminList(ctx, query)
|
||||
}
|
||||
|
||||
// AdminGetByID 管理员获取公告详情
|
||||
func (s *Service) AdminGetByID(id uint64) (*AnnouncementDTO, error) {
|
||||
dto, err := s.repo.AdminGetByID(id)
|
||||
func (s *Service) AdminGetByID(ctx context.Context, id uint64) (*AnnouncementDTO, error) {
|
||||
dto, err := s.repo.AdminGetByID(ctx, id)
|
||||
if err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return nil, ErrNotFound
|
||||
@@ -75,26 +76,26 @@ func (s *Service) AdminGetByID(id uint64) (*AnnouncementDTO, error) {
|
||||
}
|
||||
|
||||
// Create 创建公告
|
||||
func (s *Service) Create(req CreateAnnouncementRequest, createdBy uint64) (*AnnouncementDTO, error) {
|
||||
return s.repo.Create(req, createdBy)
|
||||
func (s *Service) Create(ctx context.Context, req CreateAnnouncementRequest, createdBy uint64) (*AnnouncementDTO, error) {
|
||||
return s.repo.Create(ctx, req, createdBy)
|
||||
}
|
||||
|
||||
// Update 更新公告
|
||||
func (s *Service) Update(id uint64, req UpdateAnnouncementRequest) (*AnnouncementDTO, error) {
|
||||
return s.repo.Update(id, req)
|
||||
func (s *Service) Update(ctx context.Context, id uint64, req UpdateAnnouncementRequest) (*AnnouncementDTO, error) {
|
||||
return s.repo.Update(ctx, id, req)
|
||||
}
|
||||
|
||||
// Publish 发布公告
|
||||
func (s *Service) Publish(id uint64) error {
|
||||
return s.repo.Publish(id)
|
||||
func (s *Service) Publish(ctx context.Context, id uint64) error {
|
||||
return s.repo.Publish(ctx, id)
|
||||
}
|
||||
|
||||
// Archive 归档公告
|
||||
func (s *Service) Archive(id uint64) error {
|
||||
return s.repo.Archive(id)
|
||||
func (s *Service) Archive(ctx context.Context, id uint64) error {
|
||||
return s.repo.Archive(ctx, id)
|
||||
}
|
||||
|
||||
// Delete 删除公告
|
||||
func (s *Service) Delete(id uint64) error {
|
||||
return s.repo.Delete(id)
|
||||
func (s *Service) Delete(ctx context.Context, id uint64) error {
|
||||
return s.repo.Delete(ctx, id)
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ func (h *Handler) List(c *gin.Context) {
|
||||
page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
|
||||
pageSize, _ := strconv.Atoi(c.DefaultQuery("page_size", "20"))
|
||||
|
||||
result, err := h.service.List(userID, page, pageSize)
|
||||
result, err := h.service.List(c.Request.Context(), userID, page, pageSize)
|
||||
if err != nil {
|
||||
writeError(c, err)
|
||||
return
|
||||
@@ -46,7 +46,7 @@ func (h *Handler) FindByID(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
account, err := h.service.FindByID(userID, id)
|
||||
account, err := h.service.FindByID(c.Request.Context(), userID, id)
|
||||
if err != nil {
|
||||
writeError(c, err)
|
||||
return
|
||||
@@ -68,7 +68,7 @@ func (h *Handler) Create(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
account, err := h.service.Create(userID, req)
|
||||
account, err := h.service.Create(c.Request.Context(), userID, req)
|
||||
if err != nil {
|
||||
writeError(c, err)
|
||||
return
|
||||
@@ -95,7 +95,7 @@ func (h *Handler) Update(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
account, err := h.service.Update(userID, id, req)
|
||||
account, err := h.service.Update(c.Request.Context(), userID, id, req)
|
||||
if err != nil {
|
||||
writeError(c, err)
|
||||
return
|
||||
@@ -116,7 +116,7 @@ func (h *Handler) Delete(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
if err := h.service.Delete(userID, id); err != nil {
|
||||
if err := h.service.Delete(c.Request.Context(), userID, id); err != nil {
|
||||
writeError(c, err)
|
||||
return
|
||||
}
|
||||
@@ -136,7 +136,7 @@ func (h *Handler) SetDefault(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
if err := h.service.SetDefault(userID, id); err != nil {
|
||||
if err := h.service.SetDefault(c.Request.Context(), userID, id); err != nil {
|
||||
writeError(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package paymentaccount
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"strings"
|
||||
@@ -22,9 +23,10 @@ func NewRepository(db *gorm.DB) *Repository {
|
||||
return &Repository{db: db}
|
||||
}
|
||||
|
||||
func (r *Repository) List(userID uint64, page, pageSize int) (*PaginatedResult, error) {
|
||||
func (r *Repository) List(ctx context.Context, userID uint64, page, pageSize int) (*PaginatedResult, error) {
|
||||
db := r.db.WithContext(ctx)
|
||||
var total int64
|
||||
if err := r.db.Model(&model.UserPaymentAccount{}).
|
||||
if err := db.Model(&model.UserPaymentAccount{}).
|
||||
Where("user_id = ? AND status = ?", userID, "active").
|
||||
Count(&total).Error; err != nil {
|
||||
return nil, err
|
||||
@@ -32,7 +34,7 @@ func (r *Repository) List(userID uint64, page, pageSize int) (*PaginatedResult,
|
||||
|
||||
offset := (page - 1) * pageSize
|
||||
var accounts []model.UserPaymentAccount
|
||||
if err := r.db.Where("user_id = ? AND status = ?", userID, "active").
|
||||
if err := db.Where("user_id = ? AND status = ?", userID, "active").
|
||||
Order("is_default DESC, created_at DESC").
|
||||
Offset(offset).Limit(pageSize).
|
||||
Find(&accounts).Error; err != nil {
|
||||
@@ -56,9 +58,9 @@ func (r *Repository) List(userID uint64, page, pageSize int) (*PaginatedResult,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (r *Repository) FindByID(userID, id uint64) (*PaymentAccountDTO, error) {
|
||||
func (r *Repository) FindByID(ctx context.Context, userID, id uint64) (*PaymentAccountDTO, error) {
|
||||
var account model.UserPaymentAccount
|
||||
if err := r.db.Where("id = ? AND user_id = ? AND status = ?", id, userID, "active").
|
||||
if err := r.db.WithContext(ctx).Where("id = ? AND user_id = ? AND status = ?", id, userID, "active").
|
||||
First(&account).Error; err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return nil, ErrAccountNotFound
|
||||
@@ -68,7 +70,8 @@ func (r *Repository) FindByID(userID, id uint64) (*PaymentAccountDTO, error) {
|
||||
return r.toDTO(account)
|
||||
}
|
||||
|
||||
func (r *Repository) Create(userID uint64, req CreatePaymentAccountRequest) (*PaymentAccountDTO, error) {
|
||||
func (r *Repository) Create(ctx context.Context, userID uint64, req CreatePaymentAccountRequest) (*PaymentAccountDTO, error) {
|
||||
db := r.db.WithContext(ctx)
|
||||
// 加密账号
|
||||
encryptedNo, err := crypto.Encrypt(req.AccountNo)
|
||||
if err != nil {
|
||||
@@ -84,7 +87,7 @@ func (r *Repository) Create(userID uint64, req CreatePaymentAccountRequest) (*Pa
|
||||
// 如果是第一个账号,自动设为默认
|
||||
isDefault := false
|
||||
var count int64
|
||||
r.db.Model(&model.UserPaymentAccount{}).Where("user_id = ? AND status = ?", userID, "active").Count(&count)
|
||||
db.Model(&model.UserPaymentAccount{}).Where("user_id = ? AND status = ?", userID, "active").Count(&count)
|
||||
if count == 0 {
|
||||
isDefault = true
|
||||
}
|
||||
@@ -101,16 +104,17 @@ func (r *Repository) Create(userID uint64, req CreatePaymentAccountRequest) (*Pa
|
||||
Status: "active",
|
||||
}
|
||||
|
||||
if err := r.db.Create(&account).Error; err != nil {
|
||||
if err := db.Create(&account).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return r.FindByID(userID, account.ID)
|
||||
return r.FindByID(ctx, userID, account.ID)
|
||||
}
|
||||
|
||||
func (r *Repository) Update(userID, id uint64, req UpdatePaymentAccountRequest) (*PaymentAccountDTO, error) {
|
||||
func (r *Repository) Update(ctx context.Context, userID, id uint64, req UpdatePaymentAccountRequest) (*PaymentAccountDTO, error) {
|
||||
db := r.db.WithContext(ctx)
|
||||
var account model.UserPaymentAccount
|
||||
if err := r.db.Where("id = ? AND user_id = ? AND status = ?", id, userID, "active").
|
||||
if err := db.Where("id = ? AND user_id = ? AND status = ?", id, userID, "active").
|
||||
First(&account).Error; err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return nil, ErrAccountNotFound
|
||||
@@ -131,24 +135,25 @@ func (r *Repository) Update(userID, id uint64, req UpdatePaymentAccountRequest)
|
||||
|
||||
if req.IsDefault != nil && *req.IsDefault {
|
||||
// 先取消其他默认账号
|
||||
r.db.Model(&model.UserPaymentAccount{}).
|
||||
db.Model(&model.UserPaymentAccount{}).
|
||||
Where("user_id = ? AND id != ?", userID, id).
|
||||
Update("is_default", false)
|
||||
updates["is_default"] = true
|
||||
}
|
||||
|
||||
if len(updates) > 0 {
|
||||
if err := r.db.Model(&account).Updates(updates).Error; err != nil {
|
||||
if err := db.Model(&account).Updates(updates).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return r.FindByID(userID, id)
|
||||
return r.FindByID(ctx, userID, id)
|
||||
}
|
||||
|
||||
func (r *Repository) Delete(userID, id uint64) error {
|
||||
func (r *Repository) Delete(ctx context.Context, userID, id uint64) error {
|
||||
db := r.db.WithContext(ctx)
|
||||
var account model.UserPaymentAccount
|
||||
if err := r.db.Where("id = ? AND user_id = ? AND status = ?", id, userID, "active").
|
||||
if err := db.Where("id = ? AND user_id = ? AND status = ?", id, userID, "active").
|
||||
First(&account).Error; err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return ErrAccountNotFound
|
||||
@@ -157,13 +162,13 @@ func (r *Repository) Delete(userID, id uint64) error {
|
||||
}
|
||||
|
||||
// 软删除
|
||||
return r.db.Model(&account).Update("status", "disabled").Error
|
||||
return db.Model(&account).Update("status", "disabled").Error
|
||||
}
|
||||
|
||||
func (r *Repository) SetDefault(userID, id uint64) error {
|
||||
func (r *Repository) SetDefault(ctx context.Context, userID, id uint64) error {
|
||||
// 验证账号存在
|
||||
var account model.UserPaymentAccount
|
||||
if err := r.db.Where("id = ? AND user_id = ? AND status = ?", id, userID, "active").
|
||||
if err := r.db.WithContext(ctx).Where("id = ? AND user_id = ? AND status = ?", id, userID, "active").
|
||||
First(&account).Error; err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return ErrAccountNotFound
|
||||
@@ -171,7 +176,7 @@ func (r *Repository) SetDefault(userID, id uint64) error {
|
||||
return err
|
||||
}
|
||||
|
||||
return r.db.Transaction(func(tx *gorm.DB) error {
|
||||
return r.db.WithContext(ctx).Transaction(func(tx *gorm.DB) error {
|
||||
// 取消其他默认账号
|
||||
if err := tx.Model(&model.UserPaymentAccount{}).
|
||||
Where("user_id = ? AND id != ?", userID, id).
|
||||
@@ -183,17 +188,18 @@ func (r *Repository) SetDefault(userID, id uint64) error {
|
||||
})
|
||||
}
|
||||
|
||||
func (r *Repository) CountByUser(userID uint64) (int64, error) {
|
||||
func (r *Repository) CountByUser(ctx context.Context, userID uint64) (int64, error) {
|
||||
var count int64
|
||||
err := r.db.Model(&model.UserPaymentAccount{}).
|
||||
err := r.db.WithContext(ctx).Model(&model.UserPaymentAccount{}).
|
||||
Where("user_id = ? AND status = ?", userID, "active").
|
||||
Count(&count).Error
|
||||
return count, err
|
||||
}
|
||||
|
||||
func (r *Repository) ValidateRealname(userID uint64, accountName string) error {
|
||||
func (r *Repository) ValidateRealname(ctx context.Context, userID uint64, accountName string) error {
|
||||
var user model.User
|
||||
if err := r.db.First(&user, userID).Error; err != nil {
|
||||
db := r.db.WithContext(ctx)
|
||||
if err := db.First(&user, userID).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -203,7 +209,7 @@ func (r *Repository) ValidateRealname(userID uint64, accountName string) error {
|
||||
|
||||
// 获取实名信息
|
||||
var realname model.UserRealname
|
||||
if err := r.db.Where("user_id = ? AND status = ?", userID, "verified").
|
||||
if err := db.Where("user_id = ? AND status = ?", userID, "verified").
|
||||
First(&realname).Error; err != nil {
|
||||
return ErrRealnameRequired
|
||||
}
|
||||
@@ -303,9 +309,9 @@ func maskAccountNo(accountNo, accountType string) string {
|
||||
}
|
||||
|
||||
// 获取解密后的账号(仅供内部使用,如提现申请时)
|
||||
func (r *Repository) GetDecryptedAccountNo(userID, id uint64) (string, error) {
|
||||
func (r *Repository) GetDecryptedAccountNo(ctx context.Context, userID, id uint64) (string, error) {
|
||||
var account model.UserPaymentAccount
|
||||
if err := r.db.Where("id = ? AND user_id = ?", id, userID).First(&account).Error; err != nil {
|
||||
if err := r.db.WithContext(ctx).Where("id = ? AND user_id = ?", id, userID).First(&account).Error; err != nil {
|
||||
return "", err
|
||||
}
|
||||
return crypto.Decrypt(account.AccountNo)
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
package paymentaccount
|
||||
|
||||
import "errors"
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrDependencyUnavailable = errors.New("dependency unavailable")
|
||||
@@ -19,7 +22,7 @@ func NewService(repo *Repository) *Service {
|
||||
return &Service{repo: repo}
|
||||
}
|
||||
|
||||
func (s *Service) List(userID uint64, page, pageSize int) (*PaginatedResult, error) {
|
||||
func (s *Service) List(ctx context.Context, userID uint64, page, pageSize int) (*PaginatedResult, error) {
|
||||
if s.repo == nil {
|
||||
return nil, ErrDependencyUnavailable
|
||||
}
|
||||
@@ -29,52 +32,52 @@ func (s *Service) List(userID uint64, page, pageSize int) (*PaginatedResult, err
|
||||
if pageSize < 1 || pageSize > 100 {
|
||||
pageSize = 20
|
||||
}
|
||||
return s.repo.List(userID, page, pageSize)
|
||||
return s.repo.List(ctx, userID, page, pageSize)
|
||||
}
|
||||
|
||||
func (s *Service) FindByID(userID, id uint64) (*PaymentAccountDTO, error) {
|
||||
func (s *Service) FindByID(ctx context.Context, userID, id uint64) (*PaymentAccountDTO, error) {
|
||||
if s.repo == nil {
|
||||
return nil, ErrDependencyUnavailable
|
||||
}
|
||||
return s.repo.FindByID(userID, id)
|
||||
return s.repo.FindByID(ctx, userID, id)
|
||||
}
|
||||
|
||||
func (s *Service) Create(userID uint64, req CreatePaymentAccountRequest) (*PaymentAccountDTO, error) {
|
||||
func (s *Service) Create(ctx context.Context, userID uint64, req CreatePaymentAccountRequest) (*PaymentAccountDTO, error) {
|
||||
if s.repo == nil {
|
||||
return nil, ErrDependencyUnavailable
|
||||
}
|
||||
// 验证实名状态
|
||||
if err := s.repo.ValidateRealname(userID, req.AccountName); err != nil {
|
||||
if err := s.repo.ValidateRealname(ctx, userID, req.AccountName); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// 检查账号数量限制(最多5个)
|
||||
count, err := s.repo.CountByUser(userID)
|
||||
count, err := s.repo.CountByUser(ctx, userID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if count >= 5 {
|
||||
return nil, ErrAccountLimit
|
||||
}
|
||||
return s.repo.Create(userID, req)
|
||||
return s.repo.Create(ctx, userID, req)
|
||||
}
|
||||
|
||||
func (s *Service) Update(userID, id uint64, req UpdatePaymentAccountRequest) (*PaymentAccountDTO, error) {
|
||||
func (s *Service) Update(ctx context.Context, userID, id uint64, req UpdatePaymentAccountRequest) (*PaymentAccountDTO, error) {
|
||||
if s.repo == nil {
|
||||
return nil, ErrDependencyUnavailable
|
||||
}
|
||||
return s.repo.Update(userID, id, req)
|
||||
return s.repo.Update(ctx, userID, id, req)
|
||||
}
|
||||
|
||||
func (s *Service) Delete(userID, id uint64) error {
|
||||
func (s *Service) Delete(ctx context.Context, userID, id uint64) error {
|
||||
if s.repo == nil {
|
||||
return ErrDependencyUnavailable
|
||||
}
|
||||
return s.repo.Delete(userID, id)
|
||||
return s.repo.Delete(ctx, userID, id)
|
||||
}
|
||||
|
||||
func (s *Service) SetDefault(userID, id uint64) error {
|
||||
func (s *Service) SetDefault(ctx context.Context, userID, id uint64) error {
|
||||
if s.repo == nil {
|
||||
return ErrDependencyUnavailable
|
||||
}
|
||||
return s.repo.SetDefault(userID, id)
|
||||
return s.repo.SetDefault(ctx, userID, id)
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@ func (h *Handler) Create(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
withdrawal, err := h.service.Create(userID, req)
|
||||
withdrawal, err := h.service.Create(c.Request.Context(), userID, req)
|
||||
if err != nil {
|
||||
writeError(c, err)
|
||||
return
|
||||
@@ -49,7 +49,7 @@ func (h *Handler) List(c *gin.Context) {
|
||||
page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
|
||||
pageSize, _ := strconv.Atoi(c.DefaultQuery("page_size", "20"))
|
||||
|
||||
result, err := h.service.List(userID, page, pageSize)
|
||||
result, err := h.service.List(c.Request.Context(), userID, page, pageSize)
|
||||
if err != nil {
|
||||
writeError(c, err)
|
||||
return
|
||||
@@ -70,7 +70,7 @@ func (h *Handler) FindByID(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
withdrawal, err := h.service.FindByID(userID, id)
|
||||
withdrawal, err := h.service.FindByID(c.Request.Context(), userID, id)
|
||||
if err != nil {
|
||||
writeError(c, err)
|
||||
return
|
||||
@@ -91,7 +91,7 @@ func (h *Handler) Cancel(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
if err := h.service.Cancel(userID, id); err != nil {
|
||||
if err := h.service.Cancel(c.Request.Context(), userID, id); err != nil {
|
||||
writeError(c, err)
|
||||
return
|
||||
}
|
||||
@@ -108,7 +108,7 @@ func (h *Handler) AdminList(c *gin.Context) {
|
||||
query.Size = 20
|
||||
}
|
||||
|
||||
result, err := h.service.AdminList(query)
|
||||
result, err := h.service.AdminList(c.Request.Context(), query)
|
||||
if err != nil {
|
||||
writeError(c, err)
|
||||
return
|
||||
@@ -123,7 +123,7 @@ func (h *Handler) AdminFindByID(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
withdrawal, err := h.service.AdminFindByID(id)
|
||||
withdrawal, err := h.service.AdminFindByID(c.Request.Context(), id)
|
||||
if err != nil {
|
||||
writeError(c, err)
|
||||
return
|
||||
@@ -150,7 +150,7 @@ func (h *Handler) Review(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
withdrawal, err := h.service.Review(adminID, id, req)
|
||||
withdrawal, err := h.service.Review(c.Request.Context(), adminID, id, req)
|
||||
if err != nil {
|
||||
writeError(c, err)
|
||||
return
|
||||
@@ -177,7 +177,7 @@ func (h *Handler) ConfirmPayment(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
withdrawal, err := h.service.ConfirmPayment(adminID, id, req)
|
||||
withdrawal, err := h.service.ConfirmPayment(c.Request.Context(), adminID, id, req)
|
||||
if err != nil {
|
||||
writeError(c, err)
|
||||
return
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package withdrawal
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/rand"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
@@ -28,10 +29,11 @@ func NewRepository(db *gorm.DB, walletRepo *wallet.Repository) *Repository {
|
||||
}
|
||||
|
||||
// 用户创建提现申请
|
||||
func (r *Repository) Create(userID uint64, req CreateWithdrawalRequest) (*WithdrawalDTO, error) {
|
||||
func (r *Repository) Create(ctx context.Context, userID uint64, req CreateWithdrawalRequest) (*WithdrawalDTO, error) {
|
||||
db := r.db.WithContext(ctx)
|
||||
// 验证收款账号
|
||||
var paymentAccount model.UserPaymentAccount
|
||||
if err := r.db.Where("id = ? AND user_id = ? AND status = ?", req.PaymentAccountID, userID, "active").
|
||||
if err := db.Where("id = ? AND user_id = ? AND status = ?", req.PaymentAccountID, userID, "active").
|
||||
First(&paymentAccount).Error; err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return nil, errors.New("payment account not found")
|
||||
@@ -71,7 +73,7 @@ func (r *Repository) Create(userID uint64, req CreateWithdrawalRequest) (*Withdr
|
||||
}
|
||||
|
||||
// 事务处理
|
||||
err = r.db.Transaction(func(tx *gorm.DB) error {
|
||||
err = db.Transaction(func(tx *gorm.DB) error {
|
||||
// 创建提现申请
|
||||
if err := tx.Create(&withdrawal).Error; err != nil {
|
||||
return err
|
||||
@@ -105,13 +107,14 @@ func (r *Repository) Create(userID uint64, req CreateWithdrawalRequest) (*Withdr
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return r.FindByID(userID, withdrawal.ID)
|
||||
return r.FindByID(ctx, userID, withdrawal.ID)
|
||||
}
|
||||
|
||||
// 用户查询提现列表
|
||||
func (r *Repository) List(userID uint64, page, pageSize int) (*PaginatedResult, error) {
|
||||
func (r *Repository) List(ctx context.Context, userID uint64, page, pageSize int) (*PaginatedResult, error) {
|
||||
db := r.db.WithContext(ctx)
|
||||
var total int64
|
||||
if err := r.db.Model(&model.WithdrawalRequest{}).
|
||||
if err := db.Model(&model.WithdrawalRequest{}).
|
||||
Where("user_id = ?", userID).
|
||||
Count(&total).Error; err != nil {
|
||||
return nil, err
|
||||
@@ -119,7 +122,7 @@ func (r *Repository) List(userID uint64, page, pageSize int) (*PaginatedResult,
|
||||
|
||||
offset := (page - 1) * pageSize
|
||||
var withdrawals []model.WithdrawalRequest
|
||||
if err := r.db.Where("user_id = ?", userID).
|
||||
if err := db.Where("user_id = ?", userID).
|
||||
Order("created_at DESC").
|
||||
Offset(offset).Limit(pageSize).
|
||||
Find(&withdrawals).Error; err != nil {
|
||||
@@ -140,9 +143,9 @@ func (r *Repository) List(userID uint64, page, pageSize int) (*PaginatedResult,
|
||||
}
|
||||
|
||||
// 用户查询提现详情
|
||||
func (r *Repository) FindByID(userID, id uint64) (*WithdrawalDTO, error) {
|
||||
func (r *Repository) FindByID(ctx context.Context, userID, id uint64) (*WithdrawalDTO, error) {
|
||||
var withdrawal model.WithdrawalRequest
|
||||
if err := r.db.Where("id = ? AND user_id = ?", id, userID).
|
||||
if err := r.db.WithContext(ctx).Where("id = ? AND user_id = ?", id, userID).
|
||||
First(&withdrawal).Error; err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return nil, ErrWithdrawalNotFound
|
||||
@@ -154,9 +157,10 @@ func (r *Repository) FindByID(userID, id uint64) (*WithdrawalDTO, error) {
|
||||
}
|
||||
|
||||
// 用户取消提现
|
||||
func (r *Repository) Cancel(userID, id uint64) error {
|
||||
func (r *Repository) Cancel(ctx context.Context, userID, id uint64) error {
|
||||
db := r.db.WithContext(ctx)
|
||||
var withdrawal model.WithdrawalRequest
|
||||
if err := r.db.Where("id = ? AND user_id = ?", id, userID).
|
||||
if err := db.Where("id = ? AND user_id = ?", id, userID).
|
||||
First(&withdrawal).Error; err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return ErrWithdrawalNotFound
|
||||
@@ -169,7 +173,7 @@ func (r *Repository) Cancel(userID, id uint64) error {
|
||||
return ErrWithdrawalLocked
|
||||
}
|
||||
|
||||
return r.db.Transaction(func(tx *gorm.DB) error {
|
||||
return db.Transaction(func(tx *gorm.DB) error {
|
||||
// 更新状态
|
||||
if err := tx.Model(&withdrawal).Update("status", "cancelled").Error; err != nil {
|
||||
return err
|
||||
@@ -201,8 +205,8 @@ func (r *Repository) Cancel(userID, id uint64) error {
|
||||
}
|
||||
|
||||
// 管理员查询提现列表
|
||||
func (r *Repository) AdminList(query AdminListQuery) (*AdminPaginatedResult, error) {
|
||||
db := r.db.Model(&model.WithdrawalRequest{})
|
||||
func (r *Repository) AdminList(ctx context.Context, query AdminListQuery) (*AdminPaginatedResult, error) {
|
||||
db := r.db.WithContext(ctx).Model(&model.WithdrawalRequest{})
|
||||
|
||||
if query.Status != "" {
|
||||
db = db.Where("status = ?", query.Status)
|
||||
@@ -226,7 +230,7 @@ func (r *Repository) AdminList(query AdminListQuery) (*AdminPaginatedResult, err
|
||||
|
||||
items := make([]WithdrawalDetailDTO, 0, len(withdrawals))
|
||||
for _, w := range withdrawals {
|
||||
dto, err := r.toDetailDTO(w)
|
||||
dto, err := r.toDetailDTO(ctx, w)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
@@ -242,21 +246,22 @@ func (r *Repository) AdminList(query AdminListQuery) (*AdminPaginatedResult, err
|
||||
}
|
||||
|
||||
// 管理员查询提现详情
|
||||
func (r *Repository) AdminFindByID(id uint64) (*WithdrawalDetailDTO, error) {
|
||||
func (r *Repository) AdminFindByID(ctx context.Context, id uint64) (*WithdrawalDetailDTO, error) {
|
||||
var withdrawal model.WithdrawalRequest
|
||||
if err := r.db.First(&withdrawal, id).Error; err != nil {
|
||||
if err := r.db.WithContext(ctx).First(&withdrawal, id).Error; err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return nil, ErrWithdrawalNotFound
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
return r.toDetailDTO(withdrawal)
|
||||
return r.toDetailDTO(ctx, withdrawal)
|
||||
}
|
||||
|
||||
// 管理员审核提现
|
||||
func (r *Repository) Review(adminID, id uint64, req ReviewWithdrawalRequest) (*WithdrawalDetailDTO, error) {
|
||||
func (r *Repository) Review(ctx context.Context, adminID, id uint64, req ReviewWithdrawalRequest) (*WithdrawalDetailDTO, error) {
|
||||
db := r.db.WithContext(ctx)
|
||||
var withdrawal model.WithdrawalRequest
|
||||
if err := r.db.First(&withdrawal, id).Error; err != nil {
|
||||
if err := db.First(&withdrawal, id).Error; err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return nil, ErrWithdrawalNotFound
|
||||
}
|
||||
@@ -282,7 +287,7 @@ func (r *Repository) Review(adminID, id uint64, req ReviewWithdrawalRequest) (*W
|
||||
withdrawal.ReviewedAt = &now
|
||||
withdrawal.ReviewRemark = req.Remark
|
||||
|
||||
err := r.db.Transaction(func(tx *gorm.DB) error {
|
||||
err := db.Transaction(func(tx *gorm.DB) error {
|
||||
if err := tx.Save(&withdrawal).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -317,13 +322,14 @@ func (r *Repository) Review(adminID, id uint64, req ReviewWithdrawalRequest) (*W
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return r.AdminFindByID(id)
|
||||
return r.AdminFindByID(ctx, id)
|
||||
}
|
||||
|
||||
// 管理员确认打款
|
||||
func (r *Repository) ConfirmPayment(adminID, id uint64, req ConfirmPaymentRequest) (*WithdrawalDetailDTO, error) {
|
||||
func (r *Repository) ConfirmPayment(ctx context.Context, adminID, id uint64, req ConfirmPaymentRequest) (*WithdrawalDetailDTO, error) {
|
||||
db := r.db.WithContext(ctx)
|
||||
var withdrawal model.WithdrawalRequest
|
||||
if err := r.db.First(&withdrawal, id).Error; err != nil {
|
||||
if err := db.First(&withdrawal, id).Error; err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return nil, ErrWithdrawalNotFound
|
||||
}
|
||||
@@ -342,7 +348,7 @@ func (r *Repository) ConfirmPayment(adminID, id uint64, req ConfirmPaymentReques
|
||||
withdrawal.PaymentProofURL = req.PaymentProofURL
|
||||
withdrawal.PaymentRemark = req.Remark
|
||||
|
||||
err := r.db.Transaction(func(tx *gorm.DB) error {
|
||||
err := db.Transaction(func(tx *gorm.DB) error {
|
||||
if err := tx.Save(&withdrawal).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -367,7 +373,7 @@ func (r *Repository) ConfirmPayment(adminID, id uint64, req ConfirmPaymentReques
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return r.AdminFindByID(id)
|
||||
return r.AdminFindByID(ctx, id)
|
||||
}
|
||||
|
||||
// 转换为用户DTO
|
||||
@@ -393,16 +399,17 @@ func toDTO(w model.WithdrawalRequest) WithdrawalDTO {
|
||||
}
|
||||
|
||||
// 转换为管理员详细DTO
|
||||
func (r *Repository) toDetailDTO(w model.WithdrawalRequest) (*WithdrawalDetailDTO, error) {
|
||||
func (r *Repository) toDetailDTO(ctx context.Context, w model.WithdrawalRequest) (*WithdrawalDetailDTO, error) {
|
||||
db := r.db.WithContext(ctx)
|
||||
// 查询用户信息
|
||||
var user model.User
|
||||
r.db.Select("nickname, phone").First(&user, w.UserID)
|
||||
db.Select("nickname, phone").First(&user, w.UserID)
|
||||
|
||||
// 查询审核人信息
|
||||
var reviewedByName string
|
||||
if w.ReviewedBy != nil {
|
||||
var admin model.AdminUser
|
||||
if err := r.db.Select("nickname").First(&admin, *w.ReviewedBy).Error; err == nil {
|
||||
if err := db.Select("nickname").First(&admin, *w.ReviewedBy).Error; err == nil {
|
||||
reviewedByName = admin.Nickname
|
||||
}
|
||||
}
|
||||
@@ -411,7 +418,7 @@ func (r *Repository) toDetailDTO(w model.WithdrawalRequest) (*WithdrawalDetailDT
|
||||
var paidByName string
|
||||
if w.PaidBy != nil {
|
||||
var admin model.AdminUser
|
||||
if err := r.db.Select("nickname").First(&admin, *w.PaidBy).Error; err == nil {
|
||||
if err := db.Select("nickname").First(&admin, *w.PaidBy).Error; err == nil {
|
||||
paidByName = admin.Nickname
|
||||
}
|
||||
}
|
||||
@@ -421,7 +428,7 @@ func (r *Repository) toDetailDTO(w model.WithdrawalRequest) (*WithdrawalDetailDT
|
||||
var certificateURLs []string
|
||||
if w.PaymentAccountID != nil {
|
||||
var paymentAccount model.UserPaymentAccount
|
||||
if err := r.db.First(&paymentAccount, *w.PaymentAccountID).Error; err == nil {
|
||||
if err := db.First(&paymentAccount, *w.PaymentAccountID).Error; err == nil {
|
||||
// 解密账号
|
||||
decrypted, err := crypto.Decrypt(paymentAccount.AccountNo)
|
||||
if err == nil {
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
package withdrawal
|
||||
|
||||
import "errors"
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrDependencyUnavailable = errors.New("dependency unavailable")
|
||||
@@ -14,7 +17,7 @@ var (
|
||||
)
|
||||
|
||||
const (
|
||||
MinWithdrawalAmountCent = 1000 // 最低提现金额:10元 = 1000分
|
||||
MinWithdrawalAmountCent = 1000 // 最低提现金额:10元 = 1000分
|
||||
MaxWithdrawalAmountCent = 500000 // 单笔最高提现金额:5000元 = 500000分
|
||||
WithdrawalFeeRate = 0.0 // 手续费率(暂时0%)
|
||||
)
|
||||
@@ -28,7 +31,7 @@ func NewService(repo *Repository) *Service {
|
||||
}
|
||||
|
||||
// 用户端方法
|
||||
func (s *Service) Create(userID uint64, req CreateWithdrawalRequest) (*WithdrawalDTO, error) {
|
||||
func (s *Service) Create(ctx context.Context, userID uint64, req CreateWithdrawalRequest) (*WithdrawalDTO, error) {
|
||||
if s.repo == nil {
|
||||
return nil, ErrDependencyUnavailable
|
||||
}
|
||||
@@ -41,10 +44,10 @@ func (s *Service) Create(userID uint64, req CreateWithdrawalRequest) (*Withdrawa
|
||||
return nil, ErrMaxWithdrawalAmount
|
||||
}
|
||||
|
||||
return s.repo.Create(userID, req)
|
||||
return s.repo.Create(ctx, userID, req)
|
||||
}
|
||||
|
||||
func (s *Service) List(userID uint64, page, pageSize int) (*PaginatedResult, error) {
|
||||
func (s *Service) List(ctx context.Context, userID uint64, page, pageSize int) (*PaginatedResult, error) {
|
||||
if s.repo == nil {
|
||||
return nil, ErrDependencyUnavailable
|
||||
}
|
||||
@@ -54,25 +57,25 @@ func (s *Service) List(userID uint64, page, pageSize int) (*PaginatedResult, err
|
||||
if pageSize < 1 || pageSize > 100 {
|
||||
pageSize = 20
|
||||
}
|
||||
return s.repo.List(userID, page, pageSize)
|
||||
return s.repo.List(ctx, userID, page, pageSize)
|
||||
}
|
||||
|
||||
func (s *Service) FindByID(userID, id uint64) (*WithdrawalDTO, error) {
|
||||
func (s *Service) FindByID(ctx context.Context, userID, id uint64) (*WithdrawalDTO, error) {
|
||||
if s.repo == nil {
|
||||
return nil, ErrDependencyUnavailable
|
||||
}
|
||||
return s.repo.FindByID(userID, id)
|
||||
return s.repo.FindByID(ctx, userID, id)
|
||||
}
|
||||
|
||||
func (s *Service) Cancel(userID, id uint64) error {
|
||||
func (s *Service) Cancel(ctx context.Context, userID, id uint64) error {
|
||||
if s.repo == nil {
|
||||
return ErrDependencyUnavailable
|
||||
}
|
||||
return s.repo.Cancel(userID, id)
|
||||
return s.repo.Cancel(ctx, userID, id)
|
||||
}
|
||||
|
||||
// 管理员端方法
|
||||
func (s *Service) AdminList(query AdminListQuery) (*AdminPaginatedResult, error) {
|
||||
func (s *Service) AdminList(ctx context.Context, query AdminListQuery) (*AdminPaginatedResult, error) {
|
||||
if s.repo == nil {
|
||||
return nil, ErrDependencyUnavailable
|
||||
}
|
||||
@@ -82,26 +85,26 @@ func (s *Service) AdminList(query AdminListQuery) (*AdminPaginatedResult, error)
|
||||
if query.Size < 1 || query.Size > 100 {
|
||||
query.Size = 20
|
||||
}
|
||||
return s.repo.AdminList(query)
|
||||
return s.repo.AdminList(ctx, query)
|
||||
}
|
||||
|
||||
func (s *Service) AdminFindByID(id uint64) (*WithdrawalDetailDTO, error) {
|
||||
func (s *Service) AdminFindByID(ctx context.Context, id uint64) (*WithdrawalDetailDTO, error) {
|
||||
if s.repo == nil {
|
||||
return nil, ErrDependencyUnavailable
|
||||
}
|
||||
return s.repo.AdminFindByID(id)
|
||||
return s.repo.AdminFindByID(ctx, id)
|
||||
}
|
||||
|
||||
func (s *Service) Review(adminID, id uint64, req ReviewWithdrawalRequest) (*WithdrawalDetailDTO, error) {
|
||||
func (s *Service) Review(ctx context.Context, adminID, id uint64, req ReviewWithdrawalRequest) (*WithdrawalDetailDTO, error) {
|
||||
if s.repo == nil {
|
||||
return nil, ErrDependencyUnavailable
|
||||
}
|
||||
return s.repo.Review(adminID, id, req)
|
||||
return s.repo.Review(ctx, adminID, id, req)
|
||||
}
|
||||
|
||||
func (s *Service) ConfirmPayment(adminID, id uint64, req ConfirmPaymentRequest) (*WithdrawalDetailDTO, error) {
|
||||
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(adminID, id, req)
|
||||
return s.repo.ConfirmPayment(ctx, adminID, id, req)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user