199 lines
9.0 KiB
Go
199 lines
9.0 KiB
Go
package model
|
|
|
|
import (
|
|
"time"
|
|
|
|
"github.com/google/uuid"
|
|
"gorm.io/gorm"
|
|
)
|
|
|
|
// Base gives every persisted model a PostgreSQL uuid primary key.
|
|
// GORM's naming strategy maps Go fields to snake_case columns.
|
|
type Base struct {
|
|
ID string `gorm:"type:uuid;primaryKey" json:"id"`
|
|
CreatedAt time.Time `json:"created_at"`
|
|
UpdatedAt time.Time `json:"updated_at"`
|
|
}
|
|
|
|
func (b *Base) BeforeCreate(_ *gorm.DB) error {
|
|
if b.ID == "" {
|
|
b.ID = uuid.NewString()
|
|
}
|
|
return nil
|
|
}
|
|
|
|
type File struct {
|
|
Base
|
|
Bucket string `gorm:"size:128;not null" json:"bucket"`
|
|
ObjectKey string `gorm:"size:512;uniqueIndex;not null" json:"object_key"`
|
|
MD5 string `gorm:"column:md5;size:32;uniqueIndex;not null" json:"md5"`
|
|
URL string `gorm:"size:1024;not null" json:"url"`
|
|
Name string `gorm:"size:255;not null" json:"name"`
|
|
ContentType string `gorm:"size:128;not null" json:"content_type"`
|
|
Size int64 `gorm:"not null" json:"size"`
|
|
}
|
|
|
|
type User struct {
|
|
Base
|
|
OpenID string `gorm:"size:128;uniqueIndex;not null" json:"-"`
|
|
Nickname string `gorm:"size:64;not null" json:"nickname"`
|
|
AvatarFileID *string `gorm:"type:uuid;index" json:"avatar_file_id"`
|
|
Disabled bool `gorm:"not null;default:false" json:"disabled"`
|
|
}
|
|
|
|
type Admin struct {
|
|
Base
|
|
Username string `gorm:"size:64;uniqueIndex;not null" json:"username"`
|
|
PasswordHash string `gorm:"size:255;not null" json:"-"`
|
|
}
|
|
|
|
// RefreshSession stores only a hash of the rotating refresh credential.
|
|
type RefreshSession struct {
|
|
Base
|
|
ActorID string `gorm:"type:uuid;index;not null" json:"-"`
|
|
Role string `gorm:"size:16;index;not null" json:"-"`
|
|
TokenHash string `gorm:"size:64;uniqueIndex;not null" json:"-"`
|
|
ExpiresAt time.Time `gorm:"index;not null" json:"-"`
|
|
Revoked bool `gorm:"not null;default:false" json:"-"`
|
|
}
|
|
|
|
type Breed struct {
|
|
Base
|
|
LifeSpan string `gorm:"size:128" json:"life_span"`
|
|
Exercise string `gorm:"size:255" json:"exercise"`
|
|
Grooming string `gorm:"size:255" json:"grooming"`
|
|
EditorialLocked bool `gorm:"not null;default:false" json:"editorial_locked"`
|
|
FieldSources map[string]string `gorm:"serializer:json;type:jsonb" json:"field_sources"`
|
|
References []BreedReference `gorm:"foreignKey:BreedID" json:"references,omitempty"`
|
|
Origin string `gorm:"size:128" json:"origin"`
|
|
BreedGroup string `gorm:"size:255" json:"breed_group"`
|
|
FCINumber string `gorm:"size:16" json:"fci_number"`
|
|
Height string `gorm:"size:128" json:"height"`
|
|
Weight string `gorm:"size:128" json:"weight"`
|
|
Summary string `gorm:"type:text" json:"summary"`
|
|
Temperament string `gorm:"size:255" json:"temperament"`
|
|
Traits string `gorm:"type:text" json:"traits"`
|
|
CareNotes string `gorm:"type:text" json:"care_notes"`
|
|
EncyclopediaUpdatedAt string `gorm:"size:10" json:"encyclopedia_updated_at"`
|
|
Name string `gorm:"size:128;uniqueIndex;not null" json:"name"`
|
|
EnglishName string `gorm:"size:128" json:"english_name"`
|
|
Aliases string `gorm:"size:512" json:"aliases"`
|
|
Pinyin string `gorm:"size:1024;index;not null" json:"pinyin"`
|
|
PinyinInitials string `gorm:"size:128" json:"pinyin_initials"`
|
|
Initial string `gorm:"size:1;index;not null" json:"initial"`
|
|
Enabled bool `gorm:"not null;default:true" json:"enabled"`
|
|
Source string `gorm:"size:128" json:"source"`
|
|
SourceKey *string `gorm:"size:128;uniqueIndex" json:"source_key"`
|
|
SourceURL string `gorm:"size:512" json:"source_url"`
|
|
}
|
|
|
|
// Facts contain short structured facts, never copied articles or remote images.
|
|
type BreedReference struct {
|
|
Base
|
|
BreedID string `gorm:"type:uuid;uniqueIndex:idx_breed_provider;not null" json:"breed_id"`
|
|
Provider string `gorm:"size:32;uniqueIndex:idx_breed_provider;not null" json:"provider"`
|
|
ExternalID string `gorm:"size:128;not null" json:"external_id"`
|
|
URL string `gorm:"size:512;not null" json:"url"`
|
|
RetrievedAt string `gorm:"size:10;not null" json:"retrieved_at"`
|
|
Facts map[string]string `gorm:"serializer:json;type:jsonb;not null" json:"facts"`
|
|
}
|
|
|
|
type Pet struct {
|
|
Base
|
|
UserID string `gorm:"type:uuid;index;not null" json:"user_id"`
|
|
Name string `gorm:"size:64;not null" json:"name"`
|
|
Species string `gorm:"size:16;not null;default:dog" json:"species"`
|
|
Breed string `gorm:"size:128" json:"breed"`
|
|
BreedID *string `gorm:"type:uuid;index" json:"breed_id"`
|
|
Gender string `gorm:"size:16" json:"gender"`
|
|
BirthDate *time.Time `gorm:"type:date" json:"birth_date"`
|
|
WeightKg float64 `gorm:"type:numeric(6,2)" json:"weight_kg"`
|
|
AvatarFileID *string `gorm:"type:uuid;index" json:"avatar_file_id"`
|
|
Coat string `gorm:"size:64" json:"coat"`
|
|
Allergies string `gorm:"size:255" json:"allergies"`
|
|
CareNotes string `gorm:"size:1000" json:"care_notes"`
|
|
Archived bool `gorm:"not null;default:false" json:"archived"`
|
|
}
|
|
|
|
type CareTask struct {
|
|
Base
|
|
UserID string `gorm:"type:uuid;index;not null" json:"user_id"`
|
|
PetID string `gorm:"type:uuid;index;not null" json:"pet_id"`
|
|
Title string `gorm:"size:128;not null" json:"title"`
|
|
Category string `gorm:"size:32;not null" json:"category"`
|
|
TimeOfDay string `gorm:"size:5;not null" json:"time_of_day"`
|
|
RepeatRule string `gorm:"size:16;not null;default:daily" json:"repeat_rule"`
|
|
ReminderEnabled bool `gorm:"not null;default:false" json:"reminder_enabled"`
|
|
}
|
|
|
|
type TaskCompletion struct {
|
|
Base
|
|
TaskID string `gorm:"type:uuid;uniqueIndex:idx_task_date;not null" json:"task_id"`
|
|
UserID string `gorm:"type:uuid;index;not null" json:"user_id"`
|
|
Date time.Time `gorm:"type:date;uniqueIndex:idx_task_date;not null" json:"date"`
|
|
CompletedAt time.Time `gorm:"not null" json:"completed_at"`
|
|
}
|
|
|
|
type Walk struct {
|
|
Base
|
|
UserID string `gorm:"type:uuid;index;not null" json:"user_id"`
|
|
Status string `gorm:"size:16;index;not null" json:"status"`
|
|
StartedAt time.Time `gorm:"not null" json:"started_at"`
|
|
SegmentStartedAt time.Time `gorm:"not null" json:"segment_started_at"`
|
|
PausedAt *time.Time `json:"paused_at"`
|
|
PausedSeconds int `gorm:"not null;default:0" json:"paused_seconds"`
|
|
EndedAt *time.Time `json:"ended_at"`
|
|
DurationSeconds int `gorm:"not null;default:0" json:"duration_seconds"`
|
|
DistanceMeters float64 `gorm:"type:numeric(12,2);not null;default:0" json:"distance_meters"`
|
|
ShareEnabled bool `gorm:"not null;default:false" json:"share_enabled"`
|
|
ShareToken string `gorm:"type:uuid;uniqueIndex" json:"-"`
|
|
ShareExpiresAt *time.Time `json:"share_expires_at"`
|
|
}
|
|
|
|
type WalkPet struct {
|
|
Base
|
|
WalkID string `gorm:"type:uuid;uniqueIndex:idx_walk_pet;not null" json:"walk_id"`
|
|
PetID string `gorm:"type:uuid;uniqueIndex:idx_walk_pet;index;not null" json:"pet_id"`
|
|
}
|
|
|
|
type WalkPoint struct {
|
|
Base
|
|
WalkID string `gorm:"type:uuid;index;not null" json:"walk_id"`
|
|
Latitude float64 `gorm:"type:numeric(10,7);not null" json:"latitude"`
|
|
Longitude float64 `gorm:"type:numeric(10,7);not null" json:"longitude"`
|
|
RecordedAt time.Time `gorm:"index;not null" json:"recorded_at"`
|
|
}
|
|
|
|
type Meetup struct {
|
|
Base
|
|
HostUserID string `gorm:"type:uuid;index;not null" json:"host_user_id"`
|
|
Title string `gorm:"size:128;not null" json:"title"`
|
|
Description string `gorm:"size:1000" json:"description"`
|
|
PlaceName string `gorm:"size:255;not null" json:"place_name"`
|
|
Latitude float64 `gorm:"type:numeric(10,7)" json:"latitude"`
|
|
Longitude float64 `gorm:"type:numeric(10,7)" json:"longitude"`
|
|
StartsAt time.Time `gorm:"index;not null" json:"starts_at"`
|
|
MaxPeople int `gorm:"not null;default:8" json:"max_people"`
|
|
Status string `gorm:"size:16;index;not null;default:open" json:"status"`
|
|
CoverFileID *string `gorm:"type:uuid;index" json:"cover_file_id"`
|
|
}
|
|
|
|
type MeetupParticipant struct {
|
|
Base
|
|
MeetupID string `gorm:"type:uuid;uniqueIndex:idx_meetup_user;not null" json:"meetup_id"`
|
|
UserID string `gorm:"type:uuid;uniqueIndex:idx_meetup_user;index;not null" json:"user_id"`
|
|
}
|
|
|
|
type MeetupPet struct {
|
|
Base
|
|
ParticipantID string `gorm:"type:uuid;uniqueIndex:idx_participant_pet;not null" json:"participant_id"`
|
|
PetID string `gorm:"type:uuid;uniqueIndex:idx_participant_pet;index;not null" json:"pet_id"`
|
|
}
|
|
|
|
func All() []any {
|
|
return []any{
|
|
&File{}, &User{}, &Admin{}, &RefreshSession{}, &Breed{}, &BreedReference{}, &Pet{}, &CareTask{}, &TaskCompletion{},
|
|
&Walk{}, &WalkPet{}, &WalkPoint{}, &Meetup{}, &MeetupParticipant{}, &MeetupPet{},
|
|
}
|
|
}
|