feat: 初始化核心应用结构,新增循环交易、短信、分配规则和用户设置等服务,并更新相关依赖和配置。
This commit is contained in:
@@ -11,6 +11,7 @@ import (
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
// RecurringTransactionService handles business logic for recurring transactions
|
||||
// RecurringTransactionService handles business logic for recurring transactions
|
||||
type RecurringTransactionService struct {
|
||||
recurringRepo *repository.RecurringTransactionRepository
|
||||
@@ -20,6 +21,8 @@ type RecurringTransactionService struct {
|
||||
allocationRuleRepo *repository.AllocationRuleRepository
|
||||
recordRepo *repository.AllocationRecordRepository
|
||||
piggyBankRepo *repository.PiggyBankRepository
|
||||
userSettingsRepo *repository.UserSettingsRepository
|
||||
smsService *SmsService
|
||||
db *gorm.DB
|
||||
}
|
||||
|
||||
@@ -32,6 +35,8 @@ func NewRecurringTransactionService(
|
||||
allocationRuleRepo *repository.AllocationRuleRepository,
|
||||
recordRepo *repository.AllocationRecordRepository,
|
||||
piggyBankRepo *repository.PiggyBankRepository,
|
||||
userSettingsRepo *repository.UserSettingsRepository,
|
||||
smsService *SmsService,
|
||||
db *gorm.DB,
|
||||
) *RecurringTransactionService {
|
||||
return &RecurringTransactionService{
|
||||
@@ -42,6 +47,8 @@ func NewRecurringTransactionService(
|
||||
allocationRuleRepo: allocationRuleRepo,
|
||||
recordRepo: recordRepo,
|
||||
piggyBankRepo: piggyBankRepo,
|
||||
userSettingsRepo: userSettingsRepo,
|
||||
smsService: smsService,
|
||||
db: db,
|
||||
}
|
||||
}
|
||||
@@ -377,6 +384,27 @@ func (s *RecurringTransactionService) ProcessDueTransactions(userID uint, now ti
|
||||
result.Transactions = append(result.Transactions, transaction)
|
||||
}
|
||||
|
||||
// Send SMS notifications for auto-executed allocations
|
||||
for _, allocation := range result.Allocations {
|
||||
if allocation.AutoExecuted {
|
||||
// Get user phone number
|
||||
userSettings, err := s.userSettingsRepo.GetOrCreate(userID)
|
||||
if err != nil {
|
||||
// Log error but don't fail the request
|
||||
fmt.Printf("Failed to get user settings for SMS: %v\n", err)
|
||||
continue
|
||||
}
|
||||
|
||||
if userSettings != nil && userSettings.Phone != "" && s.smsService != nil {
|
||||
go func(phone string, amount float64, ruleName string) {
|
||||
if err := s.smsService.SendAllocationNotification(phone, amount, ruleName); err != nil {
|
||||
fmt.Printf("Failed to send allocation SMS: %v\n", err)
|
||||
}
|
||||
}(userSettings.Phone, allocation.TotalAmount, allocation.RuleName)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
@@ -429,7 +457,7 @@ func (s *RecurringTransactionService) applyAllocationRulesForIncome(userID uint,
|
||||
continue
|
||||
}
|
||||
|
||||
// Get target name and apply allocation
|
||||
// Get target name
|
||||
targetName := ""
|
||||
|
||||
switch target.TargetType {
|
||||
@@ -440,20 +468,23 @@ func (s *RecurringTransactionService) applyAllocationRulesForIncome(userID uint,
|
||||
}
|
||||
targetName = targetAccount.Name
|
||||
|
||||
// Add to target account
|
||||
targetAccount.Balance += allocatedAmount
|
||||
if err := tx.Save(&targetAccount).Error; err != nil {
|
||||
return nil, fmt.Errorf("failed to update target account balance: %w", err)
|
||||
}
|
||||
// Execute transfer only if AutoExecute is true
|
||||
if rule.AutoExecute {
|
||||
// Add to target account
|
||||
targetAccount.Balance += allocatedAmount
|
||||
if err := tx.Save(&targetAccount).Error; err != nil {
|
||||
return nil, fmt.Errorf("failed to update target account balance: %w", err)
|
||||
}
|
||||
|
||||
// Deduct from source account
|
||||
var sourceAccount models.Account
|
||||
if err := tx.First(&sourceAccount, accountID).Error; err != nil {
|
||||
return nil, fmt.Errorf("failed to get source account: %w", err)
|
||||
}
|
||||
sourceAccount.Balance -= allocatedAmount
|
||||
if err := tx.Save(&sourceAccount).Error; err != nil {
|
||||
return nil, fmt.Errorf("failed to update source account balance: %w", err)
|
||||
// Deduct from source account
|
||||
var sourceAccount models.Account
|
||||
if err := tx.First(&sourceAccount, accountID).Error; err != nil {
|
||||
return nil, fmt.Errorf("failed to get source account: %w", err)
|
||||
}
|
||||
sourceAccount.Balance -= allocatedAmount
|
||||
if err := tx.Save(&sourceAccount).Error; err != nil {
|
||||
return nil, fmt.Errorf("failed to update source account balance: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
case models.TargetTypePiggyBank:
|
||||
@@ -463,20 +494,23 @@ func (s *RecurringTransactionService) applyAllocationRulesForIncome(userID uint,
|
||||
}
|
||||
targetName = piggyBank.Name
|
||||
|
||||
// Add to piggy bank
|
||||
piggyBank.CurrentAmount += allocatedAmount
|
||||
if err := tx.Save(&piggyBank).Error; err != nil {
|
||||
return nil, fmt.Errorf("failed to update piggy bank balance: %w", err)
|
||||
}
|
||||
// Execute transfer only if AutoExecute is true
|
||||
if rule.AutoExecute {
|
||||
// Add to piggy bank
|
||||
piggyBank.CurrentAmount += allocatedAmount
|
||||
if err := tx.Save(&piggyBank).Error; err != nil {
|
||||
return nil, fmt.Errorf("failed to update piggy bank balance: %w", err)
|
||||
}
|
||||
|
||||
// Deduct from source account
|
||||
var sourceAccount models.Account
|
||||
if err := tx.First(&sourceAccount, accountID).Error; err != nil {
|
||||
return nil, fmt.Errorf("failed to get source account: %w", err)
|
||||
}
|
||||
sourceAccount.Balance -= allocatedAmount
|
||||
if err := tx.Save(&sourceAccount).Error; err != nil {
|
||||
return nil, fmt.Errorf("failed to update source account balance: %w", err)
|
||||
// Deduct from source account
|
||||
var sourceAccount models.Account
|
||||
if err := tx.First(&sourceAccount, accountID).Error; err != nil {
|
||||
return nil, fmt.Errorf("failed to get source account: %w", err)
|
||||
}
|
||||
sourceAccount.Balance -= allocatedAmount
|
||||
if err := tx.Save(&sourceAccount).Error; err != nil {
|
||||
return nil, fmt.Errorf("failed to update source account balance: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
default:
|
||||
|
||||
Reference in New Issue
Block a user