On branch main

modified:   main_dc/yalarba/api_yal/go.sum
	modified:   main_dc/yalarba/api_yal/internal/domain/account/dto.go
	modified:   main_dc/yalarba/api_yal/internal/models/account.go
	modified:   main_dc/yalarba/api_yal/internal/models/appeal.go
	modified:   main_dc/yalarba/api_yal/internal/models/comment.go
	modified:   main_dc/yalarba/api_yal/internal/models/feedback.go
	modified:   main_dc/yalarba/api_yal/internal/models/password_reset.go
	modified:   main_dc/yalarba/api_yal/internal/models/rating.go
	modified:   "main_dc/yalarba/api_yal/internal/models/\320\276bject.go"
set embedded base model anonimus as realy embedded struct
without set name for field base
This commit is contained in:
2026-03-31 07:55:55 +05:00
parent d9e04cf865
commit f304f982c0
9 changed files with 230 additions and 22 deletions
-8
View File
@@ -44,20 +44,12 @@ go.uber.org/multierr v1.10.0 h1:S0h4aNzvfcFsC3dRF1jLoaov7oRaKqRGC/pUEJ2yvPQ=
go.uber.org/multierr v1.10.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= go.uber.org/multierr v1.10.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
go.uber.org/zap v1.27.1 h1:08RqriUEv8+ArZRYSTXy1LeBScaMpVSTBhCeaZYfMYc= go.uber.org/zap v1.27.1 h1:08RqriUEv8+ArZRYSTXy1LeBScaMpVSTBhCeaZYfMYc=
go.uber.org/zap v1.27.1/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= go.uber.org/zap v1.27.1/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
golang.org/x/crypto v0.46.0 h1:cKRW/pmt1pKAfetfu+RCEvjvZkA9RimPbh7bhFjGVBU=
golang.org/x/crypto v0.46.0/go.mod h1:Evb/oLKmMraqjZ2iQTwDwvCtJkczlDuTmdJXoZVzqU0=
golang.org/x/crypto v0.49.0 h1:+Ng2ULVvLHnJ/ZFEq4KdcDd/cfjrrjjNSXNzxg0Y4U4= golang.org/x/crypto v0.49.0 h1:+Ng2ULVvLHnJ/ZFEq4KdcDd/cfjrrjjNSXNzxg0Y4U4=
golang.org/x/crypto v0.49.0/go.mod h1:ErX4dUh2UM+CFYiXZRTcMpEcN8b/1gxEuv3nODoYtCA= golang.org/x/crypto v0.49.0/go.mod h1:ErX4dUh2UM+CFYiXZRTcMpEcN8b/1gxEuv3nODoYtCA=
golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4=
golang.org/x/sync v0.19.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4= golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4=
golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0= golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0=
golang.org/x/sys v0.39.0 h1:CvCKL8MeisomCi6qNZ+wbb0DN9E5AATixKsvNtMoMFk=
golang.org/x/sys v0.39.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
golang.org/x/sys v0.42.0 h1:omrd2nAlyT5ESRdCLYdm3+fMfNFE/+Rf4bDIQImRJeo= golang.org/x/sys v0.42.0 h1:omrd2nAlyT5ESRdCLYdm3+fMfNFE/+Rf4bDIQImRJeo=
golang.org/x/sys v0.42.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= golang.org/x/sys v0.42.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
golang.org/x/text v0.32.0 h1:ZD01bjUt1FQ9WJ0ClOL5vxgxOI/sVCNgX1YtKwcY0mU=
golang.org/x/text v0.32.0/go.mod h1:o/rUWzghvpD5TXrTIBuJU77MTaN0ljMWE47kxGJQ7jY=
golang.org/x/text v0.35.0 h1:JOVx6vVDFokkpaq1AEptVzLTpDe9KGpj5tR4/X+ybL8= golang.org/x/text v0.35.0 h1:JOVx6vVDFokkpaq1AEptVzLTpDe9KGpj5tR4/X+ybL8=
golang.org/x/text v0.35.0/go.mod h1:khi/HExzZJ2pGnjenulevKNX1W67CUy0AsXcNubPGCA= golang.org/x/text v0.35.0/go.mod h1:khi/HExzZJ2pGnjenulevKNX1W67CUy0AsXcNubPGCA=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
@@ -1 +1,220 @@
package account package account
import (
"time"
"api_yal/internal/models"
)
// ==================== Request DTOs ====================
// CreateAccountRequest - DTO для создания нового аккаунта
type CreateAccountRequest struct {
Email string `json:"email" binding:"required,email"`
Password string `json:"password" binding:"required,min=6"`
FullName string `json:"full_name" binding:"required"`
FirstName string `json:"first_name" binding:"required"`
LastName string `json:"last_name" binding:"required"`
Phone string `json:"phone"`
City string `json:"city"`
// Бизнес информация
OrganizationForm string `json:"organization_form"`
OrganizationName string `json:"organization_name"`
OrganizationShort string `json:"organization_short"`
INN string `json:"inn"`
PersonalINN string `json:"personal_inn"`
}
// UpdateAccountRequest - DTO для обновления аккаунта
type UpdateAccountRequest struct {
FullName string `json:"full_name"`
FirstName string `json:"first_name"`
LastName string `json:"last_name"`
Phone string `json:"phone"`
City string `json:"city"`
// Бизнес информация
OrganizationForm string `json:"organization_form"`
OrganizationName string `json:"organization_name"`
OrganizationShort string `json:"organization_short"`
INN string `json:"inn"`
PersonalINN string `json:"personal_inn"`
}
// ChangePasswordRequest - DTO для смены пароля
type ChangePasswordRequest struct {
CurrentPassword string `json:"current_password" binding:"required"`
NewPassword string `json:"new_password" binding:"required,min=6"`
}
// ForgotPasswordRequest - DTO для запроса сброса пароля
type ForgotPasswordRequest struct {
Email string `json:"email" binding:"required,email"`
}
// ResetPasswordRequest - DTO для сброса пароля по токену
type ResetPasswordRequest struct {
Token string `json:"token" binding:"required"`
NewPassword string `json:"new_password" binding:"required,min=6"`
}
// VerifyAccountRequest - DTO для верификации аккаунта (админ)
type VerifyAccountRequest struct {
IsVerified bool `json:"is_verified"`
}
// UpdateAccountStatusRequest - DTO для изменения статуса аккаунта (админ)
type UpdateAccountStatusRequest struct {
IsActive bool `json:"is_active"`
Role string `json:"role" binding:"omitempty,oneof=user admin moderator"`
}
// ListAccountsRequest - DTO для фильтрации списка аккаунтов
type ListAccountsRequest struct {
Page int `form:"page" binding:"min=1"`
PageSize int `form:"page_size" binding:"min=1,max=100"`
Search string `form:"search"`
Role string `form:"role" binding:"omitempty,oneof=user admin moderator"`
IsActive *bool `form:"is_active"`
}
// ==================== Response DTOs ====================
// AccountResponse - базовый DTO для ответа с данными аккаунта (без чувствительной информации)
type AccountResponse struct {
ID uint `json:"id"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
// Основная информация
Email string `json:"email"`
FullName string `json:"full_name"`
FirstName string `json:"first_name"`
LastName string `json:"last_name"`
Phone string `json:"phone"`
City string `json:"city"`
// Бизнес информация
OrganizationForm string `json:"organization_form,omitempty"`
OrganizationName string `json:"organization_name,omitempty"`
OrganizationShort string `json:"organization_short,omitempty"`
INN string `json:"inn,omitempty"`
PersonalINN string `json:"personal_inn,omitempty"`
// Статус
IsActive bool `json:"is_active"`
IsVerified bool `json:"is_verified"`
Role string `json:"role"`
}
// AccountWithObjectsResponse - DTO с объектами аккаунта
type AccountWithObjectsResponse struct {
AccountResponse
Objects []ObjectBriefResponse `json:"objects,omitempty"`
}
// ObjectBriefResponse - краткая информация об объекте для вложенных ответов
type ObjectBriefResponse struct {
ID uint `json:"id"`
ShortName string `json:"short_name"`
LongName string `json:"long_name"`
Type string `json:"type"`
IsActive bool `json:"is_active"`
Address string `json:"address"`
}
// AccountListResponse - DTO для списка аккаунтов с пагинацией
type AccountListResponse struct {
Items []AccountResponse `json:"items"`
Total int64 `json:"total"`
Page int `json:"page"`
PageSize int `json:"page_size"`
TotalPages int `json:"total_pages"`
}
// AccountProfileResponse - DTO для личного кабинета (более детальная информация)
type AccountProfileResponse struct {
AccountResponse
Stats AccountStats `json:"stats"`
}
// AccountStats - статистика аккаунта
type AccountStats struct {
ObjectsCount int `json:"objects_count"`
FeedbacksCount int `json:"feedbacks_count"`
CommentsCount int `json:"comments_count"`
RatingsCount int `json:"ratings_count"`
AppealsCount int `json:"appeals_count"`
}
// AuthResponse - DTO для ответа при авторизации
type AuthResponse struct {
Token string `json:"token"`
TokenType string `json:"token_type"`
ExpiresAt int64 `json:"expires_at"`
Account AccountResponse `json:"account"`
}
// PasswordResetResponse - DTO для ответа о сбросе пароля
type PasswordResetResponse struct {
Message string `json:"message"`
Token string `json:"token,omitempty"` // только при создании, не для продакшена
}
// ==================== Helper functions ====================
// ToAccountResponse преобразует модель Account в AccountResponse
func ToAccountResponse(account *models.Account) AccountResponse {
return AccountResponse{
ID: account.ID,
CreatedAt: account.CreatedAt,
UpdatedAt: account.UpdatedAt,
Email: account.Email,
FullName: account.FullName,
FirstName: account.FirstName,
LastName: account.LastName,
Phone: account.Phone,
City: account.City,
OrganizationForm: account.OrganizationForm,
OrganizationName: account.OrganizationName,
OrganizationShort: account.OrganizationShort,
INN: account.INN,
PersonalINN: account.PersonalINN,
IsActive: account.IsActive,
IsVerified: account.IsVerified,
Role: account.Role,
}
}
// ToAccountWithObjectsResponse преобразует модель Account в AccountWithObjectsResponse
func ToAccountWithObjectsResponse(account *models.Account) AccountWithObjectsResponse {
resp := AccountWithObjectsResponse{
AccountResponse: ToAccountResponse(account),
Objects: make([]ObjectBriefResponse, 0, len(account.Objects)),
}
for _, obj := range account.Objects {
resp.Objects = append(resp.Objects, ObjectBriefResponse{
ID: obj.ID,
ShortName: obj.ShortName,
LongName: obj.LongName,
Type: obj.Type,
IsActive: obj.IsActive,
Address: obj.Address,
})
}
return resp
}
// ToObjectBriefResponse преобразует модель Object в ObjectBriefResponse
func ToObjectBriefResponse(object *models.Object) ObjectBriefResponse {
return ObjectBriefResponse{
ID: object.ID,
ShortName: object.ShortName,
LongName: object.LongName,
Type: object.Type,
IsActive: object.IsActive,
Address: object.Address,
}
}
@@ -4,7 +4,7 @@ import ()
type Account struct { type Account struct {
/*ID, CreatedAt, UpdatedAt, DeletedAt (Update's history)*/ /*ID, CreatedAt, UpdatedAt, DeletedAt (Update's history)*/
Base Base `gorm:"embedded"` Base `gorm:"embedded"`
// Основная информация // Основная информация
Email string `gorm:"uniqueIndex;not null" json:"email"` Email string `gorm:"uniqueIndex;not null" json:"email"`
@@ -27,9 +27,6 @@ type Account struct {
IsVerified bool `gorm:"default:false" json:"is_verified"` IsVerified bool `gorm:"default:false" json:"is_verified"`
Role string `gorm:"default:user" json:"role"` // user, admin, moderator Role string `gorm:"default:user" json:"role"` // user, admin, moderator
// Связь: один Account имеет много Objects // Связь: один Account имеет много Objects
Objects []Object `gorm:"foreignKey:OwnerID" json:"objects"` Objects []Object `gorm:"foreignKey:OwnerID" json:"objects"`
} }
@@ -53,7 +53,7 @@ const (
// Appeal представляет обращение пользователя (жалоба, предложение, пожелание) // Appeal представляет обращение пользователя (жалоба, предложение, пожелание)
type Appeal struct { type Appeal struct {
/*ID, CreatedAt, UpdatedAt, DeletedAt (Update's history)*/ /*ID, CreatedAt, UpdatedAt, DeletedAt (Update's history)*/
Base Base `gorm:"embedded"` Base `gorm:"embedded"`
// Автор обращения (может быть анонимным) // Автор обращения (может быть анонимным)
AuthorID *uint `gorm:"index" json:"author_id,omitempty"` // NULL для анонимных обращений AuthorID *uint `gorm:"index" json:"author_id,omitempty"` // NULL для анонимных обращений
@@ -5,7 +5,7 @@ import ()
// Comment представляет комментарий к отзыву (Feedback) // Comment представляет комментарий к отзыву (Feedback)
type Comment struct { type Comment struct {
/*ID, CreatedAt, UpdatedAt, DeletedAt (Update's history)*/ /*ID, CreatedAt, UpdatedAt, DeletedAt (Update's history)*/
Base Base `gorm:"embedded"` Base `gorm:"embedded"`
// Автор комментария // Автор комментария
AuthorID uint `gorm:"not null;index" json:"author_id"` AuthorID uint `gorm:"not null;index" json:"author_id"`
@@ -4,7 +4,7 @@ import ()
type Feedback struct { type Feedback struct {
/*ID, CreatedAt, UpdatedAt, DeletedAt (Update's history)*/ /*ID, CreatedAt, UpdatedAt, DeletedAt (Update's history)*/
Base Base `gorm:"embedded"` Base `gorm:"embedded"`
// owner account ID // owner account ID
OwnerID uint `gorm:"not null;index" json:"owner_id"` OwnerID uint `gorm:"not null;index" json:"owner_id"`
@@ -7,7 +7,7 @@ import (
// PasswordReset модель для хранения токенов сброса пароля // PasswordReset модель для хранения токенов сброса пароля
type PasswordReset struct { type PasswordReset struct {
Base Base `gorm:"embedded"`
AccountID uint `gorm:"not null;index" json:"account_id"` AccountID uint `gorm:"not null;index" json:"account_id"`
Token string `gorm:"type:varchar(255);uniqueIndex;not null" json:"token"` Token string `gorm:"type:varchar(255);uniqueIndex;not null" json:"token"`
ExpiresAt time.Time `gorm:"not null" json:"expires_at"` ExpiresAt time.Time `gorm:"not null" json:"expires_at"`
@@ -15,7 +15,7 @@ const (
type Rating struct { type Rating struct {
// Base содержит общие поля для всех моделей: // Base содержит общие поля для всех моделей:
// ID, CreatedAt, UpdatedAt, DeletedAt (история обновлений) // ID, CreatedAt, UpdatedAt, DeletedAt (история обновлений)
Base Base `gorm:"embedded"` Base `gorm:"embedded"`
// OwnerID - идентификатор владельца рейтинга (аккаунта) // OwnerID - идентификатор владельца рейтинга (аккаунта)
OwnerID uint `json:"owner_id"` OwnerID uint `json:"owner_id"`
@@ -4,7 +4,7 @@ import ()
type Object struct { type Object struct {
/*ID, CreatedAt, UpdatedAt, DeletedAt (Update's history)*/ /*ID, CreatedAt, UpdatedAt, DeletedAt (Update's history)*/
Base Base `gorm:"embedded"` Base `gorm:"embedded"`
// owner account ID // owner account ID
OwnerID uint `json:"owner_id"` OwnerID uint `json:"owner_id"`