package db import ( "context" "fmt" "time" ) // ItemFile represents a file attachment on an item. type ItemFile struct { ID string ItemID string Filename string ContentType string Size int64 ObjectKey string StorageBackend string // "minio" or "filesystem" CreatedAt time.Time } // ItemFileRepository provides item_files database operations. type ItemFileRepository struct { db *DB } // NewItemFileRepository creates a new item file repository. func NewItemFileRepository(db *DB) *ItemFileRepository { return &ItemFileRepository{db: db} } // Create inserts a new item file record. func (r *ItemFileRepository) Create(ctx context.Context, f *ItemFile) error { if f.StorageBackend == "" { f.StorageBackend = "minio" } err := r.db.pool.QueryRow(ctx, `INSERT INTO item_files (item_id, filename, content_type, size, object_key, storage_backend) VALUES ($1, $2, $3, $4, $5, $6) RETURNING id, created_at`, f.ItemID, f.Filename, f.ContentType, f.Size, f.ObjectKey, f.StorageBackend, ).Scan(&f.ID, &f.CreatedAt) if err != nil { return fmt.Errorf("creating item file: %w", err) } return nil } // ListByItem returns all file attachments for an item. func (r *ItemFileRepository) ListByItem(ctx context.Context, itemID string) ([]*ItemFile, error) { rows, err := r.db.pool.Query(ctx, `SELECT id, item_id, filename, content_type, size, object_key, COALESCE(storage_backend, 'minio'), created_at FROM item_files WHERE item_id = $1 ORDER BY created_at`, itemID, ) if err != nil { return nil, fmt.Errorf("listing item files: %w", err) } defer rows.Close() var files []*ItemFile for rows.Next() { f := &ItemFile{} if err := rows.Scan(&f.ID, &f.ItemID, &f.Filename, &f.ContentType, &f.Size, &f.ObjectKey, &f.StorageBackend, &f.CreatedAt); err != nil { return nil, fmt.Errorf("scanning item file: %w", err) } files = append(files, f) } return files, nil } // Get returns a single item file by ID. func (r *ItemFileRepository) Get(ctx context.Context, id string) (*ItemFile, error) { f := &ItemFile{} err := r.db.pool.QueryRow(ctx, `SELECT id, item_id, filename, content_type, size, object_key, COALESCE(storage_backend, 'minio'), created_at FROM item_files WHERE id = $1`, id, ).Scan(&f.ID, &f.ItemID, &f.Filename, &f.ContentType, &f.Size, &f.ObjectKey, &f.StorageBackend, &f.CreatedAt) if err != nil { return nil, fmt.Errorf("getting item file: %w", err) } return f, nil } // Delete removes an item file record. func (r *ItemFileRepository) Delete(ctx context.Context, id string) error { tag, err := r.db.pool.Exec(ctx, `DELETE FROM item_files WHERE id = $1`, id) if err != nil { return fmt.Errorf("deleting item file: %w", err) } if tag.RowsAffected() == 0 { return fmt.Errorf("item file not found") } return nil }