Skip to content

Commit

Permalink
fix: match rules are now called match rules and follow API v2 specifi…
Browse files Browse the repository at this point in the history
…cation (#787)

This deprecates the `/v2/rename-rules` endpoint and introduces
`/v2/match-rules` with the correct API semantics.
  • Loading branch information
morremeyer authored Oct 8, 2023
1 parent e823490 commit 68ebbb9
Show file tree
Hide file tree
Showing 17 changed files with 1,436 additions and 299 deletions.
458 changes: 378 additions & 80 deletions api/docs.go

Large diffs are not rendered by default.

458 changes: 378 additions & 80 deletions api/swagger.json

Large diffs are not rendered by default.

338 changes: 273 additions & 65 deletions api/swagger.yaml

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions pkg/controllers/budget.go
Original file line number Diff line number Diff line change
Expand Up @@ -470,7 +470,7 @@ func (co Controller) DeleteBudget(c *gin.Context) {
// @Param month path string true "The month in YYYY-MM format"
// @Param budgetId path string true "Budget ID formatted as string"
// @Router /v1/budgets/{budgetId}/{month}/allocations [delete]
// @Deprecated true.
// @Deprecated true
func (co Controller) DeleteAllocationsMonth(c *gin.Context) {
id, err := uuid.Parse(c.Param("budgetId"))
if err != nil {
Expand Down Expand Up @@ -524,7 +524,7 @@ func (co Controller) DeleteAllocationsMonth(c *gin.Context) {
// @Param budgetId path string true "Budget ID formatted as string"
// @Param mode body BudgetAllocationMode true "Budget"
// @Router /v1/budgets/{budgetId}/{month}/allocations [post]
// @Deprecated true.
// @Deprecated true
func (co Controller) SetAllocationsMonth(c *gin.Context) {
id, err := uuid.Parse(c.Param("budgetId"))
if err != nil {
Expand Down
28 changes: 18 additions & 10 deletions pkg/controllers/import.go
Original file line number Diff line number Diff line change
Expand Up @@ -144,21 +144,21 @@ func (co Controller) ImportYnabImportPreview(c *gin.Context) {
return
}

// Get all rename rules for the budget that the import target account is part of
var renameRules []models.RenameRule
// Get all match rules for the budget that the import target account is part of
var matchRules []models.MatchRule
err = co.DB.
Joins("JOIN accounts ON accounts.budget_id = ?", account.BudgetID).
Joins("JOIN rename_rules rr ON rr.account_id = accounts.id").
Joins("JOIN match_rules rr ON rr.account_id = accounts.id").
Order("rr.priority asc").
Find(&renameRules).Error
Find(&matchRules).Error
if err != nil {
httperrors.Handler(c, err)
return
}

for i, transaction := range transactions {
if len(renameRules) > 0 {
rename(&transaction, renameRules)
if len(matchRules) > 0 {
match(&transaction, matchRules)
}

// Only find accounts when they are not yet both set
Expand Down Expand Up @@ -349,8 +349,8 @@ func findAccounts(co Controller, transaction *importer.TransactionPreview, budge
return nil
}

// rename applies the renaming rules to a transaction.
func rename(transaction *importer.TransactionPreview, rules []models.RenameRule) {
// match applies the match rules to a transaction.
func match(transaction *importer.TransactionPreview, rules []models.MatchRule) {
replace := func(name string) (uuid.UUID, uuid.UUID) {
// Iterate over all rules
for _, rule := range rules {
Expand All @@ -364,11 +364,19 @@ func rename(transaction *importer.TransactionPreview, rules []models.RenameRule)
}

if transaction.SourceAccountName != "" {
transaction.Transaction.SourceAccountID, transaction.RenameRuleID = replace(transaction.SourceAccountName)
transaction.Transaction.SourceAccountID, transaction.MatchRuleID = replace(transaction.SourceAccountName)

// This is kept for backwards compatibility and will be removed with API version 3
// https://github.com/envelope-zero/backend/issues/763
transaction.RenameRuleID = transaction.MatchRuleID
}

if transaction.DestinationAccountName != "" {
transaction.Transaction.DestinationAccountID, transaction.RenameRuleID = replace(transaction.DestinationAccountName)
transaction.Transaction.DestinationAccountID, transaction.MatchRuleID = replace(transaction.DestinationAccountName)

// This is kept for backwards compatibility and will be removed with API version 3
// https://github.com/envelope-zero/backend/issues/763
transaction.RenameRuleID = transaction.MatchRuleID
}
}

Expand Down
28 changes: 16 additions & 12 deletions pkg/controllers/import_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,7 @@ func (suite *TestSuiteStandard) TestYnabImportFindAccounts() {
}
}

func (suite *TestSuiteStandard) TestRename() {
func (suite *TestSuiteStandard) TestMatch() {
// Create a budget and two existing accounts to use
budget := suite.createTestBudget(models.BudgetCreate{})
edeka := suite.createTestAccount(models.AccountCreate{BudgetID: budget.Data.ID, Name: "Edeka", External: true})
Expand All @@ -277,12 +277,12 @@ func (suite *TestSuiteStandard) TestRename() {
[]uuid.UUID{edeka.Data.ID, uuid.Nil, internalAccount.Data.ID},
[]*uuid.UUID{&envelopeID, nil, nil},
func(t *testing.T) [3]uuid.UUID {
edeka := suite.createTestRenameRule(t, models.RenameRuleCreate{
edeka := suite.createTestMatchRule(t, models.MatchRuleCreate{
Match: "EDEKA*",
AccountID: edeka.Data.ID,
})

return [3]uuid.UUID{edeka.Data.ID}
return [3]uuid.UUID{edeka.ID}
},
},
{
Expand All @@ -291,25 +291,25 @@ func (suite *TestSuiteStandard) TestRename() {
[]uuid.UUID{edeka.Data.ID, bahn.Data.ID, internalAccount.Data.ID},
[]*uuid.UUID{&envelopeID, nil, nil},
func(t *testing.T) [3]uuid.UUID {
edeka := suite.createTestRenameRule(t, models.RenameRuleCreate{
edeka := suite.createTestMatchRule(t, models.MatchRuleCreate{
Match: "EDEKA*",
AccountID: edeka.Data.ID,
})

db := suite.createTestRenameRule(t, models.RenameRuleCreate{
db := suite.createTestMatchRule(t, models.MatchRuleCreate{
Match: "DB Vertrieb GmbH",
AccountID: bahn.Data.ID,
})

return [3]uuid.UUID{edeka.Data.ID, db.Data.ID}
return [3]uuid.UUID{edeka.ID, db.ID}
},
},
}

for _, tt := range tests {
suite.T().Run(tt.name, func(t *testing.T) {
renameRuleIDs := tt.preTest(t)
preview := parseCSV(suite, internalAccount.Data.ID, "rename-rule-test.csv")
matchRuleIDs := tt.preTest(t)
preview := parseCSV(suite, internalAccount.Data.ID, "match-rule-test.csv")

for i, transaction := range preview.Data {
line := i + 1
Expand All @@ -321,15 +321,19 @@ func (suite *TestSuiteStandard) TestRename() {
assert.Equal(t, tt.destinationAccountIDs[i], transaction.Transaction.DestinationAccountID, "destinationAccountID does not match in line %d", line)
}

assert.Equal(t, renameRuleIDs[i], transaction.RenameRuleID, "Expected rename rule has match '%s', actual rename rule has match '%s'", renameRuleIDs[i])
assert.Equal(t, matchRuleIDs[i], transaction.MatchRuleID, "Expected match rule has match '%s', actual match rule has match '%s'", matchRuleIDs[i], transaction.MatchRuleID)

// This is kept for backwards compatibility and will be removed with API version 3
// https://github.com/envelope-zero/backend/issues/763
assert.Equal(t, matchRuleIDs[i], transaction.RenameRuleID, "Expected rename rule has match '%s', actual rename rule has match '%s'", matchRuleIDs[i], transaction.MatchRuleID)

assert.Equal(t, tt.envelopeIDs[i], transaction.Transaction.EnvelopeID, "proposed envelope ID does not match in line %d", line)
}

// Delete rename rules
for _, id := range renameRuleIDs {
// Delete match rules
for _, id := range matchRuleIDs {
if id != uuid.Nil {
suite.controller.DB.Delete(&models.RenameRule{}, id)
suite.controller.DB.Delete(&models.MatchRule{}, id)
}
}
})
Expand Down
Loading

0 comments on commit 68ebbb9

Please sign in to comment.