From 8580faefabeaf7c8136b3e50873ae9b5c8c2c71b Mon Sep 17 00:00:00 2001 From: Joerg Lehmann Date: Thu, 28 Dec 2023 17:58:17 +0100 Subject: [PATCH] working balance sheet... --- bookkeeper.go | 126 ++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 91 insertions(+), 35 deletions(-) diff --git a/bookkeeper.go b/bookkeeper.go index a74e130..2a37b09 100644 --- a/bookkeeper.go +++ b/bookkeeper.go @@ -7,6 +7,7 @@ import ( "golang.org/x/text/language" "golang.org/x/text/message" "log" + "math" "os" "regexp" "sort" @@ -42,24 +43,25 @@ var accounts = make(map[string]string) var transactions = make(map[uint16]Transaction) var account_balance = make(map[string]Balance) var balanceYear = "UNDEFINED" +var profit float64 = 0.0 const reportTitle = "Jahresrechnung - nbit Informatik GmbH" const MWST_ACCOUNT = "2201" -const defaultFontSize = 9 -const smallFontSize = 7 +const defaultFontSize = 12 +const smallFontSize = 8 const marginTop = 10 -const smallLineSpacing = 4 -const lineSpacing = 5 +const smallLineSpacing = 5 +const lineSpacing = 6 const tabstopLeft = 35 const tabstopRight = 160 const widthAmount = 28 const dashCorrectionXleft = 1.2 const dashCorrectionXright = -1.3 -const dashCorrectionY = 3 +const dashCorrectionY = 3.5 -//func round5rappen(f float64) float64 { -// return (math.Round(f*20) / 20) -//} +func roundRappen(f float64) float64 { + return (math.Round(f*100) / 100) +} func accountExists(s string) bool { _, ok := accounts[s] @@ -86,14 +88,14 @@ func calculateVAT(vat_code string, amount float64) float64 { vat_type := string(vat_code[0]) vat_perc, err := strconv.Atoi(vat_code[1:]) if err != nil { - fmt.Println(err) + fmt.Printf("ERROR: %v\n", err) return 0.0 } vat_perc_f64 := float64(vat_perc) if vat_type == "V" { - return 0 - (amount / (1000.0 + vat_perc_f64) * vat_perc_f64) + return roundRappen(0 - (amount / (1000.0 + vat_perc_f64) * vat_perc_f64)) } else if vat_type == "I" { - return (amount / (1000.0 + vat_perc_f64) * vat_perc_f64) + return roundRappen(amount / (1000.0 + vat_perc_f64) * vat_perc_f64) } else { fmt.Printf("WARNING: Invalid Vat Type: %s\n", vat_type) return 0.0 @@ -105,7 +107,7 @@ func addTransaction(document_number string, date string, text string, account_nu mydate, error := time.Parse(dateString, date) if error != nil { - fmt.Println(error) + fmt.Printf("ERROR: %v\n", error) return } @@ -130,7 +132,7 @@ func addTransaction(document_number string, date string, text string, account_nu myItem.Debit = account_number_debit myItem.Credit = account_number_credit if s, err := strconv.ParseFloat(amount, 64); err == nil { - myItem.Amount = s + myItem.Amount = roundRappen(s) } else { fmt.Printf("WARNING: Document %s, cannot convert Amount to Float64: %s and will be ignored\n", document_number, amount) return @@ -152,9 +154,6 @@ func addTransaction(document_number string, date string, text string, account_nu myBalance.balance_end = myBalance.balance_end - myItem.Amount_Vat } account_balance[account_number_debit] = myBalance - if account_number_debit == "3400" { - fmt.Printf("DEBUG DEBIT: %s,%s,%v,%v\n", account_number_debit, account_type, myItem.Amount, myBalance) - } myBalance = account_balance[account_number_credit] account_type2 := accountType(account_number_credit) @@ -167,22 +166,11 @@ func addTransaction(document_number string, date string, text string, account_nu myBalance.balance_end = myBalance.balance_end + myItem.Amount_Vat } account_balance[account_number_credit] = myBalance - if account_number_credit == "3400" { - fmt.Printf("DEBUG CREDIT: %s,%s,%v,%v\n", account_number_credit, account_type2, myItem.Amount, myBalance) - } myBalance = account_balance[MWST_ACCOUNT] myBalance.balance_end = myBalance.balance_end + myItem.Amount_Vat - fmt.Printf("DEBUG MWST: %s: %v,%v\n", document_number, myItem.Amount_Vat, myBalance) account_balance[MWST_ACCOUNT] = myBalance - if account_number_debit == "3400" { - fmt.Printf("DEBUG DEBIT: Document %s, found 3400 transaction: %v\n", document_number, amount) - } - if account_number_credit == "3400" { - fmt.Printf("DEBUG CREDIT: Document %s, found 3400 transaction: %v\n", document_number, account_balance["3400"]) - } - _, ok := transactions[uint16(document_number_i)] if ok { newtransactions := transactions[uint16(document_number_i)] @@ -234,15 +222,20 @@ func readAccountData(filename string) { } func floatToString(f float64, sep string) string { + var s string p := message.NewPrinter(language.English) - s := strings.ReplaceAll(p.Sprintf("%.2f", f), ",", sep) - //fmt.Printf("--- s: @%s@\n", s) + if roundRappen(f) == 0.00 { + s = "-.-" + } else { + s = strings.ReplaceAll(p.Sprintf("%.2f", f), ",", sep) + //fmt.Printf("--- s: @%s@\n", s) + } return s } func str2float64(f string) float64 { if s, err := strconv.ParseFloat(f, 64); err == nil { - return (s) + return roundRappen(s) } else { fmt.Printf("WARNING: cannot convert Amount to Float64: %s and will be ignored\n", f) return 0 @@ -311,7 +304,6 @@ func readTransactionData(filename string) { if err := scanner.Err(); err != nil { log.Fatal(err) } - //fmt.Printf("DEBUG BLABLA: %v\n", account_balance["3400"]) } func writeText(x float64, y float64, w float64, text string, alignStr ...string) { @@ -371,6 +363,8 @@ func printSection(section string) { pdf.SetFont("Dejavusans-Bold", "", smallFontSize) writeText(tabstopLeft, yPos, 0, title) writeText(tabstopRight, yPos, widthAmount, "31.12."+balanceYear, "TR") + pdf.SetDashPattern([]float64{}, 0) + pdf.Line(tabstopLeft+dashCorrectionXleft, yPos+dashCorrectionY, tabstopRight+widthAmount+dashCorrectionXright, yPos+dashCorrectionY) yPos = yPos + smallLineSpacing pdf.SetFont("Dejavusans", "", smallFontSize) pdf.SetDashPattern([]float64{0.2, 0.2}, 0) @@ -397,10 +391,52 @@ func printSection(section string) { yPos = yPos + smallLineSpacing } } + + switch section { + case "A": + if profit < 0 { + writeText(tabstopLeft, yPos, 0, "Verlust") + writeText(tabstopRight, yPos, widthAmount, floatToString(0-profit, "'"), "TR") + pdf.Line(tabstopLeft+dashCorrectionXleft, yPos+dashCorrectionY, tabstopRight+widthAmount+dashCorrectionXright, yPos+dashCorrectionY) + total = total - profit + yPos = yPos + smallLineSpacing + } + case "L": + if profit >= 0 { + writeText(tabstopLeft, yPos, 0, "Gewinn") + writeText(tabstopRight, yPos, widthAmount, floatToString(profit, "'"), "TR") + pdf.Line(tabstopLeft+dashCorrectionXleft, yPos+dashCorrectionY, tabstopRight+widthAmount+dashCorrectionXright, yPos+dashCorrectionY) + total = total + profit + yPos = yPos + smallLineSpacing + } + } pdf.SetFont("Dejavusans-Bold", "", smallFontSize) writeText(tabstopLeft, yPos, 0, "TOTAL "+title) writeText(tabstopRight, yPos, widthAmount, floatToString(total, "'"), "TR") - yPos = yPos + smallLineSpacing + smallLineSpacing + pdf.SetDashPattern([]float64{}, 0) + pdf.Line(tabstopLeft+dashCorrectionXleft, yPos+dashCorrectionY, tabstopRight+widthAmount+dashCorrectionXright, yPos+dashCorrectionY) + yPos = yPos + smallLineSpacing + pdf.SetDashPattern([]float64{0.2, 0.2}, 0) + pdf.SetFont("Dejavusans", "", smallFontSize) + switch section { + case "E": + if profit < 0 { + writeText(tabstopLeft, yPos, 0, "Verlust") + writeText(tabstopRight, yPos, widthAmount, floatToString(0-profit, "'"), "TR") + pdf.Line(tabstopLeft+dashCorrectionXleft, yPos+dashCorrectionY, tabstopRight+widthAmount+dashCorrectionXright, yPos+dashCorrectionY) + total = total - profit + yPos = yPos + smallLineSpacing + } + case "I": + if profit >= 0 { + writeText(tabstopLeft, yPos, 0, "Gewinn") + writeText(tabstopRight, yPos, widthAmount, floatToString(profit, "'"), "TR") + pdf.Line(tabstopLeft+dashCorrectionXleft, yPos+dashCorrectionY, tabstopRight+widthAmount+dashCorrectionXright, yPos+dashCorrectionY) + total = total + profit + yPos = yPos + smallLineSpacing + } + } + yPos = yPos + smallLineSpacing } @@ -409,16 +445,36 @@ func createBalanceSheet() { printPageHeader() printSection("A") printSection("L") + printPageHeader() printSection("E") printSection("I") err := pdf.OutputFileAndClose("output.pdf") if err == nil { - fmt.Printf("Successfully created Balance Sheet in file output.pdf\n") + fmt.Printf("INFO: Successfully created Balance Sheet in file output.pdf\n") } else { - fmt.Printf("Error: %v\n", err) + fmt.Printf("ERROR: %v\n", err) } } +func calculateProfit() float64 { + var res float64 = 0.0 + + for key := range account_balance { + if accountType(key) == "I" { + res = res + account_balance[key].balance_end + } + if accountType(key) == "E" { + res = res - account_balance[key].balance_end + } + + } + + res = roundRappen(res) + fmt.Printf("INFO: Calculated Profit: %v\n", res) + return res + +} + func usage() { fmt.Printf("usage: bookkeeper \n") fmt.Printf("\n") @@ -433,10 +489,10 @@ func main() { readAccountData(os.Args[2]) readTransactionData(os.Args[3]) + profit = calculateProfit() //fmt.Printf("accounts: %#v\n", accounts) //fmt.Printf("transactions: %#v\n", transactions) - fmt.Printf("transactions: %#v\n", transactions[18]) //fmt.Printf("account_balance: %#v\n", account_balance) switch action := os.Args[1]; action {