Skip to content

Commit

Permalink
Allow hourly calculation and added user summary at the end of the report
Browse files Browse the repository at this point in the history
  • Loading branch information
rogersole authored Aug 1, 2018
1 parent 2091756 commit d7f945a
Show file tree
Hide file tree
Showing 4 changed files with 167 additions and 50 deletions.
105 changes: 78 additions & 27 deletions cmd/generate_report.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ func processArguments() InputData {
lastMonth := now.AddDate(0, -1, 0)
startDate := time.Date(lastMonth.Year(), lastMonth.Month(), 1, 0, 0, 0, 0, time.UTC)
endDate := startDate.AddDate(0, 1, 0)
log.Printf("startDate: %s, endDate: %s", startDate, endDate)

if len(schedules) == 1 && schedules[0] == "all" {
schedules = []string{}
Expand Down Expand Up @@ -88,6 +89,14 @@ func generateReport(cmd *cobra.Command, args []string) error {
SchedulesData: make([]*report.ScheduleData, 0),
}

weekDayHourlyPrice, weekendDayHourlyPrice, bhDayHourlyPrice, err := getPrices()
if err != nil {
return err
}

log.Println(fmt.Sprintf("Hourly prices - Week day: %f, Weekend day: %f, Bank holiday: %f",
weekDayHourlyPrice, weekendDayHourlyPrice, bhDayHourlyPrice))

for _, scheduleID := range input.schedules {
log.Printf("Loading information for the schedule '%s'", scheduleID)
scheduleInfo, err := getScheduleInformation(scheduleID, input.startDate, input.endDate)
Expand All @@ -100,14 +109,18 @@ func generateReport(cmd *cobra.Command, args []string) error {
return err
}

scheduleData, err := generateScheduleData(scheduleInfo, usersRotationData)
scheduleData, err := generateScheduleData(scheduleInfo, usersRotationData,
weekDayHourlyPrice, weekendDayHourlyPrice, bhDayHourlyPrice)
if err != nil {
return err
}

printableData.SchedulesData = append(printableData.SchedulesData, scheduleData)
}

summaryPrintableData := calculateSummaryData(printableData.SchedulesData)
printableData.UsersSchedulesSummary = summaryPrintableData

var reportWriter report.Writer
if outputFormat == "pdf" {
reportWriter = report.NewPDFReport(Config.Currency)
Expand All @@ -125,6 +138,38 @@ func generateReport(cmd *cobra.Command, args []string) error {
return nil
}

func calculateSummaryData(data []*report.ScheduleData) []*report.UserSchedulesSummary {

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

for _, schedData := range data {
for _, schedUser := range schedData.RotaUsers {
userSummary, ok := usersSummary[schedUser.Name]
if !ok {
userSummary = &report.UserSchedulesSummary{
Name: schedUser.Name,
}
usersSummary[schedUser.Name] = userSummary
}

userSummary.NumWorkHours += schedUser.NumWorkHours
userSummary.NumWeekendHours += schedUser.NumWeekendHours
userSummary.NumBankHolidaysHours += schedUser.NumBankHolidaysHours
userSummary.TotalAmountWorkHours += schedUser.TotalAmountWorkHours
userSummary.TotalAmountWeekendHours += schedUser.TotalAmountWeekendHours
userSummary.TotalAmountBankHolidaysHours += schedUser.TotalAmountBankHolidaysHours
userSummary.TotalAmount += schedUser.TotalAmount
}
}

result := make([]*report.UserSchedulesSummary, 0)
for _, userSummary := range usersSummary {
result = append(result, userSummary)
}

return result
}

func getScheduleInformation(scheduleID string, startDate, endDate time.Time) (*api.ScheduleInfo, error) {
schedule, err := api.Client.GetSchedule(scheduleID,
startDate.Format("2006-01-02T15:04:05"),
Expand Down Expand Up @@ -157,7 +202,6 @@ func getUsersRotationData(scheduleInfo *api.ScheduleInfo) (api.ScheduleUserRotat
if err != nil {
return nil, err
}
//fmt.Println(fmt.Sprintf("[%s] %-25s %v - %v", entry.User.ID, entry.User.Summary, startDate, endDate))

userRotaInfo, ok := usersInfo[entry.User.ID]
if !ok {
Expand All @@ -179,25 +223,15 @@ func getUsersRotationData(scheduleInfo *api.ScheduleInfo) (api.ScheduleUserRotat
return usersInfo, nil
}

func generateScheduleData(scheduleInfo *api.ScheduleInfo, usersRotationData api.ScheduleUserRotationData) (*report.ScheduleData, error) {
weekDayPrice, err := Config.FindPriceByDay("weekday")
if err != nil {
return nil, err
}
weekendDayPrice, err := Config.FindPriceByDay("weekend")
if err != nil {
return nil, err
}
bhDayPrice, err := Config.FindPriceByDay("bankholiday")
if err != nil {
return nil, err
}
func generateScheduleData(scheduleInfo *api.ScheduleInfo, usersRotationData api.ScheduleUserRotationData,
weekDayHourlyPrice, weekendDayHourlyPrice, bhDayHourlyPrice float32) (*report.ScheduleData, error) {

scheduleData := &report.ScheduleData{
ID: scheduleInfo.ID,
Name: scheduleInfo.Name,
RotaUsers: make([]*report.ScheduleUser, 0),
}

for userID, userRotaInfo := range usersRotationData {
rotationUserConfig, err := Config.FindRotationUserInfoByID(userID)
if err != nil {
Expand All @@ -215,29 +249,46 @@ func generateScheduleData(scheduleInfo *api.ScheduleInfo, usersRotationData api.
}

for _, period := range userRotaInfo.Periods {
//fmt.Println(fmt.Sprintf("User rota info [%s] - start: %s, end: %s", userID, period.Start, period.End))
currentDate := period.Start
for currentDate.Before(period.End) {
//log.Println(userRotaInfo.Name, "current date:", currentDate, "- bank holiday: ", userCalendar.IsDateBankHoliday(currentDate), "- weekend: ", userCalendar.IsWeekend(currentDate))
if userCalendar.IsDateBankHoliday(currentDate) {
scheduleUserData.NumBankHolidaysDays++
scheduleUserData.NumBankHolidaysHours += 0.5
} else if userCalendar.IsWeekend(currentDate) {
scheduleUserData.NumWeekendDays++
scheduleUserData.NumWeekendHours += 0.5
} else {
scheduleUserData.NumWorkDays++
scheduleUserData.NumWorkHours += 0.5
}
currentDate = currentDate.Add(time.Hour * 24)

currentDate = currentDate.Add(time.Minute * 30)
}
}

scheduleUserData.TotalAmountWorkDays = scheduleUserData.NumWorkDays * *weekDayPrice
scheduleUserData.TotalAmountWeekendDays = scheduleUserData.NumWeekendDays * *weekendDayPrice
scheduleUserData.TotalAmountBankHolidaysDays = scheduleUserData.NumBankHolidaysDays * *bhDayPrice
scheduleUserData.TotalAmount = scheduleUserData.TotalAmountWorkDays +
scheduleUserData.TotalAmountWeekendDays +
scheduleUserData.TotalAmountBankHolidaysDays
scheduleUserData.TotalAmountWorkHours = scheduleUserData.NumWorkHours * weekDayHourlyPrice
scheduleUserData.TotalAmountWeekendHours = scheduleUserData.NumWeekendHours * weekendDayHourlyPrice
scheduleUserData.TotalAmountBankHolidaysHours = scheduleUserData.NumBankHolidaysHours * bhDayHourlyPrice
scheduleUserData.TotalAmount = scheduleUserData.TotalAmountWorkHours +
scheduleUserData.TotalAmountWeekendHours +
scheduleUserData.TotalAmountBankHolidaysHours
scheduleData.RotaUsers = append(scheduleData.RotaUsers, scheduleUserData)
}

return scheduleData, nil
}

func getPrices() (float32, float32, float32, error) {

weekDayPrice, err := Config.FindPriceByDay("weekday")
if err != nil {
return 0, 0, 0, err
}
weekendDayPrice, err := Config.FindPriceByDay("weekend")
if err != nil {
return 0, 0, 0, err
}
bhDayPrice, err := Config.FindPriceByDay("bankholiday")
if err != nil {
return 0, 0, 0, err
}

return float32(*weekDayPrice) / 24, float32(*weekendDayPrice) / 24, float32(*bhDayPrice) / 24, nil
}
30 changes: 25 additions & 5 deletions report/console_report.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ type consoleReport struct {

const (
blankLine = ""
separator = " -------------------------------------------------------------------------------------------------------------------------------"
rowFormat = "| %-25s || %7v | %7v | %12v | %13v | %13v | %18v | %8v |"
separator = " --------------------------------------------------------------------------------------------------------------------------------"
rowFormat = "| %-25s || %7v | %7v | %12v | %13v | %13v | %18v | %9v |"
)

func NewConsoleReport(currency string) Writer {
Expand All @@ -33,16 +33,36 @@ func (r *consoleReport) GenerateReport(data *PrintableData) (string, error) {
fmt.Println(fmt.Sprintf("| Schedule: '%s' (%s)", scheduleData.Name, scheduleData.ID))
fmt.Println(separator)
fmt.Println(fmt.Sprintf(rowFormat, "USER", "WEEKDAY", "WEEKEND", "BANK HOLIDAY", "TOTAL WEEKDAY", "TOTAL WEEKEND", "TOTAL BANK HOLIDAY", "TOTAL"))
fmt.Println(fmt.Sprintf(rowFormat, "", "HOURS", "HOURS", "HOURS", "AMOUNT", "AMOUNT", "AMOUNT", "AMOUNT"))
fmt.Println(separator)

for _, userData := range scheduleData.RotaUsers {
fmt.Println(fmt.Sprintf(rowFormat, userData.Name,
userData.NumWorkDays, userData.NumWeekendDays, userData.NumBankHolidaysDays,
userData.TotalAmountWorkDays, userData.TotalAmountWeekendDays, userData.TotalAmountBankHolidaysDays,
fmt.Sprintf("%s%d", r.currency, userData.TotalAmount)))
userData.NumWorkHours, userData.NumWeekendHours, userData.NumBankHolidaysHours,
fmt.Sprintf("%s%v", r.currency, userData.TotalAmountWorkHours),
fmt.Sprintf("%s%v", r.currency, userData.TotalAmountWeekendHours),
fmt.Sprintf("%s%v", r.currency, userData.TotalAmountBankHolidaysHours),
fmt.Sprintf("%s%v", r.currency, userData.TotalAmount)))
}
fmt.Println(separator)
}

fmt.Println("")
fmt.Println(separator)
fmt.Println("| Users summary")
fmt.Println(separator)
fmt.Println(fmt.Sprintf(rowFormat, "USER", "WEEKDAY", "WEEKEND", "BANK HOLIDAY", "TOTAL WEEKDAY", "TOTAL WEEKEND", "TOTAL BANK HOLIDAY", "TOTAL"))
fmt.Println(fmt.Sprintf(rowFormat, "", "HOURS", "HOURS", "HOURS", "AMOUNT", "AMOUNT", "AMOUNT", "AMOUNT"))
fmt.Println(separator)

for _, userData := range data.UsersSchedulesSummary {
fmt.Println(fmt.Sprintf(rowFormat, userData.Name,
userData.NumWorkHours, userData.NumWeekendHours, userData.NumBankHolidaysHours,
fmt.Sprintf("%s%v", r.currency, userData.TotalAmountWorkHours),
fmt.Sprintf("%s%v", r.currency, userData.TotalAmountWeekendHours),
fmt.Sprintf("%s%v", r.currency, userData.TotalAmountBankHolidaysHours),
fmt.Sprintf("%s%v", r.currency, userData.TotalAmount)))
}
fmt.Println(separator)

return "", nil
Expand Down
48 changes: 41 additions & 7 deletions report/pdf_report.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import (
)

const (
matrixRowFormat = "%-24s %8v %8v %11v %10v %10v %13v %8v"
matrixRowFormat = "%-23s %8v %8v %11v %10v %10v %13v %9v"
)

type pdfReport struct {
Expand Down Expand Up @@ -52,26 +52,60 @@ func (r *pdfReport) GenerateReport(data *PrintableData) (string, error) {

pdf.SetFont("Courier", "B", 9)
pdf.CellFormat(0, 5,
fmt.Sprintf(matrixRowFormat, "USER", "WEEKDAY", "WEEKEND", "B. HOLIDAY", tr(fmt.Sprintf("%s WEEKDAY", r.currency)),
tr(fmt.Sprintf("%s WEEKEND", r.currency)), tr(fmt.Sprintf("%s B. HOLIDAY", r.currency)),
tr(fmt.Sprintf("%s TOTAL", r.currency))),
fmt.Sprintf(matrixRowFormat, "USER", "WEEKDAY", "WEEKEND", "B. HOLIDAY", "WEEKDAY", "WEEKEND", "B. HOLIDAY", "TOTAL"),
"", 0, "L", false, 0, "")
pdf.Ln(3)
pdf.CellFormat(0, 5,
fmt.Sprintf(matrixRowFormat, "", "HOURS", "HOURS", "HOURS", "AMOUNT", "AMOUNT", "AMOUNT", "AMOUNT"),
"B", 0, "L", false, 0, "")
pdf.Ln(5)

pdf.SetFont("Courier", "", 9)
for _, userData := range scheduleData.RotaUsers {
pdf.CellFormat(0, 5,
fmt.Sprintf(matrixRowFormat, tr(userData.Name),
userData.NumWorkDays, userData.NumWeekendDays, userData.NumBankHolidaysDays,
userData.TotalAmountWorkDays, userData.TotalAmountWeekendDays, userData.TotalAmountBankHolidaysDays,
tr(fmt.Sprintf("%s%d", r.currency, userData.TotalAmount))),
userData.NumWorkHours, userData.NumWeekendHours, userData.NumBankHolidaysHours,
tr(fmt.Sprintf("%s%v", r.currency, userData.TotalAmountWorkHours)),
tr(fmt.Sprintf("%s%v", r.currency, userData.TotalAmountWeekendHours)),
tr(fmt.Sprintf("%s%v", r.currency, userData.TotalAmountBankHolidaysHours)),
tr(fmt.Sprintf("%s%v", r.currency, userData.TotalAmount))),
"", 0, "L", false, 0, "")
pdf.Ln(5)
}

pdf.Ln(10)
}

pdf.AddPage()

pdf.SetFont("Arial", "B", 13)
pdf.CellFormat(0, 5, " Users summary",
"L", 0, "L", false, 0, "")
pdf.Ln(8)

pdf.SetFont("Courier", "B", 9)
pdf.CellFormat(0, 5,
fmt.Sprintf(matrixRowFormat, "USER", "WEEKDAY", "WEEKEND", "B. HOLIDAY", "WEEKDAY", "WEEKEND", "B. HOLIDAY", "TOTAL"),
"", 0, "L", false, 0, "")
pdf.Ln(3)
pdf.CellFormat(0, 5,
fmt.Sprintf(matrixRowFormat, "", "HOURS", "HOURS", "HOURS", "AMOUNT", "AMOUNT", "AMOUNT", "AMOUNT"),
"B", 0, "L", false, 0, "")
pdf.Ln(5)

pdf.SetFont("Courier", "", 9)
for _, userData := range data.UsersSchedulesSummary {
pdf.CellFormat(0, 5,
fmt.Sprintf(matrixRowFormat, tr(userData.Name),
userData.NumWorkHours, userData.NumWeekendHours, userData.NumBankHolidaysHours,
tr(fmt.Sprintf("%s%v", r.currency, userData.TotalAmountWorkHours)),
tr(fmt.Sprintf("%s%v", r.currency, userData.TotalAmountWeekendHours)),
tr(fmt.Sprintf("%s%v", r.currency, userData.TotalAmountBankHolidaysHours)),
tr(fmt.Sprintf("%s%v", r.currency, userData.TotalAmount))),
"", 0, "L", false, 0, "")
pdf.Ln(5)
}

dir, _ := homedir.Dir()
filename := fmt.Sprintf("%s/pagerduty_oncall_report.%d-%d.pdf", dir, data.Start.Month(), data.Start.Year())
err := pdf.OutputFileAndClose(filename)
Expand Down
34 changes: 23 additions & 11 deletions report/writer.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@ package report
import "time"

type PrintableData struct {
Start time.Time
End time.Time
SchedulesData []*ScheduleData
Start time.Time
End time.Time
SchedulesData []*ScheduleData
UsersSchedulesSummary []*UserSchedulesSummary
}

type ScheduleData struct {
Expand All @@ -14,15 +15,26 @@ type ScheduleData struct {
RotaUsers []*ScheduleUser
}

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

type ScheduleUser struct {
Name string
NumWorkDays int
TotalAmountWorkDays int
NumWeekendDays int
TotalAmountWeekendDays int
NumBankHolidaysDays int
TotalAmountBankHolidaysDays int
TotalAmount int
Name string
NumWorkHours float32
TotalAmountWorkHours float32
NumWeekendHours float32
TotalAmountWeekendHours float32
NumBankHolidaysHours float32
TotalAmountBankHolidaysHours float32
TotalAmount float32
}

type Writer interface {
Expand Down

0 comments on commit d7f945a

Please sign in to comment.