Skip to content

Commit

Permalink
Simplify handling with custom JSON time
Browse files Browse the repository at this point in the history
  • Loading branch information
orltom committed Jan 2, 2025
1 parent d97b984 commit 1a9629e
Show file tree
Hide file tree
Showing 6 changed files with 46 additions and 58 deletions.
2 changes: 1 addition & 1 deletion .golangci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,6 @@ issues:
linters:
- funlen
- dupl
- path: pkg/apis/team_types.go
- path: pkg/apis/team_methods.go
linters:
- wrapcheck
2 changes: 1 addition & 1 deletion internal/shiftplan/default_rules.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ func (d *DefaultRule) Match(employee apis.Employee, shifts []apis.Shift, start t
func VacationConflict() *DefaultRule {
return &DefaultRule{
fn: func(e apis.Employee, _ []apis.Shift, start time.Time, end time.Time) bool {
days := e.Vacations()
days := e.VacationDays
for vIdx := range days {
day := days[vIdx]
if (day.After(start) && day.Before(end)) || day.Equal(start) || day.Equal(end) {
Expand Down
4 changes: 2 additions & 2 deletions internal/shiftplan/default_rules_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ func TestVacationConflict(t *testing.T) {
{
name: "Should detect conflict if employee has holiday between scheduled shift",
args: args{
employee: apis.Employee{ID: "a", Name: "a", VacationDays: []string{"2024-01-01"}},
employee: apis.Employee{ID: "a", Name: "a", VacationDays: vacationDays("2024-01-01")},
start: date("2024-01-01"),
end: date("2024-01-02"),
},
Expand All @@ -39,7 +39,7 @@ func TestVacationConflict(t *testing.T) {
{
name: "Should not detect conflict if employee has holiday outside scheduled shift",
args: args{
employee: apis.Employee{ID: "a", Name: "a", VacationDays: []string{"2024-01-03"}},
employee: apis.Employee{ID: "a", Name: "a", VacationDays: vacationDays("2024-01-03")},
start: date("2024-01-01"),
end: date("2024-01-02"),
},
Expand Down
27 changes: 18 additions & 9 deletions internal/shiftplan/planner_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ func TestPlanner_Plan(t *testing.T) {
{
name: "Should not schedule Primary on holiday days",
employees: []apis.Employee{
{ID: "a@test.ch", Name: "a", VacationDays: []string{"2020-04-01"}},
{ID: "a@test.ch", Name: "a", VacationDays: vacationDays("2020-04-01")},
{ID: "b@test.ch", Name: "b", VacationDays: nil},
{ID: "c@test.ch", Name: "c", VacationDays: nil},
{ID: "d@test.ch", Name: "d", VacationDays: nil},
Expand Down Expand Up @@ -99,7 +99,7 @@ func TestPlanner_Plan(t *testing.T) {
name: "Should not schedule Secondary on holiday days",
employees: []apis.Employee{
{ID: "a@test.ch", Name: "a", VacationDays: nil},
{ID: "b@test.ch", Name: "b", VacationDays: []string{"2020-04-01"}},
{ID: "b@test.ch", Name: "b", VacationDays: vacationDays("2020-04-01")},
{ID: "c@test.ch", Name: "c", VacationDays: nil},
{ID: "d@test.ch", Name: "d", VacationDays: nil},
},
Expand Down Expand Up @@ -139,10 +139,10 @@ func TestPlanner_Plan(t *testing.T) {
{
name: "Should return an error if can not find next available duty",
employees: []apis.Employee{
{ID: "a@test.ch", Name: "a", VacationDays: []string{"2020-04-01"}},
{ID: "b@test.ch", Name: "b", VacationDays: []string{"2020-04-01"}},
{ID: "c@test.ch", Name: "c", VacationDays: []string{"2020-04-01"}},
{ID: "d@test.ch", Name: "d", VacationDays: []string{"2020-04-01"}},
{ID: "a@test.ch", Name: "a", VacationDays: vacationDays("2020-04-01")},
{ID: "b@test.ch", Name: "b", VacationDays: vacationDays("2020-04-01")},
{ID: "c@test.ch", Name: "c", VacationDays: vacationDays("2020-04-01")},
{ID: "d@test.ch", Name: "d", VacationDays: vacationDays("2020-04-01")},
},
args: args{
start: date("2020-04-01"),
Expand All @@ -156,9 +156,9 @@ func TestPlanner_Plan(t *testing.T) {
name: "Should return an error if can not find next secondary",
employees: []apis.Employee{
{ID: "a@test.ch", Name: "a", VacationDays: nil},
{ID: "b@test.ch", Name: "b", VacationDays: []string{"2020-04-01"}},
{ID: "c@test.ch", Name: "c", VacationDays: []string{"2020-04-01"}},
{ID: "d@test.ch", Name: "d", VacationDays: []string{"2020-04-01"}},
{ID: "b@test.ch", Name: "b", VacationDays: vacationDays("2020-04-01")},
{ID: "c@test.ch", Name: "c", VacationDays: vacationDays("2020-04-01")},
{ID: "d@test.ch", Name: "d", VacationDays: vacationDays("2020-04-01")},
},
args: args{
start: date("2020-04-01"),
Expand Down Expand Up @@ -191,3 +191,12 @@ func date(s string) time.Time {

return t
}

func vacationDays(days ...string) []apis.VacationDay {
var tmp = make([]apis.VacationDay, len(days))
for _, day := range days {
tmp = append(tmp, apis.VacationDay{Time: date(day)})
}

return tmp
}
18 changes: 18 additions & 0 deletions pkg/apis/team_methods.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package apis

import (
"time"
)

func (v *VacationDay) UnmarshalJSON(data []byte) error {
if string(data) == "null" || string(data) == `""` {
return nil
}

t, err := time.Parse(time.DateOnly, string(data))
if err != nil {
return err
}
*v = VacationDay{t}
return nil
}
51 changes: 6 additions & 45 deletions pkg/apis/team_types.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
package apis

import (
"encoding/json"
"fmt"
"time"
)

Expand All @@ -12,49 +10,12 @@ type Team struct {
Employees []Employee `json:"employees"`
}

type Employee struct {
ID EmployeeID `json:"id"`
Name string `json:"name"`
VacationDays []string `json:"vacationDays,omitempty"`
parsedVacations []time.Time
type VacationDay struct {
time.Time
}

func (e *Employee) UnmarshalJSON(data []byte) error {
type Alias Employee
temp := &struct {
*Alias
}{
Alias: (*Alias)(e),
}

if err := json.Unmarshal(data, &temp); err != nil {
return err
}

parsedDay, err := parseDateOnly(e.VacationDays)
if err != nil {
return err
}
e.parsedVacations = parsedDay

return nil
}

func (e *Employee) Vacations() []time.Time {
if len(e.VacationDays) != len(e.parsedVacations) {
e.parsedVacations, _ = parseDateOnly(e.VacationDays)
}
return e.parsedVacations
}

func parseDateOnly(dateStr []string) ([]time.Time, error) {
days := make([]time.Time, len(dateStr))
for idx, day := range dateStr {
t, err := time.Parse(time.DateOnly, day)
if err != nil {
return nil, fmt.Errorf("failed to parse date '%s'", day)
}
days[idx] = t
}
return days, nil
type Employee struct {
ID EmployeeID `json:"id"`
Name string `json:"name"`
VacationDays []VacationDay `json:"vacationDays,omitempty"`
}

0 comments on commit 1a9629e

Please sign in to comment.