package persistence import ( domain "RenewCMS/internal/domain/image" "RenewCMS/internal/infrastructure/persistence/mappers" entity "RenewCMS/internal/infrastructure/persistence/models" "errors" "gorm.io/gorm" "gorm.io/gorm/clause" ) type VariantFileRepository struct { db *gorm.DB } var _ domain.VariantFileRepository = &VariantFileRepository{} func NewVariantFileRepository(db *gorm.DB) *VariantFileRepository { return &VariantFileRepository{db} } func (v *VariantFileRepository) Find(variantName string, sourceName string) (domain.VariantFile, bool, error) { var model entity.ImageVariantFile err := v.db.Where("variant_name = ? AND source_name = ?", variantName, sourceName).First(&model).Error if errors.Is(err, gorm.ErrRecordNotFound) { return domain.VariantFile{}, false, nil } if err != nil { return domain.VariantFile{}, false, err } return mappers.VariantFileToDomain(model), true, nil } func (v *VariantFileRepository) Save(file domain.VariantFile) (domain.VariantFile, error) { model := mappers.VariantFileToModel(file) model.ID = 0 err := v.db.Clauses(clause.OnConflict{ Columns: []clause.Column{{Name: "variant_name"}, {Name: "source_name"}}, DoUpdates: clause.AssignmentColumns([]string{"cached_name", "content_type", "size", "fingerprint"}), }).Create(&model).Error if err != nil { return domain.VariantFile{}, err } saved, _, err := v.Find(file.VariantName, file.SourceName) return saved, err } func (v *VariantFileRepository) ListByVariant(variantName string) ([]domain.VariantFile, error) { return v.list("variant_name = ?", variantName) } func (v *VariantFileRepository) ListBySource(sourceName string) ([]domain.VariantFile, error) { return v.list("source_name = ?", sourceName) } func (v *VariantFileRepository) list(condition string, value string) ([]domain.VariantFile, error) { var found []entity.ImageVariantFile if err := v.db.Where(condition, value).Order("id asc").Find(&found).Error; err != nil { return nil, err } files := make([]domain.VariantFile, 0, len(found)) for _, model := range found { files = append(files, mappers.VariantFileToDomain(model)) } return files, nil } func (v *VariantFileRepository) Delete(id uint32) error { return v.db.Delete(&entity.ImageVariantFile{}, id).Error } func (v *VariantFileRepository) TotalsBySource() (map[string]domain.VariantFileTotals, error) { var rows []struct { SourceName string Files int Bytes int64 } err := v.db.Model(&entity.ImageVariantFile{}). Select("source_name, COUNT(*) AS files, COALESCE(SUM(size), 0) AS bytes"). Group("source_name"). Scan(&rows).Error if err != nil { return nil, err } totals := make(map[string]domain.VariantFileTotals, len(rows)) for _, row := range rows { totals[row.SourceName] = domain.VariantFileTotals{Files: row.Files, Bytes: row.Bytes} } return totals, nil } func (v *VariantFileRepository) Totals() (map[string]domain.VariantFileTotals, error) { var rows []struct { VariantName string Files int Bytes int64 } err := v.db.Model(&entity.ImageVariantFile{}). Select("variant_name, COUNT(*) AS files, COALESCE(SUM(size), 0) AS bytes"). Group("variant_name"). Scan(&rows).Error if err != nil { return nil, err } totals := make(map[string]domain.VariantFileTotals, len(rows)) for _, row := range rows { totals[row.VariantName] = domain.VariantFileTotals{Files: row.Files, Bytes: row.Bytes} } return totals, nil }