@@ -88,8 +88,118 @@ func (s *super) CheckToken(ctx context.Context, token string) (*super_dto.LoginR
func ( s * super ) ListUsers ( ctx context . Context , filter * super_dto . UserListFilter ) ( * requests . Pager , error ) {
tbl , q := models . UserQuery . QueryContext ( ctx )
if filter . Username != nil && * filter . Username != "" {
q = q . Where ( tbl . Username . Like ( "%" + * filter . Username + "%" ) ) . Or ( tbl . Nickname . Like ( "%" + * filter . Username + "%" ) )
if filter . ID != nil && * filter . ID > 0 {
q = q . Where ( tbl . ID . Eq ( * filter . ID ) )
}
if filter . Username != nil && strings . TrimSpace ( * filter . Username ) != "" {
keyword := "%" + strings . TrimSpace ( * filter . Username ) + "%"
q = q . Where ( tbl . Username . Like ( keyword ) ) . Or ( tbl . Nickname . Like ( keyword ) )
}
if filter . Status != nil && * filter . Status != "" {
q = q . Where ( tbl . Status . Eq ( * filter . Status ) )
}
if filter . Role != nil && * filter . Role != "" {
q = q . Where ( tbl . Roles . Contains ( types . Array [ consts . Role ] { * filter . Role } ) )
}
if filter . TenantID != nil && * filter . TenantID > 0 {
// 按租户成员过滤用户,需要先定位租户成员关系。
tblTu , qTu := models . TenantUserQuery . QueryContext ( ctx )
userIDs , err := qTu . Where ( tblTu . TenantID . Eq ( * filter . TenantID ) ) . Select ( tblTu . UserID ) . Find ( )
if err != nil {
return nil , errorx . ErrDatabaseError . WithCause ( err )
}
ids := make ( [ ] int64 , 0 , len ( userIDs ) )
for _ , row := range userIDs {
ids = append ( ids , row . UserID )
}
if len ( ids ) == 0 {
q = q . Where ( tbl . ID . Eq ( - 1 ) )
} else {
q = q . Where ( tbl . ID . In ( ids ... ) )
}
}
if filter . CreatedAtFrom != nil {
from , err := s . parseFilterTime ( filter . CreatedAtFrom )
if err != nil {
return nil , err
}
if from != nil {
q = q . Where ( tbl . CreatedAt . Gte ( * from ) )
}
}
if filter . CreatedAtTo != nil {
to , err := s . parseFilterTime ( filter . CreatedAtTo )
if err != nil {
return nil , err
}
if to != nil {
q = q . Where ( tbl . CreatedAt . Lte ( * to ) )
}
}
if filter . VerifiedAtFrom != nil {
from , err := s . parseFilterTime ( filter . VerifiedAtFrom )
if err != nil {
return nil , err
}
if from != nil {
q = q . Where ( tbl . VerifiedAt . Gte ( * from ) )
}
}
if filter . VerifiedAtTo != nil {
to , err := s . parseFilterTime ( filter . VerifiedAtTo )
if err != nil {
return nil , err
}
if to != nil {
q = q . Where ( tbl . VerifiedAt . Lte ( * to ) )
}
}
orderApplied := false
if filter . Desc != nil && strings . TrimSpace ( * filter . Desc ) != "" {
switch strings . TrimSpace ( * filter . Desc ) {
case "id" :
q = q . Order ( tbl . ID . Desc ( ) )
case "username" :
q = q . Order ( tbl . Username . Desc ( ) )
case "status" :
q = q . Order ( tbl . Status . Desc ( ) )
case "verified_at" :
q = q . Order ( tbl . VerifiedAt . Desc ( ) )
case "created_at" :
q = q . Order ( tbl . CreatedAt . Desc ( ) )
case "updated_at" :
q = q . Order ( tbl . UpdatedAt . Desc ( ) )
case "balance" :
q = q . Order ( tbl . Balance . Desc ( ) )
case "balance_frozen" :
q = q . Order ( tbl . BalanceFrozen . Desc ( ) )
}
orderApplied = true
} else if filter . Asc != nil && strings . TrimSpace ( * filter . Asc ) != "" {
switch strings . TrimSpace ( * filter . Asc ) {
case "id" :
q = q . Order ( tbl . ID )
case "username" :
q = q . Order ( tbl . Username )
case "status" :
q = q . Order ( tbl . Status )
case "verified_at" :
q = q . Order ( tbl . VerifiedAt )
case "created_at" :
q = q . Order ( tbl . CreatedAt )
case "updated_at" :
q = q . Order ( tbl . UpdatedAt )
case "balance" :
q = q . Order ( tbl . Balance )
case "balance_frozen" :
q = q . Order ( tbl . BalanceFrozen )
}
orderApplied = true
}
if ! orderApplied {
q = q . Order ( tbl . ID . Desc ( ) )
}
filter . Pagination . Format ( )
@@ -103,6 +213,20 @@ func (s *super) ListUsers(ctx context.Context, filter *super_dto.UserListFilter)
return nil , errorx . ErrDatabaseError . WithCause ( err )
}
userIDs := make ( [ ] int64 , 0 , len ( list ) )
for _ , u := range list {
userIDs = append ( userIDs , u . ID )
}
ownedCountMap , err := s . userOwnedTenantCount ( ctx , userIDs )
if err != nil {
return nil , err
}
joinedCountMap , err := s . userJoinedTenantCount ( ctx , userIDs )
if err != nil {
return nil , err
}
var data [ ] super_dto . UserItem
for _ , u := range list {
data = append ( data , super_dto . UserItem {
@@ -112,11 +236,14 @@ func (s *super) ListUsers(ctx context.Context, filter *super_dto.UserListFilter)
Roles : u . Roles ,
Status : u . Status ,
StatusDescription : u . Status . Description ( ) ,
Creat edAt: u . CreatedAt . F ormat( time . RFC3339 ) ,
Upd atedAt: u . UpdatedAt . F ormat( time . RFC3339 ) ,
Verifi edAt: s . f ormatTime ( u . VerifiedAt ) ,
Cre atedAt: s . f ormatTime ( u . CreatedAt ) ,
UpdatedAt : s . formatTime ( u . UpdatedAt ) ,
} ,
Balance : u . Balance ,
BalanceFrozen : u . BalanceFrozen ,
Balance : u . Balance ,
BalanceFrozen : u . BalanceFrozen ,
OwnedTenantCount : ownedCountMap [ u . ID ] ,
JoinedTenantCount : joinedCountMap [ u . ID ] ,
} )
}
@@ -175,8 +302,102 @@ func (s *super) UpdateUserRoles(ctx context.Context, id int64, form *super_dto.U
func ( s * super ) ListTenants ( ctx context . Context , filter * super_dto . TenantListFilter ) ( * requests . Pager , error ) {
tbl , q := models . TenantQuery . QueryContext ( ctx )
if filter . Name != nil && * filter . Name != "" {
q = q . Where ( tbl . Name . Like ( "%" + * filter . Name + "%" ) )
if filter . ID != nil && * filter . ID > 0 {
q = q . Where ( tbl . ID . Eq ( * filter . ID ) )
}
if filter . UserID != nil && * filter . UserID > 0 {
q = q . Where ( tbl . UserID . Eq ( * filter . UserID ) )
}
if filter . Name != nil && strings . TrimSpace ( * filter . Name ) != "" {
q = q . Where ( tbl . Name . Like ( "%" + strings . TrimSpace ( * filter . Name ) + "%" ) )
}
if filter . Code != nil && strings . TrimSpace ( * filter . Code ) != "" {
q = q . Where ( tbl . Code . Like ( "%" + strings . TrimSpace ( * filter . Code ) + "%" ) )
}
if filter . Status != nil && * filter . Status != "" {
q = q . Where ( tbl . Status . Eq ( * filter . Status ) )
}
if filter . ExpiredAtFrom != nil {
from , err := s . parseFilterTime ( filter . ExpiredAtFrom )
if err != nil {
return nil , err
}
if from != nil {
q = q . Where ( tbl . ExpiredAt . Gte ( * from ) )
}
}
if filter . ExpiredAtTo != nil {
to , err := s . parseFilterTime ( filter . ExpiredAtTo )
if err != nil {
return nil , err
}
if to != nil {
q = q . Where ( tbl . ExpiredAt . Lte ( * to ) )
}
}
if filter . CreatedAtFrom != nil {
from , err := s . parseFilterTime ( filter . CreatedAtFrom )
if err != nil {
return nil , err
}
if from != nil {
q = q . Where ( tbl . CreatedAt . Gte ( * from ) )
}
}
if filter . CreatedAtTo != nil {
to , err := s . parseFilterTime ( filter . CreatedAtTo )
if err != nil {
return nil , err
}
if to != nil {
q = q . Where ( tbl . CreatedAt . Lte ( * to ) )
}
}
orderApplied := false
if filter . Desc != nil && strings . TrimSpace ( * filter . Desc ) != "" {
switch strings . TrimSpace ( * filter . Desc ) {
case "id" :
q = q . Order ( tbl . ID . Desc ( ) )
case "name" :
q = q . Order ( tbl . Name . Desc ( ) )
case "code" :
q = q . Order ( tbl . Code . Desc ( ) )
case "status" :
q = q . Order ( tbl . Status . Desc ( ) )
case "expired_at" :
q = q . Order ( tbl . ExpiredAt . Desc ( ) )
case "created_at" :
q = q . Order ( tbl . CreatedAt . Desc ( ) )
case "updated_at" :
q = q . Order ( tbl . UpdatedAt . Desc ( ) )
case "user_id" :
q = q . Order ( tbl . UserID . Desc ( ) )
}
orderApplied = true
} else if filter . Asc != nil && strings . TrimSpace ( * filter . Asc ) != "" {
switch strings . TrimSpace ( * filter . Asc ) {
case "id" :
q = q . Order ( tbl . ID )
case "name" :
q = q . Order ( tbl . Name )
case "code" :
q = q . Order ( tbl . Code )
case "status" :
q = q . Order ( tbl . Status )
case "expired_at" :
q = q . Order ( tbl . ExpiredAt )
case "created_at" :
q = q . Order ( tbl . CreatedAt )
case "updated_at" :
q = q . Order ( tbl . UpdatedAt )
case "user_id" :
q = q . Order ( tbl . UserID )
}
orderApplied = true
}
if ! orderApplied {
q = q . Order ( tbl . ID . Desc ( ) )
}
filter . Pagination . Format ( )
@@ -185,24 +406,14 @@ func (s *super) ListTenants(ctx context.Context, filter *super_dto.TenantListFil
return nil , errorx . ErrDatabaseError . WithCause ( err )
}
list , err := q . Offset ( int ( filter . Pagination . Offset ( ) ) ) . Limit ( int ( filter . Pagination . Limit ) ) . Order ( tbl . ID . Desc ( ) ) . Find( )
list , err := q . Offset ( int ( filter . Pagination . Offset ( ) ) ) . Limit ( int ( filter . Pagination . Limit ) ) . Find ( )
if err != nil {
return nil , errorx . ErrDatabaseError . WithCause ( err )
}
var data [ ] super_dto . TenantItem
for _ , t : = range list {
data = append ( data , super_dto . TenantItem {
ID : t . ID ,
UUID : t . UUID . String ( ) ,
Name : t . Name ,
Code : t . Code ,
Status : t . Status ,
StatusDescription : t . Status . Description ( ) ,
UserID : t . UserID ,
CreatedAt : t . CreatedAt . Format ( time . RFC3339 ) ,
UpdatedAt : t . UpdatedAt . Format ( time . RFC3339 ) ,
} )
data , err := s . buildTenantItems ( ctx , list )
i f err ! = nil {
return nil , err
}
return & requests . Pager {
@@ -240,17 +451,14 @@ func (s *super) GetTenant(ctx context.Context, id int64) (*super_dto.TenantItem,
}
return nil , errorx . ErrDatabaseError . WithCause ( err )
}
return & super_dto . TenantItem {
ID : t . ID ,
UUID : t . UUID . String ( ) ,
Name : t . Name ,
Code : t . Code ,
Status : t . Status ,
StatusDescription : t . Status . Description ( ) ,
UserID : t . UserID ,
CreatedAt : t . CreatedAt . Format ( time . RFC3339 ) ,
UpdatedAt : t . UpdatedAt . Format ( time . RFC3339 ) ,
} , nil
items , err := s . buildTenantItems ( ctx , [ ] * models . Tenant { t } )
if err != nil {
return nil , err
}
if len ( items ) == 0 {
return nil , errorx . ErrRecordNotFound
}
return & items [ 0 ] , nil
}
func ( s * super ) UpdateTenantStatus ( ctx context . Context , id int64 , form * super_dto . TenantStatusUpdateForm ) error {
@@ -272,6 +480,177 @@ func (s *super) UpdateTenantExpire(ctx context.Context, id int64, form *super_dt
return nil
}
func ( s * super ) ListTenantUsers ( ctx context . Context , tenantID int64 , filter * super_dto . SuperTenantUserListFilter ) ( * requests . Pager , error ) {
tbl , q := models . TenantUserQuery . QueryContext ( ctx )
q = q . Where ( tbl . TenantID . Eq ( tenantID ) )
if filter . UserID != nil && * filter . UserID > 0 {
q = q . Where ( tbl . UserID . Eq ( * filter . UserID ) )
}
if filter . Status != nil && * filter . Status != "" {
q = q . Where ( tbl . Status . Eq ( * filter . Status ) )
}
if filter . Role != nil && * filter . Role != "" {
q = q . Where ( tbl . Role . Contains ( types . Array [ consts . TenantUserRole ] { * filter . Role } ) )
}
userIDs , userFilter , err := s . lookupUserIDs ( ctx , filter . Username )
if err != nil {
return nil , err
}
if userFilter {
if len ( userIDs ) == 0 {
q = q . Where ( tbl . ID . Eq ( - 1 ) )
} else {
q = q . Where ( tbl . UserID . In ( userIDs ... ) )
}
}
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 . CreatedAt . Desc ( ) ) . Find ( )
if err != nil {
return nil , errorx . ErrDatabaseError . WithCause ( err )
}
userMap , err := s . userMapByTenantUsers ( ctx , list )
if err != nil {
return nil , err
}
items := make ( [ ] super_dto . SuperTenantUserItem , 0 , len ( list ) )
for _ , tu := range list {
items = append ( items , super_dto . SuperTenantUserItem {
User : s . toSuperUserLite ( userMap [ tu . UserID ] ) ,
TenantUser : s . toSuperTenantUserDTO ( tu ) ,
} )
}
return & requests . Pager {
Pagination : filter . Pagination ,
Total : total ,
Items : items ,
} , nil
}
func ( s * super ) ListUserTenants ( ctx context . Context , userID int64 , filter * super_dto . SuperUserTenantListFilter ) ( * requests . Pager , error ) {
tbl , q := models . TenantUserQuery . QueryContext ( ctx )
q = q . Where ( tbl . UserID . Eq ( userID ) )
if filter . TenantID != nil && * filter . TenantID > 0 {
q = q . Where ( tbl . TenantID . Eq ( * filter . TenantID ) )
}
if filter . Status != nil && * filter . Status != "" {
q = q . Where ( tbl . Status . Eq ( * filter . Status ) )
}
if filter . Role != nil && * filter . Role != "" {
q = q . Where ( tbl . Role . Contains ( types . Array [ consts . TenantUserRole ] { * filter . Role } ) )
}
tenantIDs , tenantFilter , err := s . lookupTenantIDs ( ctx , filter . Code , filter . Name )
if err != nil {
return nil , err
}
if tenantFilter {
if len ( tenantIDs ) == 0 {
q = q . Where ( tbl . ID . Eq ( - 1 ) )
} else {
q = q . Where ( tbl . TenantID . In ( tenantIDs ... ) )
}
}
if filter . CreatedAtFrom != nil {
from , err := s . parseFilterTime ( filter . CreatedAtFrom )
if err != nil {
return nil , err
}
if from != nil {
q = q . Where ( tbl . CreatedAt . Gte ( * from ) )
}
}
if filter . CreatedAtTo != nil {
to , err := s . parseFilterTime ( filter . CreatedAtTo )
if err != nil {
return nil , err
}
if to != nil {
q = q . Where ( tbl . CreatedAt . Lte ( * to ) )
}
}
orderApplied := false
if filter . Desc != nil && strings . TrimSpace ( * filter . Desc ) != "" {
switch strings . TrimSpace ( * filter . Desc ) {
case "tenant_id" :
q = q . Order ( tbl . TenantID . Desc ( ) )
case "created_at" :
q = q . Order ( tbl . CreatedAt . Desc ( ) )
}
orderApplied = true
} else if filter . Asc != nil && strings . TrimSpace ( * filter . Asc ) != "" {
switch strings . TrimSpace ( * filter . Asc ) {
case "tenant_id" :
q = q . Order ( tbl . TenantID )
case "created_at" :
q = q . Order ( tbl . CreatedAt )
}
orderApplied = true
}
if ! orderApplied {
q = q . Order ( tbl . CreatedAt . Desc ( ) )
}
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 ) ) . Find ( )
if err != nil {
return nil , errorx . ErrDatabaseError . WithCause ( err )
}
tenantMap , ownerMap , err := s . tenantMapsForTenantUsers ( ctx , list )
if err != nil {
return nil , err
}
items := make ( [ ] super_dto . UserTenantItem , 0 , len ( list ) )
for _ , tu := range list {
tenant := tenantMap [ tu . TenantID ]
owner := ownerMap [ tu . TenantID ]
item := super_dto . UserTenantItem {
TenantID : tu . TenantID ,
Role : tu . Role ,
MemberStatus : tu . Status ,
MemberStatusDescription : tu . Status . Description ( ) ,
JoinedAt : s . formatTime ( tu . CreatedAt ) ,
}
if tenant != nil {
item . TenantStatus = tenant . Status
item . TenantStatusDescription = tenant . Status . Description ( )
item . Name = tenant . Name
item . Code = tenant . Code
item . ExpiredAt = s . formatTime ( tenant . ExpiredAt )
}
if owner != nil {
item . Owner = & super_dto . TenantOwnerUserLite {
ID : owner . ID ,
Username : owner . Username ,
}
}
items = append ( items , item )
}
return & requests . Pager {
Pagination : filter . Pagination ,
Total : total ,
Items : items ,
} , nil
}
func ( s * super ) ListContents ( ctx context . Context , filter * super_dto . SuperContentListFilter ) ( * requests . Pager , error ) {
tbl , q := models . ContentQuery . QueryContext ( ctx )
@@ -804,6 +1183,22 @@ func (s *super) toSuperUserDTO(u *models.User) *super_dto.User {
}
}
func ( s * super ) toSuperUserLite ( u * models . User ) * super_dto . SuperUserLite {
if u == nil {
return nil
}
return & super_dto . SuperUserLite {
ID : u . ID ,
Username : u . Username ,
Roles : u . Roles ,
Status : u . Status ,
StatusDescription : u . Status . Description ( ) ,
VerifiedAt : s . formatTime ( u . VerifiedAt ) ,
CreatedAt : s . formatTime ( u . CreatedAt ) ,
UpdatedAt : s . formatTime ( u . UpdatedAt ) ,
}
}
func hasRole ( roles types . Array [ consts . Role ] , role consts . Role ) bool {
for _ , r := range roles {
if r == role {
@@ -813,6 +1208,15 @@ func hasRole(roles types.Array[consts.Role], role consts.Role) bool {
return false
}
func hasTenantRole ( roles types . Array [ consts . TenantUserRole ] , role consts . TenantUserRole ) bool {
for _ , r := range roles {
if r == role {
return true
}
}
return false
}
func ( s * super ) buildSuperOrderItems ( ctx context . Context , orders [ ] * models . Order ) ( [ ] super_dto . SuperOrderItem , error ) {
if len ( orders ) == 0 {
return [ ] super_dto . SuperOrderItem { } , nil
@@ -1212,6 +1616,139 @@ func (s *super) toSuperDiscountValue(price *models.ContentPrice) float64 {
return float64 ( price . DiscountValue )
}
func ( s * super ) buildTenantItems ( ctx context . Context , list [ ] * models . Tenant ) ( [ ] super_dto . TenantItem , error ) {
if len ( list ) == 0 {
return [ ] super_dto . TenantItem { } , nil
}
tenantIDs := make ( [ ] int64 , 0 , len ( list ) )
tenantOwnerIDs := make ( map [ int64 ] struct { } , len ( list ) )
for _ , t := range list {
tenantIDs = append ( tenantIDs , t . ID )
tenantOwnerIDs [ t . UserID ] = struct { } { }
}
// 统计租户成员数与管理员列表(基于 tenant_users) 。
userCountMap := make ( map [ int64 ] int64 , len ( list ) )
adminSet := make ( map [ int64 ] map [ int64 ] struct { } , len ( list ) )
tblTu , qTu := models . TenantUserQuery . QueryContext ( ctx )
tenantUsers , err := qTu . Where ( tblTu . TenantID . In ( tenantIDs ... ) ) . Find ( )
if err != nil {
return nil , errorx . ErrDatabaseError . WithCause ( err )
}
for _ , tu := range tenantUsers {
userCountMap [ tu . TenantID ] ++
if hasTenantRole ( tu . Role , consts . TenantUserRoleTenantAdmin ) {
if _ , ok := adminSet [ tu . TenantID ] ; ! ok {
adminSet [ tu . TenantID ] = make ( map [ int64 ] struct { } )
}
adminSet [ tu . TenantID ] [ tu . UserID ] = struct { } { }
}
}
adminIDs := make ( map [ int64 ] struct { } )
for _ , ids := range adminSet {
for id := range ids {
adminIDs [ id ] = struct { } { }
}
}
userIDs := make ( [ ] int64 , 0 , len ( adminIDs ) + len ( tenantOwnerIDs ) )
seen := make ( map [ int64 ] struct { } )
for id := range adminIDs {
seen [ id ] = struct { } { }
userIDs = append ( userIDs , id )
}
for id := range tenantOwnerIDs {
if _ , ok := seen [ id ] ; ok {
continue
}
seen [ id ] = struct { } { }
userIDs = append ( userIDs , id )
}
userMap := make ( map [ int64 ] * models . User , len ( userIDs ) )
if len ( userIDs ) > 0 {
tblUser , qUser := models . UserQuery . QueryContext ( ctx )
users , err := qUser . Where ( tblUser . ID . In ( userIDs ... ) ) . Find ( )
if err != nil {
return nil , errorx . ErrDatabaseError . WithCause ( err )
}
for _ , u := range users {
userMap [ u . ID ] = u
}
}
// 汇总租户收入(按已支付/退款中/已退款订单统计实付金额)。
incomeMap := make ( map [ int64 ] int64 , len ( list ) )
if len ( tenantIDs ) > 0 {
var rows [ ] struct {
TenantID int64 ` gorm:"column:tenant_id" `
AmountPaidSum int64 ` gorm:"column:amount_paid_sum" `
}
err := models . OrderQuery . WithContext ( ctx ) .
UnderlyingDB ( ) .
Model ( & models . Order { } ) .
Select ( "tenant_id, coalesce(sum(amount_paid), 0) as amount_paid_sum" ) .
Where ( "tenant_id IN ?" , tenantIDs ) .
Where ( "status IN ?" , [ ] consts . OrderStatus {
consts . OrderStatusPaid ,
consts . OrderStatusRefunding ,
consts . OrderStatusRefunded ,
} ) .
Group ( "tenant_id" ) .
Scan ( & rows ) . Error
if err != nil {
return nil , errorx . ErrDatabaseError . WithCause ( err )
}
for _ , row := range rows {
incomeMap [ row . TenantID ] = row . AmountPaidSum
}
}
items := make ( [ ] super_dto . TenantItem , 0 , len ( list ) )
for _ , t := range list {
item := super_dto . TenantItem {
ID : t . ID ,
UUID : t . UUID . String ( ) ,
Name : t . Name ,
Code : t . Code ,
Status : t . Status ,
StatusDescription : t . Status . Description ( ) ,
UserID : t . UserID ,
UserCount : userCountMap [ t . ID ] ,
IncomeAmountPaidSum : incomeMap [ t . ID ] ,
ExpiredAt : s . formatTime ( t . ExpiredAt ) ,
CreatedAt : s . formatTime ( t . CreatedAt ) ,
UpdatedAt : s . formatTime ( t . UpdatedAt ) ,
}
if owner := userMap [ t . UserID ] ; owner != nil {
item . Owner = & super_dto . TenantOwnerUserLite {
ID : owner . ID ,
Username : owner . Username ,
}
}
if adminSet [ t . ID ] != nil {
admins := make ( [ ] * super_dto . TenantAdminUserLite , 0 , len ( adminSet [ t . ID ] ) )
for adminID := range adminSet [ t . ID ] {
if u := userMap [ adminID ] ; u != nil {
admins = append ( admins , & super_dto . TenantAdminUserLite {
ID : u . ID ,
Username : u . Username ,
} )
}
}
item . AdminUsers = admins
}
items = append ( items , item )
}
return items , 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 ) )
@@ -1259,6 +1796,161 @@ func (s *super) ApproveWithdrawal(ctx context.Context, id int64) error {
return err
}
func ( s * super ) userOwnedTenantCount ( ctx context . Context , userIDs [ ] int64 ) ( map [ int64 ] int64 , error ) {
result := make ( map [ int64 ] int64 , len ( userIDs ) )
if len ( userIDs ) == 0 {
return result , nil
}
var rows [ ] struct {
UserID int64 ` gorm:"column:user_id" `
Count int64 ` gorm:"column:count" `
}
err := models . TenantQuery . WithContext ( ctx ) .
UnderlyingDB ( ) .
Model ( & models . Tenant { } ) .
Select ( "user_id, count(*) as count" ) .
Where ( "user_id IN ?" , userIDs ) .
Group ( "user_id" ) .
Scan ( & rows ) . Error
if err != nil {
return nil , errorx . ErrDatabaseError . WithCause ( err )
}
for _ , row := range rows {
result [ row . UserID ] = row . Count
}
return result , nil
}
func ( s * super ) userJoinedTenantCount ( ctx context . Context , userIDs [ ] int64 ) ( map [ int64 ] int64 , error ) {
result := make ( map [ int64 ] int64 , len ( userIDs ) )
if len ( userIDs ) == 0 {
return result , nil
}
var rows [ ] struct {
UserID int64 ` gorm:"column:user_id" `
Count int64 ` gorm:"column:count" `
}
err := models . TenantUserQuery . WithContext ( ctx ) .
UnderlyingDB ( ) .
Model ( & models . TenantUser { } ) .
Select ( "user_id, count(*) as count" ) .
Where ( "user_id IN ?" , userIDs ) .
Group ( "user_id" ) .
Scan ( & rows ) . Error
if err != nil {
return nil , errorx . ErrDatabaseError . WithCause ( err )
}
for _ , row := range rows {
result [ row . UserID ] = row . Count
}
return result , nil
}
func ( s * super ) userMapByTenantUsers ( ctx context . Context , list [ ] * models . TenantUser ) ( map [ int64 ] * models . User , error ) {
userIDs := make ( [ ] int64 , 0 , len ( list ) )
seen := make ( map [ int64 ] struct { } , len ( list ) )
for _ , tu := range list {
if _ , ok := seen [ tu . UserID ] ; ok {
continue
}
seen [ tu . UserID ] = struct { } { }
userIDs = append ( userIDs , tu . UserID )
}
userMap := make ( map [ int64 ] * models . User , len ( userIDs ) )
if len ( userIDs ) == 0 {
return userMap , nil
}
tblUser , qUser := models . UserQuery . QueryContext ( ctx )
users , err := qUser . Where ( tblUser . ID . In ( userIDs ... ) ) . Find ( )
if err != nil {
return nil , errorx . ErrDatabaseError . WithCause ( err )
}
for _ , u := range users {
userMap [ u . ID ] = u
}
return userMap , nil
}
func ( s * super ) toSuperTenantUserDTO ( tu * models . TenantUser ) * super_dto . TenantUser {
if tu == nil {
return nil
}
return & super_dto . TenantUser {
ID : tu . ID ,
TenantID : tu . TenantID ,
UserID : tu . UserID ,
Role : tu . Role ,
Status : tu . Status ,
CreatedAt : s . formatTime ( tu . CreatedAt ) ,
UpdatedAt : s . formatTime ( tu . UpdatedAt ) ,
}
}
func ( s * super ) tenantMapsForTenantUsers ( ctx context . Context , list [ ] * models . TenantUser ) ( map [ int64 ] * models . Tenant , map [ int64 ] * models . User , error ) {
tenantIDs := make ( [ ] int64 , 0 , len ( list ) )
seen := make ( map [ int64 ] struct { } , len ( list ) )
for _ , tu := range list {
if _ , ok := seen [ tu . TenantID ] ; ok {
continue
}
seen [ tu . TenantID ] = struct { } { }
tenantIDs = append ( tenantIDs , tu . TenantID )
}
tenantMap := make ( map [ int64 ] * models . Tenant , len ( tenantIDs ) )
ownerMap := make ( map [ int64 ] * models . User , len ( tenantIDs ) )
if len ( tenantIDs ) == 0 {
return tenantMap , ownerMap , nil
}
tblTenant , qTenant := models . TenantQuery . QueryContext ( ctx )
tenants , err := qTenant . Where ( tblTenant . ID . In ( tenantIDs ... ) ) . Find ( )
if err != nil {
return nil , nil , errorx . ErrDatabaseError . WithCause ( err )
}
ownerIDs := make ( [ ] int64 , 0 , len ( tenants ) )
ownerSeen := make ( map [ int64 ] struct { } , len ( tenants ) )
for _ , t := range tenants {
tenantMap [ t . ID ] = t
if _ , ok := ownerSeen [ t . UserID ] ; ok {
continue
}
ownerSeen [ t . UserID ] = struct { } { }
ownerIDs = append ( ownerIDs , t . UserID )
}
userMap := make ( map [ int64 ] * models . User , len ( ownerIDs ) )
if len ( ownerIDs ) > 0 {
tblUser , qUser := models . UserQuery . QueryContext ( ctx )
users , err := qUser . Where ( tblUser . ID . In ( ownerIDs ... ) ) . Find ( )
if err != nil {
return nil , nil , errorx . ErrDatabaseError . WithCause ( err )
}
for _ , u := range users {
userMap [ u . ID ] = u
}
}
for tenantID , tenant := range tenantMap {
if tenant == nil {
continue
}
if owner := userMap [ tenant . UserID ] ; owner != nil {
ownerMap [ tenantID ] = owner
}
}
return tenantMap , ownerMap , nil
}
func ( s * super ) formatTime ( t time . Time ) string {
if t . IsZero ( ) {
return ""
}
return t . Format ( time . RFC3339 )
}
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 ( )