From 188d4a0d9a975deaa0993be492b8baf1a42f5f95 Mon Sep 17 00:00:00 2001 From: Martin Hansen Date: Fri, 22 Dec 2023 19:02:04 +0100 Subject: [PATCH 1/3] feat(ynab)!: remove deprecated config options Remove deprecated config options and import ID v1 to simplify the code. BREAKING CHANGE: Removes YNABBER_PAYEE_STRIP and NORDIGEN_ACCOUNTMAP config options, please use NORDIGEN_PAYEE_STRIP and/or YNAB_ACCOUNTMAP instead. BREAKING CHANGE: Removes the option to chose between import ID generator versions. Please switch to v2 before upgrading to this version. --- .gitignore | 5 +---- README.md | 1 - cmd/ynabber/main.go | 20 ------------------ config.go | 27 ++---------------------- writer/ynab/ynab.go | 44 +++++++++------------------------------- writer/ynab/ynab_test.go | 25 +++-------------------- 6 files changed, 16 insertions(+), 106 deletions(-) diff --git a/.gitignore b/.gitignore index f1a09d3..047ea49 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,4 @@ .vscode *.csv *.env - -# Ignore config files -nordigen*.json -ynabber*.json +*.json diff --git a/README.md b/README.md index 1059b9d..89db369 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,6 @@ cat <> ynabber.env YNAB_BUDGETID= YNAB_TOKEN= YNAB_ACCOUNTMAP={"": ""} -YNAB_IMPORT_ID_V2=2023-01-01 # Not required but will give better results # Nordigen NORDIGEN_BANKID= diff --git a/cmd/ynabber/main.go b/cmd/ynabber/main.go index 37173bf..ae2c76a 100644 --- a/cmd/ynabber/main.go +++ b/cmd/ynabber/main.go @@ -30,26 +30,6 @@ func main() { log.Fatal("YNAB_CLEARED must be one of cleared, uncleared or reconciled") } - // Handle movement of config options and warn users if better options are - // available. - if cfg.Nordigen.PayeeStrip == nil { - if cfg.PayeeStrip != nil { - log.Printf("Config YNABBER_PAYEE_STRIP is going to be depreciated, please use NORDIGEN_PAYEE_STRIP instead") - cfg.Nordigen.PayeeStrip = cfg.PayeeStrip - } - } - if cfg.YNAB.AccountMap == nil { - if cfg.Nordigen.AccountMap != nil { - log.Printf("Config NORDIGEN_ACCOUNTMAP is going to be depreciated, please use YNAB_ACCOUNTMAP instead") - cfg.YNAB.AccountMap = cfg.Nordigen.AccountMap - } - } - // Defacto means that ImportID v2 is not used - if cfg.YNAB.ImportID.V2 == ynabber.Date(time.Date(9999, time.January, 1, 00, 00, 00, 00, time.UTC)) { - log.Printf("Consider using v2 import IDs for YNAB. See description " + - "for config option YNAB_IMPORT_ID_V2 for more information") - } - if cfg.Debug { log.Printf("Config: %+v\n", cfg) } diff --git a/config.go b/config.go index 163d7e4..e13dc58 100644 --- a/config.go +++ b/config.go @@ -32,7 +32,7 @@ func (accountMap *AccountMap) Decode(value string) error { // Config is loaded from the environment during execution with cmd/ynabber type Config struct { - // DataDir is the path for storing files e.g. Nordigen authorization + // DataDir is the path for storing files DataDir string `envconfig:"YNABBER_DATADIR" default:"."` // Debug prints more log statements @@ -45,13 +45,9 @@ type Config struct { // Nordigen is supported. Readers []string `envconfig:"YNABBER_READERS" default:"nordigen"` - // Writers is a list of destinations to write transactions from. Currently - // only YNAB is supported. + // Writers is a list of destinations to write transactions to. Writers []string `envconfig:"YNABBER_WRITERS" default:"ynab"` - // PayeeStrip is depreciated please use Nordigen.PayeeStrip instead - PayeeStrip []string `envconfig:"YNABBER_PAYEE_STRIP"` - // Reader and/or writer specific settings Nordigen Nordigen YNAB YNAB @@ -59,9 +55,6 @@ type Config struct { // Nordigen related settings type Nordigen struct { - // AccountMap is depreciated please use YNAB.AccountMap instead - AccountMap AccountMap `envconfig:"NORDIGEN_ACCOUNTMAP"` - // BankID is used to create requisition BankID string `envconfig:"NORDIGEN_BANKID"` @@ -128,20 +121,4 @@ type YNAB struct { // // Example: "DK9520000123456789,NO8330001234567" SwapFlow []string `envconfig:"YNAB_SWAPFLOW"` - - ImportID ImportID -} - -// ImportID can be either v1 or v2. All new users should use v2 because it -// have a lower potability of making duplicate transactions. But v1 remains -// the default to retain backwards compatibility. -// -// To migrate from v1 to v2 simply set the v2 to any date and all transactions -// from and including that date will be using v2 of the import ID generator. -type ImportID struct { - // V1 will be used from this date - V1 Date `envconfig:"YNAB_IMPORT_ID_V1" default:"1970-01-01"` - - // V2 will be used from this date, for example: 2022-12-24 - V2 Date `envconfig:"YNAB_IMPORT_ID_V2" default:"9999-01-01"` } diff --git a/writer/ynab/ynab.go b/writer/ynab/ynab.go index 3145909..2adaf8e 100644 --- a/writer/ynab/ynab.go +++ b/writer/ynab/ynab.go @@ -52,43 +52,19 @@ func accountParser(iban string, accountMap map[string]string) (string, error) { return "", fmt.Errorf("no account for: %s in map: %s", iban, accountMap) } -// importIDMaker tries to return a unique YNAB import ID to avoid duplicate -// transactions. -func importIDMaker(cfg ynabber.Config, t ynabber.Transaction) string { - // Common between versions +// makeID returns a unique YNAB import ID to avoid duplicate transactions. +func makeID(cfg ynabber.Config, t ynabber.Transaction) string { date := t.Date.Format("2006-01-02") amount := t.Amount.String() - // Version 1 uses the memo, amount and date from Ytransaction - v1Cutover := time.Time(cfg.YNAB.ImportID.V1) - v1 := func(t ynabber.Transaction) string { - hash := sha256.Sum256([]byte(t.Memo)) - return fmt.Sprintf("YBBR:%s:%s:%x", amount, date, hash[:2]) - } - - // Version 2 uses, in order, the account IBAN, transaction ID, date, and - // amount to build a hash of the transaction. - v2Cutover := time.Time(cfg.YNAB.ImportID.V2) - v2 := func(t ynabber.Transaction) string { - s := [][]byte{ - []byte(t.Account.IBAN), - []byte(t.ID), - []byte(date), - []byte(amount), - } - hash := sha256.Sum256(bytes.Join(s, []byte(""))) - return fmt.Sprintf("YBBR:%x", hash)[:32] - } - - // Return the first generator from latest to oldest that have a cutover date - // after or equal to the transaction date. - if t.Date.After(v2Cutover) || t.Date.Equal(v2Cutover) { - return v2(t) - } else if t.Date.After(v1Cutover) || t.Date.Equal(v1Cutover) { - return v1(t) - } else { - return v1(t) + s := [][]byte{ + []byte(t.Account.IBAN), + []byte(t.ID), + []byte(date), + []byte(amount), } + hash := sha256.Sum256(bytes.Join(s, []byte(""))) + return fmt.Sprintf("YBBR:%x", hash)[:32] } func ynabberToYNAB(cfg ynabber.Config, t ynabber.Transaction) (Ytransaction, error) { @@ -126,7 +102,7 @@ func ynabberToYNAB(cfg ynabber.Config, t ynabber.Transaction) (Ytransaction, err } return Ytransaction{ - ImportID: importIDMaker(cfg, t), + ImportID: makeID(cfg, t), AccountID: accountID, Date: date, Amount: t.Amount.String(), diff --git a/writer/ynab/ynab_test.go b/writer/ynab/ynab_test.go index 335f9ff..88c7b80 100644 --- a/writer/ynab/ynab_test.go +++ b/writer/ynab/ynab_test.go @@ -9,7 +9,7 @@ import ( "github.com/martinohansen/ynabber" ) -func TestImportIDMaker(t *testing.T) { +func TestMakeID(t *testing.T) { // The import IDs cant be more then 32 chars var maxLength = 32 @@ -29,29 +29,10 @@ func TestImportIDMaker(t *testing.T) { args args want string }{ - { - name: "v1", - args: args{ - defaultConfig, - ynabber.Transaction{ - Amount: ynabber.Milliunits(-100000), - Date: time.Date(2000, 01, 01, 0, 0, 0, 0, time.UTC), - Memo: "foo", - }, - }, - want: "YBBR:-100000:2000-01-01:2c26", - }, - { name: "v2", args: args{ - ynabber.Config{ - YNAB: ynabber.YNAB{ - ImportID: ynabber.ImportID{ - V2: ynabber.Date(time.Date(2022, 12, 24, 0, 0, 0, 0, time.UTC)), - }, - }, - }, + ynabber.Config{}, ynabber.Transaction{Date: time.Date(2022, 12, 24, 0, 0, 0, 0, time.UTC)}, }, want: "YBBR:5ca3430298b7fb93d2f4fe1e302", @@ -59,7 +40,7 @@ func TestImportIDMaker(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - got := importIDMaker(tt.args.cfg, tt.args.t) + got := makeID(tt.args.cfg, tt.args.t) // Test max length of all test cases if len(got) > maxLength { t.Errorf("importIDMaker() = %v chars long, max length is %v", len(got), maxLength) From 5de358a5eee856abec9d138377e51ac484426f53 Mon Sep 17 00:00:00 2001 From: Martin Hansen Date: Fri, 22 Dec 2023 19:08:24 +0100 Subject: [PATCH 2/3] test: fix typo in test --- reader/nordigen/auth_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reader/nordigen/auth_test.go b/reader/nordigen/auth_test.go index 518cec9..ac3f064 100644 --- a/reader/nordigen/auth_test.go +++ b/reader/nordigen/auth_test.go @@ -15,7 +15,7 @@ func TestStore(t *testing.T) { DataDir: ".", }, } - want := "foo" + want := "foo.json" got := r.requisitionStore() if want != got { t.Fatalf("default: %s != %s", want, got) From 1e41e4ee798be3928801c2bf96c60f6b4b5ddca3 Mon Sep 17 00:00:00 2001 From: Martin Hansen Date: Fri, 22 Dec 2023 19:09:07 +0100 Subject: [PATCH 3/3] ci: run build/test just once --- .github/workflows/go.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml index 52f288a..acb7d00 100644 --- a/.github/workflows/go.yml +++ b/.github/workflows/go.yml @@ -1,6 +1,6 @@ name: Go -on: [push, pull_request] +on: push jobs: