tenant: add invites and join requests

This commit is contained in:
2025-12-18 18:27:23 +08:00
parent 462bde351d
commit ec4506fd2d
28 changed files with 5206 additions and 201 deletions

View File

@@ -38,6 +38,10 @@ field_type:
currency: consts.Currency
tenant_ledgers:
type: consts.TenantLedgerType
tenant_invites:
status: consts.TenantInviteStatus
tenant_join_requests:
status: consts.TenantJoinRequestStatus
field_relate:
users:
OwnedTenant:

View File

@@ -0,0 +1,81 @@
-- +goose Up
-- +goose StatementBegin
CREATE TABLE IF NOT EXISTS tenant_invites(
id bigserial PRIMARY KEY,
tenant_id bigint NOT NULL,
user_id bigint NOT NULL,
code varchar(64) NOT NULL,
status varchar(32) NOT NULL DEFAULT 'active',
max_uses int NOT NULL DEFAULT 0,
used_count int NOT NULL DEFAULT 0,
expires_at timestamptz,
disabled_at timestamptz,
disabled_operator_user_id bigint,
remark varchar(255) NOT NULL DEFAULT '',
created_at timestamptz NOT NULL DEFAULT NOW(),
updated_at timestamptz NOT NULL DEFAULT NOW(),
UNIQUE (tenant_id, code)
);
-- tenant_invites租户邀请用于用户通过邀请码加入租户
COMMENT ON TABLE tenant_invites IS '租户邀请:租户管理员生成的邀请码;用户可通过 code 加入租户;支持禁用、过期、使用次数限制;所有查询/写入必须限定 tenant_id';
COMMENT ON COLUMN tenant_invites.id IS '主键ID自增';
COMMENT ON COLUMN tenant_invites.tenant_id IS '租户ID多租户隔离关键字段所有查询/写入必须限定 tenant_id';
COMMENT ON COLUMN tenant_invites.user_id IS '创建人用户ID生成邀请码的租户管理员审计用';
COMMENT ON COLUMN tenant_invites.code IS '邀请码:用户加入租户时提交;同一租户内唯一';
COMMENT ON COLUMN tenant_invites.status IS '邀请状态active/disabled/expiredexpired 也可由 expires_at 推导,业务侧需保持一致';
COMMENT ON COLUMN tenant_invites.max_uses IS '最大可使用次数0 表示不限制;>0 时 used_count 达到该值后视为失效';
COMMENT ON COLUMN tenant_invites.used_count IS '已使用次数:每次成功加入时 +1需事务保证并发下不超发';
COMMENT ON COLUMN tenant_invites.expires_at IS '过期时间到期后不可再使用UTC为空表示不过期';
COMMENT ON COLUMN tenant_invites.disabled_at IS '禁用时间租户管理员禁用该邀请的时间UTC';
COMMENT ON COLUMN tenant_invites.disabled_operator_user_id IS '禁用操作人用户ID租户管理员审计用';
COMMENT ON COLUMN tenant_invites.remark IS '备注:生成/禁用原因等(审计用)';
COMMENT ON COLUMN tenant_invites.created_at IS '创建时间:默认 now()';
COMMENT ON COLUMN tenant_invites.updated_at IS '更新时间:默认 now()';
CREATE INDEX IF NOT EXISTS ix_tenant_invites_tenant_status ON tenant_invites(tenant_id, status);
CREATE INDEX IF NOT EXISTS ix_tenant_invites_tenant_expires_at ON tenant_invites(tenant_id, expires_at);
CREATE TABLE IF NOT EXISTS tenant_join_requests(
id bigserial PRIMARY KEY,
tenant_id bigint NOT NULL,
user_id bigint NOT NULL,
status varchar(32) NOT NULL DEFAULT 'pending',
reason varchar(255) NOT NULL DEFAULT '',
decided_at timestamptz,
decided_operator_user_id bigint,
decided_reason varchar(255) NOT NULL DEFAULT '',
created_at timestamptz NOT NULL DEFAULT NOW(),
updated_at timestamptz NOT NULL DEFAULT NOW()
);
-- tenant_join_requests加入租户申请用于无邀请码场景的人工审核
COMMENT ON TABLE tenant_join_requests IS '加入申请:用户申请加入租户,租户管理员审核通过/拒绝;所有查询/写入必须限定 tenant_id';
COMMENT ON COLUMN tenant_join_requests.id IS '主键ID自增';
COMMENT ON COLUMN tenant_join_requests.tenant_id IS '租户ID多租户隔离关键字段所有查询/写入必须限定 tenant_id';
COMMENT ON COLUMN tenant_join_requests.user_id IS '申请人用户ID发起加入申请的用户';
COMMENT ON COLUMN tenant_join_requests.status IS '申请状态pending/approved/rejected状态变更需记录 decided_at 与 decided_operator_user_id';
COMMENT ON COLUMN tenant_join_requests.reason IS '申请原因:用户填写的加入说明(可选)';
COMMENT ON COLUMN tenant_join_requests.decided_at IS '处理时间:审核通过/拒绝时记录UTC';
COMMENT ON COLUMN tenant_join_requests.decided_operator_user_id IS '处理人用户ID租户管理员审计用';
COMMENT ON COLUMN tenant_join_requests.decided_reason IS '处理说明:管理员通过/拒绝的原因(可选,审计用)';
COMMENT ON COLUMN tenant_join_requests.created_at IS '创建时间:默认 now()';
COMMENT ON COLUMN tenant_join_requests.updated_at IS '更新时间:默认 now()';
-- 约束:同一用户同一租户同一时间仅允许存在一个 pending 申请,避免重复提交淹没审核队列。
CREATE UNIQUE INDEX IF NOT EXISTS ux_tenant_join_requests_tenant_user_pending ON tenant_join_requests(tenant_id, user_id) WHERE status = 'pending';
CREATE INDEX IF NOT EXISTS ix_tenant_join_requests_tenant_status ON tenant_join_requests(tenant_id, status);
CREATE INDEX IF NOT EXISTS ix_tenant_join_requests_tenant_created_at ON tenant_join_requests(tenant_id, created_at);
-- +goose StatementEnd
-- +goose Down
-- +goose StatementBegin
DROP INDEX IF EXISTS ix_tenant_join_requests_tenant_created_at;
DROP INDEX IF EXISTS ix_tenant_join_requests_tenant_status;
DROP INDEX IF EXISTS ux_tenant_join_requests_tenant_user_pending;
DROP TABLE IF EXISTS tenant_join_requests;
DROP INDEX IF EXISTS ix_tenant_invites_tenant_expires_at;
DROP INDEX IF EXISTS ix_tenant_invites_tenant_status;
DROP TABLE IF EXISTS tenant_invites;
-- +goose StatementEnd

View File

