187 lines
7.5 KiB
Go
187 lines
7.5 KiB
Go
package repository
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
|
|
"accounting-app/internal/models"
|
|
|
|
"gorm.io/gorm"
|
|
)
|
|
|
|
// Common repository errors for allocation rules
|
|
var (
|
|
ErrAllocationRuleNotFound = errors.New("allocation rule not found")
|
|
ErrAllocationRuleInUse = errors.New("allocation rule is in use and cannot be deleted")
|
|
)
|
|
|
|
// AllocationRuleRepository handles database operations for allocation rules
|
|
type AllocationRuleRepository struct {
|
|
db *gorm.DB
|
|
}
|
|
|
|
// NewAllocationRuleRepository creates a new AllocationRuleRepository instance
|
|
func NewAllocationRuleRepository(db *gorm.DB) *AllocationRuleRepository {
|
|
return &AllocationRuleRepository{db: db}
|
|
}
|
|
|
|
// Create creates a new allocation rule in the database
|
|
func (r *AllocationRuleRepository) Create(rule *models.AllocationRule) error {
|
|
if err := r.db.Create(rule).Error; err != nil {
|
|
return fmt.Errorf("failed to create allocation rule: %w", err)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// GetByID retrieves an allocation rule by its ID
|
|
func (r *AllocationRuleRepository) GetByID(userID uint, id uint) (*models.AllocationRule, error) {
|
|
var rule models.AllocationRule
|
|
if err := r.db.Preload("Targets").Preload("SourceAccount").Where("user_id = ?", userID).First(&rule, id).Error; err != nil {
|
|
if errors.Is(err, gorm.ErrRecordNotFound) {
|
|
return nil, ErrAllocationRuleNotFound
|
|
}
|
|
return nil, fmt.Errorf("failed to get allocation rule: %w", err)
|
|
}
|
|
return &rule, nil
|
|
}
|
|
|
|
// GetAll retrieves all allocation rules for a user
|
|
func (r *AllocationRuleRepository) GetAll(userID uint) ([]models.AllocationRule, error) {
|
|
var rules []models.AllocationRule
|
|
if err := r.db.Preload("Targets").Preload("SourceAccount").Where("user_id = ?", userID).Order("created_at DESC").Find(&rules).Error; err != nil {
|
|
return nil, fmt.Errorf("failed to get allocation rules: %w", err)
|
|
}
|
|
return rules, nil
|
|
}
|
|
|
|
// GetActive retrieves all active allocation rules for a user
|
|
func (r *AllocationRuleRepository) GetActive(userID uint) ([]models.AllocationRule, error) {
|
|
var rules []models.AllocationRule
|
|
if err := r.db.Preload("Targets").Preload("SourceAccount").Where("user_id = ? AND is_active = ?", userID, true).Order("created_at DESC").Find(&rules).Error; err != nil {
|
|
return nil, fmt.Errorf("failed to get active allocation rules: %w", err)
|
|
}
|
|
return rules, nil
|
|
}
|
|
|
|
// GetByTriggerType retrieves all allocation rules of a specific trigger type for a user
|
|
func (r *AllocationRuleRepository) GetByTriggerType(userID uint, triggerType models.TriggerType) ([]models.AllocationRule, error) {
|
|
var rules []models.AllocationRule
|
|
if err := r.db.Preload("Targets").Preload("SourceAccount").Where("user_id = ? AND trigger_type = ?", userID, triggerType).Order("created_at DESC").Find(&rules).Error; err != nil {
|
|
return nil, fmt.Errorf("failed to get allocation rules by trigger type: %w", err)
|
|
}
|
|
return rules, nil
|
|
}
|
|
|
|
// GetActiveByTriggerType retrieves all active allocation rules of a specific trigger type for a user
|
|
func (r *AllocationRuleRepository) GetActiveByTriggerType(userID uint, triggerType models.TriggerType) ([]models.AllocationRule, error) {
|
|
var rules []models.AllocationRule
|
|
if err := r.db.Preload("Targets").Preload("SourceAccount").Where("user_id = ? AND trigger_type = ? AND is_active = ?", userID, triggerType, true).Order("created_at DESC").Find(&rules).Error; err != nil {
|
|
return nil, fmt.Errorf("failed to get active allocation rules by trigger type: %w", err)
|
|
}
|
|
return rules, nil
|
|
}
|
|
|
|
// GetActiveByTriggerTypeAndAccount retrieves all active allocation rules of a specific trigger type
|
|
// that match the given account (source_account_id is NULL or equals accountID) for a user
|
|
func (r *AllocationRuleRepository) GetActiveByTriggerTypeAndAccount(userID uint, triggerType models.TriggerType, accountID uint) ([]models.AllocationRule, error) {
|
|
var rules []models.AllocationRule
|
|
if err := r.db.Preload("Targets").Preload("SourceAccount").
|
|
Where("user_id = ? AND trigger_type = ? AND is_active = ? AND (source_account_id IS NULL OR source_account_id = ?)",
|
|
userID, triggerType, true, accountID).
|
|
Order("created_at DESC").Find(&rules).Error; err != nil {
|
|
return nil, fmt.Errorf("failed to get active allocation rules by trigger type and account: %w", err)
|
|
}
|
|
return rules, nil
|
|
}
|
|
|
|
// Update updates an existing allocation rule in the database
|
|
func (r *AllocationRuleRepository) Update(userID uint, rule *models.AllocationRule) error {
|
|
// First check if the rule exists and belongs to the user
|
|
var existing models.AllocationRule
|
|
if err := r.db.Where("id = ? AND user_id = ?", rule.ID, userID).First(&existing).Error; err != nil {
|
|
if errors.Is(err, gorm.ErrRecordNotFound) {
|
|
return ErrAllocationRuleNotFound
|
|
}
|
|
return fmt.Errorf("failed to check allocation rule existence: %w", err)
|
|
}
|
|
|
|
// Update the rule
|
|
if err := r.db.Save(rule).Error; err != nil {
|
|
return fmt.Errorf("failed to update allocation rule: %w", err)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// Delete deletes an allocation rule by its ID
|
|
func (r *AllocationRuleRepository) Delete(userID uint, id uint) error {
|
|
// First check if the rule exists
|
|
var rule models.AllocationRule
|
|
if err := r.db.Where("user_id = ?", userID).First(&rule, id).Error; err != nil {
|
|
if errors.Is(err, gorm.ErrRecordNotFound) {
|
|
return ErrAllocationRuleNotFound
|
|
}
|
|
return fmt.Errorf("failed to check allocation rule existence: %w", err)
|
|
}
|
|
|
|
// Delete all targets first
|
|
if err := r.db.Where("rule_id = ?", id).Delete(&models.AllocationTarget{}).Error; err != nil {
|
|
return fmt.Errorf("failed to delete allocation targets: %w", err)
|
|
}
|
|
|
|
// Delete the rule (soft delete due to gorm.DeletedAt field)
|
|
if err := r.db.Delete(&rule).Error; err != nil {
|
|
return fmt.Errorf("failed to delete allocation rule: %w", err)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// ExistsByID checks if an allocation rule with the given ID exists for a user
|
|
func (r *AllocationRuleRepository) ExistsByID(userID, id uint) (bool, error) {
|
|
var count int64
|
|
if err := r.db.Model(&models.AllocationRule{}).Where("user_id = ? AND id = ?", userID, id).Count(&count).Error; err != nil {
|
|
return false, fmt.Errorf("failed to check allocation rule existence: %w", err)
|
|
}
|
|
return count > 0, nil
|
|
}
|
|
|
|
// CreateTarget creates a new allocation target
|
|
func (r *AllocationRuleRepository) CreateTarget(target *models.AllocationTarget) error {
|
|
if err := r.db.Create(target).Error; err != nil {
|
|
return fmt.Errorf("failed to create allocation target: %w", err)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// UpdateTarget updates an existing allocation target
|
|
func (r *AllocationRuleRepository) UpdateTarget(target *models.AllocationTarget) error {
|
|
if err := r.db.Save(target).Error; err != nil {
|
|
return fmt.Errorf("failed to update allocation target: %w", err)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// DeleteTarget deletes an allocation target by its ID
|
|
func (r *AllocationRuleRepository) DeleteTarget(id uint) error {
|
|
if err := r.db.Delete(&models.AllocationTarget{}, id).Error; err != nil {
|
|
return fmt.Errorf("failed to delete allocation target: %w", err)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// DeleteTargetsByRuleID deletes all targets for a specific rule
|
|
func (r *AllocationRuleRepository) DeleteTargetsByRuleID(ruleID uint) error {
|
|
if err := r.db.Where("rule_id = ?", ruleID).Delete(&models.AllocationTarget{}).Error; err != nil {
|
|
return fmt.Errorf("failed to delete allocation targets: %w", err)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// GetTargetsByRuleID retrieves all targets for a specific rule
|
|
func (r *AllocationRuleRepository) GetTargetsByRuleID(ruleID uint) ([]models.AllocationTarget, error) {
|
|
var targets []models.AllocationTarget
|
|
if err := r.db.Where("rule_id = ?", ruleID).Find(&targets).Error; err != nil {
|
|
return nil, fmt.Errorf("failed to get allocation targets: %w", err)
|
|
}
|
|
return targets, nil
|
|
}
|