-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathofx.go
101 lines (92 loc) · 2.54 KB
/
ofx.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
package money
import (
"fmt"
"os"
"regexp"
"strings"
ofx "github.com/aclindsa/ofxgo"
sqlc "github.com/keeth/money/model/sqlc"
)
var (
descRe1 = regexp.MustCompile(`(\w)\*+(\w)`)
descRe2 = regexp.MustCompile(`(\b\*+|\*+\b)`)
memoRe = regexp.MustCompile(`[,;(].*$`)
)
type ParsedTransaction struct {
Date string
Desc string
Amount float64
ID string
}
func cleanDesc(s string) string {
s = strings.ToLower(s)
s = descRe1.ReplaceAllString(s, `$1-$2`)
s = descRe2.ReplaceAllString(s, "")
s = strings.TrimSpace(s)
return s
}
func cleanMemo(s string) string {
return memoRe.ReplaceAllString(s, "")
}
func ParseOfxTransaction(trans ofx.Transaction) sqlc.Tx {
amount, _ := trans.TrnAmt.Float64()
var desc []string
if trans.Name != "" {
desc = append(desc, trans.Name.String())
} else if trans.Payee != nil {
desc = append(desc, trans.Payee.Name.String())
}
if trans.Memo != "" {
desc = append(desc, cleanMemo(trans.Memo.String()))
}
return sqlc.Tx{
Date: trans.DtPosted.Format("2006-01-02"),
Desc: cleanDesc(strings.Join(desc, " ")),
Amount: amount,
Xid: trans.FiTID.String(),
}
}
type ParsedResponse struct {
Transactions []sqlc.Tx
Kind string
ID string
}
func ParseOfxResponse(file *os.File) (ParsedResponse, error) {
resp, err := ofx.ParseResponse(file)
if err != nil {
return ParsedResponse{}, err
}
parsed := ParsedResponse{}
xidParts := []string{}
if len(resp.Bank) > 0 {
if stmt, ok := resp.Bank[0].(*ofx.StatementResponse); ok {
parsed.Transactions = make([]sqlc.Tx, len(stmt.BankTranList.Transactions))
for i, tx := range stmt.BankTranList.Transactions {
parsed.Transactions[i] = ParseOfxTransaction(tx)
}
if stmt.BankAcctFrom.BankID != "" {
xidParts = append(xidParts, stmt.BankAcctFrom.BankID.String())
}
if stmt.BankAcctFrom.BranchID != "" {
xidParts = append(xidParts, stmt.BankAcctFrom.BranchID.String())
}
if stmt.BankAcctFrom.AcctID != "" {
xidParts = append(xidParts, stmt.BankAcctFrom.AcctID.String())
}
}
parsed.Kind = "bank"
} else if len(resp.CreditCard) > 0 {
if stmt, ok := resp.CreditCard[0].(*ofx.CCStatementResponse); ok {
parsed.Transactions = make([]sqlc.Tx, len(stmt.BankTranList.Transactions))
for i, tx := range stmt.BankTranList.Transactions {
parsed.Transactions[i] = ParseOfxTransaction(tx)
}
xidParts = append(xidParts, stmt.CCAcctFrom.AcctID.String())
}
parsed.Kind = "cc"
} else {
return parsed, fmt.Errorf("no information found in file")
}
parsed.ID = strings.Join(xidParts, " ")
return parsed, nil
}