initial processing for Trial Balances.

master
dtookey 4 years ago
parent 8e105637e3
commit 7a3f678aa9

@ -6,6 +6,6 @@ rm build/*
go build -o ./build/mercury ./src
mercury_path="/home/dtookey/work/clarity-reporting/qb/" ./build/mercury
mercury_qb_path="/home/dtookey/work/clarity-reporting/qb/" ./build/mercury

@ -6,11 +6,17 @@ import (
"mercury/src/insight"
"mercury/src/mercury"
"os"
"time"
)
func main() {
s := time.Now()
processQbBilling()
f := time.Now()
log.Println(f.Sub(s).Microseconds())
//fetchInsightData()
test()
//test()
}
func test() {
@ -29,12 +35,13 @@ func test() {
}
func processQbBilling() {
reportBase := os.Getenv("mercury_path")
reportBase := os.Getenv("mercury_qb_path")
log.Printf("Searching for documents in %s\n", reportBase)
if len(reportBase) == 0 {
log.Fatalln("please set the mercury_path env var. we don't know where to look otherwise")
}
mercury.ProcessCSVsFromPath(reportBase, "/home/dtookey/work/clarity-reporting/qb_all_bc.csv")
mercury.ProcessTrialBalances(reportBase, "./test.csv")
}
func fetchInsightData() {

@ -5,6 +5,8 @@ import (
"fmt"
"log"
"os"
"path"
"strconv"
"strings"
)
@ -17,13 +19,166 @@ const (
Amount
)
type BillingLine struct {
BillingCode string
Date string
InvoiceNumber string
AccountName string
Class string
Amount string
const (
DotRune = 65533
expenseAccountCutoff = 50000
)
var (
TrialBalanceHeaders = []string{"Account Name", "Amount", "Period", "Account Type"}
)
type (
BillingLine struct {
BillingCode string
Date string
InvoiceNumber string
AccountName string
Class string
Amount string
}
TrialBalanceLine struct {
Amount float64
AccountName string
Period string
AccountType string
}
)
func ProcessTrialBalances(pathlikeIn string, pathlikeOut string) {
paths := enumFiles(pathlikeIn)
table := make([]*[]*TrialBalanceLine, 0, 100)
for _, p := range *paths {
table = append(table, processTrialBalance(p))
}
writeTable(&table, pathlikeOut)
}
func writeTable(table *[]*[]*TrialBalanceLine, pathlikeOut string) {
writer := createCsvWriter(pathlikeOut)
writer.Write(TrialBalanceHeaders)
for _, sheet := range *table {
for _, line := range *sheet {
writer.Write(line.toRow())
}
}
writer.Flush()
}
func formatDate(period string) string {
month := period[0:2]
date := period[2:4]
year := period[4:6]
return fmt.Sprintf("20%s-%s-%s", year, month, date)
}
func processTrialBalance(pathlike *string) *[]*TrialBalanceLine {
ret := make([]*TrialBalanceLine, 0, 50)
file, err := os.OpenFile(*pathlike, os.O_RDONLY, 0755)
if err != nil {
log.Fatalln(err)
}
defer file.Close()
reader := csv.NewReader(file)
table, err := reader.ReadAll()
if err != nil {
log.Fatalln(err)
}
period := getDateFromFileName(pathlike)
buff := make([]rune, 500)
for _, row := range table {
ret = append(ret, rowBufferToBalanceLine(&row, &buff, period))
}
return &ret
}
func getDateFromFileName(pathlike *string) string {
fileName := path.Base(*pathlike)
date := strings.Split(fileName, " ")[0]
return date
}
func getAccountTypeFromName(accountName string) string {
parts := strings.Split(accountName, " ")
number, err := strconv.Atoi(parts[0])
if err != nil {
log.Fatalln(err)
}
if number < expenseAccountCutoff {
return "income"
} else {
return "expense"
}
}
func rowBufferToBalanceLine(row *[]string, buffer *[]rune, date string) *TrialBalanceLine {
if strings.Index((*row)[0], ":") > -1 {
return revenueRowBufferToBalanceLine(row, buffer, date)
} else {
return expenseRowBufferToBalanceLine(row, buffer, date)
}
}
func revenueRowBufferToBalanceLine(row *[]string, buffer *[]rune, date string) *TrialBalanceLine {
balance := TrialBalanceLine{}
target := strings.Split((*row)[0], ":")[1]
dotIdx := strings.IndexRune(target, DotRune)
buff := *buffer
if dotIdx > -1 {
src := []rune(target)
copy(buff[:dotIdx-1], src[:dotIdx-1])
copy(buff[dotIdx-1:len(src)-2], src[dotIdx+1:])
target = string(buff[:len(src)-2])
}
amount, err := strconv.ParseFloat((*row)[2], 64)
if err != nil {
log.Println("Error in revenueRowBufferToBalanceLine")
log.Println(err)
amount = 0.0
}
balance.AccountName = target
balance.Amount = amount
balance.Period = formatDate(date)
balance.AccountType = getAccountTypeFromName(target)
return &balance
}
func expenseRowBufferToBalanceLine(row *[]string, buffer *[]rune, date string) *TrialBalanceLine {
balance := TrialBalanceLine{}
target := (*row)[0]
dotIdx := strings.IndexRune(target, DotRune)
buff := *buffer
if dotIdx > -1 {
src := []rune(target)
copy(buff[:dotIdx-1], src[:dotIdx-1])
copy(buff[dotIdx-1:len(src)-2], src[dotIdx+1:])
target = string(buff[:len(src)-2])
}
//carve-out for the revenue parent account
amountIdx := 1
if target == "40000 Revenue" {
amountIdx = 2
}
amount, err := strconv.ParseFloat((*row)[amountIdx], 64)
if err != nil {
log.Println("Error in expenseRowBufferToBalanceLine")
log.Println(err)
amount = 0.0
}
balance.AccountName = target
balance.Amount = amount
balance.Period = formatDate(date)
balance.AccountType = getAccountTypeFromName(target)
return &balance
}
func ProcessCSVsFromPath(pathlikeIn string, pathlikeOut string) {
@ -53,7 +208,8 @@ func createCsvWriter(pathlike string) *csv.Writer {
log.Fatal(err)
}
} else {
file, err = os.OpenFile(pathlike, os.O_RDWR, 0777)
os.Remove(pathlike)
file, err = os.Create(pathlike)
if err != nil {
log.Fatal(err)
}
@ -127,3 +283,7 @@ func enumFiles(pathlikebase string) *[]*string {
func (b *BillingLine) toRow() []string {
return []string{b.BillingCode, b.Date, b.InvoiceNumber, b.AccountName, b.Class, b.Amount}
}
func (t *TrialBalanceLine) toRow() []string {
return []string{t.AccountName, strconv.FormatFloat(t.Amount, 'f', 2, 64), t.Period, t.AccountType}
}

Loading…
Cancel
Save