Skip to content

Commit

Permalink
Merge pull request #13 from joeyede/addCSVWriter
Browse files Browse the repository at this point in the history
Added option to write to CSV file.
  • Loading branch information
admin-kevin-holditch authored Jul 7, 2020
2 parents d4052a1 + 046a094 commit f8333a3
Show file tree
Hide file tree
Showing 6 changed files with 151 additions and 25 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ Use "pd-report [command] --help" for more information about a command.

Flags:
-h, --help help for report
-o, --output-format string pdf, console (default "console")
-o, --output-format string pdf, console, csv (default "console")
-d --output string filepath output path (default is $HOME)
-s, --schedules strings schedule ids to report (comma-separated with no spaces), or 'all' (default [all])

Expand Down
14 changes: 8 additions & 6 deletions cmd/generate_report.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ var (

func init() {
scheduleReportCmd.Flags().StringSliceVarP(&schedules, "schedules", "s", []string{"all"}, "schedule ids to report (comma-separated with no spaces), or 'all'")
scheduleReportCmd.Flags().StringVarP(&outputFormat, "output-format", "o", "console", "pdf, console")
scheduleReportCmd.Flags().StringVarP(&outputFormat, "output-format", "o", "console", "pdf, console, csv")
scheduleReportCmd.Flags().StringVarP(&directory, "output", "d", "", "output path (default is $HOME)")
rootCmd.AddCommand(scheduleReportCmd)
}
Expand All @@ -49,7 +49,7 @@ func contains(s []string, e string) bool {

func processArguments() InputData {

if !contains([]string{"console", "pdf"}, outputFormat) {
if !contains([]string{"console", "pdf", "csv"}, outputFormat) {
log.Printf("output format %s not supported. Defaulting to 'console'", outputFormat)
outputFormat = "console"
}
Expand Down Expand Up @@ -130,6 +130,8 @@ func generateReport(cmd *cobra.Command, args []string) error {
var reportWriter report.Writer
if outputFormat == "pdf" {
reportWriter = report.NewPDFReport(Config.RotationPrices.Currency, directory)
} else if outputFormat == "csv" {
reportWriter = report.NewCsvReport(Config.RotationPrices.Currency, directory)
} else {
reportWriter = report.NewConsoleReport(Config.RotationPrices.Currency)
}
Expand All @@ -144,15 +146,15 @@ func generateReport(cmd *cobra.Command, args []string) error {
return nil
}

func calculateSummaryData(data []*report.ScheduleData, pricesInfo *PricesInfo) []*report.UserSchedulesSummary {
func calculateSummaryData(data []*report.ScheduleData, pricesInfo *PricesInfo) []*report.ScheduleUser {

usersSummary := make(map[string]*report.UserSchedulesSummary)
usersSummary := make(map[string]*report.ScheduleUser)

for _, schedData := range data {
for _, schedUser := range schedData.RotaUsers {
userSummary, ok := usersSummary[schedUser.Name]
if !ok {
userSummary = &report.UserSchedulesSummary{
userSummary = &report.ScheduleUser{
Name: schedUser.Name,
}
usersSummary[schedUser.Name] = userSummary
Expand All @@ -168,7 +170,7 @@ func calculateSummaryData(data []*report.ScheduleData, pricesInfo *PricesInfo) [
}
}

result := make([]*report.UserSchedulesSummary, 0)
result := make([]*report.ScheduleUser, 0)
for _, userSummary := range usersSummary {
userSummary.NumWorkDays = userSummary.NumWorkHours / float32(pricesInfo.HoursWeekDay)
userSummary.NumWeekendDays = userSummary.NumWeekendHours / float32(pricesInfo.HoursWeekendDay)
Expand Down
2 changes: 1 addition & 1 deletion cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ import (

"log"

"github.com/mitchellh/go-homedir"
"github.com/form3tech-oss/go-pagerduty-oncall-report/api"
"github.com/form3tech-oss/go-pagerduty-oncall-report/configuration"
"github.com/mitchellh/go-homedir"
"github.com/spf13/cobra"
"github.com/spf13/viper"
)
Expand Down
138 changes: 138 additions & 0 deletions report/csv_report.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
package report

import (
"encoding/csv"
"fmt"
"log"
"os"
"sort"
"strings"
"time"
)

type csvReport struct {
currency string
outPath string
}

func NewCsvReport(currency string, outPath string) Writer {
return &csvReport{
currency: strings.TrimSpace(currency),
outPath: outPath,
}
}

func (r *csvReport) GenerateReport(data *PrintableData) (string, error) {

fmt.Println(separator)
fmt.Println(fmt.Sprintf("| Generating report(s) from '%s' to '%s'", data.Start.Format("Mon Jan _2 15:04:05 2006"), data.End.Add(time.Second*-1).Format("Mon Jan _2 15:04:05 2006")))
fmt.Println(separator)

header := []string{"User",
"Weekday Hours", "Weekday Days", "Weekend Hours", "Weekend Days", "Bank Holiday Hours", "Bank Holiday Days",
"Total Weekday Amount (" + r.currency + ")", "Total Weekend Amount (" + r.currency + ")",
"Total Bank Holiday Amount (" + r.currency + ")", "Total Amount (" + r.currency + ")"}

for _, scheduleData := range data.SchedulesData {
err := r.writeSingleRotation(scheduleData, data, header)
if err != nil {
log.Println("Error creating report for rotation: ", scheduleData.Name, " ID: ", scheduleData.ID, err)
return "", err
}
}

filename := fmt.Sprintf("%s/pagerduty_oncall_report.%d-%d-Summary.csv", r.outPath, data.Start.Month(), data.Start.Year())
_ = os.Remove(filename)
file, err := os.Create(filename)
if err != nil {
log.Println("Error creating report file: ", filename, err)
return "", err
}
defer file.Close()
w := csv.NewWriter(file)

if err := w.Write(header); err != nil {
log.Println("error writing record to csv:", err)
return "", err

}

sort.Slice(data.UsersSchedulesSummary, func(i, j int) bool {
return strings.Compare(data.UsersSchedulesSummary[i].Name, data.UsersSchedulesSummary[j].Name) < 1
})

for _, userData := range data.UsersSchedulesSummary {
err := writeUser(userData, w)
if err != nil {
log.Println("error writing user record to csv: ", filename, " user: ", userData.Name, " err: ", err)
return "", err
}
}

w.Flush()
if err := w.Error(); err != nil {
log.Fatal("Error flushing writr", err)
return "", err
}
return fmt.Sprintf("Report successfully generated: file://%s", filename), nil
}

func (r *csvReport) writeSingleRotation(scheduleData *ScheduleData, data *PrintableData, header []string) error {
fmt.Println(separator)
fmt.Println(fmt.Sprintf("| Writing Schedule: '%s' (%s)", scheduleData.Name, scheduleData.ID))
fmt.Println(separator)
noSpaceName := strings.Replace(scheduleData.Name, " ", "_", -1)

filename := fmt.Sprintf("%s/pagerduty_oncall_report.%d-%d-%s-%s.csv", r.outPath, data.Start.Month(), data.Start.Year(), noSpaceName, scheduleData.ID)
_ = os.Remove(filename)
file, err := os.Create(filename)
if err != nil {
log.Println("Error creating report file: ", filename, err)
return err
}
defer file.Close()
w := csv.NewWriter(file)

if err := w.Write(header); err != nil {
log.Println("error writing record to csv: ", filename, " err: ", err)
return err

}
sort.Slice(scheduleData.RotaUsers, func(i, j int) bool {
return strings.Compare(scheduleData.RotaUsers[i].Name, scheduleData.RotaUsers[j].Name) < 1
})

for _, userData := range scheduleData.RotaUsers {
err := writeUser(userData, w)
if err != nil {
log.Println("error writing user record to csv: ", filename, " user: ", userData.Name, " err: ", err)
return err
}
}
w.Flush()
if err := w.Error(); err != nil {
log.Fatal("Error flushing writr", err)
return err
}
log.Println(fmt.Sprintf("Report successfully generated: file://%s", filename))
return nil
}

func writeUser(userData *ScheduleUser, w *csv.Writer) error {
dat := []string{userData.Name,
fmt.Sprintf("%v", userData.NumWorkHours),
fmt.Sprintf("%.1f", userData.NumWorkDays),
fmt.Sprintf("%v", userData.NumWeekendHours),
fmt.Sprintf("%.1f", userData.NumWeekendDays),
fmt.Sprintf("%v", userData.NumBankHolidaysHours),
fmt.Sprintf("%.1f", userData.NumBankHolidaysDays),
fmt.Sprintf("%v", userData.TotalAmountWorkHours),
fmt.Sprintf("%v", userData.TotalAmountWeekendHours),
fmt.Sprintf("%v", userData.TotalAmountBankHolidaysHours),
fmt.Sprintf("%v", userData.TotalAmount)}
if err := w.Write(dat); err != nil {
log.Println("error writing record to csv:", err)
return err
}
return nil
}
4 changes: 2 additions & 2 deletions report/pdf_report.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,13 @@ const (

type pdfReport struct {
currency string
outPath string
outPath string
}

func NewPDFReport(currency string, outPath string) Writer {
return &pdfReport{
currency: currency,
outPath: outPath,
outPath: outPath,
}
}

Expand Down
16 changes: 1 addition & 15 deletions report/writer.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ type PrintableData struct {
Start time.Time
End time.Time
SchedulesData []*ScheduleData
UsersSchedulesSummary []*UserSchedulesSummary
UsersSchedulesSummary []*ScheduleUser
}

type ScheduleData struct {
Expand All @@ -17,20 +17,6 @@ type ScheduleData struct {
RotaUsers []*ScheduleUser
}

type UserSchedulesSummary struct {
Name string
NumWorkHours float32
NumWorkDays float32
TotalAmountWorkHours float32
NumWeekendHours float32
NumWeekendDays float32
TotalAmountWeekendHours float32
NumBankHolidaysHours float32
NumBankHolidaysDays float32
TotalAmountBankHolidaysHours float32
TotalAmount float32
}

type ScheduleUser struct {
Name string
NumWorkHours float32
Expand Down

0 comments on commit f8333a3

Please sign in to comment.