initial commit

This commit is contained in:
2025-11-29 00:28:21 +05:00
parent 46229acc82
commit ec3b03a935
76 changed files with 13492 additions and 0 deletions

530
internal/database/models.go Normal file
View File

@@ -0,0 +1,530 @@
// Code generated by sqlc. DO NOT EDIT.
// versions:
// sqlc v1.30.0
package database
import (
"database/sql/driver"
"fmt"
"net/netip"
"github.com/jackc/pgx/v5/pgtype"
)
// Статусы жизненного цикла жалобы
type ComplaintStatus string
const (
ComplaintStatusPending ComplaintStatus = "pending"
ComplaintStatusInReview ComplaintStatus = "in_review"
ComplaintStatusResolved ComplaintStatus = "resolved"
ComplaintStatusRejected ComplaintStatus = "rejected"
)
func (e *ComplaintStatus) Scan(src interface{}) error {
switch s := src.(type) {
case []byte:
*e = ComplaintStatus(s)
case string:
*e = ComplaintStatus(s)
default:
return fmt.Errorf("unsupported scan type for ComplaintStatus: %T", src)
}
return nil
}
type NullComplaintStatus struct {
ComplaintStatus ComplaintStatus `json:"complaint_status"`
Valid bool `json:"valid"` // Valid is true if ComplaintStatus is not NULL
}
// Scan implements the Scanner interface.
func (ns *NullComplaintStatus) Scan(value interface{}) error {
if value == nil {
ns.ComplaintStatus, ns.Valid = "", false
return nil
}
ns.Valid = true
return ns.ComplaintStatus.Scan(value)
}
// Value implements the driver Valuer interface.
func (ns NullComplaintStatus) Value() (driver.Value, error) {
if !ns.Valid {
return nil, nil
}
return string(ns.ComplaintStatus), nil
}
func AllComplaintStatusValues() []ComplaintStatus {
return []ComplaintStatus{
ComplaintStatusPending,
ComplaintStatusInReview,
ComplaintStatusResolved,
ComplaintStatusRejected,
}
}
// Типы жалоб на пользователей
type ComplaintType string
const (
ComplaintTypeInappropriateBehavior ComplaintType = "inappropriate_behavior"
ComplaintTypeNoShow ComplaintType = "no_show"
ComplaintTypeFraud ComplaintType = "fraud"
ComplaintTypeSpam ComplaintType = "spam"
ComplaintTypeOther ComplaintType = "other"
)
func (e *ComplaintType) Scan(src interface{}) error {
switch s := src.(type) {
case []byte:
*e = ComplaintType(s)
case string:
*e = ComplaintType(s)
default:
return fmt.Errorf("unsupported scan type for ComplaintType: %T", src)
}
return nil
}
type NullComplaintType struct {
ComplaintType ComplaintType `json:"complaint_type"`
Valid bool `json:"valid"` // Valid is true if ComplaintType is not NULL
}
// Scan implements the Scanner interface.
func (ns *NullComplaintType) Scan(value interface{}) error {
if value == nil {
ns.ComplaintType, ns.Valid = "", false
return nil
}
ns.Valid = true
return ns.ComplaintType.Scan(value)
}
// Value implements the driver Valuer interface.
func (ns NullComplaintType) Value() (driver.Value, error) {
if !ns.Valid {
return nil, nil
}
return string(ns.ComplaintType), nil
}
func AllComplaintTypeValues() []ComplaintType {
return []ComplaintType{
ComplaintTypeInappropriateBehavior,
ComplaintTypeNoShow,
ComplaintTypeFraud,
ComplaintTypeSpam,
ComplaintTypeOther,
}
}
// Типы действий модераторов для аудита
type ModeratorActionType string
const (
ModeratorActionTypeApproveRequest ModeratorActionType = "approve_request"
ModeratorActionTypeRejectRequest ModeratorActionType = "reject_request"
ModeratorActionTypeBlockUser ModeratorActionType = "block_user"
ModeratorActionTypeUnblockUser ModeratorActionType = "unblock_user"
ModeratorActionTypeResolveComplaint ModeratorActionType = "resolve_complaint"
ModeratorActionTypeRejectComplaint ModeratorActionType = "reject_complaint"
ModeratorActionTypeEditRequest ModeratorActionType = "edit_request"
ModeratorActionTypeDeleteRequest ModeratorActionType = "delete_request"
)
func (e *ModeratorActionType) Scan(src interface{}) error {
switch s := src.(type) {
case []byte:
*e = ModeratorActionType(s)
case string:
*e = ModeratorActionType(s)
default:
return fmt.Errorf("unsupported scan type for ModeratorActionType: %T", src)
}
return nil
}
type NullModeratorActionType struct {
ModeratorActionType ModeratorActionType `json:"moderator_action_type"`
Valid bool `json:"valid"` // Valid is true if ModeratorActionType is not NULL
}
// Scan implements the Scanner interface.
func (ns *NullModeratorActionType) Scan(value interface{}) error {
if value == nil {
ns.ModeratorActionType, ns.Valid = "", false
return nil
}
ns.Valid = true
return ns.ModeratorActionType.Scan(value)
}
// Value implements the driver Valuer interface.
func (ns NullModeratorActionType) Value() (driver.Value, error) {
if !ns.Valid {
return nil, nil
}
return string(ns.ModeratorActionType), nil
}
func AllModeratorActionTypeValues() []ModeratorActionType {
return []ModeratorActionType{
ModeratorActionTypeApproveRequest,
ModeratorActionTypeRejectRequest,
ModeratorActionTypeBlockUser,
ModeratorActionTypeUnblockUser,
ModeratorActionTypeResolveComplaint,
ModeratorActionTypeRejectComplaint,
ModeratorActionTypeEditRequest,
ModeratorActionTypeDeleteRequest,
}
}
// Статусы жизненного цикла заявки на помощь
type RequestStatus string
const (
RequestStatusPendingModeration RequestStatus = "pending_moderation"
RequestStatusApproved RequestStatus = "approved"
RequestStatusInProgress RequestStatus = "in_progress"
RequestStatusCompleted RequestStatus = "completed"
RequestStatusCancelled RequestStatus = "cancelled"
RequestStatusRejected RequestStatus = "rejected"
)
func (e *RequestStatus) Scan(src interface{}) error {
switch s := src.(type) {
case []byte:
*e = RequestStatus(s)
case string:
*e = RequestStatus(s)
default:
return fmt.Errorf("unsupported scan type for RequestStatus: %T", src)
}
return nil
}
type NullRequestStatus struct {
RequestStatus RequestStatus `json:"request_status"`
Valid bool `json:"valid"` // Valid is true if RequestStatus is not NULL
}
// Scan implements the Scanner interface.
func (ns *NullRequestStatus) Scan(value interface{}) error {
if value == nil {
ns.RequestStatus, ns.Valid = "", false
return nil
}
ns.Valid = true
return ns.RequestStatus.Scan(value)
}
// Value implements the driver Valuer interface.
func (ns NullRequestStatus) Value() (driver.Value, error) {
if !ns.Valid {
return nil, nil
}
return string(ns.RequestStatus), nil
}
func AllRequestStatusValues() []RequestStatus {
return []RequestStatus{
RequestStatusPendingModeration,
RequestStatusApproved,
RequestStatusInProgress,
RequestStatusCompleted,
RequestStatusCancelled,
RequestStatusRejected,
}
}
// Статусы отклика волонтёра на заявку
type ResponseStatus string
const (
ResponseStatusPending ResponseStatus = "pending"
ResponseStatusAccepted ResponseStatus = "accepted"
ResponseStatusRejected ResponseStatus = "rejected"
ResponseStatusCancelled ResponseStatus = "cancelled"
)
func (e *ResponseStatus) Scan(src interface{}) error {
switch s := src.(type) {
case []byte:
*e = ResponseStatus(s)
case string:
*e = ResponseStatus(s)
default:
return fmt.Errorf("unsupported scan type for ResponseStatus: %T", src)
}
return nil
}
type NullResponseStatus struct {
ResponseStatus ResponseStatus `json:"response_status"`
Valid bool `json:"valid"` // Valid is true if ResponseStatus is not NULL
}
// Scan implements the Scanner interface.
func (ns *NullResponseStatus) Scan(value interface{}) error {
if value == nil {
ns.ResponseStatus, ns.Valid = "", false
return nil
}
ns.Valid = true
return ns.ResponseStatus.Scan(value)
}
// Value implements the driver Valuer interface.
func (ns NullResponseStatus) Value() (driver.Value, error) {
if !ns.Valid {
return nil, nil
}
return string(ns.ResponseStatus), nil
}
func AllResponseStatusValues() []ResponseStatus {
return []ResponseStatus{
ResponseStatusPending,
ResponseStatusAccepted,
ResponseStatusRejected,
ResponseStatusCancelled,
}
}
// Жалобы пользователей друг на друга
type Complaint struct {
ID int64 `json:"id"`
// Пользователь, подающий жалобу
ComplainantID int64 `json:"complainant_id"`
// Пользователь, на которого жалуются
DefendantID int64 `json:"defendant_id"`
RequestID pgtype.Int8 `json:"request_id"`
Type ComplaintType `json:"type"`
Title string `json:"title"`
Description string `json:"description"`
Status NullComplaintStatus `json:"status"`
ModeratorID pgtype.Int8 `json:"moderator_id"`
ModeratorComment pgtype.Text `json:"moderator_comment"`
ResolvedAt pgtype.Timestamptz `json:"resolved_at"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
}
// Полный аудит всех действий модераторов в системе
type ModeratorAction struct {
ID int64 `json:"id"`
ModeratorID int64 `json:"moderator_id"`
ActionType ModeratorActionType `json:"action_type"`
TargetUserID pgtype.Int8 `json:"target_user_id"`
TargetRequestID pgtype.Int8 `json:"target_request_id"`
TargetComplaintID pgtype.Int8 `json:"target_complaint_id"`
Comment pgtype.Text `json:"comment"`
// Дополнительные данные в JSON (изменённые поля, причины и т.д.)
Metadata []byte `json:"metadata"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
}
// Справочник разрешений для RBAC системы
type Permission struct {
ID int64 `json:"id"`
Name string `json:"name"`
// Ресурс: request, user, complaint и т.д.
Resource string `json:"resource"`
// Действие: create, read, update, delete, moderate
Action string `json:"action"`
Description pgtype.Text `json:"description"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
}
// Рейтинги волонтёров за выполненную помощь
type Rating struct {
ID int64 `json:"id"`
// Связь с откликом (один рейтинг на один отклик)
VolunteerResponseID int64 `json:"volunteer_response_id"`
// Денормализация для быстрого доступа
VolunteerID int64 `json:"volunteer_id"`
// Кто оставил рейтинг
RequesterID int64 `json:"requester_id"`
RequestID int64 `json:"request_id"`
// Оценка от 1 до 5 звёзд
Rating int32 `json:"rating"`
Comment pgtype.Text `json:"comment"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
}
// Refresh токены для JWT аутентификации
type RefreshToken struct {
ID int64 `json:"id"`
UserID int64 `json:"user_id"`
// Хеш refresh токена
Token string `json:"token"`
ExpiresAt pgtype.Timestamptz `json:"expires_at"`
UserAgent pgtype.Text `json:"user_agent"`
IpAddress *netip.Addr `json:"ip_address"`
// Токен отозван (для принудительного логаута)
Revoked pgtype.Bool `json:"revoked"`
RevokedAt pgtype.Timestamptz `json:"revoked_at"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
}
// Заявки на помощь от маломобильных граждан
type Request struct {
ID int64 `json:"id"`
RequesterID int64 `json:"requester_id"`
RequestTypeID int64 `json:"request_type_id"`
// Волонтёр, который взял заявку в работу
AssignedVolunteerID pgtype.Int8 `json:"assigned_volunteer_id"`
Title string `json:"title"`
Description string `json:"description"`
// Координаты места, где нужна помощь (WGS84, SRID 4326)
Location interface{} `json:"location"`
Address string `json:"address"`
City pgtype.Text `json:"city"`
DesiredCompletionDate pgtype.Timestamptz `json:"desired_completion_date"`
// Срочность: low, medium, high, urgent
Urgency pgtype.Text `json:"urgency"`
Status NullRequestStatus `json:"status"`
ModerationComment pgtype.Text `json:"moderation_comment"`
ModeratedBy pgtype.Int8 `json:"moderated_by"`
ModeratedAt pgtype.Timestamptz `json:"moderated_at"`
ContactPhone pgtype.Text `json:"contact_phone"`
// Дополнительная информация: код домофона, этаж и т.д.
ContactNotes pgtype.Text `json:"contact_notes"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
CompletedAt pgtype.Timestamptz `json:"completed_at"`
// Soft delete - дата удаления заявки
DeletedAt pgtype.Timestamptz `json:"deleted_at"`
}
// Полная история изменения статусов заявок для аудита
type RequestStatusHistory struct {
ID int64 `json:"id"`
RequestID int64 `json:"request_id"`
// Предыдущий статус (NULL при создании)
FromStatus NullRequestStatus `json:"from_status"`
ToStatus RequestStatus `json:"to_status"`
ChangedBy int64 `json:"changed_by"`
Comment pgtype.Text `json:"comment"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
}
// Справочник типов помощи (продукты, медикаменты, техника)
type RequestType struct {
ID int64 `json:"id"`
Name string `json:"name"`
Description pgtype.Text `json:"description"`
// Название иконки для UI
Icon pgtype.Text `json:"icon"`
// Активность типа (для скрытия без удаления)
IsActive pgtype.Bool `json:"is_active"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
}
// Справочник ролей для RBAC системы
type Role struct {
ID int64 `json:"id"`
// Уникальное название роли
Name string `json:"name"`
Description pgtype.Text `json:"description"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
}
// Связь ролей и разрешений (Many-to-Many) для гибкой системы RBAC
type RolePermission struct {
ID int64 `json:"id"`
RoleID int64 `json:"role_id"`
PermissionID int64 `json:"permission_id"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
}
// Пользователи системы: маломобильные граждане, волонтёры, модераторы
type User struct {
ID int64 `json:"id"`
Email string `json:"email"`
Phone pgtype.Text `json:"phone"`
PasswordHash string `json:"password_hash"`
FirstName string `json:"first_name"`
LastName string `json:"last_name"`
AvatarUrl pgtype.Text `json:"avatar_url"`
// Координаты домашнего адреса в формате WGS84 (SRID 4326)
Location interface{} `json:"location"`
Address pgtype.Text `json:"address"`
City pgtype.Text `json:"city"`
// Средний рейтинг волонтёра (0-5), обновляется триггером
VolunteerRating pgtype.Numeric `json:"volunteer_rating"`
// Количество выполненных заявок, обновляется триггером
CompletedRequestsCount pgtype.Int4 `json:"completed_requests_count"`
IsVerified pgtype.Bool `json:"is_verified"`
IsBlocked pgtype.Bool `json:"is_blocked"`
EmailVerified pgtype.Bool `json:"email_verified"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
LastLoginAt pgtype.Timestamptz `json:"last_login_at"`
// Soft delete - дата удаления пользователя
DeletedAt pgtype.Timestamptz `json:"deleted_at"`
}
// Блокировки пользователей модераторами
type UserBlock struct {
ID int64 `json:"id"`
UserID int64 `json:"user_id"`
BlockedBy int64 `json:"blocked_by"`
ComplaintID pgtype.Int8 `json:"complaint_id"`
Reason string `json:"reason"`
// Дата окончания блокировки (NULL = бессрочная)
BlockedUntil pgtype.Timestamptz `json:"blocked_until"`
// Активна ли блокировка в данный момент
IsActive pgtype.Bool `json:"is_active"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
UnblockedAt pgtype.Timestamptz `json:"unblocked_at"`
UnblockedBy pgtype.Int8 `json:"unblocked_by"`
}
// Связь пользователей и ролей (Many-to-Many). Один пользователь может иметь несколько ролей
type UserRole struct {
ID int64 `json:"id"`
UserID int64 `json:"user_id"`
RoleID int64 `json:"role_id"`
AssignedAt pgtype.Timestamptz `json:"assigned_at"`
// Кто назначил роль (для аудита)
AssignedBy pgtype.Int8 `json:"assigned_by"`
}
// Активные сессии пользователей для отслеживания активности
type UserSession struct {
ID int64 `json:"id"`
UserID int64 `json:"user_id"`
SessionToken string `json:"session_token"`
RefreshTokenID pgtype.Int8 `json:"refresh_token_id"`
ExpiresAt pgtype.Timestamptz `json:"expires_at"`
// Последняя активность пользователя в сессии
LastActivityAt pgtype.Timestamptz `json:"last_activity_at"`
UserAgent pgtype.Text `json:"user_agent"`
IpAddress *netip.Addr `json:"ip_address"`
// Информация об устройстве: ОС, браузер, версия и т.д.
DeviceInfo []byte `json:"device_info"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
}
// Отклики волонтёров на заявки помощи
type VolunteerResponse struct {
ID int64 `json:"id"`
RequestID int64 `json:"request_id"`
VolunteerID int64 `json:"volunteer_id"`
Status NullResponseStatus `json:"status"`
// Сообщение волонтёра при отклике (опционально)
Message pgtype.Text `json:"message"`
// Время создания отклика
RespondedAt pgtype.Timestamptz `json:"responded_at"`
AcceptedAt pgtype.Timestamptz `json:"accepted_at"`
RejectedAt pgtype.Timestamptz `json:"rejected_at"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
}