diff --git a/go.mod b/go.mod index 02df840..065c382 100644 --- a/go.mod +++ b/go.mod @@ -1,13 +1,11 @@ module github.com/samuelattwood/cashflow -go 1.19 +go 1.20 require ( - github.com/sirupsen/logrus v1.9.0 + github.com/google/uuid v1.3.0 + github.com/sirupsen/logrus v1.9.3 gopkg.in/yaml.v3 v3.0.1 ) -require ( - github.com/google/uuid v1.3.0 // indirect - golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 // indirect -) +require golang.org/x/sys v0.9.0 // indirect diff --git a/go.sum b/go.sum index fc92ce7..5d8792f 100644 --- a/go.sum +++ b/go.sum @@ -7,11 +7,15 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0= github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= +github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= +github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 h1:0A+M6Uqn+Eje4kHMK80dtF3JCXC4ykBgQG4Fe06QRhQ= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.9.0 h1:KS/R3tvhPqvJvwcKfnBHJwwthS11LRhmM5D59eEXa0s= +golang.org/x/sys v0.9.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/main.go b/main.go index 3e013f5..9773789 100644 --- a/main.go +++ b/main.go @@ -117,15 +117,15 @@ func (tl *TransactionLog) dates() timeSlice { return dateSlice } -func (t TransactionLog) first() time.Time { +func (t *TransactionLog) first() time.Time { return t.dates()[0] } -func (t TransactionLog) last() time.Time { +func (t *TransactionLog) last() time.Time { return t.dates()[t.dates().Len()-1] } -func (logDay LogDay) transactions() transactionList { +func (logDay *LogDay) transactions() transactionList { transactions := transactionList{} for _, t := range logDay.Transactions { @@ -137,28 +137,33 @@ func (logDay LogDay) transactions() transactionList { return transactions } -func nextLogDay(transactionLog *TransactionLog, currentDate time.Time) *LogDay { +func (tl *TransactionLog) nextLogDay(currentDate time.Time) *LogDay { var next time.Time - for i, date := range transactionLog.dates() { + for i, date := range tl.dates() { + j := i + 1 + if j >= len(tl.dates()) { + next = tl.dates()[i] + break + } if date == currentDate { - next = transactionLog.dates()[i+1] + next = tl.dates()[j] break } } - return transactionLog.LogDays[next] + return tl.LogDays[next] } -func previousLogDay(transactionLog *TransactionLog, currentDate time.Time) *LogDay { +func (tl *TransactionLog) previousLogDay(currentDate time.Time) *LogDay { var previous time.Time - for _, date := range transactionLog.dates() { + for _, date := range tl.dates() { if date == currentDate { break } previous = date } - return transactionLog.LogDays[previous] + return tl.LogDays[previous] } func isWeekend(date time.Time) bool { @@ -188,6 +193,8 @@ func parseTransaction(transactionYaml TransactionYaml) (*Transaction, error) { return nil, err } + date = stripTime(date) + if transactionYaml.Shift == "" { transactionYaml.Shift = "late" } @@ -224,6 +231,7 @@ func parseConfig(configYaml ConfigYaml) *Config { logrus.Error(err) } config.Transactions = append(config.Transactions, newTransaction) + logrus.Debugf("Parsed Transaction: %s", transaction.Name) } for _, transaction := range configYaml.Transactions { @@ -232,6 +240,7 @@ func parseConfig(configYaml ConfigYaml) *Config { logrus.Error(err) } config.Transactions = append(config.Transactions, newTransaction) + logrus.Debugf("Parsed Transaction: %s", transaction.Name) } return config @@ -246,7 +255,11 @@ func parseDate(dateString string) (time.Time, error) { } if regMatch { - return time.Parse("2006-1-2", dateString) + parsedDate, err := time.Parse("2006-1-2", dateString) + if err != nil { + return time.Time{}, err + } + return parsedDate, err } if dateString == "first" { @@ -299,7 +312,7 @@ func (tl *TransactionLog) addTransaction(transaction *Transaction) { for _, date := range dateList { tl.addDay(date) - t := Transaction{ + t := &Transaction{ Amount: transaction.Amount, Date: date, Delayable: transaction.Delayable, @@ -310,15 +323,17 @@ func (tl *TransactionLog) addTransaction(transaction *Transaction) { OriginDate: date, Shift: transaction.Shift, } - tl.LogDays[date].Transactions[t.ID] = &t - tl.Transactions[t.ID] = &t + tl.LogDays[date].Transactions[t.ID] = t + tl.Transactions[t.ID] = t + logrus.Debugf("Adding transaction %s (%s | %f) to %s", + t.ID, t.Name, t.Amount, t.Date.String()) } } func (tl *TransactionLog) addDay(date time.Time) { if _, ok := tl.LogDays[date]; !ok { - logrus.Debugf("Adding Log Day %s", date.String()) + logrus.Debugf("Adding Log Day %s", stripTime(date).String()) tl.LogDays[date] = &LogDay{ Date: stripTime(date), Transactions: make(map[string]*Transaction), @@ -349,10 +364,10 @@ func calculateShift(transactionLog TransactionLog, transaction Transaction) time } if transaction.Shift == "early" { - return previousLogDay(&transactionLog, transaction.Date).Date + return transactionLog.previousLogDay(transaction.Date).Date } - return nextLogDay(&transactionLog, transaction.Date).Date + return transactionLog.nextLogDay(transaction.Date).Date } func (tl *TransactionLog) delayTransaction(transaction *Transaction) { @@ -385,8 +400,9 @@ func (tl *TransactionLog) executeTransaction(transaction *Transaction) bool { if isWeekend(transaction.Date) && transaction.Delayable { logrus.Debugf("Delaying %s due to weekend scheduling\n", transaction.Name) tl.delayTransaction(transaction) - - return false + if transaction.Delayable { + return false + } } logrus.Debugf("Balance: %f | Minimum: %f\n", accounts[0].Balance, accounts[0].Minimum) @@ -424,19 +440,23 @@ func isAffordable(charge, balance, minimum float64) bool { } func currentDay() time.Time { - return stripTime(time.Now().Local()) + return stripTime(time.Now()) +} + +func currentTZ() *time.Location { + return time.Now().Local().Location() } func firstOfMonth(t time.Time) time.Time { - return time.Date(t.Year(), t.Month(), 1, 0, 0, 0, 0, t.Location()) + return time.Date(t.Year(), t.Month(), 1, 0, 0, 0, 0, currentTZ()) } func lastOfMonth(t time.Time) time.Time { - return time.Date(t.Year(), t.Month()+1, 0, 0, 0, 0, 0, t.Location()) + return time.Date(t.Year(), t.Month()+1, 0, 0, 0, 0, 0, currentTZ()) } func stripTime(t time.Time) time.Time { - return time.Date(t.Year(), t.Month(), t.Day(), 0, 0, 0, 0, t.Location()) + return time.Date(t.Year(), t.Month(), t.Day(), 0, 0, 0, 0, currentTZ()) } func calculateFrequency(frequency string, startDate time.Time, endDate time.Time, hardDate bool) []time.Time { @@ -461,7 +481,7 @@ func calculateFrequency(frequency string, startDate time.Time, endDate time.Time initDate = initDate.AddDate(0, 1, 0) } } else { - logrus.Error("Invalid Frequency") + logrus.Fatal("Invalid Frequency") } } @@ -637,7 +657,11 @@ func printOutput(logDay LogDay) { fmt.Println(divider) for _, v := range logDay.EndingBalance { - printTransactionLine(v.Balance, v.Name, "", "|", fullWidth) + prefix := "" + if v.Balance < 0 { + prefix = "-" + } + printTransactionLine(v.Balance, v.Name, prefix, "|", fullWidth) } fmt.Printf("%s\n\n", border) }