6.9 KiB
6.9 KiB
Account Model Extension Implementation
Overview
This document describes the implementation of task 1.6: Extending the Account model to support asset management enhancements for the accounting-feature-upgrade specification.
Feature
Feature: accounting-feature-upgrade
Task: 1.6 扩展Account模型
Validates: Requirements 1.2-1.10
Changes Made
1. Model Extension (backend/internal/models/models.go)
Added the following fields to the Account struct:
// Asset management enhancements
// Feature: accounting-feature-upgrade
// Validates: Requirements 1.2-1.10
SortOrder int `gorm:"default:0" json:"sort_order"` // Display order for account list
WarningThreshold *float64 `gorm:"type:decimal(15,2)" json:"warning_threshold,omitempty"` // Balance warning threshold
LastSyncTime *time.Time `json:"last_sync_time,omitempty"` // Last synchronization time
AccountCode string `gorm:"size:50" json:"account_code,omitempty"` // Account identifier (e.g., Alipay, Wechat)
AccountType string `gorm:"size:20;default:'asset'" json:"account_type"` // asset or liability
2. Database Migration (backend/migrations/004_extend_account_model.sql)
Created a SQL migration file that:
- Adds all five new fields to the
accountstable - Adds indexes for
sort_orderandaccount_typeto optimize queries - Includes proper comments for each field
- Follows the project's migration file format
3. Unit Tests (backend/internal/models/account_extension_test.go)
Created comprehensive unit tests covering:
Test Coverage
- TestAccountExtension_SortOrderField - Verifies the sort_order field works correctly
- TestAccountExtension_WarningThresholdField - Tests warning threshold with and without values
- TestAccountExtension_LastSyncTimeField - Tests last sync time with and without values
- TestAccountExtension_AccountCodeField - Tests various account codes (Alipay, Wechat, etc.)
- TestAccountExtension_AccountTypeField - Tests asset and liability account types
- TestAccountExtension_WarningThresholdLogic - Tests the warning threshold logic (Validates Requirements 1.5, 1.10)
- TestAccountExtension_AllFieldsTogether - Tests all fields working together
- TestAccountExtension_AssetVsLiability - Tests asset vs liability distinction (Validates Requirements 1.2)
Test Results
All tests pass successfully:
PASS: TestAccountExtension_SortOrderField
PASS: TestAccountExtension_WarningThresholdField
PASS: TestAccountExtension_LastSyncTimeField
PASS: TestAccountExtension_AccountCodeField
PASS: TestAccountExtension_AccountTypeField
PASS: TestAccountExtension_WarningThresholdLogic
PASS: TestAccountExtension_AllFieldsTogether
PASS: TestAccountExtension_AssetVsLiability
Field Descriptions
SortOrder (int)
- Purpose: Controls the display order of accounts in the account list
- Default: 0
- Usage: Allows users to drag and reorder accounts, with the order persisted to the database
- Validates: Requirements 1.3, 1.4
WarningThreshold (*float64)
- Purpose: Balance threshold below which a warning should be displayed
- Type: Pointer to allow null values (no warning if not set)
- Usage: When balance < threshold, display an orange "预警" (warning) badge
- Validates: Requirements 1.5, 1.7, 1.10
LastSyncTime (*time.Time)
- Purpose: Tracks the last time the account was synchronized
- Type: Pointer to allow null values
- Format: Displayed as "MM月DD日 HH:mm" in the UI
- Validates: Requirements 1.8
AccountCode (string)
- Purpose: Unique identifier for the account (e.g., "Alipay", "Wechat", "ICBC-1234")
- Max Length: 50 characters
- Usage: Displayed in account details to help users identify accounts
- Validates: Requirements 1.9
AccountType (string)
- Purpose: Classifies accounts as either "asset" or "liability"
- Default: "asset"
- Values: "asset" (positive balance accounts) or "liability" (negative balance accounts like credit cards)
- Usage: Used to calculate total assets (only includes asset type accounts)
- Validates: Requirements 1.2
Requirements Validation
This implementation validates the following requirements from the specification:
- 1.2 - Total assets calculation only includes asset type accounts
- 1.3 - Accounts can be reordered using drag handles
- 1.4 - Account order is persisted using sort_order field
- 1.5 - Warning badge displayed when balance < threshold
- 1.7 - Warning threshold can be set in account details
- 1.8 - Last sync time is displayed in account details
- 1.9 - Account unique ID (code) is displayed in account details
- 1.10 - No warning displayed when threshold is not set (null)
Database Schema Changes
The migration adds the following columns to the accounts table:
ALTER TABLE accounts
ADD COLUMN sort_order INT DEFAULT 0,
ADD COLUMN warning_threshold DECIMAL(15,2) DEFAULT NULL,
ADD COLUMN last_sync_time DATETIME DEFAULT NULL,
ADD COLUMN account_code VARCHAR(50) DEFAULT NULL,
ADD COLUMN account_type VARCHAR(20) DEFAULT 'asset';
With indexes:
ALTER TABLE accounts
ADD INDEX idx_accounts_sort_order (sort_order),
ADD INDEX idx_accounts_account_type (account_type);
Running the Migration
Option 1: Using GORM AutoMigrate (Recommended)
cd backend
go run cmd/migrate/main.go
GORM will automatically detect the new fields and add them to the database.
Option 2: Manual SQL Execution
mysql -u your_username -p your_database < backend/migrations/004_extend_account_model.sql
Testing
Run the unit tests:
cd backend
go test -v ./internal/models -run TestAccountExtension
All tests should pass.
Next Steps
After this implementation:
- The Account model is ready for use in the asset management page
- Backend API handlers can now use these fields for:
- Account reordering (PUT /api/accounts/reorder)
- Warning threshold settings
- Sync time tracking
- Asset vs liability filtering
- Frontend components can display:
- Sorted account lists
- Warning badges
- Sync times
- Account codes
- Total assets (excluding liabilities)
Related Tasks
- Task 6.1: Implement account reordering API
- Task 9.1: Implement AssetSummaryCard component (uses AccountType)
- Task 9.2: Implement DraggableAccountList component (uses SortOrder, WarningThreshold, LastSyncTime, AccountCode)
Notes
- All new fields are optional (nullable or have defaults) to maintain backward compatibility
- The AccountType field defaults to "asset" for existing accounts
- Warning threshold logic:
shouldWarn = threshold != nil && balance < threshold - The model is already registered in
AllModels()function, so no additional registration is needed