-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathspending_plan.go
169 lines (158 loc) · 4.46 KB
/
spending_plan.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
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
package api
import (
"database/sql"
"time"
"github.com/pkg/errors"
"github.com/lieut-data/go-moneywell/api/money"
)
// SpendingPlan represents spending plan events associated with a bucket in a MoneyWell document.
// This is a subset of the ZACTIVITY table, where both transactions, favourite transactions and
// spending plan amounts are recorded. Not all spending plan columns are exported.
//
// The MoneyWell SQLite schema for the ZACTIVITY table is as follows:
// > .schema ZACTIVITY
// CREATE TABLE ZACTIVITY (
// Z_PK INTEGER PRIMARY KEY,
// Z_ENT INTEGER,
// Z_OPT INTEGER,
// ZDATEYMD INTEGER,
// ZISBUCKETOPTIONAL INTEGER,
// ZISFLAGGED INTEGER,
// ZISLOCKED INTEGER,
// ZSEQUENCE INTEGER,
// ZSOURCE INTEGER,
// ZTYPE INTEGER,
// ZSPLITPARENT INTEGER,
// Z3_SPLITPARENT INTEGER,
// ZTRANSFERACCOUNT INTEGER,
// ZTRANSFERSIBLING INTEGER,
// Z3_TRANSFERSIBLING INTEGER,
// ZARETAGSSAVED INTEGER,
// ZISAMOUNTSAVED INTEGER,
// ZISBUCKETSAVEDINTEGER,
// ZISMEMOSAVED INTEGER,
// ZISTYPESAVED INTEGER,
// ZACCOUNT INTEGER,
// ZBUCKET INTEGER,
// ZGENERATECOUNT INTEGER,
// ZHASVARIABLEAMOUNT INTEGER,
// ZACCOUNT1 INTEGER,
// ZBUCKET1 INTEGER,
// ZRECURRENCERULE INTEGER,
// ZISPERCENTAGE INTEGER,
// ZFILLRECURRENCERULE INTEGER,
// ZSPENDINGPLAN INTEGER,
// ZDATERECONCILEDYMD INTEGER,
// ZISLASTIMPORT INTEGER,
// ZISQUARANTINED INTEGER,
// ZISREPEATING INTEGER,
// ZSPLITINDEX INTEGER,
// ZSTATUS INTEGER,
// ZACCOUNT2 INTEGER,
// ZBUCKET2 INTEGER,
// ZINVESTMENTSECURITYID INTEGER,
// ZDATELASTUSED TIMESTAMP,
// ZLASTGENERATEDDATE TIMESTAMP,
// ZAMOUNT DECIMAL,
// ZCHECKREF DECIMAL,
// ZLOCALIZEDAMOUNT DECIMAL,
// ZSALEAMOUNT DECIMAL,
// ZCOMMISSION DECIMAL,
// ZFEES DECIMAL,
// ZLOCALIZEDAMOUNT1 DECIMAL,
// ZSALEAMOUNT1 DECIMAL,
// ZSHAREPRICE DECIMAL,
// ZSHARES DECIMAL,
// ZSHARESSPLITDENOMINATOR DECIMAL,
// ZSHARESSPLITNUMERATOR DECIMAL,
// ZSPLITTOTAL DECIMAL,
// ZTAXES DECIMAL,
// ZAMOUNTSTRING VARCHAR,
// ZCHECKREFSTRING VARCHAR,
// ZMEMO VARCHAR,
// ZPAYEE VARCHAR,
// ZTICDSSYNCID VARCHAR,
// ZUNIQUEID VARCHAR,
// ZSALECURRENCYCODE VARCHAR,
// ZEXTERNALID VARCHAR,
// ZLOCALIZEDAMOUNTSTRING VARCHAR,
// ZORIGINALMEMO VARCHAR,
// ZORIGINALPAYEE VARCHAR,
// ZRECEIPTFILENAME VARCHAR,
// ZSALEAMOUNTSTRING VARCHAR,
// ZSALECURRENCYCODE1 VARCHAR
// );
type SpendingPlan struct {
PrimaryKey int64
Date time.Time
Name string
Amount money.Money
Bucket int64
RecurrenceRule int64
FillRecurrenceRule int64
}
// GetSpendingPlan fetches the set of spending plan events in a MoneyWell document.
func GetSpendingPlan(database *sql.DB) ([]SpendingPlan, error) {
rows, err := database.Query(`
SELECT
za.Z_PK,
za.ZDATEYMD,
za.ZPAYEE,
CAST(ROUND(za.ZAMOUNT * 100) AS INTEGER),
COALESCE(za.ZBUCKET, za.ZBUCKET1, za.ZBUCKET2),
zb.ZCURRENCYCODE,
za.ZRECURRENCERULE,
za.ZFILLRECURRENCERULE
FROM
ZACTIVITY za
JOIN
ZBUCKET zb ON (zb.Z_PK = COALESCE(za.ZBUCKET, za.ZBUCKET1, za.ZBUCKET2))
WHERE
za.Z_ENT = ?
ORDER BY
za.Z_PK ASC
`, ActivityTypeSpendingPlan)
if err != nil {
return nil, errors.Wrap(err, "failed to query spending plan")
}
defer rows.Close()
spendingPlan := []SpendingPlan{}
var primaryKey, amountRaw int64
var dateymd int
var name string
var bucket sql.NullInt64
var currencyCode sql.NullString
var recurrenceRule, fillRecurrenceRule sql.NullInt64
for rows.Next() {
err := rows.Scan(
&primaryKey,
&dateymd,
&name,
&amountRaw,
&bucket,
¤cyCode,
&recurrenceRule,
&fillRecurrenceRule,
)
if err != nil {
return nil, errors.Wrap(err, "failed to scan spending plan")
}
date, err := parseDateymd(dateymd)
if err != nil {
return nil, errors.Wrap(err, "failed to parse spending plan date")
}
spendingPlan = append(spendingPlan, SpendingPlan{
PrimaryKey: primaryKey,
Date: date,
Name: name,
Amount: money.Money{
Currency: currencyCode.String,
Amount: amountRaw,
},
Bucket: bucket.Int64,
RecurrenceRule: recurrenceRule.Int64,
FillRecurrenceRule: fillRecurrenceRule.Int64,
})
}
return spendingPlan, nil
}