working balance sheet...

This commit is contained in:
Joerg Lehmann 2023-12-28 17:58:17 +01:00
parent d9e2ed5e2f
commit 8580faefab
1 changed files with 91 additions and 35 deletions

View File

@ -7,6 +7,7 @@ import (
"golang.org/x/text/language" "golang.org/x/text/language"
"golang.org/x/text/message" "golang.org/x/text/message"
"log" "log"
"math"
"os" "os"
"regexp" "regexp"
"sort" "sort"
@ -42,24 +43,25 @@ var accounts = make(map[string]string)
var transactions = make(map[uint16]Transaction) var transactions = make(map[uint16]Transaction)
var account_balance = make(map[string]Balance) var account_balance = make(map[string]Balance)
var balanceYear = "UNDEFINED" var balanceYear = "UNDEFINED"
var profit float64 = 0.0
const reportTitle = "Jahresrechnung - nbit Informatik GmbH" const reportTitle = "Jahresrechnung - nbit Informatik GmbH"
const MWST_ACCOUNT = "2201" const MWST_ACCOUNT = "2201"
const defaultFontSize = 9 const defaultFontSize = 12
const smallFontSize = 7 const smallFontSize = 8
const marginTop = 10 const marginTop = 10
const smallLineSpacing = 4 const smallLineSpacing = 5
const lineSpacing = 5 const lineSpacing = 6
const tabstopLeft = 35 const tabstopLeft = 35
const tabstopRight = 160 const tabstopRight = 160
const widthAmount = 28 const widthAmount = 28
const dashCorrectionXleft = 1.2 const dashCorrectionXleft = 1.2
const dashCorrectionXright = -1.3 const dashCorrectionXright = -1.3
const dashCorrectionY = 3 const dashCorrectionY = 3.5
//func round5rappen(f float64) float64 { func roundRappen(f float64) float64 {
// return (math.Round(f*20) / 20) return (math.Round(f*100) / 100)
//} }
func accountExists(s string) bool { func accountExists(s string) bool {
_, ok := accounts[s] _, ok := accounts[s]
@ -86,14 +88,14 @@ func calculateVAT(vat_code string, amount float64) float64 {
vat_type := string(vat_code[0]) vat_type := string(vat_code[0])
vat_perc, err := strconv.Atoi(vat_code[1:]) vat_perc, err := strconv.Atoi(vat_code[1:])
if err != nil { if err != nil {
fmt.Println(err) fmt.Printf("ERROR: %v\n", err)
return 0.0 return 0.0
} }
vat_perc_f64 := float64(vat_perc) vat_perc_f64 := float64(vat_perc)
if vat_type == "V" { 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" { } 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 { } else {
fmt.Printf("WARNING: Invalid Vat Type: %s\n", vat_type) fmt.Printf("WARNING: Invalid Vat Type: %s\n", vat_type)
return 0.0 return 0.0
@ -105,7 +107,7 @@ func addTransaction(document_number string, date string, text string, account_nu
mydate, error := time.Parse(dateString, date) mydate, error := time.Parse(dateString, date)
if error != nil { if error != nil {
fmt.Println(error) fmt.Printf("ERROR: %v\n", error)
return return
} }
@ -130,7 +132,7 @@ func addTransaction(document_number string, date string, text string, account_nu
myItem.Debit = account_number_debit myItem.Debit = account_number_debit
myItem.Credit = account_number_credit myItem.Credit = account_number_credit
if s, err := strconv.ParseFloat(amount, 64); err == nil { if s, err := strconv.ParseFloat(amount, 64); err == nil {
myItem.Amount = s myItem.Amount = roundRappen(s)
} else { } else {
fmt.Printf("WARNING: Document %s, cannot convert Amount to Float64: %s and will be ignored\n", document_number, amount) fmt.Printf("WARNING: Document %s, cannot convert Amount to Float64: %s and will be ignored\n", document_number, amount)
return 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 myBalance.balance_end = myBalance.balance_end - myItem.Amount_Vat
} }
account_balance[account_number_debit] = myBalance 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] myBalance = account_balance[account_number_credit]
account_type2 := accountType(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 myBalance.balance_end = myBalance.balance_end + myItem.Amount_Vat
} }
account_balance[account_number_credit] = myBalance 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 = account_balance[MWST_ACCOUNT]
myBalance.balance_end = myBalance.balance_end + myItem.Amount_Vat 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 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)] _, ok := transactions[uint16(document_number_i)]
if ok { if ok {
newtransactions := transactions[uint16(document_number_i)] newtransactions := transactions[uint16(document_number_i)]
@ -234,15 +222,20 @@ func readAccountData(filename string) {
} }
func floatToString(f float64, sep string) string { func floatToString(f float64, sep string) string {
var s string
p := message.NewPrinter(language.English) p := message.NewPrinter(language.English)
s := strings.ReplaceAll(p.Sprintf("%.2f", f), ",", sep) if roundRappen(f) == 0.00 {
s = "-.-"
} else {
s = strings.ReplaceAll(p.Sprintf("%.2f", f), ",", sep)
//fmt.Printf("--- s: @%s@\n", s) //fmt.Printf("--- s: @%s@\n", s)
}
return s return s
} }
func str2float64(f string) float64 { func str2float64(f string) float64 {
if s, err := strconv.ParseFloat(f, 64); err == nil { if s, err := strconv.ParseFloat(f, 64); err == nil {
return (s) return roundRappen(s)
} else { } else {
fmt.Printf("WARNING: cannot convert Amount to Float64: %s and will be ignored\n", f) fmt.Printf("WARNING: cannot convert Amount to Float64: %s and will be ignored\n", f)
return 0 return 0
@ -311,7 +304,6 @@ func readTransactionData(filename string) {
if err := scanner.Err(); err != nil { if err := scanner.Err(); err != nil {
log.Fatal(err) log.Fatal(err)
} }
//fmt.Printf("DEBUG BLABLA: %v\n", account_balance["3400"])
} }
func writeText(x float64, y float64, w float64, text string, alignStr ...string) { 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) pdf.SetFont("Dejavusans-Bold", "", smallFontSize)
writeText(tabstopLeft, yPos, 0, title) writeText(tabstopLeft, yPos, 0, title)
writeText(tabstopRight, yPos, widthAmount, "31.12."+balanceYear, "TR") 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 yPos = yPos + smallLineSpacing
pdf.SetFont("Dejavusans", "", smallFontSize) pdf.SetFont("Dejavusans", "", smallFontSize)
pdf.SetDashPattern([]float64{0.2, 0.2}, 0) pdf.SetDashPattern([]float64{0.2, 0.2}, 0)
@ -397,10 +391,52 @@ func printSection(section string) {
yPos = yPos + smallLineSpacing 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) pdf.SetFont("Dejavusans-Bold", "", smallFontSize)
writeText(tabstopLeft, yPos, 0, "TOTAL "+title) writeText(tabstopLeft, yPos, 0, "TOTAL "+title)
writeText(tabstopRight, yPos, widthAmount, floatToString(total, "'"), "TR") 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() printPageHeader()
printSection("A") printSection("A")
printSection("L") printSection("L")
printPageHeader()
printSection("E") printSection("E")
printSection("I") printSection("I")
err := pdf.OutputFileAndClose("output.pdf") err := pdf.OutputFileAndClose("output.pdf")
if err == nil { 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 { } 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() { func usage() {
fmt.Printf("usage: bookkeeper <action> <accounts file> <transactions file>\n") fmt.Printf("usage: bookkeeper <action> <accounts file> <transactions file>\n")
fmt.Printf("\n") fmt.Printf("\n")
@ -433,10 +489,10 @@ func main() {
readAccountData(os.Args[2]) readAccountData(os.Args[2])
readTransactionData(os.Args[3]) readTransactionData(os.Args[3])
profit = calculateProfit()
//fmt.Printf("accounts: %#v\n", accounts) //fmt.Printf("accounts: %#v\n", accounts)
//fmt.Printf("transactions: %#v\n", transactions) //fmt.Printf("transactions: %#v\n", transactions)
fmt.Printf("transactions: %#v\n", transactions[18])
//fmt.Printf("account_balance: %#v\n", account_balance) //fmt.Printf("account_balance: %#v\n", account_balance)
switch action := os.Args[1]; action { switch action := os.Args[1]; action {