Skip to content

Commit c4d9db1

Browse files
authored
feat: add rename rule to transaction preview (#737)
This adds the ID of the rename rule that mapped a transaction preview to an account to the transaction preview.
1 parent 743950b commit c4d9db1

File tree

6 files changed

+55
-25
lines changed

6 files changed

+55
-25
lines changed

api/docs.go

Lines changed: 7 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

api/swagger.json

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3634,7 +3634,7 @@
36343634
"type": "object",
36353635
"properties": {
36363636
"destinationAccountName": {
3637-
"description": "Name of the destination account if the ID is not known",
3637+
"description": "Name of the destination account from the CSV file",
36383638
"type": "string",
36393639
"example": "Deutsche Bahn"
36403640
},
@@ -3645,8 +3645,13 @@
36453645
"type": "string"
36463646
}
36473647
},
3648+
"renameRuleId": {
3649+
"description": "ID of the rename rule that was applied to this transaction preview",
3650+
"type": "string",
3651+
"example": "042d101d-f1de-4403-9295-59dc0ea58677"
3652+
},
36483653
"sourceAccountName": {
3649-
"description": "Name of the source account if the ID is not known",
3654+
"description": "Name of the source account from the CSV file",
36503655
"type": "string",
36513656
"example": "Employer"
36523657
},

api/swagger.yaml

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -284,16 +284,20 @@ definitions:
284284
importer.TransactionPreview:
285285
properties:
286286
destinationAccountName:
287-
description: Name of the destination account if the ID is not known
287+
description: Name of the destination account from the CSV file
288288
example: Deutsche Bahn
289289
type: string
290290
duplicateTransactionIds:
291291
description: IDs of transactions that this transaction duplicates
292292
items:
293293
type: string
294294
type: array
295+
renameRuleId:
296+
description: ID of the rename rule that was applied to this transaction preview
297+
example: 042d101d-f1de-4403-9295-59dc0ea58677
298+
type: string
295299
sourceAccountName:
296-
description: Name of the source account if the ID is not known
300+
description: Name of the source account from the CSV file
297301
example: Employer
298302
type: string
299303
transaction:

pkg/controllers/import.go

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,9 @@ func (co Controller) ImportYnabImportPreview(c *gin.Context) {
157157
}
158158

