Files
fm_be/internal/domain/file_manager/model_file.go
2026-07-16 22:16:45 +07:00

150 lines
7.0 KiB
Go

package filemanager
import (
"strings"
"time"
"gorm.io/gorm"
"wucher/internal/shared/pkg/uuidv7"
)
const (
FileStatusUploaded = "uploaded"
FileStatusProcessing = "processing"
FileStatusValidated = "validated"
FileStatusFailed = "failed"
FileStatusReady = "ready"
FileStatusTrashed = "trashed"
FileLifecycleStatusTemp = "temp"
FileLifecycleStatusDraft = "draft"
FileLifecycleStatusActive = "active"
FileLifecycleStatusFinal = "final"
FileLifecycleStatusOrphanPending = "orphan_pending"
FileLifecycleStatusDeleted = "deleted"
)
type File struct {
ID []byte `gorm:"type:binary(16);primaryKey;column:id"`
FolderID []byte `gorm:"type:binary(16);not null;column:folder_id;index:idx_file_files_folder_active,priority:1;index:uq_file_files_folder_name_slot,priority:1"`
Name string `gorm:"type:varchar(255);not null;column:name"`
NameNormalized string `gorm:"type:varchar(255);not null;column:name_normalized;index:uq_file_files_folder_name_slot,priority:2"`
Extension string `gorm:"type:varchar(32);column:extension"`
SizeBytes int64 `gorm:"type:bigint unsigned;not null;default:0;column:size_bytes"`
MimeType string `gorm:"type:varchar(255);not null;column:mime_type"`
Bucket string `gorm:"type:varchar(128);not null;column:bucket"`
ObjectKey string `gorm:"type:varchar(512);not null;column:object_key;uniqueIndex:uq_file_files_object_key"`
ObjectVersion string `gorm:"type:varchar(128);column:object_version"`
ETag string `gorm:"type:varchar(128);column:etag"`
ThumbnailMimeType *string `gorm:"type:varchar(255);column:thumbnail_mime_type"`
ThumbnailSizeBytes int64 `gorm:"type:bigint unsigned;column:thumbnail_size_bytes"`
ThumbnailBucket *string `gorm:"type:varchar(128);column:thumbnail_bucket"`
ThumbnailObjectKey *string `gorm:"type:varchar(512);column:thumbnail_object_key;uniqueIndex:uq_file_files_thumbnail_object_key"`
ThumbnailObjectVersion *string `gorm:"type:varchar(128);column:thumbnail_object_version"`
ThumbnailETag *string `gorm:"type:varchar(128);column:thumbnail_etag"`
PreviewMimeType *string `gorm:"type:varchar(255);column:preview_mime_type"`
PreviewSizeBytes int64 `gorm:"type:bigint unsigned;column:preview_size_bytes"`
PreviewBucket *string `gorm:"type:varchar(128);column:preview_bucket"`
PreviewObjectKey *string `gorm:"type:varchar(512);column:preview_object_key;uniqueIndex:uq_file_files_preview_object_key"`
PreviewObjectVersion *string `gorm:"type:varchar(128);column:preview_object_version"`
PreviewETag *string `gorm:"type:varchar(128);column:preview_etag"`
ChecksumSHA256 string `gorm:"type:char(64);column:checksum_sha256"`
IsTemplate bool `gorm:"column:is_template;not null;default:false"`
TemplateUUID []byte `gorm:"type:binary(16);column:template_uuid;index:idx_file_files_template_takeover,priority:1"`
TakeoverID []byte `gorm:"type:binary(16);column:takeover_id;index:idx_file_files_template_takeover,priority:2"`
Status string `gorm:"type:varchar(32);not null;default:'uploaded';column:status;index:idx_file_files_status_updated,priority:1"`
ProcessingStartedAt *time.Time `gorm:"column:processing_started_at"`
ProcessedAt *time.Time `gorm:"column:processed_at"`
ValidatedAt *time.Time `gorm:"column:validated_at"`
FailedAt *time.Time `gorm:"column:failed_at"`
FailureReason string `gorm:"type:text;column:failure_reason"`
UploadError string `gorm:"type:text;column:upload_error"`
NameSlot string `gorm:"type:char(36);not null;default:'live';column:name_slot;index:uq_file_files_folder_name_slot,priority:3"`
CreatedAt time.Time `gorm:"column:created_at"`
CreatedBy []byte `gorm:"type:binary(16);column:created_by"`
UpdatedAt time.Time `gorm:"column:updated_at;index:idx_file_files_status_updated,priority:2"`
UpdatedBy []byte `gorm:"type:binary(16);column:updated_by"`
DeletedAt *time.Time `gorm:"column:deleted_at;index:idx_file_files_folder_active,priority:2"`
DeletedBy []byte `gorm:"type:binary(16);column:deleted_by"`
TrashedAt *time.Time `gorm:"column:trashed_at"`
PurgeAt *time.Time `gorm:"column:purge_at;index:idx_file_files_purge_at"`
LifecycleStatus string `gorm:"type:varchar(32);not null;default:'temp';column:lifecycle_status;index:idx_file_files_lifecycle_status_orphaned,priority:1"`
AttachedAt *time.Time `gorm:"column:attached_at"`
OrphanedAt *time.Time `gorm:"column:orphaned_at;index:idx_file_files_lifecycle_status_orphaned,priority:2"`
LifecycleDeletedAt *time.Time `gorm:"column:lifecycle_deleted_at"`
WOPILockID string `gorm:"type:varchar(128);column:wopi_lock_id"`
WOPILockJTI string `gorm:"type:varchar(128);column:wopi_lock_jti"`
WOPILockedAt *time.Time `gorm:"column:wopi_locked_at"`
WOPILockExpiresAt *time.Time `gorm:"column:wopi_lock_expires_at"`
Folder *Folder `gorm:"foreignKey:FolderID;references:ID;constraint:OnUpdate:CASCADE,OnDelete:RESTRICT"`
}
func (File) TableName() string { return "file_files" }
func (f *File) BeforeCreate(tx *gorm.DB) error {
if len(f.ID) == 0 {
f.ID = uuidv7.MustBytes()
}
return nil
}
func NormalizeFileStatus(status string) string {
s := strings.ToLower(strings.TrimSpace(status))
switch s {
case "pending":
return FileStatusUploaded
case "uploading":
return FileStatusProcessing
default:
return s
}
}
func IsKnownFileStatus(status string) bool {
switch NormalizeFileStatus(status) {
case FileStatusUploaded, FileStatusProcessing, FileStatusValidated, FileStatusFailed, FileStatusReady, FileStatusTrashed:
return true
default:
return false
}
}
func CanTransitionFileStatus(fromStatus, toStatus string) bool {
from := NormalizeFileStatus(fromStatus)
to := NormalizeFileStatus(toStatus)
switch from {
case FileStatusUploaded:
return to == FileStatusProcessing || to == FileStatusFailed
case FileStatusProcessing:
return to == FileStatusValidated || to == FileStatusFailed
case FileStatusValidated:
return to == FileStatusReady || to == FileStatusFailed
case FileStatusReady:
return to == FileStatusTrashed
default:
return false
}
}
func NormalizeFileLifecycleStatus(status string) string {
s := strings.ToLower(strings.TrimSpace(status))
switch s {
case "":
return FileLifecycleStatusTemp
default:
return s
}
}
func IsKnownFileLifecycleStatus(status string) bool {
switch NormalizeFileLifecycleStatus(status) {
case FileLifecycleStatusTemp, FileLifecycleStatusDraft, FileLifecycleStatusActive, FileLifecycleStatusFinal, FileLifecycleStatusOrphanPending, FileLifecycleStatusDeleted:
return true
default:
return false
}
}