From f304f982c0f9cdcda59c526fd16f8d73c9d88cbb Mon Sep 17 00:00:00 2001 From: valitovgaziz Date: Tue, 31 Mar 2026 07:55:55 +0500 Subject: [PATCH] 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 --- main_dc/yalarba/api_yal/go.sum | 8 - .../api_yal/internal/domain/account/dto.go | 221 +++++++++++++++++- .../api_yal/internal/models/account.go | 11 +- .../yalarba/api_yal/internal/models/appeal.go | 2 +- .../api_yal/internal/models/comment.go | 2 +- .../api_yal/internal/models/feedback.go | 2 +- .../api_yal/internal/models/password_reset.go | 2 +- .../yalarba/api_yal/internal/models/rating.go | 2 +- .../yalarba/api_yal/internal/models/оbject.go | 2 +- 9 files changed, 230 insertions(+), 22 deletions(-) diff --git a/main_dc/yalarba/api_yal/go.sum b/main_dc/yalarba/api_yal/go.sum index b0689e0..d9394c3 100644 --- a/main_dc/yalarba/api_yal/go.sum +++ b/main_dc/yalarba/api_yal/go.sum @@ -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/zap v1.27.1 h1:08RqriUEv8+ArZRYSTXy1LeBScaMpVSTBhCeaZYfMYc= 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/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/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/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/go.mod h1:khi/HExzZJ2pGnjenulevKNX1W67CUy0AsXcNubPGCA= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/main_dc/yalarba/api_yal/internal/domain/account/dto.go b/main_dc/yalarba/api_yal/internal/domain/account/dto.go index f8f035e..6730d23 100644 --- a/main_dc/yalarba/api_yal/internal/domain/account/dto.go +++ b/main_dc/yalarba/api_yal/internal/domain/account/dto.go @@ -1 +1,220 @@ -package account \ No newline at end of file +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, + } +} \ No newline at end of file diff --git a/main_dc/yalarba/api_yal/internal/models/account.go b/main_dc/yalarba/api_yal/internal/models/account.go index 53599ff..90f91f8 100644 --- a/main_dc/yalarba/api_yal/internal/models/account.go +++ b/main_dc/yalarba/api_yal/internal/models/account.go @@ -4,7 +4,7 @@ import () type Account struct { /*ID, CreatedAt, UpdatedAt, DeletedAt (Update's history)*/ - Base Base `gorm:"embedded"` + Base `gorm:"embedded"` // Основная информация Email string `gorm:"uniqueIndex;not null" json:"email"` @@ -21,15 +21,12 @@ type Account struct { OrganizationShort string `json:"organization_short"` INN string `json:"inn"` // ИНН организации PersonalINN string `json:"personal_inn"` // Личный ИНН - + // Статус IsActive bool `gorm:"default:true" json:"is_active"` IsVerified bool `gorm:"default:false" json:"is_verified"` Role string `gorm:"default:user" json:"role"` // user, admin, moderator - - // Связь: один Account имеет много Objects - Objects []Object `gorm:"foreignKey:OwnerID" json:"objects"` - - + // Связь: один Account имеет много Objects + Objects []Object `gorm:"foreignKey:OwnerID" json:"objects"` } diff --git a/main_dc/yalarba/api_yal/internal/models/appeal.go b/main_dc/yalarba/api_yal/internal/models/appeal.go index dad69e5..eac9fec 100644 --- a/main_dc/yalarba/api_yal/internal/models/appeal.go +++ b/main_dc/yalarba/api_yal/internal/models/appeal.go @@ -53,7 +53,7 @@ const ( // Appeal представляет обращение пользователя (жалоба, предложение, пожелание) type Appeal struct { /*ID, CreatedAt, UpdatedAt, DeletedAt (Update's history)*/ - Base Base `gorm:"embedded"` + Base `gorm:"embedded"` // Автор обращения (может быть анонимным) AuthorID *uint `gorm:"index" json:"author_id,omitempty"` // NULL для анонимных обращений diff --git a/main_dc/yalarba/api_yal/internal/models/comment.go b/main_dc/yalarba/api_yal/internal/models/comment.go index d7f9ab1..0db1bdb 100644 --- a/main_dc/yalarba/api_yal/internal/models/comment.go +++ b/main_dc/yalarba/api_yal/internal/models/comment.go @@ -5,7 +5,7 @@ import () // Comment представляет комментарий к отзыву (Feedback) type Comment struct { /*ID, CreatedAt, UpdatedAt, DeletedAt (Update's history)*/ - Base Base `gorm:"embedded"` + Base `gorm:"embedded"` // Автор комментария AuthorID uint `gorm:"not null;index" json:"author_id"` diff --git a/main_dc/yalarba/api_yal/internal/models/feedback.go b/main_dc/yalarba/api_yal/internal/models/feedback.go index 0c9fe4f..f209303 100644 --- a/main_dc/yalarba/api_yal/internal/models/feedback.go +++ b/main_dc/yalarba/api_yal/internal/models/feedback.go @@ -4,7 +4,7 @@ import () type Feedback struct { /*ID, CreatedAt, UpdatedAt, DeletedAt (Update's history)*/ - Base Base `gorm:"embedded"` + Base `gorm:"embedded"` // owner account ID OwnerID uint `gorm:"not null;index" json:"owner_id"` diff --git a/main_dc/yalarba/api_yal/internal/models/password_reset.go b/main_dc/yalarba/api_yal/internal/models/password_reset.go index 60d96f8..7d3676c 100644 --- a/main_dc/yalarba/api_yal/internal/models/password_reset.go +++ b/main_dc/yalarba/api_yal/internal/models/password_reset.go @@ -7,7 +7,7 @@ import ( // PasswordReset модель для хранения токенов сброса пароля type PasswordReset struct { - Base + Base `gorm:"embedded"` AccountID uint `gorm:"not null;index" json:"account_id"` Token string `gorm:"type:varchar(255);uniqueIndex;not null" json:"token"` ExpiresAt time.Time `gorm:"not null" json:"expires_at"` diff --git a/main_dc/yalarba/api_yal/internal/models/rating.go b/main_dc/yalarba/api_yal/internal/models/rating.go index 7f0c7a0..56d98fa 100644 --- a/main_dc/yalarba/api_yal/internal/models/rating.go +++ b/main_dc/yalarba/api_yal/internal/models/rating.go @@ -15,7 +15,7 @@ const ( type Rating struct { // Base содержит общие поля для всех моделей: // ID, CreatedAt, UpdatedAt, DeletedAt (история обновлений) - Base Base `gorm:"embedded"` + Base `gorm:"embedded"` // OwnerID - идентификатор владельца рейтинга (аккаунта) OwnerID uint `json:"owner_id"` diff --git a/main_dc/yalarba/api_yal/internal/models/оbject.go b/main_dc/yalarba/api_yal/internal/models/оbject.go index e6796f8..d605cbe 100644 --- a/main_dc/yalarba/api_yal/internal/models/оbject.go +++ b/main_dc/yalarba/api_yal/internal/models/оbject.go @@ -4,7 +4,7 @@ import () type Object struct { /*ID, CreatedAt, UpdatedAt, DeletedAt (Update's history)*/ - Base Base `gorm:"embedded"` + Base `gorm:"embedded"` // owner account ID OwnerID uint `json:"owner_id"`