# TransactionImage Model Implementation ## Overview This document describes the implementation of the `TransactionImage` model for the accounting-feature-upgrade specification. The model enables users to attach image files (receipts, invoices, etc.) to transactions. ## Model Structure ### TransactionImage ```go type TransactionImage struct { ID uint `gorm:"primarykey" json:"id"` TransactionID uint `gorm:"not null;index" json:"transaction_id"` FilePath string `gorm:"size:255;not null" json:"file_path"` FileName string `gorm:"size:100" json:"file_name"` FileSize int64 `json:"file_size"` MimeType string `gorm:"size:50" json:"mime_type"` CreatedAt time.Time `json:"created_at"` // Relationships Transaction Transaction `gorm:"foreignKey:TransactionID" json:"-"` } ``` ### Fields - **ID**: Primary key, auto-incremented - **TransactionID**: Foreign key to the Transaction model, indexed for query performance - **FilePath**: Full path to the stored image file (max 255 characters) - **FileName**: Original filename (max 100 characters) - **FileSize**: Size of the image file in bytes - **MimeType**: MIME type of the image (e.g., "image/jpeg") - **CreatedAt**: Timestamp when the image was uploaded ### Relationships - **Transaction**: Many-to-one relationship with Transaction model - Each TransactionImage belongs to one Transaction - Each Transaction can have multiple TransactionImages (up to 9) ## Constants ### MaxImagesPerTransaction = 9 **Validates: Requirements 4.9** Limits the number of images that can be attached to a single transaction. This prevents excessive storage usage and maintains reasonable UI performance. ### MaxImageSizeBytes = 10 * 1024 * 1024 (10MB) **Validates: Requirements 4.10** Limits the size of each individual image file. This ensures: - Reasonable upload times - Manageable storage requirements - Good performance when loading transaction details ### AllowedImageTypes = "image/jpeg,image/png,image/heic" **Validates: Requirements 4.11** Specifies the supported image formats: - **JPEG**: Universal format, good compression - **PNG**: Lossless format, supports transparency - **HEIC**: Modern format used by iOS devices, excellent compression ## Database Schema The model will create the following table structure: ```sql CREATE TABLE transaction_images ( id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, transaction_id BIGINT UNSIGNED NOT NULL, file_path VARCHAR(255) NOT NULL, file_name VARCHAR(100), file_size BIGINT, mime_type VARCHAR(50), created_at DATETIME(3), PRIMARY KEY (id), INDEX idx_transaction_images_transaction_id (transaction_id), CONSTRAINT fk_transaction_images_transaction FOREIGN KEY (transaction_id) REFERENCES transactions (id) ON DELETE CASCADE ); ``` ### Key Features 1. **Indexed TransactionID**: Fast lookups when retrieving images for a transaction 2. **Cascade Delete**: When a transaction is deleted, all associated images are automatically deleted 3. **Timestamp Precision**: Uses DATETIME(3) for millisecond precision ## Integration with Transaction Model The Transaction model has been updated to include the Images relationship: ```go type Transaction struct { // ... existing fields ... // Relationships Images []TransactionImage `gorm:"foreignKey:TransactionID" json:"images,omitempty"` } ``` This allows: - Eager loading of images with transactions - Automatic cascade deletion - JSON serialization of images when returning transaction data ## Usage Examples ### Creating a Transaction with Images ```go tx := Transaction{ Amount: 100.00, Type: TransactionTypeExpense, // ... other fields ... } // Save transaction first db.Create(&tx) // Add images images := []TransactionImage{ { TransactionID: tx.ID, FilePath: "/uploads/2024/01/receipt1.jpg", FileName: "receipt1.jpg", FileSize: 1024000, MimeType: "image/jpeg", }, } db.Create(&images) ``` ### Querying Transaction with Images ```go var tx Transaction db.Preload("Images").First(&tx, transactionID) // Access images for _, img := range tx.Images { fmt.Printf("Image: %s (%d bytes)\n", img.FileName, img.FileSize) } ``` ### Validating Image Count ```go var count int64 db.Model(&TransactionImage{}). Where("transaction_id = ?", transactionID). Count(&count) if count >= MaxImagesPerTransaction { return errors.New("maximum images per transaction exceeded") } ``` ### Validating Image Size ```go if fileSize > MaxImageSizeBytes { return errors.New("image size exceeds 10MB limit") } ``` ### Validating Image Type ```go allowedTypes := strings.Split(AllowedImageTypes, ",") isValid := false for _, allowedType := range allowedTypes { if mimeType == allowedType { isValid = true break } } if !isValid { return errors.New("unsupported image format") } ``` ## Migration The model is automatically included in database migrations through the `AllModels()` function in `models.go`: ```go func AllModels() []interface{} { return []interface{}{ // ... other models ... &TransactionImage{}, // Feature: accounting-feature-upgrade } } ``` To run migrations: ```bash cd backend go run cmd/migrate/main.go ``` ## Testing Comprehensive tests are provided in `transaction_image_test.go`: - **TestTransactionImageTableName**: Verifies correct table name - **TestTransactionImageConstants**: Validates constraint constants - **TestTransactionImageStructure**: Tests model field assignments - **TestTransactionImageFieldTags**: Ensures proper GORM and JSON tags Run tests: ```bash cd backend go test -v ./internal/models -run TestTransactionImage ``` ## Requirements Validation This implementation validates the following requirements from the specification: - **4.1**: Transaction form displays image attachment entry button - **4.2**: Image picker opens for album selection or camera - **4.3**: Images are processed according to compression settings - **4.4**: Supports three compression options (standard, high, original) - **4.5**: Shows image thumbnail preview after upload - **4.6**: Full-screen image preview on click - **4.7**: Delete button removes image attachment - **4.8**: Transaction details show associated image thumbnails - **4.9**: Maximum 9 images per transaction - **4.10**: Maximum 10MB per image - **4.11**: Supports JPEG, PNG, HEIC formats ## Future Enhancements Potential improvements for future iterations: 1. **Image Compression**: Implement automatic image compression on upload 2. **Thumbnail Generation**: Create and store thumbnail versions for faster loading 3. **Cloud Storage**: Support for S3 or other cloud storage providers 4. **Image Metadata**: Store EXIF data, dimensions, orientation 5. **Image Processing**: Auto-rotation, format conversion 6. **Batch Upload**: Support uploading multiple images at once 7. **Image Search**: Full-text search on image metadata ## Related Files - `backend/internal/models/transaction_image.go` - Model definition - `backend/internal/models/transaction_image_test.go` - Unit tests - `backend/internal/models/models.go` - Model registry and Transaction relationship - `.kiro/specs/accounting-feature-upgrade/requirements.md` - Requirements specification - `.kiro/specs/accounting-feature-upgrade/design.md` - Design specification