Skip to content

Commit ed8a240

Browse files
committed
fix: import of YNAB 4 subtransactions that are transfers
1 parent 8b4e19d commit ed8a240

File tree

3 files changed

+36
-16
lines changed

3 files changed

+36
-16
lines changed

.golangci.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,11 @@ issues:
1414
- gocyclo
1515
text: "func `\\(Envelope\\).Balance`"
1616

17+
- path: pkg/importer/parser/ynab4/parse.go
18+
linters:
19+
- gocyclo
20+
text: "func `parseTransactions`"
21+
1722
linters:
1823
enable:
1924
- gocyclo

pkg/importer/parser/ynab4/parse.go

Lines changed: 26 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -240,7 +240,7 @@ func parseTransactions(resources *types.ParsedResources, transactions []Transact
240240

241241
// Add all transactions
242242
for _, transaction := range transactions {
243-
// Don't import deleted transactions or transactions that are 0
243+
// Don't import deleted transactions or transactions that have an amount of 0
244244
//
245245
// Transfers create two corresponding transaction entries in YNAB 4
246246
//
@@ -251,12 +251,15 @@ func parseTransactions(resources *types.ParsedResources, transactions []Transact
251251
continue
252252
}
253253

254-
// For transfers, the payee string has the prefix "Payee/Transfer:"
255-
payeeID := strings.TrimPrefix(transaction.PayeeID, "Payee/Transfer:")
254+
// For transfers, the payee string has the prefix "Payee/Transfer:",
255+
// the actual account is stored in the TargetAccountID
256+
if strings.HasPrefix(transaction.PayeeID, "Payee/Transfer:") {
257+
transaction.PayeeID = transaction.TargetAccountID
258+
}
256259

257260
// If we do not have a Payee for a transaction, we use the special import payee/account
258261
// that will be created only if it is needed
259-
payee := accountIDNames[payeeID]
262+
payee := accountIDNames[transaction.PayeeID]
260263
if payee == "" {
261264
payee = "YNAB 4 Import - No Payee"
262265
addNoPayee = true
@@ -322,27 +325,36 @@ func parseTransactions(resources *types.ParsedResources, transactions []Transact
322325

323326
// Transaction has subtransactions, add them
324327
for _, sub := range transaction.SubTransactions {
328+
subTransaction := newTransaction
329+
325330
if mapping, ok := envelopeIDNames[sub.CategoryID]; ok {
326-
newTransaction.Envelope = mapping.Envelope
327-
newTransaction.Category = mapping.Category
328-
} else {
329-
newTransaction.Envelope = ""
330-
newTransaction.Category = ""
331+
subTransaction.Envelope = mapping.Envelope
332+
subTransaction.Category = mapping.Category
331333
}
332334

333335
if sub.CategoryID == "Category/__DeferredIncome__" {
334-
newTransaction.Model.AvailableFrom = internal_types.MonthOf(date).AddDate(0, 1)
336+
subTransaction.Model.AvailableFrom = internal_types.MonthOf(date).AddDate(0, 1)
335337
} else {
336-
newTransaction.Model.AvailableFrom = internal_types.MonthOf(date)
338+
subTransaction.Model.AvailableFrom = internal_types.MonthOf(date)
337339
}
338340

339341
if sub.Amount.IsPositive() {
340-
newTransaction.Model.Amount = sub.Amount
342+
subTransaction.Model.Amount = sub.Amount
341343
} else {
342-
newTransaction.Model.Amount = sub.Amount.Neg()
344+
subTransaction.Model.Amount = sub.Amount.Neg()
343345
}
344346

345-
resources.Transactions = append(resources.Transactions, newTransaction)
347+
if sub.TargetAccountID != "" {
348+
subTransaction.DestinationAccount = accountIDNames[sub.TargetAccountID]
349+
}
350+
351+
if sub.Memo != "" && subTransaction.Model.Note != "" {
352+
subTransaction.Model.Note = subTransaction.Model.Note + ": " + sub.Memo
353+
} else if sub.Memo != "" {
354+
subTransaction.Model.Note = sub.Memo
355+
}
356+
357+
resources.Transactions = append(resources.Transactions, subTransaction)
346358
}
347359
}
348360

pkg/importer/parser/ynab4/types.go

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,9 +76,12 @@ type Transaction struct {
7676
PayeeID string `json:"payeeId"`
7777
AccountID string `json:"accountId"`
7878
Cleared string `json:"cleared"`
79+
TargetAccountID string `json:"targetAccountId"`
7980
SubTransactions []struct {
80-
CategoryID string `json:"categoryId"`
81-
Amount decimal.Decimal `json:"amount"`
81+
CategoryID string `json:"categoryId"`
82+
Amount decimal.Decimal `json:"amount"`
83+
Memo string `json:"memo"`
84+
TargetAccountID string `json:"targetAccountId"`
8285
} `json:"subTransactions"`
8386
}
8487

0 commit comments

Comments
 (0)