package finance import ( "database/sql" "fmt" "log" "mercury/src/db" "os" "path" "strconv" "strings" ) var ( ArInputHeaders = []string{"Acct Name", "Current", "30", "60", "90", ">90"} arReportInputLineMappingFunction = func(s *sql.Stmt, item *arReportInputLine) { _, err := s.Exec( item.AccountName, item.Current, item.Thirty, item.Sixty, item.Ninety, item.OverNinety, item.TotalForPeriod, item.ReportNameInfo.DateString, item.ReportNameInfo.Region) if err != nil { log.Printf("%#v\n", s) log.Panic(err) } } ) type ( arReportInputLine struct { AccountName string Current float64 Thirty float64 Sixty float64 Ninety float64 OverNinety float64 TotalForPeriod float64 ReportNameInfo *arReportNameInfo } arReportNameInfo struct { DateString string Region string } ) func (ar arReportInputLine) ToQueryBlock() string { companyName := strings.ReplaceAll(ar.AccountName, "'", "\\'") return fmt.Sprintf("('%s',%.2f,%.2f,%.2f,%.2f,%.2f,%.2f,'%s','%s')", companyName, ar.Current, ar.Thirty, ar.Sixty, ar.Ninety, ar.OverNinety, ar.TotalForPeriod, ar.ReportNameInfo.DateString, ar.ReportNameInfo.Region) } func GenerateArAgingReport(pathlike string) { connector := &db.ConnectorGeneric{} res := make([]*arReportInputLine, 0, 5000) listing, err := os.ReadDir(pathlike) if err != nil { log.Panic(err) } for _, listing := range listing { subPath := path.Join(pathlike, listing.Name()) parts := processArReport(subPath) for _, part := range *parts { res = append(res, part) } } tableWipe := db.NewRunner("create-mercury-arReports-table.sql", db.MercuryDatabaseName) connector.ExecuteSqlScript(tableWipe) log.Println("Updating database") db.BlockUpdate[arReportInputLine](connector, db.MercuryDatabaseName, "update-mercury-arReport.sql", &res) log.Println("Updates finished.") } func processArReport(pathlike string) *[]*arReportInputLine { log.Printf("Processing AR Report for: %s\n", pathlike) res := make([]*arReportInputLine, 0, 500) contents := readCsv(pathlike) for _, row := range *contents { if row[0] == "" || row[0] == "TOTAL" { continue } reportNameInfo := parseReportNameToInfo(pathlike) inputLine := rawRowToArReportInputLine(row, reportNameInfo) res = append(res, inputLine) } return &res } func parseReportNameToInfo(pathlike string) *arReportNameInfo { base := path.Base(pathlike) parts := strings.Split(base, "_") date := reformatSolidDateString(parts[0]) region := parts[2] return &arReportNameInfo{date, region} } func reformatSolidDateString(dateString string) string { year := dateString[:4] month := dateString[4:6] day := dateString[6:8] return fmt.Sprintf("%s-%s-%s", year, month, day) } func rawRowToArReportInputLine(row []string, fileNameInfo *arReportNameInfo) *arReportInputLine { res := arReportInputLine{} res.AccountName = row[0] current, err := strconv.ParseFloat(row[1], 64) if err != nil { log.Panicln(err) } thirty, err := strconv.ParseFloat(row[2], 64) if err != nil { log.Panicln(err) } sixty, err := strconv.ParseFloat(row[3], 64) if err != nil { log.Panicln(err) } ninety, err := strconv.ParseFloat(row[4], 64) if err != nil { log.Panicln(err) } overninety, err := strconv.ParseFloat(row[5], 64) if err != nil { log.Panicln(err) } res.Current = current res.Thirty = thirty res.Sixty = sixty res.Ninety = ninety res.OverNinety = overninety res.TotalForPeriod = current + thirty + sixty + ninety + overninety res.ReportNameInfo = fileNameInfo return &res }