init
This commit is contained in:
259
internal/models/TRANSACTION_IMAGE_IMPLEMENTATION.md
Normal file
259
internal/models/TRANSACTION_IMAGE_IMPLEMENTATION.md
Normal file
@@ -0,0 +1,259 @@
|
||||
# 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
|
||||
Reference in New Issue
Block a user