-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.go
155 lines (125 loc) · 3.64 KB
/
main.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
package main
import (
"embed"
"flag"
"fmt"
"os"
"strconv"
"text/template"
"time"
"gopkg.in/yaml.v3"
)
//go:embed invoice.templ
var templateFS embed.FS
type Document struct {
Config Config
Invoice Invoice
}
type Config struct {
CompanyName string `yaml:"companyName"`
CompanyAddress []string `yaml:"companyAddress"`
BankName string `yaml:"bankName"`
BankAddress []string `yaml:"bankAddress"`
AccountName string `yaml:"accountName"`
IBAN string `yaml:"iban"`
BIC string `yaml:"bic"`
}
type Invoice struct {
Name string `yaml:"name"`
CustomerName string `yaml:"customerName"`
Services []Service `yaml:"services"`
DueDate string `yaml:"dueDate"`
IssueDate string `yaml:"issueDate"`
OnCallNOK int `yaml:"onCallNOK"`
TotalAmount string
}
type Service struct {
Name string `yaml:"name"`
Description string `yaml:"description"`
Quantity int `yaml:"quantity"`
Price float64 `yaml:"price"`
PriceTotal float64
}
func main() {
var configPath, invoicePath string
flag.StringVar(&configPath, "config", "", "path to a config.yaml (required)")
flag.StringVar(&invoicePath, "invoice", "", "path to an invoice.yaml (required)")
flag.Parse()
if configPath == "" || invoicePath == "" {
fmt.Println("required flags missing, see usage with -h")
os.Exit(1)
}
config := Config{}
invoice := Invoice{}
parseYAML(configPath, &config)
parseYAML(invoicePath, &invoice)
template, err := template.New("invoice.templ").ParseFS(templateFS, "invoice.templ")
if err != nil {
fmt.Println("error parsing template:", err.Error())
os.Exit(1)
}
document := Document{
Config: config,
Invoice: invoice,
}
t := time.Now()
date := fmt.Sprintf("%d %s %d", t.Day(), t.Month().String(), t.Year())
if document.Invoice.DueDate == "" {
document.Invoice.DueDate = date
}
if document.Invoice.IssueDate == "" {
document.Invoice.IssueDate = date
}
rates, err := GetDailyRates(30)
if err != nil {
fmt.Fprintf(os.Stderr, "error getting exchange rates: %s", err.Error())
os.Exit(1)
}
rate, err := FindRateOn15th(rates)
if err != nil {
fmt.Fprintf(os.Stderr, "error getting rate on 15th: %s", err.Error())
os.Exit(1)
}
rateFloat, err := strconv.ParseFloat(rate, 64)
if err != nil {
fmt.Fprintf(os.Stderr, "error converting rate to float64: %s", err.Error())
os.Exit(1)
}
onCallEUR := float64(document.Invoice.OnCallNOK) / rateFloat
onCallEURShort := fmt.Sprintf("%.2f", onCallEUR)
onCallEurShortFloat, err := strconv.ParseFloat(onCallEURShort, 64)
if err != nil {
fmt.Fprintf(os.Stderr, "error converting to float64: %s", err.Error())
}
onCallService := Service{
Name: "On call",
Description: fmt.Sprintf("NOK %d converted using NOK/EUR rate %s", document.Invoice.OnCallNOK, rate),
Quantity: 1,
Price: onCallEurShortFloat,
}
document.Invoice.Services = append(document.Invoice.Services, onCallService)
var totalRaw float64
for i, item := range document.Invoice.Services {
item.PriceTotal = item.Price * float64(item.Quantity)
totalRaw += item.PriceTotal
document.Invoice.Services[i].PriceTotal = item.PriceTotal
}
document.Invoice.TotalAmount = fmt.Sprintf("%.2f", totalRaw)
err = template.Execute(os.Stdout, document)
if err != nil {
fmt.Fprintf(os.Stderr, "error executing template: %s", err.Error())
os.Exit(1)
}
}
func parseYAML(path string, out interface{}) {
data, err := os.ReadFile(path)
if err != nil {
fmt.Println("error reading file:", err.Error())
os.Exit(1)
}
yamlerr := yaml.Unmarshal(data, out)
if yamlerr != nil {
fmt.Println("error parsing yaml:", err.Error())
os.Exit(1)
}
}