@@ -16,18 +16,20 @@ import (
)
var (
Q = new(Query)
ContentQuery *contentQuery
ContentAccessQuery *contentAccessQuery
ContentAssetQuery *contentAssetQuery
ContentPriceQuery *contentPriceQuery
MediaAssetQuery *mediaAssetQuery
OrderQuery *orderQuery
OrderItemQuery *orderItemQuery
TenantQuery *tenantQuery
TenantLedgerQuery *tenantLedgerQuery
TenantUserQuery *tenantUserQuery
UserQuery *userQuery
Q = new(Query)
ContentQuery *contentQuery
ContentAccessQuery *contentAccessQuery
ContentAssetQuery *contentAssetQuery
ContentPriceQuery *contentPriceQuery
MediaAssetQuery *mediaAssetQuery
OrderQuery *orderQuery
OrderItemQuery *orderItemQuery
TenantQuery *tenantQuery
TenantInviteQuery *tenantInviteQuery
TenantJoinRequestQuery *tenantJoinRequestQuery
TenantLedgerQuery *tenantLedgerQuery
TenantUserQuery *tenantUserQuery
UserQuery *userQuery
)
func SetDefault(db *gorm.DB, opts ...gen.DOOption) {
@@ -40,6 +42,8 @@ func SetDefault(db *gorm.DB, opts ...gen.DOOption) {
OrderQuery = &Q.Order
OrderItemQuery = &Q.OrderItem
TenantQuery = &Q.Tenant
TenantInviteQuery = &Q.TenantInvite
TenantJoinRequestQuery = &Q.TenantJoinRequest
TenantLedgerQuery = &Q.TenantLedger
TenantUserQuery = &Q.TenantUser
UserQuery = &Q.User
@@ -47,53 +51,59 @@ func SetDefault(db *gorm.DB, opts ...gen.DOOption) {
func Use(db *gorm.DB, opts ...gen.DOOption) *Query {
return &Query{
db: db,
Content: newContent(db, opts...),
ContentAccess: newContentAccess(db, opts...),
ContentAsset: newContentAsset(db, opts...),
ContentPrice: newContentPrice(db, opts...),
MediaAsset: newMediaAsset(db, opts...),
Order: newOrder(db, opts...),
OrderItem: newOrderItem(db, opts...),
Tenant: newTenant(db, opts...),
TenantLedger: newTenantLedger(db, opts...),
TenantUser: newTenantUser(db, opts...),
User: newUser(db, opts...),
db: db,
Content: newContent(db, opts...),
ContentAccess: newContentAccess(db, opts...),
ContentAsset: newContentAsset(db, opts...),
ContentPrice: newContentPrice(db, opts...),
MediaAsset: newMediaAsset(db, opts...),
Order: newOrder(db, opts...),
OrderItem: newOrderItem(db, opts...),
Tenant: newTenant(db, opts...),
TenantInvite: newTenantInvite(db, opts...),
TenantJoinRequest: newTenantJoinRequest(db, opts...),
TenantLedger: newTenantLedger(db, opts...),
TenantUser: newTenantUser(db, opts...),
User: newUser(db, opts...),
}
}
type Query struct {
db *gorm.DB
Content contentQuery
ContentAccess contentAccessQuery
ContentAsset contentAssetQuery
ContentPrice contentPriceQuery
MediaAsset mediaAssetQuery
Order orderQuery
OrderItem orderItemQuery
Tenant tenantQuery
TenantLedger tenantLedgerQuery
TenantUser tenantUserQuery
User userQuery
Content contentQuery
ContentAccess contentAccessQuery
ContentAsset contentAssetQuery
ContentPrice contentPriceQuery
MediaAsset mediaAssetQuery
Order orderQuery
OrderItem orderItemQuery
Tenant tenantQuery
TenantInvite tenantInviteQuery
TenantJoinRequest tenantJoinRequestQuery
TenantLedger tenantLedgerQuery
TenantUser tenantUserQuery
User userQuery
}
func (q *Query) Available() bool { return q.db != nil }
func (q *Query) clone(db *gorm.DB) *Query {
return &Query{
db: db,
Content: q.Content.clone(db),
ContentAccess: q.ContentAccess.clone(db),
ContentAsset: q.ContentAsset.clone(db),
ContentPrice: q.ContentPrice.clone(db),
MediaAsset: q.MediaAsset.clone(db),
Order: q.Order.clone(db),
OrderItem: q.OrderItem.clone(db),
Tenant: q.Tenant.clone(db),
TenantLedger: q.TenantLedger.clone(db),
TenantUser: q.TenantUser.clone(db),
User: q.User.clone(db),
db: db,
Content: q.Content.clone(db),
ContentAccess: q.ContentAccess.clone(db),
ContentAsset: q.ContentAsset.clone(db),
ContentPrice: q.ContentPrice.clone(db),
MediaAsset: q.MediaAsset.clone(db),
Order: q.Order.clone(db),
OrderItem: q.OrderItem.clone(db),
Tenant: q.Tenant.clone(db),
TenantInvite: q.TenantInvite.clone(db),
TenantJoinRequest: q.TenantJoinRequest.clone(db),
TenantLedger: q.TenantLedger.clone(db),
TenantUser: q.TenantUser.clone(db),
User: q.User.clone(db),
}
}
@@ -107,48 +117,54 @@ func (q *Query) WriteDB() *Query {
func (q *Query) ReplaceDB(db *gorm.DB) *Query {
return &Query{
db: db,
Content: q.Content.replaceDB(db),
ContentAccess: q.ContentAccess.replaceDB(db),
ContentAsset: q.ContentAsset.replaceDB(db),
ContentPrice: q.ContentPrice.replaceDB(db),
MediaAsset: q.MediaAsset.replaceDB(db),
Order: q.Order.replaceDB(db),
OrderItem: q.OrderItem.replaceDB(db),
Tenant: q.Tenant.replaceDB(db),
TenantLedger: q.TenantLedger.replaceDB(db),
TenantUser: q.TenantUser.replaceDB(db),
User: q.User.replaceDB(db),
db: db,
Content: q.Content.replaceDB(db),
ContentAccess: q.ContentAccess.replaceDB(db),
ContentAsset: q.ContentAsset.replaceDB(db),
ContentPrice: q.ContentPrice.replaceDB(db),
MediaAsset: q.MediaAsset.replaceDB(db),
Order: q.Order.replaceDB(db),
OrderItem: q.OrderItem.replaceDB(db),
Tenant: q.Tenant.replaceDB(db),
TenantInvite: q.TenantInvite.replaceDB(db),
TenantJoinRequest: q.TenantJoinRequest.replaceDB(db),
TenantLedger: q.TenantLedger.replaceDB(db),
TenantUser: q.TenantUser.replaceDB(db),
User: q.User.replaceDB(db),
}
}
type queryCtx struct {
Content *contentQueryDo
ContentAccess *contentAccessQueryDo
ContentAsset *contentAssetQueryDo
ContentPrice *contentPriceQueryDo
MediaAsset *mediaAssetQueryDo
Order *orderQueryDo
OrderItem *orderItemQueryDo
Tenant *tenantQueryDo
TenantLedger *tenantLedgerQueryDo
TenantUser *tenantUserQueryDo
User *userQueryDo
Content *contentQueryDo
ContentAccess *contentAccessQueryDo
ContentAsset *contentAssetQueryDo
ContentPrice *contentPriceQueryDo
MediaAsset *mediaAssetQueryDo
Order *orderQueryDo
OrderItem *orderItemQueryDo
Tenant *tenantQueryDo
TenantInvite *tenantInviteQueryDo
TenantJoinRequest *tenantJoinRequestQueryDo
TenantLedger *tenantLedgerQueryDo
TenantUser *tenantUserQueryDo
User *userQueryDo
}
func (q *Query) WithContext(ctx context.Context) *queryCtx {
return &queryCtx{
Content: q.Content.WithContext(ctx),
ContentAccess: q.ContentAccess.WithContext(ctx),
ContentAsset: q.ContentAsset.WithContext(ctx),
ContentPrice: q.ContentPrice.WithContext(ctx),
MediaAsset: q.MediaAsset.WithContext(ctx),
Order: q.Order.WithContext(ctx),
OrderItem: q.OrderItem.WithContext(ctx),
Tenant: q.Tenant.WithContext(ctx),
TenantLedger: q.TenantLedger.WithContext(ctx),
TenantUser: q.TenantUser.WithContext(ctx),
User: q.User.WithContext(ctx),
Content: q.Content.WithContext(ctx),
ContentAccess: q.ContentAccess.WithContext(ctx),
ContentAsset: q.ContentAsset.WithContext(ctx),
ContentPrice: q.ContentPrice.WithContext(ctx),
MediaAsset: q.MediaAsset.WithContext(ctx),
Order: q.Order.WithContext(ctx),
OrderItem: q.OrderItem.WithContext(ctx),
Tenant: q.Tenant.WithContext(ctx),
TenantInvite: q.TenantInvite.WithContext(ctx),
TenantJoinRequest: q.TenantJoinRequest.WithContext(ctx),
TenantLedger: q.TenantLedger.WithContext(ctx),
TenantUser: q.TenantUser.WithContext(ctx),
User: q.User.WithContext(ctx),
}
}

View File

@@ -0,0 +1,69 @@
// Code generated by go.ipao.vip/gen. DO NOT EDIT.
// Code generated by go.ipao.vip/gen. DO NOT EDIT.
// Code generated by go.ipao.vip/gen. DO NOT EDIT.
package models
import (
"context"
"time"
"quyun/v2/pkg/consts"
"go.ipao.vip/gen"
)
const TableNameTenantInvite = "tenant_invites"
// TenantInvite mapped from table <tenant_invites>
type TenantInvite struct {
ID int64 `gorm:"column:id;type:bigint;primaryKey;autoIncrement:true;comment:主键ID自增" json:"id"` // 主键ID自增
TenantID int64 `gorm:"column:tenant_id;type:bigint;not null;comment:租户ID多租户隔离关键字段所有查询/写入必须限定 tenant_id" json:"tenant_id"` // 租户ID多租户隔离关键字段所有查询/写入必须限定 tenant_id
UserID int64 `gorm:"column:user_id;type:bigint;not null;comment:创建人用户ID生成邀请码的租户管理员审计用" json:"user_id"` // 创建人用户ID生成邀请码的租户管理员审计用
Code string `gorm:"column:code;type:character varying(64);not null;comment:邀请码:用户加入租户时提交;同一租户内唯一" json:"code"` // 邀请码:用户加入租户时提交;同一租户内唯一
Status consts.TenantInviteStatus `gorm:"column:status;type:character varying(32);not null;default:active;comment:邀请状态active/disabled/expiredexpired 也可由 expires_at 推导,业务侧需保持一致" json:"status"` // 邀请状态active/disabled/expiredexpired 也可由 expires_at 推导,业务侧需保持一致
MaxUses int32 `gorm:"column:max_uses;type:integer;not null;comment:最大可使用次数0 表示不限制;>0 时 used_count 达到该值后视为失效" json:"max_uses"` // 最大可使用次数0 表示不限制;>0 时 used_count 达到该值后视为失效
UsedCount int32 `gorm:"column:used_count;type:integer;not null;comment:已使用次数:每次成功加入时 +1需事务保证并发下不超发" json:"used_count"` // 已使用次数:每次成功加入时 +1需事务保证并发下不超发
ExpiresAt time.Time `gorm:"column:expires_at;type:timestamp with time zone;comment:过期时间到期后不可再使用UTC为空表示不过期" json:"expires_at"` // 过期时间到期后不可再使用UTC为空表示不过期
DisabledAt time.Time `gorm:"column:disabled_at;type:timestamp with time zone;comment:禁用时间租户管理员禁用该邀请的时间UTC" json:"disabled_at"` // 禁用时间租户管理员禁用该邀请的时间UTC
DisabledOperatorUserID int64 `gorm:"column:disabled_operator_user_id;type:bigint;comment:禁用操作人用户ID租户管理员审计用" json:"disabled_operator_user_id"` // 禁用操作人用户ID租户管理员审计用
Remark string `gorm:"column:remark;type:character varying(255);not null;comment:备注:生成/禁用原因等(审计用)" json:"remark"` // 备注:生成/禁用原因等(审计用)
CreatedAt time.Time `gorm:"column:created_at;type:timestamp with time zone;not null;default:now();comment:创建时间:默认 now()" json:"created_at"` // 创建时间:默认 now()
UpdatedAt time.Time `gorm:"column:updated_at;type:timestamp with time zone;not null;default:now();comment:更新时间:默认 now()" json:"updated_at"` // 更新时间:默认 now()
}
// Quick operations without importing query package
// Update applies changed fields to the database using the default DB.
func (m *TenantInvite) Update(ctx context.Context) (gen.ResultInfo, error) {
return Q.TenantInvite.WithContext(ctx).Updates(m)
}
// Save upserts the model using the default DB.
func (m *TenantInvite) Save(ctx context.Context) error {
return Q.TenantInvite.WithContext(ctx).Save(m)
}
// Create inserts the model using the default DB.
func (m *TenantInvite) Create(ctx context.Context) error {
return Q.TenantInvite.WithContext(ctx).Create(m)
}
// Delete removes the row represented by the model using the default DB.
func (m *TenantInvite) Delete(ctx context.Context) (gen.ResultInfo, error) {
return Q.TenantInvite.WithContext(ctx).Delete(m)
}
// ForceDelete permanently deletes the row (ignores soft delete) using the default DB.
func (m *TenantInvite) ForceDelete(ctx context.Context) (gen.ResultInfo, error) {
return Q.TenantInvite.WithContext(ctx).Unscoped().Delete(m)
}
// Reload reloads the model from database by its primary key and overwrites current fields.
func (m *TenantInvite) Reload(ctx context.Context) error {
fresh, err := Q.TenantInvite.WithContext(ctx).GetByID(m.ID)
if err != nil {
return err
}
*m = *fresh
return nil
}

View File

@@ -0,0 +1,509 @@
// Code generated by go.ipao.vip/gen. DO NOT EDIT.
// Code generated by go.ipao.vip/gen. DO NOT EDIT.
// Code generated by go.ipao.vip/gen. DO NOT EDIT.
package models
import (
"context"
"gorm.io/gorm"
"gorm.io/gorm/clause"
"gorm.io/gorm/schema"
"go.ipao.vip/gen"
"go.ipao.vip/gen/field"
"gorm.io/plugin/dbresolver"
)
func newTenantInvite(db *gorm.DB, opts ...gen.DOOption) tenantInviteQuery {
_tenantInviteQuery := tenantInviteQuery{}
_tenantInviteQuery.tenantInviteQueryDo.UseDB(db, opts...)
_tenantInviteQuery.tenantInviteQueryDo.UseModel(&TenantInvite{})
tableName := _tenantInviteQuery.tenantInviteQueryDo.TableName()
_tenantInviteQuery.ALL = field.NewAsterisk(tableName)
_tenantInviteQuery.ID = field.NewInt64(tableName, "id")
_tenantInviteQuery.TenantID = field.NewInt64(tableName, "tenant_id")
_tenantInviteQuery.UserID = field.NewInt64(tableName, "user_id")
_tenantInviteQuery.Code = field.NewString(tableName, "code")
_tenantInviteQuery.Status = field.NewField(tableName, "status")
_tenantInviteQuery.MaxUses = field.NewInt32(tableName, "max_uses")
_tenantInviteQuery.UsedCount = field.NewInt32(tableName, "used_count")
_tenantInviteQuery.ExpiresAt = field.NewTime(tableName, "expires_at")
_tenantInviteQuery.DisabledAt = field.NewTime(tableName, "disabled_at")
_tenantInviteQuery.DisabledOperatorUserID = field.NewInt64(tableName, "disabled_operator_user_id")
_tenantInviteQuery.Remark = field.NewString(tableName, "remark")
_tenantInviteQuery.CreatedAt = field.NewTime(tableName, "created_at")
_tenantInviteQuery.UpdatedAt = field.NewTime(tableName, "updated_at")
_tenantInviteQuery.fillFieldMap()
return _tenantInviteQuery
}
type tenantInviteQuery struct {
tenantInviteQueryDo tenantInviteQueryDo
ALL field.Asterisk
ID field.Int64 // 主键ID自增
TenantID field.Int64 // 租户ID多租户隔离关键字段所有查询/写入必须限定 tenant_id
UserID field.Int64 // 创建人用户ID生成邀请码的租户管理员审计用
Code field.String // 邀请码:用户加入租户时提交;同一租户内唯一
Status field.Field // 邀请状态active/disabled/expiredexpired 也可由 expires_at 推导,业务侧需保持一致
MaxUses field.Int32 // 最大可使用次数0 表示不限制;>0 时 used_count 达到该值后视为失效
UsedCount field.Int32 // 已使用次数:每次成功加入时 +1需事务保证并发下不超发
ExpiresAt field.Time // 过期时间到期后不可再使用UTC为空表示不过期
DisabledAt field.Time // 禁用时间租户管理员禁用该邀请的时间UTC
DisabledOperatorUserID field.Int64 // 禁用操作人用户ID租户管理员审计用
Remark field.String // 备注:生成/禁用原因等(审计用)
CreatedAt field.Time // 创建时间:默认 now()
UpdatedAt field.Time // 更新时间:默认 now()
fieldMap map[string]field.Expr
}
func (t tenantInviteQuery) Table(newTableName string) *tenantInviteQuery {
t.tenantInviteQueryDo.UseTable(newTableName)
return t.updateTableName(newTableName)
}
func (t tenantInviteQuery) As(alias string) *tenantInviteQuery {
t.tenantInviteQueryDo.DO = *(t.tenantInviteQueryDo.As(alias).(*gen.DO))
return t.updateTableName(alias)
}
func (t *tenantInviteQuery) updateTableName(table string) *tenantInviteQuery {
t.ALL = field.NewAsterisk(table)
t.ID = field.NewInt64(table, "id")
t.TenantID = field.NewInt64(table, "tenant_id")
t.UserID = field.NewInt64(table, "user_id")
t.Code = field.NewString(table, "code")
t.Status = field.NewField(table, "status")
t.MaxUses = field.NewInt32(table, "max_uses")
t.UsedCount = field.NewInt32(table, "used_count")
t.ExpiresAt = field.NewTime(table, "expires_at")
t.DisabledAt = field.NewTime(table, "disabled_at")
t.DisabledOperatorUserID = field.NewInt64(table, "disabled_operator_user_id")
t.Remark = field.NewString(table, "remark")
t.CreatedAt = field.NewTime(table, "created_at")
t.UpdatedAt = field.NewTime(table, "updated_at")
t.fillFieldMap()
return t
}
func (t *tenantInviteQuery) QueryContext(ctx context.Context) (*tenantInviteQuery, *tenantInviteQueryDo) {
return t, t.tenantInviteQueryDo.WithContext(ctx)
}
func (t *tenantInviteQuery) WithContext(ctx context.Context) *tenantInviteQueryDo {
return t.tenantInviteQueryDo.WithContext(ctx)
}
func (t tenantInviteQuery) TableName() string { return t.tenantInviteQueryDo.TableName() }
func (t tenantInviteQuery) Alias() string { return t.tenantInviteQueryDo.Alias() }
func (t tenantInviteQuery) Columns(cols ...field.Expr) gen.Columns {
return t.tenantInviteQueryDo.Columns(cols...)
}
func (t *tenantInviteQuery) GetFieldByName(fieldName string) (field.OrderExpr, bool) {
_f, ok := t.fieldMap[fieldName]
if !ok || _f == nil {
return nil, false
}
_oe, ok := _f.(field.OrderExpr)
return _oe, ok
}
func (t *tenantInviteQuery) fillFieldMap() {
t.fieldMap = make(map[string]field.Expr, 13)
t.fieldMap["id"] = t.ID
t.fieldMap["tenant_id"] = t.TenantID
t.fieldMap["user_id"] = t.UserID
t.fieldMap["code"] = t.Code
t.fieldMap["status"] = t.Status
t.fieldMap["max_uses"] = t.MaxUses
t.fieldMap["used_count"] = t.UsedCount
t.fieldMap["expires_at"] = t.ExpiresAt
t.fieldMap["disabled_at"] = t.DisabledAt
t.fieldMap["disabled_operator_user_id"] = t.DisabledOperatorUserID
t.fieldMap["remark"] = t.Remark
t.fieldMap["created_at"] = t.CreatedAt
t.fieldMap["updated_at"] = t.UpdatedAt
}
func (t tenantInviteQuery) clone(db *gorm.DB) tenantInviteQuery {
t.tenantInviteQueryDo.ReplaceConnPool(db.Statement.ConnPool)
return t
}
func (t tenantInviteQuery) replaceDB(db *gorm.DB) tenantInviteQuery {
t.tenantInviteQueryDo.ReplaceDB(db)
return t
}
type tenantInviteQueryDo struct{ gen.DO }
func (t tenantInviteQueryDo) Debug() *tenantInviteQueryDo {
return t.withDO(t.DO.Debug())
}
func (t tenantInviteQueryDo) WithContext(ctx context.Context) *tenantInviteQueryDo {
return t.withDO(t.DO.WithContext(ctx))
}
func (t tenantInviteQueryDo) ReadDB() *tenantInviteQueryDo {
return t.Clauses(dbresolver.Read)
}
func (t tenantInviteQueryDo) WriteDB() *tenantInviteQueryDo {
return t.Clauses(dbresolver.Write)
}
func (t tenantInviteQueryDo) Session(config *gorm.Session) *tenantInviteQueryDo {
return t.withDO(t.DO.Session(config))
}
func (t tenantInviteQueryDo) Clauses(conds ...clause.Expression) *tenantInviteQueryDo {
return t.withDO(t.DO.Clauses(conds...))
}
func (t tenantInviteQueryDo) Returning(value interface{}, columns ...string) *tenantInviteQueryDo {
return t.withDO(t.DO.Returning(value, columns...))
}
func (t tenantInviteQueryDo) Not(conds ...gen.Condition) *tenantInviteQueryDo {
return t.withDO(t.DO.Not(conds...))
}
func (t tenantInviteQueryDo) Or(conds ...gen.Condition) *tenantInviteQueryDo {
return t.withDO(t.DO.Or(conds...))
}
func (t tenantInviteQueryDo) Select(conds ...field.Expr) *tenantInviteQueryDo {
return t.withDO(t.DO.Select(conds...))
}
func (t tenantInviteQueryDo) Where(conds ...gen.Condition) *tenantInviteQueryDo {
return t.withDO(t.DO.Where(conds...))
}
func (t tenantInviteQueryDo) Order(conds ...field.Expr) *tenantInviteQueryDo {
return t.withDO(t.DO.Order(conds...))
}
func (t tenantInviteQueryDo) Distinct(cols ...field.Expr) *tenantInviteQueryDo {
return t.withDO(t.DO.Distinct(cols...))
}
func (t tenantInviteQueryDo) Omit(cols ...field.Expr) *tenantInviteQueryDo {
return t.withDO(t.DO.Omit(cols...))
}
func (t tenantInviteQueryDo) Join(table schema.Tabler, on ...field.Expr) *tenantInviteQueryDo {
return t.withDO(t.DO.Join(table, on...))
}
func (t tenantInviteQueryDo) LeftJoin(table schema.Tabler, on ...field.Expr) *tenantInviteQueryDo {
return t.withDO(t.DO.LeftJoin(table, on...))
}
func (t tenantInviteQueryDo) RightJoin(table schema.Tabler, on ...field.Expr) *tenantInviteQueryDo {
return t.withDO(t.DO.RightJoin(table, on...))
}
func (t tenantInviteQueryDo) Group(cols ...field.Expr) *tenantInviteQueryDo {
return t.withDO(t.DO.Group(cols...))
}
func (t tenantInviteQueryDo) Having(conds ...gen.Condition) *tenantInviteQueryDo {
return t.withDO(t.DO.Having(conds...))
}
func (t tenantInviteQueryDo) Limit(limit int) *tenantInviteQueryDo {
return t.withDO(t.DO.Limit(limit))
}
func (t tenantInviteQueryDo) Offset(offset int) *tenantInviteQueryDo {
return t.withDO(t.DO.Offset(offset))
}
func (t tenantInviteQueryDo) Scopes(funcs ...func(gen.Dao) gen.Dao) *tenantInviteQueryDo {
return t.withDO(t.DO.Scopes(funcs...))
}
func (t tenantInviteQueryDo) Unscoped() *tenantInviteQueryDo {
return t.withDO(t.DO.Unscoped())
}
func (t tenantInviteQueryDo) Create(values ...*TenantInvite) error {
if len(values) == 0 {
return nil
}
return t.DO.Create(values)
}
func (t tenantInviteQueryDo) CreateInBatches(values []*TenantInvite, batchSize int) error {
return t.DO.CreateInBatches(values, batchSize)
}
// Save : !!! underlying implementation is different with GORM
// The method is equivalent to executing the statement: db.Clauses(clause.OnConflict{UpdateAll: true}).Create(values)
func (t tenantInviteQueryDo) Save(values ...*TenantInvite) error {
if len(values) == 0 {
return nil
}
return t.DO.Save(values)
}
func (t tenantInviteQueryDo) First() (*TenantInvite, error) {
if result, err := t.DO.First(); err != nil {
return nil, err
} else {
return result.(*TenantInvite), nil
}
}
func (t tenantInviteQueryDo) Take() (*TenantInvite, error) {
if result, err := t.DO.Take(); err != nil {
return nil, err
} else {
return result.(*TenantInvite), nil
}
}
func (t tenantInviteQueryDo) Last() (*TenantInvite, error) {
if result, err := t.DO.Last(); err != nil {
return nil, err
} else {
return result.(*TenantInvite), nil
}
}
func (t tenantInviteQueryDo) Find() ([]*TenantInvite, error) {
result, err := t.DO.Find()
return result.([]*TenantInvite), err
}
func (t tenantInviteQueryDo) FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*TenantInvite, err error) {
buf := make([]*TenantInvite, 0, batchSize)
err = t.DO.FindInBatches(&buf, batchSize, func(tx gen.Dao, batch int) error {
defer func() { results = append(results, buf...) }()
return fc(tx, batch)
})
return results, err
}
func (t tenantInviteQueryDo) FindInBatches(result *[]*TenantInvite, batchSize int, fc func(tx gen.Dao, batch int) error) error {
return t.DO.FindInBatches(result, batchSize, fc)
}
func (t tenantInviteQueryDo) Attrs(attrs ...field.AssignExpr) *tenantInviteQueryDo {
return t.withDO(t.DO.Attrs(attrs...))
}
func (t tenantInviteQueryDo) Assign(attrs ...field.AssignExpr) *tenantInviteQueryDo {
return t.withDO(t.DO.Assign(attrs...))
}
func (t tenantInviteQueryDo) Joins(fields ...field.RelationField) *tenantInviteQueryDo {
for _, _f := range fields {
t = *t.withDO(t.DO.Joins(_f))
}
return &t
}
func (t tenantInviteQueryDo) Preload(fields ...field.RelationField) *tenantInviteQueryDo {
for _, _f := range fields {
t = *t.withDO(t.DO.Preload(_f))
}
return &t
}
func (t tenantInviteQueryDo) FirstOrInit() (*TenantInvite, error) {
if result, err := t.DO.FirstOrInit(); err != nil {
return nil, err
} else {
return result.(*TenantInvite), nil
}
}
func (t tenantInviteQueryDo) FirstOrCreate() (*TenantInvite, error) {
if result, err := t.DO.FirstOrCreate(); err != nil {
return nil, err
} else {
return result.(*TenantInvite), nil
}
}
func (t tenantInviteQueryDo) FindByPage(offset int, limit int) (result []*TenantInvite, count int64, err error) {
result, err = t.Offset(offset).Limit(limit).Find()
if err != nil {
return
}
if size := len(result); 0 < limit && 0 < size && size < limit {
count = int64(size + offset)
return
}
count, err = t.Offset(-1).Limit(-1).Count()
return
}
func (t tenantInviteQueryDo) ScanByPage(result interface{}, offset int, limit int) (count int64, err error) {
count, err = t.Count()
if err != nil {
return
}
err = t.Offset(offset).Limit(limit).Scan(result)
return
}
func (t tenantInviteQueryDo) Scan(result interface{}) (err error) {
return t.DO.Scan(result)
}
func (t tenantInviteQueryDo) Delete(models ...*TenantInvite) (result gen.ResultInfo, err error) {
return t.DO.Delete(models)
}
// ForceDelete performs a permanent delete (ignores soft-delete) for current scope.
func (t tenantInviteQueryDo) ForceDelete() (gen.ResultInfo, error) {
return t.Unscoped().Delete()
}
// Inc increases the given column by step for current scope.
func (t tenantInviteQueryDo) Inc(column field.Expr, step int64) (gen.ResultInfo, error) {
// column = column + step
e := field.NewUnsafeFieldRaw("?+?", column.RawExpr(), step)
return t.DO.UpdateColumn(column, e)
}
// Dec decreases the given column by step for current scope.
func (t tenantInviteQueryDo) Dec(column field.Expr, step int64) (gen.ResultInfo, error) {
// column = column - step
e := field.NewUnsafeFieldRaw("?-?", column.RawExpr(), step)
return t.DO.UpdateColumn(column, e)
}
// Sum returns SUM(column) for current scope.
func (t tenantInviteQueryDo) Sum(column field.Expr) (float64, error) {
var _v float64
agg := field.NewUnsafeFieldRaw("SUM(?)", column.RawExpr())
if err := t.Select(agg).Scan(&_v); err != nil {
return 0, err
}
return _v, nil
}
// Avg returns AVG(column) for current scope.
func (t tenantInviteQueryDo) Avg(column field.Expr) (float64, error) {
var _v float64
agg := field.NewUnsafeFieldRaw("AVG(?)", column.RawExpr())
if err := t.Select(agg).Scan(&_v); err != nil {
return 0, err
}
return _v, nil
}
// Min returns MIN(column) for current scope.
func (t tenantInviteQueryDo) Min(column field.Expr) (float64, error) {
var _v float64
agg := field.NewUnsafeFieldRaw("MIN(?)", column.RawExpr())
if err := t.Select(agg).Scan(&_v); err != nil {
return 0, err
}
return _v, nil
}
// Max returns MAX(column) for current scope.
func (t tenantInviteQueryDo) Max(column field.Expr) (float64, error) {
var _v float64
agg := field.NewUnsafeFieldRaw("MAX(?)", column.RawExpr())
if err := t.Select(agg).Scan(&_v); err != nil {
return 0, err
}
return _v, nil
}
// PluckMap returns a map[key]value for selected key/value expressions within current scope.
func (t tenantInviteQueryDo) PluckMap(key, val field.Expr) (map[interface{}]interface{}, error) {
do := t.Select(key, val)
rows, err := do.DO.Rows()
if err != nil {
return nil, err
}
defer rows.Close()
mm := make(map[interface{}]interface{})
for rows.Next() {
var k interface{}
var v interface{}
if err := rows.Scan(&k, &v); err != nil {
return nil, err
}
mm[k] = v
}
return mm, rows.Err()
}
// Exists returns true if any record matches the given conditions.
func (t tenantInviteQueryDo) Exists(conds ...gen.Condition) (bool, error) {
cnt, err := t.Where(conds...).Count()
if err != nil {
return false, err
}
return cnt > 0, nil
}
// PluckIDs returns all primary key values under current scope.
func (t tenantInviteQueryDo) PluckIDs() ([]int64, error) {
ids := make([]int64, 0, 16)
pk := field.NewInt64(t.TableName(), "id")
if err := t.DO.Pluck(pk, &ids); err != nil {
return nil, err
}
return ids, nil
}
// GetByID finds a single record by primary key.
func (t tenantInviteQueryDo) GetByID(id int64) (*TenantInvite, error) {
pk := field.NewInt64(t.TableName(), "id")
return t.Where(pk.Eq(id)).First()
}
// GetByIDs finds records by primary key list.
func (t tenantInviteQueryDo) GetByIDs(ids ...int64) ([]*TenantInvite, error) {
if len(ids) == 0 {
return []*TenantInvite{}, nil
}
pk := field.NewInt64(t.TableName(), "id")
return t.Where(pk.In(ids...)).Find()
}
// DeleteByID deletes records by primary key.
func (t tenantInviteQueryDo) DeleteByID(id int64) (gen.ResultInfo, error) {
pk := field.NewInt64(t.TableName(), "id")
return t.Where(pk.Eq(id)).Delete()
}
// DeleteByIDs deletes records by a list of primary keys.
func (t tenantInviteQueryDo) DeleteByIDs(ids ...int64) (gen.ResultInfo, error) {
if len(ids) == 0 {
return gen.ResultInfo{RowsAffected: 0, Error: nil}, nil
}
pk := field.NewInt64(t.TableName(), "id")
return t.Where(pk.In(ids...)).Delete()
}
func (t *tenantInviteQueryDo) withDO(do gen.Dao) *tenantInviteQueryDo {
t.DO = *do.(*gen.DO)
return t
}

View File

@@ -0,0 +1,66 @@
// Code generated by go.ipao.vip/gen. DO NOT EDIT.
// Code generated by go.ipao.vip/gen. DO NOT EDIT.
// Code generated by go.ipao.vip/gen. DO NOT EDIT.
package models
import (
"context"
"time"
"quyun/v2/pkg/consts"
"go.ipao.vip/gen"
)
const TableNameTenantJoinRequest = "tenant_join_requests"
// TenantJoinRequest mapped from table <tenant_join_requests>
type TenantJoinRequest struct {
ID int64 `gorm:"column:id;type:bigint;primaryKey;autoIncrement:true;comment:主键ID自增" json:"id"` // 主键ID自增
TenantID int64 `gorm:"column:tenant_id;type:bigint;not null;comment:租户ID多租户隔离关键字段所有查询/写入必须限定 tenant_id" json:"tenant_id"` // 租户ID多租户隔离关键字段所有查询/写入必须限定 tenant_id
UserID int64 `gorm:"column:user_id;type:bigint;not null;comment:申请人用户ID发起加入申请的用户" json:"user_id"` // 申请人用户ID发起加入申请的用户
Status consts.TenantJoinRequestStatus `gorm:"column:status;type:character varying(32);not null;default:pending;comment:申请状态pending/approved/rejected状态变更需记录 decided_at 与 decided_operator_user_id" json:"status"` // 申请状态pending/approved/rejected状态变更需记录 decided_at 与 decided_operator_user_id
Reason string `gorm:"column:reason;type:character varying(255);not null;comment:申请原因:用户填写的加入说明(可选)" json:"reason"` // 申请原因:用户填写的加入说明(可选)
DecidedAt time.Time `gorm:"column:decided_at;type:timestamp with time zone;comment:处理时间:审核通过/拒绝时记录UTC" json:"decided_at"` // 处理时间:审核通过/拒绝时记录UTC
DecidedOperatorUserID int64 `gorm:"column:decided_operator_user_id;type:bigint;comment:处理人用户ID租户管理员审计用" json:"decided_operator_user_id"` // 处理人用户ID租户管理员审计用
DecidedReason string `gorm:"column:decided_reason;type:character varying(255);not null;comment:处理说明:管理员通过/拒绝的原因(可选,审计用)" json:"decided_reason"` // 处理说明:管理员通过/拒绝的原因(可选,审计用)
CreatedAt time.Time `gorm:"column:created_at;type:timestamp with time zone;not null;default:now();comment:创建时间:默认 now()" json:"created_at"` // 创建时间:默认 now()
UpdatedAt time.Time `gorm:"column:updated_at;type:timestamp with time zone;not null;default:now();comment:更新时间:默认 now()" json:"updated_at"` // 更新时间:默认 now()
}
// Quick operations without importing query package
// Update applies changed fields to the database using the default DB.
func (m *TenantJoinRequest) Update(ctx context.Context) (gen.ResultInfo, error) {
return Q.TenantJoinRequest.WithContext(ctx).Updates(m)
}
// Save upserts the model using the default DB.
func (m *TenantJoinRequest) Save(ctx context.Context) error {
return Q.TenantJoinRequest.WithContext(ctx).Save(m)
}
// Create inserts the model using the default DB.
func (m *TenantJoinRequest) Create(ctx context.Context) error {
return Q.TenantJoinRequest.WithContext(ctx).Create(m)
}
// Delete removes the row represented by the model using the default DB.
func (m *TenantJoinRequest) Delete(ctx context.Context) (gen.ResultInfo, error) {
return Q.TenantJoinRequest.WithContext(ctx).Delete(m)
}
// ForceDelete permanently deletes the row (ignores soft delete) using the default DB.
func (m *TenantJoinRequest) ForceDelete(ctx context.Context) (gen.ResultInfo, error) {
return Q.TenantJoinRequest.WithContext(ctx).Unscoped().Delete(m)
}
// Reload reloads the model from database by its primary key and overwrites current fields.
func (m *TenantJoinRequest) Reload(ctx context.Context) error {
fresh, err := Q.TenantJoinRequest.WithContext(ctx).GetByID(m.ID)
if err != nil {
return err
}
*m = *fresh
return nil
}

View File

@@ -0,0 +1,497 @@
// Code generated by go.ipao.vip/gen. DO NOT EDIT.
// Code generated by go.ipao.vip/gen. DO NOT EDIT.
// Code generated by go.ipao.vip/gen. DO NOT EDIT.
package models
import (
"context"
"gorm.io/gorm"
"gorm.io/gorm/clause"
"gorm.io/gorm/schema"
"go.ipao.vip/gen"
"go.ipao.vip/gen/field"
"gorm.io/plugin/dbresolver"
)
func newTenantJoinRequest(db *gorm.DB, opts ...gen.DOOption) tenantJoinRequestQuery {
_tenantJoinRequestQuery := tenantJoinRequestQuery{}
_tenantJoinRequestQuery.tenantJoinRequestQueryDo.UseDB(db, opts...)
_tenantJoinRequestQuery.tenantJoinRequestQueryDo.UseModel(&TenantJoinRequest{})
tableName := _tenantJoinRequestQuery.tenantJoinRequestQueryDo.TableName()
_tenantJoinRequestQuery.ALL = field.NewAsterisk(tableName)
_tenantJoinRequestQuery.ID = field.NewInt64(tableName, "id")
_tenantJoinRequestQuery.TenantID = field.NewInt64(tableName, "tenant_id")
_tenantJoinRequestQuery.UserID = field.NewInt64(tableName, "user_id")
_tenantJoinRequestQuery.Status = field.NewField(tableName, "status")
_tenantJoinRequestQuery.Reason = field.NewString(tableName, "reason")
_tenantJoinRequestQuery.DecidedAt = field.NewTime(tableName, "decided_at")
_tenantJoinRequestQuery.DecidedOperatorUserID = field.NewInt64(tableName, "decided_operator_user_id")
_tenantJoinRequestQuery.DecidedReason = field.NewString(tableName, "decided_reason")
_tenantJoinRequestQuery.CreatedAt = field.NewTime(tableName, "created_at")
_tenantJoinRequestQuery.UpdatedAt = field.NewTime(tableName, "updated_at")
_tenantJoinRequestQuery.fillFieldMap()
return _tenantJoinRequestQuery
}
type tenantJoinRequestQuery struct {
tenantJoinRequestQueryDo tenantJoinRequestQueryDo
ALL field.Asterisk
ID field.Int64 // 主键ID自增
TenantID field.Int64 // 租户ID多租户隔离关键字段所有查询/写入必须限定 tenant_id
UserID field.Int64 // 申请人用户ID发起加入申请的用户
Status field.Field // 申请状态pending/approved/rejected状态变更需记录 decided_at 与 decided_operator_user_id
Reason field.String // 申请原因:用户填写的加入说明(可选)
DecidedAt field.Time // 处理时间:审核通过/拒绝时记录UTC
DecidedOperatorUserID field.Int64 // 处理人用户ID租户管理员审计用
DecidedReason field.String // 处理说明:管理员通过/拒绝的原因(可选,审计用)
CreatedAt field.Time // 创建时间:默认 now()
UpdatedAt field.Time // 更新时间:默认 now()
fieldMap map[string]field.Expr
}
func (t tenantJoinRequestQuery) Table(newTableName string) *tenantJoinRequestQuery {
t.tenantJoinRequestQueryDo.UseTable(newTableName)
return t.updateTableName(newTableName)
}
func (t tenantJoinRequestQuery) As(alias string) *tenantJoinRequestQuery {
t.tenantJoinRequestQueryDo.DO = *(t.tenantJoinRequestQueryDo.As(alias).(*gen.DO))
return t.updateTableName(alias)
}
func (t *tenantJoinRequestQuery) updateTableName(table string) *tenantJoinRequestQuery {
t.ALL = field.NewAsterisk(table)
t.ID = field.NewInt64(table, "id")
t.TenantID = field.NewInt64(table, "tenant_id")
t.UserID = field.NewInt64(table, "user_id")
t.Status = field.NewField(table, "status")
t.Reason = field.NewString(table, "reason")
t.DecidedAt = field.NewTime(table, "decided_at")
t.DecidedOperatorUserID = field.NewInt64(table, "decided_operator_user_id")
t.DecidedReason = field.NewString(table, "decided_reason")
t.CreatedAt = field.NewTime(table, "created_at")
t.UpdatedAt = field.NewTime(table, "updated_at")
t.fillFieldMap()
return t
}
func (t *tenantJoinRequestQuery) QueryContext(ctx context.Context) (*tenantJoinRequestQuery, *tenantJoinRequestQueryDo) {
return t, t.tenantJoinRequestQueryDo.WithContext(ctx)
}
func (t *tenantJoinRequestQuery) WithContext(ctx context.Context) *tenantJoinRequestQueryDo {
return t.tenantJoinRequestQueryDo.WithContext(ctx)
}
func (t tenantJoinRequestQuery) TableName() string { return t.tenantJoinRequestQueryDo.TableName() }
func (t tenantJoinRequestQuery) Alias() string { return t.tenantJoinRequestQueryDo.Alias() }
func (t tenantJoinRequestQuery) Columns(cols ...field.Expr) gen.Columns {
return t.tenantJoinRequestQueryDo.Columns(cols...)
}
func (t *tenantJoinRequestQuery) GetFieldByName(fieldName string) (field.OrderExpr, bool) {
_f, ok := t.fieldMap[fieldName]
if !ok || _f == nil {
return nil, false
}
_oe, ok := _f.(field.OrderExpr)
return _oe, ok
}
func (t *tenantJoinRequestQuery) fillFieldMap() {
t.fieldMap = make(map[string]field.Expr, 10)
t.fieldMap["id"] = t.ID
t.fieldMap["tenant_id"] = t.TenantID
t.fieldMap["user_id"] = t.UserID
t.fieldMap["status"] = t.Status
t.fieldMap["reason"] = t.Reason
t.fieldMap["decided_at"] = t.DecidedAt
t.fieldMap["decided_operator_user_id"] = t.DecidedOperatorUserID
t.fieldMap["decided_reason"] = t.DecidedReason
t.fieldMap["created_at"] = t.CreatedAt
t.fieldMap["updated_at"] = t.UpdatedAt
}
func (t tenantJoinRequestQuery) clone(db *gorm.DB) tenantJoinRequestQuery {
t.tenantJoinRequestQueryDo.ReplaceConnPool(db.Statement.ConnPool)
return t
}
func (t tenantJoinRequestQuery) replaceDB(db *gorm.DB) tenantJoinRequestQuery {
t.tenantJoinRequestQueryDo.ReplaceDB(db)
return t
}
type tenantJoinRequestQueryDo struct{ gen.DO }
func (t tenantJoinRequestQueryDo) Debug() *tenantJoinRequestQueryDo {
return t.withDO(t.DO.Debug())
}
func (t tenantJoinRequestQueryDo) WithContext(ctx context.Context) *tenantJoinRequestQueryDo {
return t.withDO(t.DO.WithContext(ctx))
}
func (t tenantJoinRequestQueryDo) ReadDB() *tenantJoinRequestQueryDo {
return t.Clauses(dbresolver.Read)
}
func (t tenantJoinRequestQueryDo) WriteDB() *tenantJoinRequestQueryDo {
return t.Clauses(dbresolver.Write)
}
func (t tenantJoinRequestQueryDo) Session(config *gorm.Session) *tenantJoinRequestQueryDo {
return t.withDO(t.DO.Session(config))
}
func (t tenantJoinRequestQueryDo) Clauses(conds ...clause.Expression) *tenantJoinRequestQueryDo {
return t.withDO(t.DO.Clauses(conds...))
}
func (t tenantJoinRequestQueryDo) Returning(value interface{}, columns ...string) *tenantJoinRequestQueryDo {
return t.withDO(t.DO.Returning(value, columns...))
}
func (t tenantJoinRequestQueryDo) Not(conds ...gen.Condition) *tenantJoinRequestQueryDo {
return t.withDO(t.DO.Not(conds...))
}
func (t tenantJoinRequestQueryDo) Or(conds ...gen.Condition) *tenantJoinRequestQueryDo {
return t.withDO(t.DO.Or(conds...))
}
func (t tenantJoinRequestQueryDo) Select(conds ...field.Expr) *tenantJoinRequestQueryDo {
return t.withDO(t.DO.Select(conds...))
}
func (t tenantJoinRequestQueryDo) Where(conds ...gen.Condition) *tenantJoinRequestQueryDo {
return t.withDO(t.DO.Where(conds...))
}
func (t tenantJoinRequestQueryDo) Order(conds ...field.Expr) *tenantJoinRequestQueryDo {
return t.withDO(t.DO.Order(conds...))
}
func (t tenantJoinRequestQueryDo) Distinct(cols ...field.Expr) *tenantJoinRequestQueryDo {
return t.withDO(t.DO.Distinct(cols...))
}
func (t tenantJoinRequestQueryDo) Omit(cols ...field.Expr) *tenantJoinRequestQueryDo {
return t.withDO(t.DO.Omit(cols...))
}
func (t tenantJoinRequestQueryDo) Join(table schema.Tabler, on ...field.Expr) *tenantJoinRequestQueryDo {
return t.withDO(t.DO.Join(table, on...))
}
func (t tenantJoinRequestQueryDo) LeftJoin(table schema.Tabler, on ...field.Expr) *tenantJoinRequestQueryDo {
return t.withDO(t.DO.LeftJoin(table, on...))
}
func (t tenantJoinRequestQueryDo) RightJoin(table schema.Tabler, on ...field.Expr) *tenantJoinRequestQueryDo {
return t.withDO(t.DO.RightJoin(table, on...))
}
func (t tenantJoinRequestQueryDo) Group(cols ...field.Expr) *tenantJoinRequestQueryDo {
return t.withDO(t.DO.Group(cols...))
}
func (t tenantJoinRequestQueryDo) Having(conds ...gen.Condition) *tenantJoinRequestQueryDo {
return t.withDO(t.DO.Having(conds...))
}
func (t tenantJoinRequestQueryDo) Limit(limit int) *tenantJoinRequestQueryDo {
return t.withDO(t.DO.Limit(limit))
}
func (t tenantJoinRequestQueryDo) Offset(offset int) *tenantJoinRequestQueryDo {
return t.withDO(t.DO.Offset(offset))
}
func (t tenantJoinRequestQueryDo) Scopes(funcs ...func(gen.Dao) gen.Dao) *tenantJoinRequestQueryDo {
return t.withDO(t.DO.Scopes(funcs...))
}
func (t tenantJoinRequestQueryDo) Unscoped() *tenantJoinRequestQueryDo {
return t.withDO(t.DO.Unscoped())
}
func (t tenantJoinRequestQueryDo) Create(values ...*TenantJoinRequest) error {
if len(values) == 0 {
return nil
}
return t.DO.Create(values)
}
func (t tenantJoinRequestQueryDo) CreateInBatches(values []*TenantJoinRequest, batchSize int) error {
return t.DO.CreateInBatches(values, batchSize)
}
// Save : !!! underlying implementation is different with GORM
// The method is equivalent to executing the statement: db.Clauses(clause.OnConflict{UpdateAll: true}).Create(values)
func (t tenantJoinRequestQueryDo) Save(values ...*TenantJoinRequest) error {
if len(values) == 0 {
return nil
}
return t.DO.Save(values)
}
func (t tenantJoinRequestQueryDo) First() (*TenantJoinRequest, error) {
if result, err := t.DO.First(); err != nil {
return nil, err
} else {
return result.(*TenantJoinRequest), nil
}
}
func (t tenantJoinRequestQueryDo) Take() (*TenantJoinRequest, error) {
if result, err := t.DO.Take(); err != nil {
return nil, err
} else {
return result.(*TenantJoinRequest), nil
}
}
func (t tenantJoinRequestQueryDo) Last() (*TenantJoinRequest, error) {
if result, err := t.DO.Last(); err != nil {
return nil, err
} else {
return result.(*TenantJoinRequest), nil
}
}
func (t tenantJoinRequestQueryDo) Find() ([]*TenantJoinRequest, error) {
result, err := t.DO.Find()
return result.([]*TenantJoinRequest), err
}
func (t tenantJoinRequestQueryDo) FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*TenantJoinRequest, err error) {
buf := make([]*TenantJoinRequest, 0, batchSize)
err = t.DO.FindInBatches(&buf, batchSize, func(tx gen.Dao, batch int) error {
defer func() { results = append(results, buf...) }()
return fc(tx, batch)
})
return results, err
}
func (t tenantJoinRequestQueryDo) FindInBatches(result *[]*TenantJoinRequest, batchSize int, fc func(tx gen.Dao, batch int) error) error {
return t.DO.FindInBatches(result, batchSize, fc)
}
func (t tenantJoinRequestQueryDo) Attrs(attrs ...field.AssignExpr) *tenantJoinRequestQueryDo {
return t.withDO(t.DO.Attrs(attrs...))
}
func (t tenantJoinRequestQueryDo) Assign(attrs ...field.AssignExpr) *tenantJoinRequestQueryDo {
return t.withDO(t.DO.Assign(attrs...))
}
func (t tenantJoinRequestQueryDo) Joins(fields ...field.RelationField) *tenantJoinRequestQueryDo {
for _, _f := range fields {
t = *t.withDO(t.DO.Joins(_f))
}
return &t
}
func (t tenantJoinRequestQueryDo) Preload(fields ...field.RelationField) *tenantJoinRequestQueryDo {
for _, _f := range fields {
t = *t.withDO(t.DO.Preload(_f))
}
return &t
}
func (t tenantJoinRequestQueryDo) FirstOrInit() (*TenantJoinRequest, error) {
if result, err := t.DO.FirstOrInit(); err != nil {
return nil, err
} else {
return result.(*TenantJoinRequest), nil
}
}
func (t tenantJoinRequestQueryDo) FirstOrCreate() (*TenantJoinRequest, error) {
if result, err := t.DO.FirstOrCreate(); err != nil {
return nil, err
} else {
return result.(*TenantJoinRequest), nil
}
}
func (t tenantJoinRequestQueryDo) FindByPage(offset int, limit int) (result []*TenantJoinRequest, count int64, err error) {
result, err = t.Offset(offset).Limit(limit).Find()
if err != nil {
return
}
if size := len(result); 0 < limit && 0 < size && size < limit {
count = int64(size + offset)
return
}
count, err = t.Offset(-1).Limit(-1).Count()
return
}
func (t tenantJoinRequestQueryDo) ScanByPage(result interface{}, offset int, limit int) (count int64, err error) {
count, err = t.Count()
if err != nil {
return
}
err = t.Offset(offset).Limit(limit).Scan(result)
return
}
func (t tenantJoinRequestQueryDo) Scan(result interface{}) (err error) {
return t.DO.Scan(result)
}
func (t tenantJoinRequestQueryDo) Delete(models ...*TenantJoinRequest) (result gen.ResultInfo, err error) {
return t.DO.Delete(models)
}
// ForceDelete performs a permanent delete (ignores soft-delete) for current scope.
func (t tenantJoinRequestQueryDo) ForceDelete() (gen.ResultInfo, error) {
return t.Unscoped().Delete()
}
// Inc increases the given column by step for current scope.
func (t tenantJoinRequestQueryDo) Inc(column field.Expr, step int64) (gen.ResultInfo, error) {
// column = column + step
e := field.NewUnsafeFieldRaw("?+?", column.RawExpr(), step)
return t.DO.UpdateColumn(column, e)
}
// Dec decreases the given column by step for current scope.
func (t tenantJoinRequestQueryDo) Dec(column field.Expr, step int64) (gen.ResultInfo, error) {
// column = column - step
e := field.NewUnsafeFieldRaw("?-?", column.RawExpr(), step)
return t.DO.UpdateColumn(column, e)
}
// Sum returns SUM(column) for current scope.
func (t tenantJoinRequestQueryDo) Sum(column field.Expr) (float64, error) {
var _v float64
agg := field.NewUnsafeFieldRaw("SUM(?)", column.RawExpr())
if err := t.Select(agg).Scan(&_v); err != nil {
return 0, err
}
return _v, nil
}
// Avg returns AVG(column) for current scope.
func (t tenantJoinRequestQueryDo) Avg(column field.Expr) (float64, error) {
var _v float64
agg := field.NewUnsafeFieldRaw("AVG(?)", column.RawExpr())
if err := t.Select(agg).Scan(&_v); err != nil {
return 0, err
}
return _v, nil
}
// Min returns MIN(column) for current scope.
func (t tenantJoinRequestQueryDo) Min(column field.Expr) (float64, error) {
var _v float64
agg := field.NewUnsafeFieldRaw("MIN(?)", column.RawExpr())
if err := t.Select(agg).Scan(&_v); err != nil {
return 0, err
}
return _v, nil
}
// Max returns MAX(column) for current scope.
func (t tenantJoinRequestQueryDo) Max(column field.Expr) (float64, error) {
var _v float64
agg := field.NewUnsafeFieldRaw("MAX(?)", column.RawExpr())
if err := t.Select(agg).Scan(&_v); err != nil {
return 0, err
}
return _v, nil
}
// PluckMap returns a map[key]value for selected key/value expressions within current scope.
func (t tenantJoinRequestQueryDo) PluckMap(key, val field.Expr) (map[interface{}]interface{}, error) {
do := t.Select(key, val)
rows, err := do.DO.Rows()
if err != nil {
return nil, err
}
defer rows.Close()
mm := make(map[interface{}]interface{})
for rows.Next() {
var k interface{}
var v interface{}
if err := rows.Scan(&k, &v); err != nil {
return nil, err
}
mm[k] = v
}
return mm, rows.Err()
}
// Exists returns true if any record matches the given conditions.
func (t tenantJoinRequestQueryDo) Exists(conds ...gen.Condition) (bool, error) {
cnt, err := t.Where(conds...).Count()
if err != nil {
return false, err
}
return cnt > 0, nil
}
// PluckIDs returns all primary key values under current scope.
func (t tenantJoinRequestQueryDo) PluckIDs() ([]int64, error) {
ids := make([]int64, 0, 16)
pk := field.NewInt64(t.TableName(), "id")
if err := t.DO.Pluck(pk, &ids); err != nil {
return nil, err
}
return ids, nil
}
// GetByID finds a single record by primary key.
func (t tenantJoinRequestQueryDo) GetByID(id int64) (*TenantJoinRequest, error) {
pk := field.NewInt64(t.TableName(), "id")
return t.Where(pk.Eq(id)).First()
}
// GetByIDs finds records by primary key list.
func (t tenantJoinRequestQueryDo) GetByIDs(ids ...int64) ([]*TenantJoinRequest, error) {
if len(ids) == 0 {
return []*TenantJoinRequest{}, nil
}
pk := field.NewInt64(t.TableName(), "id")
return t.Where(pk.In(ids...)).Find()
}
// DeleteByID deletes records by primary key.
func (t tenantJoinRequestQueryDo) DeleteByID(id int64) (gen.ResultInfo, error) {
pk := field.NewInt64(t.TableName(), "id")
return t.Where(pk.Eq(id)).Delete()
}
// DeleteByIDs deletes records by a list of primary keys.
func (t tenantJoinRequestQueryDo) DeleteByIDs(ids ...int64) (gen.ResultInfo, error) {
if len(ids) == 0 {
return gen.ResultInfo{RowsAffected: 0, Error: nil}, nil
}
pk := field.NewInt64(t.TableName(), "id")
return t.Where(pk.In(ids...)).Delete()
}
func (t *tenantJoinRequestQueryDo) withDO(do gen.Dao) *tenantJoinRequestQueryDo {
t.DO = *do.(*gen.DO)
return t
}

View File

@@ -23,7 +23,7 @@ type TenantUser struct {
UserID int64 `gorm:"column:user_id;type:bigint;not null" json:"user_id"`
Role types.Array[consts.TenantUserRole] `gorm:"column:role;type:text[];not null;default:ARRAY['member" json:"role"`
Balance int64 `gorm:"column:balance;type:bigint;not null" json:"balance"`
Status consts.UserStatus `gorm:"column:status;type:character varying(50);not null;default:active" json:"status"`
Status consts.UserStatus `gorm:"column:status;type:character varying(50);not null;default:verified" json:"status"`
CreatedAt time.Time `gorm:"column:created_at;type:timestamp with time zone;not null;default:now()" json:"created_at"`
UpdatedAt time.Time `gorm:"column:updated_at;type:timestamp with time zone;not null;default:now()" json:"updated_at"`
BalanceFrozen int64 `gorm:"column:balance_frozen;type:bigint;not null;comment:冻结余额:分/最小货币单位;下单冻结时从可用余额转入,最终扣款或回滚时转出;默认 0" json:"balance_frozen"` // 冻结余额:分/最小货币单位;下单冻结时从可用余额转入,最终扣款或回滚时转出;默认 0

View File

@@ -29,8 +29,8 @@ type User struct {
Status consts.UserStatus `gorm:"column:status;type:character varying(50);not null;default:active" json:"status"`
Metas types.JSON `gorm:"column:metas;type:jsonb;not null;default:{}" json:"metas"`
VerifiedAt time.Time `gorm:"column:verified_at;type:timestamp with time zone" json:"verified_at"`
Tenants []*Tenant `gorm:"joinForeignKey:UserID;joinReferences:TenantID;many2many:tenant_users" json:"tenants,omitempty"`
OwnedTenant *Tenant `json:"owned,omitempty"`
Tenants []*Tenant `gorm:"joinForeignKey:UserID;joinReferences:TenantID;many2many:tenant_users" json:"tenants,omitempty"`
}
// Quick operations without importing query package

View File

@@ -35,18 +35,18 @@ func newUser(db *gorm.DB, opts ...gen.DOOption) userQuery {
_userQuery.Status = field.NewField(tableName, "status")
_userQuery.Metas = field.NewJSONB(tableName, "metas")
_userQuery.VerifiedAt = field.NewTime(tableName, "verified_at")
_userQuery.Tenants = userQueryManyToManyTenants{
db: db.Session(&gorm.Session{}),
RelationField: field.NewRelation("Tenants", "Tenant"),
}
_userQuery.OwnedTenant = userQueryBelongsToOwnedTenant{
db: db.Session(&gorm.Session{}),
RelationField: field.NewRelation("OwnedTenant", "Tenant"),
}
_userQuery.Tenants = userQueryManyToManyTenants{
db: db.Session(&gorm.Session{}),
RelationField: field.NewRelation("Tenants", "Tenant"),
}
_userQuery.fillFieldMap()
return _userQuery
@@ -55,21 +55,21 @@ func newUser(db *gorm.DB, opts ...gen.DOOption) userQuery {
type userQuery struct {
userQueryDo userQueryDo
ALL field.Asterisk
ID field.Int64
CreatedAt field.Time
UpdatedAt field.Time
DeletedAt field.Field
Username field.String
Password field.String
Roles field.Array
Status field.Field
Metas field.JSONB
VerifiedAt field.Time
Tenants userQueryManyToManyTenants
ALL field.Asterisk
ID field.Int64
CreatedAt field.Time
UpdatedAt field.Time
DeletedAt field.Field
Username field.String
Password field.String
Roles field.Array
Status field.Field
Metas field.JSONB
VerifiedAt field.Time
OwnedTenant userQueryBelongsToOwnedTenant
Tenants userQueryManyToManyTenants
fieldMap map[string]field.Expr
}
@@ -141,101 +141,20 @@ func (u *userQuery) fillFieldMap() {
func (u userQuery) clone(db *gorm.DB) userQuery {
u.userQueryDo.ReplaceConnPool(db.Statement.ConnPool)
u.Tenants.db = db.Session(&gorm.Session{Initialized: true})
u.Tenants.db.Statement.ConnPool = db.Statement.ConnPool
u.OwnedTenant.db = db.Session(&gorm.Session{Initialized: true})
u.OwnedTenant.db.Statement.ConnPool = db.Statement.ConnPool
u.Tenants.db = db.Session(&gorm.Session{Initialized: true})
u.Tenants.db.Statement.ConnPool = db.Statement.ConnPool
return u
}
func (u userQuery) replaceDB(db *gorm.DB) userQuery {
u.userQueryDo.ReplaceDB(db)
u.Tenants.db = db.Session(&gorm.Session{})
u.OwnedTenant.db = db.Session(&gorm.Session{})
u.Tenants.db = db.Session(&gorm.Session{})
return u
}
type userQueryManyToManyTenants struct {
db *gorm.DB
field.RelationField
}
func (a userQueryManyToManyTenants) Where(conds ...field.Expr) *userQueryManyToManyTenants {
if len(conds) == 0 {
return &a
}
exprs := make([]clause.Expression, 0, len(conds))
for _, cond := range conds {
exprs = append(exprs, cond.BeCond().(clause.Expression))
}
a.db = a.db.Clauses(clause.Where{Exprs: exprs})
return &a
}
func (a userQueryManyToManyTenants) WithContext(ctx context.Context) *userQueryManyToManyTenants {
a.db = a.db.WithContext(ctx)
return &a
}
func (a userQueryManyToManyTenants) Session(session *gorm.Session) *userQueryManyToManyTenants {
a.db = a.db.Session(session)
return &a
}
func (a userQueryManyToManyTenants) Model(m *User) *userQueryManyToManyTenantsTx {
return &userQueryManyToManyTenantsTx{a.db.Model(m).Association(a.Name())}
}
func (a userQueryManyToManyTenants) Unscoped() *userQueryManyToManyTenants {
a.db = a.db.Unscoped()
return &a
}
type userQueryManyToManyTenantsTx struct{ tx *gorm.Association }
func (a userQueryManyToManyTenantsTx) Find() (result []*Tenant, err error) {
return result, a.tx.Find(&result)
}
func (a userQueryManyToManyTenantsTx) Append(values ...*Tenant) (err error) {
targetValues := make([]interface{}, len(values))
for i, v := range values {
targetValues[i] = v
}
return a.tx.Append(targetValues...)
}
func (a userQueryManyToManyTenantsTx) Replace(values ...*Tenant) (err error) {
targetValues := make([]interface{}, len(values))
for i, v := range values {
targetValues[i] = v
}
return a.tx.Replace(targetValues...)
}
func (a userQueryManyToManyTenantsTx) Delete(values ...*Tenant) (err error) {
targetValues := make([]interface{}, len(values))
for i, v := range values {
targetValues[i] = v
}
return a.tx.Delete(targetValues...)
}
func (a userQueryManyToManyTenantsTx) Clear() error {
return a.tx.Clear()
}
func (a userQueryManyToManyTenantsTx) Count() int64 {
return a.tx.Count()
}
func (a userQueryManyToManyTenantsTx) Unscoped() *userQueryManyToManyTenantsTx {
a.tx = a.tx.Unscoped()
return &a
}
type userQueryBelongsToOwnedTenant struct {
db *gorm.DB
@@ -317,6 +236,87 @@ func (a userQueryBelongsToOwnedTenantTx) Unscoped() *userQueryBelongsToOwnedTena
return &a
}
type userQueryManyToManyTenants struct {
db *gorm.DB
field.RelationField
}
func (a userQueryManyToManyTenants) Where(conds ...field.Expr) *userQueryManyToManyTenants {
if len(conds) == 0 {
return &a
}
exprs := make([]clause.Expression, 0, len(conds))
for _, cond := range conds {
exprs = append(exprs, cond.BeCond().(clause.Expression))
}
a.db = a.db.Clauses(clause.Where{Exprs: exprs})
return &a
}
func (a userQueryManyToManyTenants) WithContext(ctx context.Context) *userQueryManyToManyTenants {
a.db = a.db.WithContext(ctx)
return &a
}
func (a userQueryManyToManyTenants) Session(session *gorm.Session) *userQueryManyToManyTenants {
a.db = a.db.Session(session)
return &a
}
func (a userQueryManyToManyTenants) Model(m *User) *userQueryManyToManyTenantsTx {
return &userQueryManyToManyTenantsTx{a.db.Model(m).Association(a.Name())}
}
func (a userQueryManyToManyTenants) Unscoped() *userQueryManyToManyTenants {
a.db = a.db.Unscoped()
return &a
}
type userQueryManyToManyTenantsTx struct{ tx *gorm.Association }
func (a userQueryManyToManyTenantsTx) Find() (result []*Tenant, err error) {
return result, a.tx.Find(&result)
}
func (a userQueryManyToManyTenantsTx) Append(values ...*Tenant) (err error) {
targetValues := make([]interface{}, len(values))
for i, v := range values {
targetValues[i] = v
}
return a.tx.Append(targetValues...)
}
func (a userQueryManyToManyTenantsTx) Replace(values ...*Tenant) (err error) {
targetValues := make([]interface{}, len(values))
for i, v := range values {
targetValues[i] = v
}
return a.tx.Replace(targetValues...)
}
func (a userQueryManyToManyTenantsTx) Delete(values ...*Tenant) (err error) {
targetValues := make([]interface{}, len(values))
for i, v := range values {
targetValues[i] = v
}
return a.tx.Delete(targetValues...)
}
func (a userQueryManyToManyTenantsTx) Clear() error {
return a.tx.Clear()
}
func (a userQueryManyToManyTenantsTx) Count() int64 {
return a.tx.Count()
}
func (a userQueryManyToManyTenantsTx) Unscoped() *userQueryManyToManyTenantsTx {
a.tx = a.tx.Unscoped()
return &a
}
type userQueryDo struct{ gen.DO }
func (u userQueryDo) Debug() *userQueryDo {