6
6
"flag"
7
7
"fmt"
8
8
"os"
9
+ "strings"
9
10
"time"
10
11
11
12
"github.com/orltom/on-call-schedule/internal/cli"
@@ -41,20 +42,22 @@ func RunCreateShiftPlan(arguments []string) error {
41
42
},
42
43
}
43
44
44
- str := new (time.Time )
45
+ start := new (time.Time )
45
46
end := new (time.Time )
47
+ enabledRules := new (string )
46
48
duration := new (int )
47
49
teamFilePath := new (string )
48
50
transform := Table
49
51
var showHelp bool
50
52
51
53
createCommand := flag .NewFlagSet ("create" , flag .ExitOnError )
52
54
createCommand .BoolVar (& showHelp , "h" , false , "help for ocsctl create" )
53
- createCommand .IntVar (duration , "duration" , 7 * 24 , "shift duration in hours. " )
54
- createCommand .Func ("start" , "(required) start time of the schedule plan" , cli .TimeValueVar (str ))
55
+ createCommand .IntVar (duration , "duration" , 7 * 24 , "shift duration in hours" )
56
+ createCommand .Func ("start" , "(required) start time of the schedule plan" , cli .TimeValueVar (start ))
55
57
createCommand .Func ("end" , "(required) end time of the schedule plan" , cli .TimeValueVar (end ))
56
58
createCommand .Func ("team-file" , "(required) path to the file that contain all on-call duties" , cli .FilePathVar (teamFilePath ))
57
59
createCommand .Func ("output" , "output format. One of (cvs, table, json)" , cli .EnumValueVar (enums , & transform ))
60
+ createCommand .StringVar (enabledRules , "enabled-rules" , "vacation" , "Rule to decide which employee should be on-call for the next shift" )
58
61
createCommand .Usage = func () {
59
62
fmt .Fprintf (os .Stdout , "Create on-call schedule\n " )
60
63
fmt .Fprintf (os .Stdout , "\n Usage\n " )
@@ -66,7 +69,7 @@ func RunCreateShiftPlan(arguments []string) error {
66
69
67
70
if err := createCommand .Parse (arguments ); err != nil {
68
71
createCommand .Usage ()
69
- return fmt .Errorf ("could not parse CLI arguments: %w" , err )
72
+ return fmt .Errorf ("could not readTeamFile CLI arguments: %w" , err )
70
73
}
71
74
72
75
if showHelp {
@@ -75,34 +78,23 @@ func RunCreateShiftPlan(arguments []string) error {
75
78
}
76
79
77
80
// check that the required flags are set...
78
- if ! cli .IsFlagPassed (createCommand , "start" ) {
81
+ if ok , missed := cli .RequiredFlagPassed (createCommand , "start" , "end" , "team-file" ); ! ok {
79
82
createCommand .Usage ()
80
- return fmt .Errorf ("%w: %s" , ErrMissingArguments , "start" )
81
- }
82
-
83
- if ! cli .IsFlagPassed (createCommand , "end" ) {
84
- createCommand .Usage ()
85
- return fmt .Errorf ("%w: %s" , ErrMissingArguments , "end" )
86
- }
87
-
88
- if ! cli .IsFlagPassed (createCommand , "team-file" ) {
89
- createCommand .Usage ()
90
- return fmt .Errorf ("%w: %s" , ErrMissingArguments , "team-file" )
91
- }
92
-
93
- // validate input data...
94
- if str == end {
95
- createCommand .Usage ()
96
- return ErrInvalidArgument
83
+ return fmt .Errorf ("%w: %s" , ErrMissingArguments , strings .Join (missed , "," ))
97
84
}
98
85
99
86
// initialize and run...
100
- team , err := parse (* teamFilePath )
87
+ team , err := readTeamFile (* teamFilePath )
101
88
if err != nil {
102
89
return fmt .Errorf ("%w: invalid team config file: %w" , ErrInvalidArgument , err )
103
90
}
104
91
105
- plan , err := shiftplan .NewDefaultShiftPlanner (team .Employees ).Plan (* str , * end , time .Duration (* duration )* time .Hour )
92
+ rules , err := readRules (* enabledRules )
93
+ if err != nil {
94
+ return fmt .Errorf ("%w: invalid rules: %w" , ErrInvalidArgument , err )
95
+ }
96
+
97
+ plan , err := shiftplan .NewShiftPlanner (team .Employees , rules , rules ).Plan (* start , * end , time .Duration (* duration )* time .Hour )
106
98
if err != nil {
107
99
return fmt .Errorf ("can not create on-call schedule: %w" , err )
108
100
}
@@ -114,16 +106,37 @@ func RunCreateShiftPlan(arguments []string) error {
114
106
return nil
115
107
}
116
108
117
- func parse (path string ) (apis.Team , error ) {
109
+ func readTeamFile (path string ) (apis.Team , error ) {
118
110
content , err := os .ReadFile (path )
119
111
if err != nil {
120
112
return apis.Team {}, fmt .Errorf ("could not read file '%s': %w" , path , err )
121
113
}
122
114
123
115
var team apis.Team
124
116
if err := json .Unmarshal (content , & team ); err != nil {
125
- return apis.Team {}, fmt .Errorf ("could not pars json file '%s': %w" , path , err )
117
+ return apis.Team {}, fmt .Errorf ("could not parse json file '%s': %w" , path , err )
126
118
}
127
119
128
120
return team , nil
129
121
}
122
+
123
+ func readRules (value string ) ([]apis.Rule , error ) {
124
+ var rules []apis.Rule
125
+ for _ , s := range strings .Split (value , "," ) {
126
+ switch strings .ToLower (s ) {
127
+ case "vacation" :
128
+ rules = append (rules , shiftplan .NoVacationOverlap ())
129
+ case "minimumoneshiftgap" :
130
+ rules = append (rules , shiftplan .MinimumOneShiftGap ())
131
+ case "minimumtwoshiftgap" :
132
+ rules = append (rules , shiftplan .MinimumTwoShiftGap ())
133
+ case "minimumthreeshiftgap" :
134
+ rules = append (rules , shiftplan .MinimumThreeShiftGap ())
135
+ case "minimumfourshiftgap" :
136
+ rules = append (rules , shiftplan .MinimumFourShiftGap ())
137
+ default :
138
+ return nil , fmt .Errorf ("unknow rule: %s" , s )
139
+ }
140
+ }
141
+ return rules , nil
142
+ }
0 commit comments