init
This commit is contained in:
188
internal/models/LEDGER_IMPLEMENTATION.md
Normal file
188
internal/models/LEDGER_IMPLEMENTATION.md
Normal file
@@ -0,0 +1,188 @@
|
||||
# Ledger Model Implementation
|
||||
|
||||
## Overview
|
||||
|
||||
This document describes the implementation of the Ledger model for the multi-ledger accounting system feature.
|
||||
|
||||
## Feature
|
||||
|
||||
**Feature:** accounting-feature-upgrade
|
||||
**Task:** 1.1 创建Ledger账本模型和数据库迁移
|
||||
**Requirements:** 3.1
|
||||
|
||||
## Model Definition
|
||||
|
||||
### Ledger Struct
|
||||
|
||||
```go
|
||||
type Ledger struct {
|
||||
BaseModel
|
||||
Name string `gorm:"size:100;not null" json:"name"`
|
||||
Theme string `gorm:"size:50" json:"theme"` // pink, beige, brown
|
||||
CoverImage string `gorm:"size:255" json:"cover_image"`
|
||||
IsDefault bool `gorm:"default:false" json:"is_default"`
|
||||
SortOrder int `gorm:"default:0" json:"sort_order"`
|
||||
|
||||
// Relationships
|
||||
Transactions []Transaction `gorm:"foreignKey:LedgerID" json:"-"`
|
||||
}
|
||||
```
|
||||
|
||||
### Fields
|
||||
|
||||
- **ID** (inherited from BaseModel): Primary key, auto-increment
|
||||
- **CreatedAt** (inherited from BaseModel): Timestamp when ledger was created
|
||||
- **UpdatedAt** (inherited from BaseModel): Timestamp when ledger was last updated
|
||||
- **DeletedAt** (inherited from BaseModel): Soft delete timestamp (NULL if not deleted)
|
||||
- **Name**: Ledger name (max 100 characters, required)
|
||||
- **Theme**: Theme color identifier (max 50 characters, optional)
|
||||
- Supported values: "pink", "beige", "brown"
|
||||
- **CoverImage**: Path to cover image (max 255 characters, optional)
|
||||
- **IsDefault**: Whether this is the default ledger (boolean, default: false)
|
||||
- **SortOrder**: Display order for ledgers (integer, default: 0)
|
||||
|
||||
### Relationships
|
||||
|
||||
- **Transactions**: One-to-many relationship with Transaction model
|
||||
- A ledger can have multiple transactions
|
||||
- Foreign key: `LedgerID` in Transaction model
|
||||
|
||||
### Constants
|
||||
|
||||
```go
|
||||
const MaxLedgersPerUser = 10
|
||||
```
|
||||
|
||||
Maximum number of ledgers a user can create (Requirement 3.12)
|
||||
|
||||
## Database Schema
|
||||
|
||||
### Table: ledgers
|
||||
|
||||
```sql
|
||||
CREATE TABLE IF NOT EXISTS ledgers (
|
||||
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
created_at DATETIME(3) DEFAULT NULL,
|
||||
updated_at DATETIME(3) DEFAULT NULL,
|
||||
deleted_at DATETIME(3) DEFAULT NULL,
|
||||
name VARCHAR(100) NOT NULL,
|
||||
theme VARCHAR(50) DEFAULT NULL,
|
||||
cover_image VARCHAR(255) DEFAULT NULL,
|
||||
is_default TINYINT(1) DEFAULT 0,
|
||||
sort_order INT DEFAULT 0,
|
||||
PRIMARY KEY (id),
|
||||
INDEX idx_ledgers_deleted_at (deleted_at)
|
||||
);
|
||||
```
|
||||
|
||||
### Transaction Model Extension
|
||||
|
||||
The Transaction model has been extended with a `LedgerID` field:
|
||||
|
||||
```go
|
||||
LedgerID *uint `gorm:"index" json:"ledger_id,omitempty"`
|
||||
```
|
||||
|
||||
This creates a foreign key relationship between transactions and ledgers.
|
||||
|
||||
## Migration
|
||||
|
||||
### Using Go Migration Tool
|
||||
|
||||
```bash
|
||||
cd backend
|
||||
go run cmd/migrate/main.go
|
||||
```
|
||||
|
||||
This will automatically create the `ledgers` table and add the `ledger_id` column to the `transactions` table.
|
||||
|
||||
### Manual SQL Migration
|
||||
|
||||
```bash
|
||||
mysql -u username -p database_name < backend/migrations/001_add_ledger_support.sql
|
||||
```
|
||||
|
||||
## Testing
|
||||
|
||||
Unit tests are provided in `ledger_test.go`:
|
||||
|
||||
```bash
|
||||
cd backend
|
||||
go test ./internal/models/... -v
|
||||
```
|
||||
|
||||
Tests verify:
|
||||
- Table name is correct ("ledgers")
|
||||
- All model fields work correctly
|
||||
- MaxLedgersPerUser constant has the correct value
|
||||
|
||||
## Usage Example
|
||||
|
||||
```go
|
||||
// Create a new ledger
|
||||
ledger := models.Ledger{
|
||||
Name: "Wedding Expenses",
|
||||
Theme: "pink",
|
||||
CoverImage: "/images/wedding-cover.jpg",
|
||||
IsDefault: false,
|
||||
SortOrder: 1,
|
||||
}
|
||||
|
||||
// Save to database
|
||||
db.Create(&ledger)
|
||||
|
||||
// Query ledgers
|
||||
var ledgers []models.Ledger
|
||||
db.Where("deleted_at IS NULL").Order("sort_order ASC").Find(&ledgers)
|
||||
|
||||
// Soft delete a ledger
|
||||
db.Delete(&ledger)
|
||||
|
||||
// Restore a soft-deleted ledger
|
||||
db.Model(&ledger).Update("deleted_at", nil)
|
||||
```
|
||||
|
||||
## Next Steps
|
||||
|
||||
The following tasks will build upon this model:
|
||||
|
||||
1. **Task 3.1**: Implement Ledger CRUD API endpoints
|
||||
2. **Task 3.2**: Implement soft delete and restore functionality
|
||||
3. **Task 10.1-10.3**: Implement frontend components for ledger management
|
||||
|
||||
## Validation Rules
|
||||
|
||||
When implementing the API layer, ensure:
|
||||
|
||||
1. **Name validation**: Required, max 100 characters
|
||||
2. **Theme validation**: Optional, must be one of: "pink", "beige", "brown"
|
||||
3. **Ledger count limit**: User cannot create more than 10 ledgers (MaxLedgersPerUser)
|
||||
4. **Default ledger**: At least one ledger must exist and be marked as default
|
||||
5. **Soft delete**: Use GORM's soft delete feature (DeletedAt field)
|
||||
|
||||
## Design Considerations
|
||||
|
||||
### Soft Delete
|
||||
|
||||
The model uses GORM's soft delete feature (DeletedAt field from BaseModel). This means:
|
||||
- Deleted ledgers are not physically removed from the database
|
||||
- Deleted ledgers are automatically excluded from queries
|
||||
- Historical transaction data is preserved even after ledger deletion
|
||||
- Ledgers can be restored if needed
|
||||
|
||||
### Sort Order
|
||||
|
||||
The `SortOrder` field allows users to customize the display order of their ledgers. Lower values appear first.
|
||||
|
||||
### Default Ledger
|
||||
|
||||
The `IsDefault` field ensures there's always a default ledger for new transactions. Business logic should ensure:
|
||||
- At least one ledger is always marked as default
|
||||
- When the default ledger is deleted, another ledger is automatically promoted to default
|
||||
|
||||
## Compliance
|
||||
|
||||
This implementation satisfies:
|
||||
- **Requirement 3.1**: Ledger data model with all specified fields
|
||||
- **Requirement 3.12**: Maximum 10 ledgers per user (constant defined)
|
||||
- **Design Document**: Ledger model structure matches the design specification
|
||||
Reference in New Issue
Block a user