feat(user): implement OTP login, user creation, and profile management

- Added SendOTP method for simulating OTP sending.
- Implemented LoginWithOTP method for user login/registration via OTP, including user creation if not found.
- Added Me method to retrieve current user information.
- Implemented Update method for updating user profile details.
- Added RealName method for real-name verification.
- Implemented GetNotifications method to fetch user notifications.
- Created user_test.go for comprehensive unit tests covering login, profile retrieval, updates, real-name verification, and notifications.
- Updated database models to use appropriate consts for fields like gender, status, and roles.
This commit is contained in:
2025-12-29 10:55:13 +08:00
parent bc2064639f
commit b78f1e1c84
17 changed files with 497 additions and 120 deletions

View File

@@ -11,4 +11,22 @@ imports:
- quyun/v2/pkg/consts
- quyun/v2/database/fields
field_type:
field_relate:
users:
gender: consts.Gender
roles: types.Array[consts.Role]
contents:
status: consts.ContentStatus
visibility: consts.ContentVisibility
genre: string # genre is varchar(64) but no enum defined yet?
content_prices:
currency: consts.Currency
discount_type: consts.DiscountType
orders:
status: consts.OrderStatus
type: consts.OrderType
tenants:
status: consts.TenantStatus
tenant_users:
role: types.Array[consts.TenantUserRole]
# status: consts.UserStatus # Skipping status for now to avoid mismatch 'active' vs 'verified' without enum update
field_relate:

View File

@@ -8,6 +8,8 @@ import (
"context"
"time"
"quyun/v2/pkg/consts"
"go.ipao.vip/gen"
)
@@ -15,18 +17,18 @@ const TableNameContentPrice = "content_prices"
// ContentPrice mapped from table <content_prices>
type ContentPrice struct {
ID int64 `gorm:"column:id;type:bigint;primaryKey;autoIncrement:true" json:"id"`
TenantID int64 `gorm:"column:tenant_id;type:bigint;not null" json:"tenant_id"`
UserID int64 `gorm:"column:user_id;type:bigint;not null" json:"user_id"`
ContentID int64 `gorm:"column:content_id;type:bigint;not null" json:"content_id"`
Currency string `gorm:"column:currency;type:character varying(16);default:CNY" json:"currency"`
PriceAmount int64 `gorm:"column:price_amount;type:bigint;not null" json:"price_amount"`
DiscountType string `gorm:"column:discount_type;type:character varying(16);default:none" json:"discount_type"`
DiscountValue int64 `gorm:"column:discount_value;type:bigint" json:"discount_value"`
DiscountStartAt time.Time `gorm:"column:discount_start_at;type:timestamp with time zone" json:"discount_start_at"`
DiscountEndAt time.Time `gorm:"column:discount_end_at;type:timestamp with time zone" json:"discount_end_at"`
CreatedAt time.Time `gorm:"column:created_at;type:timestamp with time zone;default:now()" json:"created_at"`
UpdatedAt time.Time `gorm:"column:updated_at;type:timestamp with time zone;default:now()" json:"updated_at"`
ID int64 `gorm:"column:id;type:bigint;primaryKey;autoIncrement:true" json:"id"`
TenantID int64 `gorm:"column:tenant_id;type:bigint;not null" json:"tenant_id"`
UserID int64 `gorm:"column:user_id;type:bigint;not null" json:"user_id"`
ContentID int64 `gorm:"column:content_id;type:bigint;not null" json:"content_id"`
Currency consts.Currency `gorm:"column:currency;type:character varying(16);default:CNY" json:"currency"`
PriceAmount int64 `gorm:"column:price_amount;type:bigint;not null" json:"price_amount"`
DiscountType consts.DiscountType `gorm:"column:discount_type;type:character varying(16);default:none" json:"discount_type"`
DiscountValue int64 `gorm:"column:discount_value;type:bigint" json:"discount_value"`
DiscountStartAt time.Time `gorm:"column:discount_start_at;type:timestamp with time zone" json:"discount_start_at"`
DiscountEndAt time.Time `gorm:"column:discount_end_at;type:timestamp with time zone" json:"discount_end_at"`
CreatedAt time.Time `gorm:"column:created_at;type:timestamp with time zone;default:now()" json:"created_at"`
UpdatedAt time.Time `gorm:"column:updated_at;type:timestamp with time zone;default:now()" json:"updated_at"`
}
// Quick operations without importing query package

