178 lines
6.0 KiB
Markdown
178 lines
6.0 KiB
Markdown
# Transaction Model Extension Implementation
|
|
|
|
## Overview
|
|
|
|
This document describes the implementation of Task 1.5: 扩展Transaction模型 (Extend Transaction Model) from the accounting-feature-upgrade specification.
|
|
|
|
## Implementation Summary
|
|
|
|
### 1. Model Extensions
|
|
|
|
Extended the `Transaction` model in `backend/internal/models/models.go` with the following new fields:
|
|
|
|
#### Multi-Ledger Support
|
|
- **LedgerID** (`*uint`): Associates transaction with a specific ledger
|
|
- Validates: Requirements 3.10
|
|
|
|
#### Precise Time Recording
|
|
- **TransactionTime** (`*time.Time`): Records precise transaction time (HH:mm:ss)
|
|
- Validates: Requirements 5.2
|
|
|
|
#### Reimbursement Fields
|
|
- **ReimbursementStatus** (`string`): Status of reimbursement (none, pending, completed)
|
|
- **ReimbursementAmount** (`*float64`): Amount to be reimbursed
|
|
- **ReimbursementIncomeID** (`*uint`): Links to the generated reimbursement income transaction
|
|
- Validates: Requirements 8.4-8.9
|
|
|
|
#### Refund Fields
|
|
- **RefundStatus** (`string`): Status of refund (none, partial, full)
|
|
- **RefundAmount** (`*float64`): Amount refunded
|
|
- **RefundIncomeID** (`*uint`): Links to the generated refund income transaction
|
|
- Validates: Requirements 8.10-8.18
|
|
|
|
#### Original Transaction Link
|
|
- **OriginalTransactionID** (`*uint`): Links refund/reimbursement income back to original expense
|
|
- **IncomeType** (`string`): Type of income (normal, refund, reimbursement)
|
|
- Validates: Requirements 8.19-8.22
|
|
|
|
#### New Relationships
|
|
- **Ledger**: Foreign key relationship to Ledger model
|
|
- **Images**: One-to-many relationship with TransactionImage
|
|
- **OriginalTransaction**: Self-referencing relationship for refund/reimbursement tracking
|
|
|
|
### 2. Database Migration
|
|
|
|
Created migration file: `backend/migrations/003_extend_transaction_model.sql`
|
|
|
|
The migration adds the following columns to the `transactions` table:
|
|
- `transaction_time` (TIME)
|
|
- `reimbursement_status` (VARCHAR(20), default: 'none')
|
|
- `reimbursement_amount` (DECIMAL(15,2))
|
|
- `reimbursement_income_id` (BIGINT UNSIGNED)
|
|
- `refund_status` (VARCHAR(20), default: 'none')
|
|
- `refund_amount` (DECIMAL(15,2))
|
|
- `refund_income_id` (BIGINT UNSIGNED)
|
|
- `original_transaction_id` (BIGINT UNSIGNED)
|
|
- `income_type` (VARCHAR(20))
|
|
|
|
Indexes created:
|
|
- `idx_transactions_reimbursement_income_id`
|
|
- `idx_transactions_refund_income_id`
|
|
- `idx_transactions_original_transaction_id`
|
|
|
|
### 3. Test Coverage
|
|
|
|
Created comprehensive test file: `backend/internal/models/transaction_extension_test.go`
|
|
|
|
Test functions:
|
|
1. **TestTransactionExtensionFields**: Verifies all new fields are properly set
|
|
2. **TestTransactionReimbursementStatuses**: Validates reimbursement status values
|
|
3. **TestTransactionRefundStatuses**: Validates refund status values
|
|
4. **TestTransactionIncomeTypes**: Validates income type values
|
|
5. **TestTransactionDefaultValues**: Verifies default values for new fields
|
|
6. **TestTransactionRelationships**: Verifies new relationship fields
|
|
7. **TestTransactionPreciseTime**: Tests precise time recording functionality
|
|
8. **TestTransactionReimbursementFlow**: Tests complete reimbursement workflow
|
|
9. **TestTransactionRefundFlow**: Tests complete refund workflow (full and partial)
|
|
10. **TestTransactionOriginalLink**: Tests original transaction linking
|
|
11. **TestTransactionLedgerAssociation**: Tests ledger association
|
|
|
|
All tests pass successfully ✓
|
|
|
|
### 4. Migration Execution
|
|
|
|
The migration was successfully executed using:
|
|
```bash
|
|
go run cmd/migrate/main.go
|
|
```
|
|
|
|
Results:
|
|
- ✓ All existing tables updated
|
|
- ✓ New `transaction_images` table created
|
|
- ✓ New `user_settings` table created
|
|
- ✓ System categories initialized (refund, reimbursement)
|
|
|
|
## Field Details
|
|
|
|
### Reimbursement Status Values
|
|
- `none`: No reimbursement requested
|
|
- `pending`: Reimbursement requested, awaiting confirmation
|
|
- `completed`: Reimbursement confirmed and income record created
|
|
|
|
### Refund Status Values
|
|
- `none`: No refund processed
|
|
- `partial`: Partial refund (amount < original amount)
|
|
- `full`: Full refund (amount = original amount)
|
|
|
|
### Income Type Values
|
|
- `normal`: Regular income transaction
|
|
- `refund`: Income generated from a refund
|
|
- `reimbursement`: Income generated from a reimbursement
|
|
|
|
## Usage Examples
|
|
|
|
### Creating a Transaction with Precise Time
|
|
```go
|
|
transactionTime := time.Date(2024, 1, 15, 14, 30, 0, 0, time.UTC)
|
|
tx := Transaction{
|
|
Amount: 100.00,
|
|
Type: TransactionTypeExpense,
|
|
TransactionDate: transactionTime,
|
|
TransactionTime: &transactionTime,
|
|
LedgerID: &ledgerID,
|
|
}
|
|
```
|
|
|
|
### Applying for Reimbursement
|
|
```go
|
|
reimbursementAmount := 80.00
|
|
expense.ReimbursementStatus = "pending"
|
|
expense.ReimbursementAmount = &reimbursementAmount
|
|
```
|
|
|
|
### Processing a Refund
|
|
```go
|
|
refundAmount := 50.00
|
|
incomeID := uint(200)
|
|
expense.RefundStatus = "partial"
|
|
expense.RefundAmount = &refundAmount
|
|
expense.RefundIncomeID = &incomeID
|
|
```
|
|
|
|
### Creating Linked Income Record
|
|
```go
|
|
refundIncome := Transaction{
|
|
Type: TransactionTypeIncome,
|
|
Amount: 50.00,
|
|
IncomeType: "refund",
|
|
OriginalTransactionID: &originalExpenseID,
|
|
LedgerID: originalExpense.LedgerID, // Same ledger as original
|
|
}
|
|
```
|
|
|
|
## Requirements Validation
|
|
|
|
This implementation validates the following requirements:
|
|
- ✓ 3.10: Multi-ledger transaction association
|
|
- ✓ 5.2: Precise time recording
|
|
- ✓ 8.4-8.9: Reimbursement workflow
|
|
- ✓ 8.10-8.18: Refund workflow
|
|
- ✓ 8.19-8.22: Original transaction linking
|
|
- ✓ 8.28: Ledger consistency for refund/reimbursement income
|
|
|
|
## Next Steps
|
|
|
|
The Transaction model is now ready for:
|
|
1. Backend API implementation for reimbursement operations (Task 5.1)
|
|
2. Backend API implementation for refund operations (Task 5.2)
|
|
3. Frontend integration with transaction forms
|
|
4. Property-based testing for transaction workflows
|
|
|
|
## Notes
|
|
|
|
- All pointer fields (`*uint`, `*float64`, `*time.Time`) are optional and can be nil
|
|
- Default values for status fields are set by GORM on database insert
|
|
- Foreign key constraints are commented out in the migration to avoid circular reference issues
|
|
- The implementation maintains backward compatibility with existing transactions
|
|
|