invoice: calculate GTU codes for invoice, implement some tests
Also drive-by fix two proto issues:
- rename gtu_codes to gtu_code (following convention)
- move denormalized Item.due_date field past denormalized comment.
Change-Id: Ibfe0a21aadc0a5d4e2f784b182e530b9603aae62
diff --git a/bgpwtf/invoice/calc.go b/bgpwtf/invoice/calc.go
index 9c411da..72933d3 100644
--- a/bgpwtf/invoice/calc.go
+++ b/bgpwtf/invoice/calc.go
@@ -1,17 +1,23 @@
package main
import (
+ "sort"
"time"
pb "code.hackerspace.pl/hscloud/bgpwtf/invoice/proto"
)
+// calculateInvoiceData applies all business logic to populate an Invoice's
+// denormalized fields from its InvoiceData.
func calculateInvoiceData(p *pb.Invoice) {
+ // Populate default unit.
+ // TODO(q3k): this really should be done on invoice submit instead.
p.Unit = p.Data.Unit
if p.Unit == "" {
p.Unit = "€"
}
+ // Calculate totals.
p.TotalNet = 0
p.Total = 0
for _, i := range p.Data.Item {
@@ -24,6 +30,21 @@
i.Total = rowTotal
}
+ // Calculate due date.
due := int64(time.Hour*24) * p.Data.DaysDue
p.DueDate = time.Unix(0, p.Date).Add(time.Duration(due)).UnixNano()
+
+ // Denormalize Items' GTUCodes into the Invoice's summary GTU codes.
+ codeSet := make(map[pb.GTUCode]bool)
+ for _, item := range p.Data.Item {
+ for _, code := range item.GtuCode {
+ codeSet[code] = true
+ }
+ }
+ var codes []pb.GTUCode
+ for c, _ := range codeSet {
+ codes = append(codes, c)
+ }
+ sort.Slice(codes, func(i, j int) bool { return codes[i] < codes[j] })
+ p.GtuCode = codes
}