| 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 { |
| rowTotalNet := uint64(i.UnitPrice * i.Count) |
| rowTotal := uint64(float64(rowTotalNet) * (float64(1) + float64(i.Vat)/100000)) |
| |
| p.TotalNet += rowTotalNet |
| p.Total += rowTotal |
| i.TotalNet = rowTotalNet |
| 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 |
| } |