feat: 实现平台抽成、提现审批、异步任务集成及安全审计功能
This commit is contained in:
@@ -291,3 +291,97 @@ func (s *super) UserStatuses(ctx context.Context) ([]requests.KV, error) {
|
||||
func (s *super) TenantStatuses(ctx context.Context) ([]requests.KV, error) {
|
||||
return consts.TenantStatusItems(), nil
|
||||
}
|
||||
|
||||
func (s *super) ListWithdrawals(ctx context.Context, filter *super_dto.SuperOrderListFilter) (*requests.Pager, error) {
|
||||
tbl, q := models.OrderQuery.QueryContext(ctx)
|
||||
q = q.Where(tbl.Type.Eq(consts.OrderTypeWithdrawal))
|
||||
|
||||
filter.Pagination.Format()
|
||||
total, err := q.Count()
|
||||
if err != nil {
|
||||
return nil, errorx.ErrDatabaseError.WithCause(err)
|
||||
}
|
||||
|
||||
list, err := q.Offset(int(filter.Pagination.Offset())).Limit(int(filter.Pagination.Limit)).Order(tbl.ID.Desc()).Find()
|
||||
if err != nil {
|
||||
return nil, errorx.ErrDatabaseError.WithCause(err)
|
||||
}
|
||||
|
||||
// TODO: Map to SuperOrderItem properly with Tenant/User lookup
|
||||
return &requests.Pager{
|
||||
Pagination: filter.Pagination,
|
||||
Total: total,
|
||||
Items: list,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *super) ApproveWithdrawal(ctx context.Context, id int64) error {
|
||||
o, err := models.OrderQuery.WithContext(ctx).Where(models.OrderQuery.ID.Eq(id)).First()
|
||||
if err != nil {
|
||||
return errorx.ErrRecordNotFound
|
||||
}
|
||||
if o.Status != consts.OrderStatusCreated {
|
||||
return errorx.ErrStatusConflict.WithMsg("订单状态不正确")
|
||||
}
|
||||
|
||||
// Mark as Paid (Assumes external transfer done)
|
||||
_, err = models.OrderQuery.WithContext(ctx).Where(models.OrderQuery.ID.Eq(id)).Updates(&models.Order{
|
||||
Status: consts.OrderStatusPaid,
|
||||
PaidAt: time.Now(),
|
||||
UpdatedAt: time.Now(),
|
||||
})
|
||||
if err == nil && Audit != nil {
|
||||
Audit.Log(ctx, "approve_withdrawal", cast.ToString(id), "Approved withdrawal")
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (s *super) RejectWithdrawal(ctx context.Context, id int64, reason string) error {
|
||||
err := models.Q.Transaction(func(tx *models.Query) error {
|
||||
o, err := tx.Order.WithContext(ctx).Where(tx.Order.ID.Eq(id)).First()
|
||||
if err != nil {
|
||||
return errorx.ErrRecordNotFound
|
||||
}
|
||||
if o.Status != consts.OrderStatusCreated {
|
||||
return errorx.ErrStatusConflict.WithMsg("订单状态不正确")
|
||||
}
|
||||
|
||||
// Refund User Balance
|
||||
_, err = tx.User.WithContext(ctx).Where(tx.User.ID.Eq(o.UserID)).Update(tx.User.Balance, gorm.Expr("balance + ?", o.AmountPaid))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Update Order
|
||||
_, err = tx.Order.WithContext(ctx).Where(tx.Order.ID.Eq(id)).Updates(&models.Order{
|
||||
Status: consts.OrderStatusFailed, // or Canceled
|
||||
RefundReason: reason,
|
||||
UpdatedAt: time.Now(),
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Create Ledger (Adjustment/Unfreeze)
|
||||
ledger := &models.TenantLedger{
|
||||
TenantID: o.TenantID,
|
||||
UserID: o.UserID,
|
||||
OrderID: o.ID,
|
||||
Type: consts.TenantLedgerTypeAdjustment,
|
||||
Amount: o.AmountPaid,
|
||||
Remark: "提现拒绝返还: " + reason,
|
||||
OperatorUserID: 0, // System/Admin
|
||||
IdempotencyKey: uuid.NewString(),
|
||||
}
|
||||
if err := tx.TenantLedger.WithContext(ctx).Create(ledger); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
|
||||
if err == nil && Audit != nil {
|
||||
Audit.Log(ctx, "reject_withdrawal", cast.ToString(id), "Rejected: "+reason)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user