159159
for i, transaction := range transactions {
160-
rename(&transaction, renameRules)
160+
if len(renameRules) > 0 {
161+
rename(&transaction, renameRules)
162+
}
161163

162164
// Only find accounts when they are not yet both set
163165
if transaction.Transaction.SourceAccountID == uuid.Nil || transaction.Transaction.DestinationAccountID == uuid.Nil {
@@ -346,23 +348,23 @@ func findAccounts(co Controller, transaction *importer.TransactionPreview, budge
346348

347349
// rename applies the renaming rules to a transaction.
348350
func rename(transaction *importer.TransactionPreview, rules []models.RenameRule) {
349-
replace := func(name string) uuid.UUID {
351+
replace := func(name string) (uuid.UUID, uuid.UUID) {
350352
// Iterate over all rules
351353
for _, rule := range rules {
352354
// If the rule matches, return the account ID. Since rules are loaded from
353355
// the database in priority order, we can simply return the first match
354356
if glob.Glob(rule.Match, name) {
355-
return rule.AccountID
357+
return rule.AccountID, rule.ID
356358
}
357359
}
358-
return uuid.Nil
360+
return uuid.Nil, uuid.Nil
359361
}
360362

361363
if transaction.SourceAccountName != "" {
362-
transaction.Transaction.SourceAccountID = replace(transaction.SourceAccountName)
364+
transaction.Transaction.SourceAccountID, transaction.RenameRuleID = replace(transaction.SourceAccountName)
363365
}
364366

365367
if transaction.DestinationAccountName != "" {
366-
transaction.Transaction.DestinationAccountID = replace(transaction.DestinationAccountName)
368+
transaction.Transaction.DestinationAccountID, transaction.RenameRuleID = replace(transaction.DestinationAccountName)
367369
}
368370
}

pkg/controllers/import_test.go

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -260,43 +260,47 @@ func (suite *TestSuiteStandard) TestRename() {
260260
internalAccount := suite.createTestAccount(models.AccountCreate{BudgetID: budget.Data.ID, Name: "Envelope Zero Account"})
261261

262262
tests := []struct {
263-
name string // Name of the test
264-
sourceAccountIDs []uuid.UUID // The IDs of the source accounts
265-
destinationAccountIDs []uuid.UUID // The IDs of the destination accounts
266-
preTest func(*testing.T) // Function to execute before running tests
263+
name string // Name of the test
264+
sourceAccountIDs []uuid.UUID // The IDs of the source accounts
265+
destinationAccountIDs []uuid.UUID // The IDs of the destination accounts
266+
preTest func(*testing.T) [3]uuid.UUID // Function to execute before running tests
267267
}{
268268
{
269269
"Rule for Edeka",
270270
[]uuid.UUID{internalAccount.Data.ID, internalAccount.Data.ID, uuid.Nil},
271271
[]uuid.UUID{edeka.Data.ID, uuid.Nil, internalAccount.Data.ID},
272-
func(t *testing.T) {
273-
_ = suite.createTestRenameRule(t, models.RenameRuleCreate{
272+
func(t *testing.T) [3]uuid.UUID {
273+
edeka := suite.createTestRenameRule(t, models.RenameRuleCreate{
274274
Match: "EDEKA*",
275275
AccountID: edeka.Data.ID,
276276
})
277+
278+
return [3]uuid.UUID{edeka.Data.ID}
277279
},
278280
},
279281
{
280282
"Rule for Edeka and DB",
281283
[]uuid.UUID{internalAccount.Data.ID, internalAccount.Data.ID, uuid.Nil},
282284
[]uuid.UUID{edeka.Data.ID, bahn.Data.ID, internalAccount.Data.ID},
283-
func(t *testing.T) {
284-
_ = suite.createTestRenameRule(t, models.RenameRuleCreate{
285+
func(t *testing.T) [3]uuid.UUID {
286+
edeka := suite.createTestRenameRule(t, models.RenameRuleCreate{
285287
Match: "EDEKA*",
286288
AccountID: edeka.Data.ID,
287289
})
288290

289-
_ = suite.createTestRenameRule(t, models.RenameRuleCreate{
291+
db := suite.createTestRenameRule(t, models.RenameRuleCreate{
290292
Match: "DB Vertrieb GmbH",
291293
AccountID: bahn.Data.ID,
292294
})
295+
296+
return [3]uuid.UUID{edeka.Data.ID, db.Data.ID}
293297
},
294298
},
295299
}
296300

297301
for _, tt := range tests {
298302
suite.T().Run(tt.name, func(t *testing.T) {
299-
tt.preTest(t)
303+
renameRuleIDs := tt.preTest(t)
300304
preview := parseCSV(suite, internalAccount.Data.ID, "rename-rule-test.csv")
301305

302306
for i, transaction := range preview.Data {
@@ -308,6 +312,15 @@ func (suite *TestSuiteStandard) TestRename() {
308312
if tt.destinationAccountIDs[i] != uuid.Nil {
309313
assert.Equal(t, tt.destinationAccountIDs[i], transaction.Transaction.DestinationAccountID, "destinationAccountID does not match in line %d", line)
310314
}
315+
316+
assert.Equal(t, renameRuleIDs[i], transaction.RenameRuleID, "Expected rename rule has match '%s', actual rename rule has match '%s'", renameRuleIDs[i])
317+
}
318+
319+
// Delete rename rules
320+
for _, id := range renameRuleIDs {
321+
if id != uuid.Nil {
322+
suite.controller.DB.Delete(&models.RenameRule{}, id)
323+
}
311324
}
312325
})
313326
}

pkg/importer/types.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,8 @@ type Transaction struct {
4949
// TransactionPreview is used to preview transactions that will be imported to allow for editing.
5050
type TransactionPreview struct {
5151
Transaction models.TransactionCreate `json:"transaction"`
52-
SourceAccountName string `json:"sourceAccountName" example:"Employer"` // Name of the source account if the ID is not known
53-
DestinationAccountName string `json:"destinationAccountName" example:"Deutsche Bahn"` // Name of the destination account if the ID is not known
54-
DuplicateTransactionIDs []uuid.UUID `json:"duplicateTransactionIds"` // IDs of transactions that this transaction duplicates
52+
SourceAccountName string `json:"sourceAccountName" example:"Employer"` // Name of the source account from the CSV file
53+
DestinationAccountName string `json:"destinationAccountName" example:"Deutsche Bahn"` // Name of the destination account from the CSV file
54+
DuplicateTransactionIDs []uuid.UUID `json:"duplicateTransactionIds"` // IDs of transactions that this transaction duplicates
55+
RenameRuleID uuid.UUID `json:"renameRuleId" example:"042d101d-f1de-4403-9295-59dc0ea58677"` // ID of the rename rule that was applied to this transaction preview
5556
}

0 commit comments

Comments
 (0)