initial go code to examine gnucash data
[outofuni/gocash.git] / gocash.go
1 package main
2
3 import (
4         "encoding/xml"
5         "fmt"
6         "io/ioutil"
7         "os"
8 )
9
10 type Account struct {
11         XMLName xml.Name `xml:"account"`
12         Name string `xml:"name"`
13         AccountId string `xml:"id"`
14         ParentId string `xml:"parent"`
15 }
16
17 type Split struct {
18         XMLName xml.Name `xml:"split"`
19         Id string `xml:"id"`
20         Value string `xml:"value"`
21         Quantity string `xml:"quantity"`
22         AccountId string `xml:"account"`
23 }
24
25 type Transaction struct {
26         XMLName xml.Name `xml:"transaction"`
27         Id string `xml:"id"`
28         Date string `xml:"date-posted>date"`
29         Description string `xml:"description"`
30         Spl []Split `xml:"splits>split"`
31 }
32
33 type ParsedData struct {
34         XMLName xml.Name `xml:"gnc-v2"`
35         DataCnt []string `xml:"count-data"`
36         Accnt []Account `xml:"book>account"`
37         Trn []Transaction `xml:"book>transaction"`
38 }
39
40 // 'global' data
41 var data ParsedData
42
43 func main() {
44
45         // open xml file
46         file, err := os.Open("c13_skr03.gnucash")
47         if err != nil {
48                 fmt.Println("Error opening file:", err)
49                 return
50         }
51         defer file.Close()
52
53         // read xml file
54         xmldata, err := ioutil.ReadAll(file)
55         if err != nil {
56                 fmt.Println("Error reading file:", err)
57                 return
58         }
59
60         // unmarshal xml data
61         err = xml.Unmarshal(xmldata,&data)
62         if err != nil {
63                 fmt.Println("Error unmarshaling xml data:", err)
64                 return
65         }
66
67         // whooha, this is our data!
68         fmt.Println("Parsed accounts:",len(data.Accnt))
69         fmt.Println("Parsed transactions:",len(data.Trn))
70
71         //
72         // hardcoded account ids we have to look at
73         //
74         // wareneingang 19% and 7%
75         pid_buy_n := string("8e3b7c42e3173ed85f3d4736e82afb4d")
76         pid_buy_s := string("0cfd2ceb45fff89b9d1b7ce3af66cdf3")
77         // abziehbare vst 19% and 7%
78         aid_vst_n := string("7c449e13125d6b93043f963628106db2")
79         aid_vst_s := string("006643c1c0a91f2b40614c75a49c6295")
80
81         // account maps
82         type amap struct {
83                 pid string
84                 num int
85                 taxval int
86                 buy bool
87                 tax bool
88         }
89         accnt := make(map[string]amap)
90
91         for ac := range data.Accnt {
92                 aid := data.Accnt[ac].AccountId
93                 pid := data.Accnt[ac].ParentId
94                 // general map
95                 accnt[aid]=amap{
96                         pid,ac,0,false,false,
97                 }
98                 tmp := accnt[aid]
99                 switch {
100                 case pid == pid_buy_n:
101                         tmp.taxval=19
102                         tmp.buy=true
103                         accnt[aid]=tmp
104                         //accnt[aid].taxval=19
105                         //accnt[aid].buy=true
106                 case pid == pid_buy_s:
107                         //accnt[aid].tax=7
108                         //accnt[aid].buy=true
109                 case aid == aid_vst_n:
110                         //accnt[aid].taxval=19
111                         //accnt[aid].buy=true
112                         //accnt[aid].tax=true
113                 case aid == aid_vst_s:
114                         //accnt[aid].tax=7
115                         //accnt[aid].buy=true
116                         //accnt[aid].tax=true
117                 // there will be more assignments later on!
118                 }
119         }
120
121         // check transactions
122         for tc := range data.Trn {
123                 for tsc := range data.Trn[tc].Spl {
124                         aid := data.Trn[tc].Spl[tsc].AccountId
125                         switch {
126                         case accnt[aid].buy:
127                                 var ret bool
128                                 switch accnt[aid].taxval {
129                                 case 19:
130                                         ret=check_buy(&data.Trn[tc],aid_vst_n)
131                                 case 7:
132                                         ret=check_buy(&data.Trn[tc],aid_vst_s)
133                                 }
134                                 anum := accnt[aid].num
135                                 if ret == false {
136                                         fmt.Println("Problem:", data.Accnt[anum].Name)
137                                 }
138                         }
139                 }
140         }
141
142 }
143
144 func check_buy(ta *Transaction,id string) bool {
145         for  sc := range ta.Spl {
146                 if ta.Spl[sc].AccountId == id {
147                         return true
148                 }
149         }
150         return false
151 }
152