View File

@@ -29,9 +29,9 @@ func newContentPrice(db *gorm.DB, opts ...gen.DOOption) contentPriceQuery {
_contentPriceQuery.TenantID = field.NewInt64(tableName, "tenant_id")
_contentPriceQuery.UserID = field.NewInt64(tableName, "user_id")
_contentPriceQuery.ContentID = field.NewInt64(tableName, "content_id")
_contentPriceQuery.Currency = field.NewString(tableName, "currency")
_contentPriceQuery.Currency = field.NewField(tableName, "currency")
_contentPriceQuery.PriceAmount = field.NewInt64(tableName, "price_amount")
_contentPriceQuery.DiscountType = field.NewString(tableName, "discount_type")
_contentPriceQuery.DiscountType = field.NewField(tableName, "discount_type")
_contentPriceQuery.DiscountValue = field.NewInt64(tableName, "discount_value")
_contentPriceQuery.DiscountStartAt = field.NewTime(tableName, "discount_start_at")
_contentPriceQuery.DiscountEndAt = field.NewTime(tableName, "discount_end_at")
@@ -51,9 +51,9 @@ type contentPriceQuery struct {
TenantID field.Int64
UserID field.Int64
ContentID field.Int64
Currency field.String
Currency field.Field
PriceAmount field.Int64
DiscountType field.String
DiscountType field.Field
DiscountValue field.Int64
DiscountStartAt field.Time
DiscountEndAt field.Time
@@ -79,9 +79,9 @@ func (c *contentPriceQuery) updateTableName(table string) *contentPriceQuery {
c.TenantID = field.NewInt64(table, "tenant_id")
c.UserID = field.NewInt64(table, "user_id")
c.ContentID = field.NewInt64(table, "content_id")
c.Currency = field.NewString(table, "currency")
c.Currency = field.NewField(table, "currency")
c.PriceAmount = field.NewInt64(table, "price_amount")
c.DiscountType = field.NewString(table, "discount_type")
c.DiscountType = field.NewField(table, "discount_type")
c.DiscountValue = field.NewInt64(table, "discount_value")
c.DiscountStartAt = field.NewTime(table, "discount_start_at")
c.DiscountEndAt = field.NewTime(table, "discount_end_at")

View File

@@ -8,6 +8,8 @@ import (
"context"
"time"
"quyun/v2/pkg/consts"
"go.ipao.vip/gen"
"go.ipao.vip/gen/types"
"gorm.io/gorm"
@@ -17,25 +19,25 @@ const TableNameContent = "contents"
// Content mapped from table <contents>
type Content struct {
ID int64 `gorm:"column:id;type:bigint;primaryKey;autoIncrement:true" json:"id"`
TenantID int64 `gorm:"column:tenant_id;type:bigint;not null" json:"tenant_id"`
UserID int64 `gorm:"column:user_id;type:bigint;not null" json:"user_id"`
Title string `gorm:"column:title;type:character varying(255);not null" json:"title"`
Description string `gorm:"column:description;type:text;not null" json:"description"`
Status string `gorm:"column:status;type:character varying(32);default:draft" json:"status"`
Visibility string `gorm:"column:visibility;type:character varying(32);default:tenant_only" json:"visibility"`
PreviewSeconds int32 `gorm:"column:preview_seconds;type:integer;default:60" json:"preview_seconds"`
PreviewDownloadable bool `gorm:"column:preview_downloadable;type:boolean" json:"preview_downloadable"`
PublishedAt time.Time `gorm:"column:published_at;type:timestamp with time zone" json:"published_at"`
Summary string `gorm:"column:summary;type:character varying(256)" json:"summary"`
Tags types.JSON `gorm:"column:tags;type:jsonb;default:[]" json:"tags"`
Body string `gorm:"column:body;type:text" json:"body"`
Genre string `gorm:"column:genre;type:character varying(64)" json:"genre"`
Views int32 `gorm:"column:views;type:integer" json:"views"`
Likes int32 `gorm:"column:likes;type:integer" json:"likes"`
CreatedAt time.Time `gorm:"column:created_at;type:timestamp with time zone;default:now()" json:"created_at"`
UpdatedAt time.Time `gorm:"column:updated_at;type:timestamp with time zone;default:now()" json:"updated_at"`
DeletedAt gorm.DeletedAt `gorm:"column:deleted_at;type:timestamp with time zone" json:"deleted_at"`
ID int64 `gorm:"column:id;type:bigint;primaryKey;autoIncrement:true" json:"id"`
TenantID int64 `gorm:"column:tenant_id;type:bigint;not null" json:"tenant_id"`
UserID int64 `gorm:"column:user_id;type:bigint;not null" json:"user_id"`
Title string `gorm:"column:title;type:character varying(255);not null" json:"title"`
Description string `gorm:"column:description;type:text;not null" json:"description"`
Status consts.ContentStatus `gorm:"column:status;type:character varying(32);default:draft" json:"status"`
Visibility consts.ContentVisibility `gorm:"column:visibility;type:character varying(32);default:tenant_only" json:"visibility"`
PreviewSeconds int32 `gorm:"column:preview_seconds;type:integer;default:60" json:"preview_seconds"`
PreviewDownloadable bool `gorm:"column:preview_downloadable;type:boolean" json:"preview_downloadable"`
PublishedAt time.Time `gorm:"column:published_at;type:timestamp with time zone" json:"published_at"`
Summary string `gorm:"column:summary;type:character varying(256)" json:"summary"`
Tags types.JSON `gorm:"column:tags;type:jsonb;default:[]" json:"tags"`
Body string `gorm:"column:body;type:text" json:"body"`
Genre string `gorm:"column:genre;type:character varying(64)" json:"genre"`
Views int32 `gorm:"column:views;type:integer" json:"views"`
Likes int32 `gorm:"column:likes;type:integer" json:"likes"`
CreatedAt time.Time `gorm:"column:created_at;type:timestamp with time zone;default:now()" json:"created_at"`
UpdatedAt time.Time `gorm:"column:updated_at;type:timestamp with time zone;default:now()" json:"updated_at"`
DeletedAt gorm.DeletedAt `gorm:"column:deleted_at;type:timestamp with time zone" json:"deleted_at"`
}
// Quick operations without importing query package

View File

@@ -30,8 +30,8 @@ func newContent(db *gorm.DB, opts ...gen.DOOption) contentQuery {
_contentQuery.UserID = field.NewInt64(tableName, "user_id")
_contentQuery.Title = field.NewString(tableName, "title")
_contentQuery.Description = field.NewString(tableName, "description")
_contentQuery.Status = field.NewString(tableName, "status")
_contentQuery.Visibility = field.NewString(tableName, "visibility")
_contentQuery.Status = field.NewField(tableName, "status")
_contentQuery.Visibility = field.NewField(tableName, "visibility")
_contentQuery.PreviewSeconds = field.NewInt32(tableName, "preview_seconds")
_contentQuery.PreviewDownloadable = field.NewBool(tableName, "preview_downloadable")
_contentQuery.PublishedAt = field.NewTime(tableName, "published_at")
@@ -59,8 +59,8 @@ type contentQuery struct {
UserID field.Int64
Title field.String
Description field.String
Status field.String
Visibility field.String
Status field.Field
Visibility field.Field
PreviewSeconds field.Int32
PreviewDownloadable field.Bool
PublishedAt field.Time
@@ -94,8 +94,8 @@ func (c *contentQuery) updateTableName(table string) *contentQuery {
c.UserID = field.NewInt64(table, "user_id")
c.Title = field.NewString(table, "title")
c.Description = field.NewString(table, "description")
c.Status = field.NewString(table, "status")
c.Visibility = field.NewString(table, "visibility")
c.Status = field.NewField(table, "status")
c.Visibility = field.NewField(table, "visibility")
c.PreviewSeconds = field.NewInt32(table, "preview_seconds")
c.PreviewDownloadable = field.NewBool(table, "preview_downloadable")
c.PublishedAt = field.NewTime(table, "published_at")

View File

@@ -8,6 +8,8 @@ import (
"context"
"time"
"quyun/v2/pkg/consts"
"go.ipao.vip/gen"
"go.ipao.vip/gen/types"
)
@@ -16,24 +18,24 @@ const TableNameOrder = "orders"
// Order mapped from table <orders>
type Order struct {
ID int64 `gorm:"column:id;type:bigint;primaryKey;autoIncrement:true" json:"id"`
TenantID int64 `gorm:"column:tenant_id;type:bigint;not null" json:"tenant_id"`
UserID int64 `gorm:"column:user_id;type:bigint;not null" json:"user_id"`
Type string `gorm:"column:type;type:character varying(32);default:content_purchase" json:"type"`
Status string `gorm:"column:status;type:character varying(32);default:created" json:"status"`
Currency string `gorm:"column:currency;type:character varying(16);default:CNY" json:"currency"`
AmountOriginal int64 `gorm:"column:amount_original;type:bigint;not null" json:"amount_original"`
AmountDiscount int64 `gorm:"column:amount_discount;type:bigint;not null" json:"amount_discount"`
AmountPaid int64 `gorm:"column:amount_paid;type:bigint;not null" json:"amount_paid"`
Snapshot types.JSON `gorm:"column:snapshot;type:jsonb;default:{}" json:"snapshot"`
IdempotencyKey string `gorm:"column:idempotency_key;type:character varying(128);not null" json:"idempotency_key"`
PaidAt time.Time `gorm:"column:paid_at;type:timestamp with time zone" json:"paid_at"`
RefundedAt time.Time `gorm:"column:refunded_at;type:timestamp with time zone" json:"refunded_at"`
RefundForced bool `gorm:"column:refund_forced;type:boolean" json:"refund_forced"`
RefundOperatorUserID int64 `gorm:"column:refund_operator_user_id;type:bigint" json:"refund_operator_user_id"`
RefundReason string `gorm:"column:refund_reason;type:character varying(255)" json:"refund_reason"`
CreatedAt time.Time `gorm:"column:created_at;type:timestamp with time zone;default:now()" json:"created_at"`
UpdatedAt time.Time `gorm:"column:updated_at;type:timestamp with time zone;default:now()" json:"updated_at"`
ID int64 `gorm:"column:id;type:bigint;primaryKey;autoIncrement:true" json:"id"`
TenantID int64 `gorm:"column:tenant_id;type:bigint;not null" json:"tenant_id"`
UserID int64 `gorm:"column:user_id;type:bigint;not null" json:"user_id"`
Type consts.OrderType `gorm:"column:type;type:character varying(32);default:content_purchase" json:"type"`
Status consts.OrderStatus `gorm:"column:status;type:character varying(32);default:created" json:"status"`
Currency string `gorm:"column:currency;type:character varying(16);default:CNY" json:"currency"`
AmountOriginal int64 `gorm:"column:amount_original;type:bigint;not null" json:"amount_original"`
AmountDiscount int64 `gorm:"column:amount_discount;type:bigint;not null" json:"amount_discount"`
AmountPaid int64 `gorm:"column:amount_paid;type:bigint;not null" json:"amount_paid"`
Snapshot types.JSON `gorm:"column:snapshot;type:jsonb;default:{}" json:"snapshot"`
IdempotencyKey string `gorm:"column:idempotency_key;type:character varying(128);not null" json:"idempotency_key"`
PaidAt time.Time `gorm:"column:paid_at;type:timestamp with time zone" json:"paid_at"`
RefundedAt time.Time `gorm:"column:refunded_at;type:timestamp with time zone" json:"refunded_at"`
RefundForced bool `gorm:"column:refund_forced;type:boolean" json:"refund_forced"`
RefundOperatorUserID int64 `gorm:"column:refund_operator_user_id;type:bigint" json:"refund_operator_user_id"`
RefundReason string `gorm:"column:refund_reason;type:character varying(255)" json:"refund_reason"`
CreatedAt time.Time `gorm:"column:created_at;type:timestamp with time zone;default:now()" json:"created_at"`
UpdatedAt time.Time `gorm:"column:updated_at;type:timestamp with time zone;default:now()" json:"updated_at"`
}
// Quick operations without importing query package

View File

@@ -28,8 +28,8 @@ func newOrder(db *gorm.DB, opts ...gen.DOOption) orderQuery {
_orderQuery.ID = field.NewInt64(tableName, "id")
_orderQuery.TenantID = field.NewInt64(tableName, "tenant_id")
_orderQuery.UserID = field.NewInt64(tableName, "user_id")
_orderQuery.Type = field.NewString(tableName, "type")
_orderQuery.Status = field.NewString(tableName, "status")
_orderQuery.Type = field.NewField(tableName, "type")
_orderQuery.Status = field.NewField(tableName, "status")
_orderQuery.Currency = field.NewString(tableName, "currency")
_orderQuery.AmountOriginal = field.NewInt64(tableName, "amount_original")
_orderQuery.AmountDiscount = field.NewInt64(tableName, "amount_discount")
@@ -56,8 +56,8 @@ type orderQuery struct {
ID field.Int64
TenantID field.Int64
UserID field.Int64
Type field.String
Status field.String
Type field.Field
Status field.Field
Currency field.String
AmountOriginal field.Int64
AmountDiscount field.Int64
@@ -90,8 +90,8 @@ func (o *orderQuery) updateTableName(table string) *orderQuery {
o.ID = field.NewInt64(table, "id")
o.TenantID = field.NewInt64(table, "tenant_id")
o.UserID = field.NewInt64(table, "user_id")
o.Type = field.NewString(table, "type")
o.Status = field.NewString(table, "status")
o.Type = field.NewField(table, "type")
o.Status = field.NewField(table, "status")
o.Currency = field.NewString(table, "currency")
o.AmountOriginal = field.NewInt64(table, "amount_original")
o.AmountDiscount = field.NewInt64(table, "amount_discount")

View File

@@ -8,6 +8,8 @@ import (
"context"
"time"
"quyun/v2/pkg/consts"
"go.ipao.vip/gen"
"go.ipao.vip/gen/types"
)
@@ -16,13 +18,13 @@ const TableNameTenantUser = "tenant_users"
// TenantUser mapped from table <tenant_users>
type TenantUser struct {
ID int64 `gorm:"column:id;type:bigint;primaryKey;autoIncrement:true" json:"id"`
TenantID int64 `gorm:"column:tenant_id;type:bigint;not null" json:"tenant_id"`
UserID int64 `gorm:"column:user_id;type:bigint;not null" json:"user_id"`
Role types.Array[string] `gorm:"column:role;type:text[];default:{member}" json:"role"`
Status string `gorm:"column:status;type:character varying(50);default:verified" json:"status"`
CreatedAt time.Time `gorm:"column:created_at;type:timestamp with time zone;default:now()" json:"created_at"`
UpdatedAt time.Time `gorm:"column:updated_at;type:timestamp with time zone;default:now()" json:"updated_at"`
ID int64 `gorm:"column:id;type:bigint;primaryKey;autoIncrement:true" json:"id"`
TenantID int64 `gorm:"column:tenant_id;type:bigint;not null" json:"tenant_id"`
UserID int64 `gorm:"column:user_id;type:bigint;not null" json:"user_id"`
Role types.Array[consts.TenantUserRole] `gorm:"column:role;type:text[];default:{member}" json:"role"`
Status string `gorm:"column:status;type:character varying(50);default:verified" json:"status"`
CreatedAt time.Time `gorm:"column:created_at;type:timestamp with time zone;default:now()" json:"created_at"`
UpdatedAt time.Time `gorm:"column:updated_at;type:timestamp with time zone;default:now()" json:"updated_at"`
}
// Quick operations without importing query package

View File

@@ -8,6 +8,8 @@ import (
"context"
"time"
"quyun/v2/pkg/consts"
"go.ipao.vip/gen"
"go.ipao.vip/gen/types"
)
@@ -16,16 +18,16 @@ const TableNameTenant = "tenants"
// Tenant mapped from table <tenants>
type Tenant struct {
ID int64 `gorm:"column:id;type:bigint;primaryKey;autoIncrement:true" json:"id"`
UserID int64 `gorm:"column:user_id;type:bigint;not null" json:"user_id"`
Code string `gorm:"column:code;type:character varying(64);not null" json:"code"`
UUID types.UUID `gorm:"column:uuid;type:uuid;not null" json:"uuid"`
Name string `gorm:"column:name;type:character varying(128);not null" json:"name"`
Status string `gorm:"column:status;type:character varying(64);not null" json:"status"`
Config types.JSON `gorm:"column:config;type:jsonb;default:{}" json:"config"`
ExpiredAt time.Time `gorm:"column:expired_at;type:timestamp with time zone" json:"expired_at"`
CreatedAt time.Time `gorm:"column:created_at;type:timestamp with time zone;default:now()" json:"created_at"`
UpdatedAt time.Time `gorm:"column:updated_at;type:timestamp with time zone;default:now()" json:"updated_at"`
ID int64 `gorm:"column:id;type:bigint;primaryKey;autoIncrement:true" json:"id"`
UserID int64 `gorm:"column:user_id;type:bigint;not null" json:"user_id"`
Code string `gorm:"column:code;type:character varying(64);not null" json:"code"`
UUID types.UUID `gorm:"column:uuid;type:uuid;not null" json:"uuid"`
Name string `gorm:"column:name;type:character varying(128);not null" json:"name"`
Status consts.TenantStatus `gorm:"column:status;type:character varying(64);not null" json:"status"`
Config types.JSON `gorm:"column:config;type:jsonb;default:{}" json:"config"`
ExpiredAt time.Time `gorm:"column:expired_at;type:timestamp with time zone" json:"expired_at"`
CreatedAt time.Time `gorm:"column:created_at;type:timestamp with time zone;default:now()" json:"created_at"`
UpdatedAt time.Time `gorm:"column:updated_at;type:timestamp with time zone;default:now()" json:"updated_at"`
}
// Quick operations without importing query package

View File

@@ -30,7 +30,7 @@ func newTenant(db *gorm.DB, opts ...gen.DOOption) tenantQuery {
_tenantQuery.Code = field.NewString(tableName, "code")
_tenantQuery.UUID = field.NewField(tableName, "uuid")
_tenantQuery.Name = field.NewString(tableName, "name")
_tenantQuery.Status = field.NewString(tableName, "status")
_tenantQuery.Status = field.NewField(tableName, "status")
_tenantQuery.Config = field.NewJSONB(tableName, "config")
_tenantQuery.ExpiredAt = field.NewTime(tableName, "expired_at")
_tenantQuery.CreatedAt = field.NewTime(tableName, "created_at")
@@ -50,7 +50,7 @@ type tenantQuery struct {
Code field.String
UUID field.Field
Name field.String
Status field.String
Status field.Field
Config field.JSONB
ExpiredAt field.Time
CreatedAt field.Time
@@ -76,7 +76,7 @@ func (t *tenantQuery) updateTableName(table string) *tenantQuery {
t.Code = field.NewString(table, "code")
t.UUID = field.NewField(table, "uuid")
t.Name = field.NewString(table, "name")
t.Status = field.NewString(table, "status")
t.Status = field.NewField(table, "status")
t.Config = field.NewJSONB(table, "config")
t.ExpiredAt = field.NewTime(table, "expired_at")
t.CreatedAt = field.NewTime(table, "created_at")

View File

@@ -8,6 +8,8 @@ import (
"context"
"time"
"quyun/v2/pkg/consts"
"go.ipao.vip/gen"
"go.ipao.vip/gen/types"
"gorm.io/gorm"
@@ -17,27 +19,27 @@ const TableNameUser = "users"
// User mapped from table <users>
type User struct {
ID int64 `gorm:"column:id;type:bigint;primaryKey;autoIncrement:true" json:"id"`
Username string `gorm:"column:username;type:character varying(255);not null" json:"username"`
Password string `gorm:"column:password;type:character varying(255);not null" json:"password"`
Roles types.Array[string] `gorm:"column:roles;type:text[];default:{user}" json:"roles"`
Status string `gorm:"column:status;type:character varying(50);default:active" json:"status"`
Metas types.JSON `gorm:"column:metas;type:jsonb;default:{}" json:"metas"`
Balance int64 `gorm:"column:balance;type:bigint" json:"balance"`
BalanceFrozen int64 `gorm:"column:balance_frozen;type:bigint" json:"balance_frozen"`
VerifiedAt time.Time `gorm:"column:verified_at;type:timestamp with time zone" json:"verified_at"`
Nickname string `gorm:"column:nickname;type:character varying(255)" json:"nickname"`
Avatar string `gorm:"column:avatar;type:character varying(512)" json:"avatar"`
Gender string `gorm:"column:gender;type:character varying(32);default:secret" json:"gender"`
Bio string `gorm:"column:bio;type:character varying(512)" json:"bio"`
Birthday types.Date `gorm:"column:birthday;type:date" json:"birthday"`
Location types.JSON `gorm:"column:location;type:jsonb;default:{}" json:"location"`
Points int64 `gorm:"column:points;type:bigint" json:"points"`
Phone string `gorm:"column:phone;type:character varying(32)" json:"phone"`
IsRealNameVerified bool `gorm:"column:is_real_name_verified;type:boolean" json:"is_real_name_verified"`
CreatedAt time.Time `gorm:"column:created_at;type:timestamp with time zone;default:now()" json:"created_at"`
UpdatedAt time.Time `gorm:"column:updated_at;type:timestamp with time zone;default:now()" json:"updated_at"`
DeletedAt gorm.DeletedAt `gorm:"column:deleted_at;type:timestamp with time zone" json:"deleted_at"`
ID int64 `gorm:"column:id;type:bigint;primaryKey;autoIncrement:true" json:"id"`
Username string `gorm:"column:username;type:character varying(255);not null" json:"username"`
Password string `gorm:"column:password;type:character varying(255);not null" json:"password"`
Roles types.Array[consts.Role] `gorm:"column:roles;type:text[];default:{user}" json:"roles"`
Status string `gorm:"column:status;type:character varying(50);default:active" json:"status"`
Metas types.JSON `gorm:"column:metas;type:jsonb;default:{}" json:"metas"`
Balance int64 `gorm:"column:balance;type:bigint" json:"balance"`
BalanceFrozen int64 `gorm:"column:balance_frozen;type:bigint" json:"balance_frozen"`
VerifiedAt time.Time `gorm:"column:verified_at;type:timestamp with time zone" json:"verified_at"`
Nickname string `gorm:"column:nickname;type:character varying(255)" json:"nickname"`
Avatar string `gorm:"column:avatar;type:character varying(512)" json:"avatar"`
Gender consts.Gender `gorm:"column:gender;type:character varying(32);default:secret" json:"gender"`
Bio string `gorm:"column:bio;type:character varying(512)" json:"bio"`
Birthday types.Date `gorm:"column:birthday;type:date" json:"birthday"`
Location types.JSON `gorm:"column:location;type:jsonb;default:{}" json:"location"`
Points int64 `gorm:"column:points;type:bigint" json:"points"`
Phone string `gorm:"column:phone;type:character varying(32)" json:"phone"`
IsRealNameVerified bool `gorm:"column:is_real_name_verified;type:boolean" json:"is_real_name_verified"`
CreatedAt time.Time `gorm:"column:created_at;type:timestamp with time zone;default:now()" json:"created_at"`
UpdatedAt time.Time `gorm:"column:updated_at;type:timestamp with time zone;default:now()" json:"updated_at"`
DeletedAt gorm.DeletedAt `gorm:"column:deleted_at;type:timestamp with time zone" json:"deleted_at"`
}
// Quick operations without importing query package

View File

@@ -36,7 +36,7 @@ func newUser(db *gorm.DB, opts ...gen.DOOption) userQuery {
_userQuery.VerifiedAt = field.NewTime(tableName, "verified_at")
_userQuery.Nickname = field.NewString(tableName, "nickname")
_userQuery.Avatar = field.NewString(tableName, "avatar")
_userQuery.Gender = field.NewString(tableName, "gender")
_userQuery.Gender = field.NewField(tableName, "gender")
_userQuery.Bio = field.NewString(tableName, "bio")
_userQuery.Birthday = field.NewField(tableName, "birthday")
_userQuery.Location = field.NewJSONB(tableName, "location")
@@ -67,7 +67,7 @@ type userQuery struct {
VerifiedAt field.Time
Nickname field.String
Avatar field.String
Gender field.String
Gender field.Field
Bio field.String
Birthday field.Field
Location field.JSONB
@@ -104,7 +104,7 @@ func (u *userQuery) updateTableName(table string) *userQuery {
u.VerifiedAt = field.NewTime(table, "verified_at")
u.Nickname = field.NewString(table, "nickname")
u.Avatar = field.NewString(table, "avatar")
u.Gender = field.NewString(table, "gender")
u.Gender = field.NewField(table, "gender")
u.Bio = field.NewString(table, "bio")
u.Birthday = field.NewField(table, "birthday")
u.Location = field.NewJSONB(table, "location")