Initial commit.

master
dtookey 4 years ago
commit 418fc5f7f2

@ -0,0 +1,11 @@
#! /bin/bash
cd /opt/go/src/mercury || exit
rm build/*
go build -o ./build/mercury ./src
mercury_path="/home/dtookey/work/clarity-reporting/qb/" ./build/mercury

@ -0,0 +1,3 @@
module mercury
go 1.18

@ -0,0 +1,17 @@
package main
import (
"log"
"mercury/src/mercury"
"os"
)
func main() {
reportBase := os.Getenv("mercury_path")
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")
}

@ -0,0 +1,133 @@
package mercury
import (
"encoding/csv"
"fmt"
"log"
"os"
"strings"
)
const (
BillingCode = iota
Date
InvoiceNumber
AccountName
BillingClass
Amount
)
type BillingLine struct {
BillingCode string
Date string
InvoiceNumber string
AccountName string
Class string
Amount string
}
func ProcessCSVsFromPath(pathlikeIn string, pathlikeOut string) {
paths := enumFiles(pathlikeIn)
writer := createCsvWriter(pathlikeOut)
headers := []string{"Billing Code", "Date", "Invoice Number", "Account Name", "Class", "Amount"}
err := writer.Write(headers)
if err != nil {
log.Fatal(err)
}
for _, pptr := range *paths {
lines := processFile(pptr)
for _, line := range *lines {
writer.Write(line.toRow())
}
}
writer.Flush()
}
func createCsvWriter(pathlike string) *csv.Writer {
_, err := os.Stat(pathlike)
var file *os.File
if os.IsNotExist(err) {
file, err = os.Create(pathlike)
if err != nil {
panic(err)
}
} else {
file, err = os.OpenFile(pathlike, os.O_RDWR, 0777)
if err != nil {
log.Fatal(err)
}
}
writer := csv.NewWriter(file)
return writer
}
func processFile(pathlike *string) *[]*BillingLine {
ret := make([]*BillingLine, 0, 500000)
content, err := os.OpenFile(*pathlike, os.O_RDONLY, 0755)
if err != nil {
log.Panic(err)
}
csvReader := csv.NewReader(content)
records, err := csvReader.ReadAll()
if err != nil {
log.Panic(err)
}
currentBillingCode := ""
for idx, recordRow := range records {
serviceName := recordRow[BillingCode]
if idx < 2 || strings.ToLower(serviceName) == "total" {
continue //every ignorable row basically starts with "TOTAL"
} else if len(serviceName) > 0 {
currentBillingCode = serviceName
continue
}
txnDate := recordRow[Date]
acctNum := recordRow[InvoiceNumber]
acctName := recordRow[AccountName]
billClass := recordRow[BillingClass]
total := recordRow[Amount]
lineItem := BillingLine{
BillingCode: currentBillingCode,
Date: convertDateToSqlDate(txnDate),
InvoiceNumber: acctNum,
AccountName: acctName,
Class: billClass,
Amount: total,
}
if err != nil {
log.Printf("%#v\n", recordRow)
log.Fatal(err)
}
ret = append(ret, &lineItem)
}
return &ret
}
func convertDateToSqlDate(datelike string) string {
parts := strings.Split(datelike, "/")
return fmt.Sprintf("%s-%s-%s", parts[2], parts[1], parts[0])
}
func enumFiles(pathlikebase string) *[]*string {
files, err := os.ReadDir(pathlikebase)
ret := make([]*string, 0, 100)
if err != nil {
panic(err)
}
for _, file := range files {
subPath := fmt.Sprintf("%s%s", pathlikebase, file.Name())
ret = append(ret, &subPath)
}
return &ret
}
func (b *BillingLine) toRow() []string {
return []string{b.BillingCode, b.Date, b.InvoiceNumber, b.AccountName, b.Class, b.Amount}
}
Loading…
Cancel
Save