@@ -29,7 +29,7 @@ func handleGetSLA(r *fastglue.Request) error {
29
29
)
30
30
id , err := strconv .Atoi (r .RequestCtx .UserValue ("id" ).(string ))
31
31
if err != nil || id == 0 {
32
- return r .SendErrorEnvelope (fasthttp .StatusBadRequest , app .i18n .Ts ("globals.messages.invalid" , "name" , "SLA `id`" ), nil , envelope .InputError )
32
+ return r .SendErrorEnvelope (fasthttp .StatusBadRequest , app .i18n .Ts ("globals.messages.invalid" , "name" , "`id`" ), nil , envelope .InputError )
33
33
}
34
34
35
35
sla , err := app .sla .Get (id )
@@ -54,7 +54,7 @@ func handleCreateSLA(r *fastglue.Request) error {
54
54
return sendErrorEnvelope (r , err )
55
55
}
56
56
57
- if err := app .sla .Create (sla .Name , sla .Description , sla .FirstResponseTime , sla .ResolutionTime , sla .Notifications ); err != nil {
57
+ if err := app .sla .Create (sla .Name , sla .Description , sla .FirstResponseTime , sla .ResolutionTime , sla .NextResponseTime , sla . Notifications ); err != nil {
58
58
return sendErrorEnvelope (r , err )
59
59
}
60
60
@@ -70,7 +70,7 @@ func handleUpdateSLA(r *fastglue.Request) error {
70
70
71
71
id , err := strconv .Atoi (r .RequestCtx .UserValue ("id" ).(string ))
72
72
if err != nil || id == 0 {
73
- return r .SendErrorEnvelope (fasthttp .StatusBadRequest , app .i18n .Ts ("globals.messages.invalid" , "name" , "SLA `id`" ), nil , envelope .InputError )
73
+ return r .SendErrorEnvelope (fasthttp .StatusBadRequest , app .i18n .Ts ("globals.messages.invalid" , "name" , "`id`" ), nil , envelope .InputError )
74
74
}
75
75
76
76
if err := r .Decode (& sla , "json" ); err != nil {
@@ -81,11 +81,11 @@ func handleUpdateSLA(r *fastglue.Request) error {
81
81
return sendErrorEnvelope (r , err )
82
82
}
83
83
84
- if err := app .sla .Update (id , sla .Name , sla .Description , sla .FirstResponseTime , sla .ResolutionTime , sla .Notifications ); err != nil {
84
+ if err := app .sla .Update (id , sla .Name , sla .Description , sla .FirstResponseTime , sla .ResolutionTime , sla .NextResponseTime , sla . Notifications ); err != nil {
85
85
return sendErrorEnvelope (r , err )
86
86
}
87
87
88
- return r .SendEnvelope ("SLA updated successfully." )
88
+ return r .SendEnvelope (true )
89
89
}
90
90
91
91
// handleDeleteSLA deletes the SLA with the given ID.
@@ -95,7 +95,7 @@ func handleDeleteSLA(r *fastglue.Request) error {
95
95
)
96
96
id , err := strconv .Atoi (r .RequestCtx .UserValue ("id" ).(string ))
97
97
if err != nil || id == 0 {
98
- return r .SendErrorEnvelope (fasthttp .StatusBadRequest , app .i18n .Ts ("globals.messages.invalid" , "name" , "SLA `id`" ), nil , envelope .InputError )
98
+ return r .SendErrorEnvelope (fasthttp .StatusBadRequest , app .i18n .Ts ("globals.messages.invalid" , "name" , "`id`" ), nil , envelope .InputError )
99
99
}
100
100
101
101
if err = app .sla .Delete (id ); err != nil {
@@ -108,51 +108,79 @@ func handleDeleteSLA(r *fastglue.Request) error {
108
108
// validateSLA validates the SLA policy and returns an envelope.Error if any validation fails.
109
109
func validateSLA (app * App , sla * smodels.SLAPolicy ) error {
110
110
if sla .Name == "" {
111
- return envelope .NewError (envelope .InputError , app .i18n .Ts ("globals.messages.empty" , "name" , "SLA `name`" ), nil )
112
- }
113
- if sla .FirstResponseTime == "" {
114
- return envelope .NewError (envelope .InputError , app .i18n .Ts ("globals.messages.empty" , "name" , "SLA `first_response_time`" ), nil )
111
+ return envelope .NewError (envelope .InputError , app .i18n .Ts ("globals.messages.empty" , "name" , "`name`" ), nil )
115
112
}
116
- if sla .ResolutionTime == "" {
117
- return envelope .NewError (envelope .InputError , app .i18n .Ts ("globals.messages.empty" , "name" , "SLA ` resolution_time`" ), nil )
113
+ if sla .FirstResponseTime . String == "" && sla . NextResponseTime . String == "" && sla . ResolutionTime . String == "" {
114
+ return envelope .NewError (envelope .InputError , app .i18n .Ts ("globals.messages.empty" , "name" , "At least one of `first_response_time`, `next_response_time`, or ` resolution_time` must be provided. " ), nil )
118
115
}
119
116
120
- // Validate notifications if any
117
+ // Validate notifications if any.
121
118
for _ , n := range sla .Notifications {
122
119
if n .Type == "" {
123
- return envelope .NewError (envelope .InputError , app .i18n .Ts ("globals.messages.empty" , "name" , "SLA notification `type`" ), nil )
120
+ return envelope .NewError (envelope .InputError , app .i18n .Ts ("globals.messages.empty" , "name" , "`type`" ), nil )
124
121
}
125
122
if n .TimeDelayType == "" {
126
- return envelope .NewError (envelope .InputError , app .i18n .Ts ("globals.messages.empty" , "name" , "SLA notification `time_delay_type`" ), nil )
123
+ return envelope .NewError (envelope .InputError , app .i18n .Ts ("globals.messages.empty" , "name" , "`time_delay_type`" ), nil )
124
+ }
125
+ if n .Metric == "" {
126
+ return envelope .NewError (envelope .InputError , app .i18n .Ts ("globals.messages.empty" , "name" , "`metric`" ), nil )
127
127
}
128
128
if n .TimeDelayType != "immediately" {
129
129
if n .TimeDelay == "" {
130
- return envelope .NewError (envelope .InputError , app .i18n .Ts ("globals.messages.empty" , "name" , "SLA notification `time_delay`" ), nil )
130
+ return envelope .NewError (envelope .InputError , app .i18n .Ts ("globals.messages.empty" , "name" , "`time_delay`" ), nil )
131
+ }
132
+ // Validate time delay duration.
133
+ td , err := time .ParseDuration (n .TimeDelay )
134
+ if err != nil {
135
+ return envelope .NewError (envelope .InputError , app .i18n .Ts ("globals.messages.invalid" , "name" , "`time_delay`" ), nil )
136
+ }
137
+ if td .Minutes () < 1 {
138
+ return envelope .NewError (envelope .InputError , app .i18n .Ts ("globals.messages.invalid" , "name" , "`time_delay`" ), nil )
131
139
}
132
140
}
133
141
if len (n .Recipients ) == 0 {
134
- return envelope .NewError (envelope .InputError , app .i18n .Ts ("globals.messages.empty" , "name" , "SLA notification `recipients`" ), nil )
142
+ return envelope .NewError (envelope .InputError , app .i18n .Ts ("globals.messages.empty" , "name" , "`recipients`" ), nil )
135
143
}
136
144
}
137
145
138
- // Validate time duration strings
139
- frt , err := time .ParseDuration (sla .FirstResponseTime )
140
- if err != nil {
141
- return envelope .NewError (envelope .InputError , app .i18n .Ts ("globals.messages.invalid" , "name" , "`first_response_time`" ), nil )
142
- }
143
- if frt .Minutes () < 1 {
144
- return envelope .NewError (envelope .InputError , app .i18n .Ts ("globals.messages.invalid" , "name" , "`first_response_time`" ), nil )
146
+ // Validate first response time duration string if not empty.
147
+ if sla .FirstResponseTime .String != "" {
148
+ frt , err := time .ParseDuration (sla .FirstResponseTime .String )
149
+ if err != nil {
150
+ return envelope .NewError (envelope .InputError , app .i18n .Ts ("globals.messages.invalid" , "name" , "`first_response_time`" ), nil )
151
+ }
152
+ if frt .Minutes () < 1 {
153
+ return envelope .NewError (envelope .InputError , app .i18n .Ts ("globals.messages.invalid" , "name" , "`first_response_time`" ), nil )
154
+ }
145
155
}
146
156
147
- rt , err := time .ParseDuration (sla .ResolutionTime )
148
- if err != nil {
149
- return envelope .NewError (envelope .InputError , app .i18n .Ts ("globals.messages.invalid" , "name" , "`resolution_time`" ), nil )
150
- }
151
- if rt .Minutes () < 1 {
152
- return envelope .NewError (envelope .InputError , app .i18n .Ts ("globals.messages.invalid" , "name" , "`resolution_time`" ), nil )
157
+ // Validate resolution time duration string if not empty.
158
+ if sla .ResolutionTime .String != "" {
159
+ rt , err := time .ParseDuration (sla .ResolutionTime .String )
160
+ if err != nil {
161
+ return envelope .NewError (envelope .InputError , app .i18n .Ts ("globals.messages.invalid" , "name" , "`resolution_time`" ), nil )
162
+ }
163
+ if rt .Minutes () < 1 {
164
+ return envelope .NewError (envelope .InputError , app .i18n .Ts ("globals.messages.invalid" , "name" , "`resolution_time`" ), nil )
165
+ }
166
+ // Compare with first response time if both are present.
167
+ if sla .FirstResponseTime .String != "" {
168
+ frt , _ := time .ParseDuration (sla .FirstResponseTime .String )
169
+ if frt > rt {
170
+ return envelope .NewError (envelope .InputError , app .i18n .T ("sla.firstResponseTimeAfterResolution" ), nil )
171
+ }
172
+ }
153
173
}
154
- if frt > rt {
155
- return envelope .NewError (envelope .InputError , app .i18n .T ("sla.firstResponseTimeAfterResolution" ), nil )
174
+
175
+ // Validate next response time duration string if not empty.
176
+ if sla .NextResponseTime .String != "" {
177
+ nrt , err := time .ParseDuration (sla .NextResponseTime .String )
178
+ if err != nil {
179
+ return envelope .NewError (envelope .InputError , app .i18n .Ts ("globals.messages.invalid" , "name" , "`next_response_time`" ), nil )
180
+ }
181
+ if nrt .Minutes () < 1 {
182
+ return envelope .NewError (envelope .InputError , app .i18n .Ts ("globals.messages.invalid" , "name" , "`next_response_time`" ), nil )
183
+ }
156
184
}
157
185
158
186
return nil
0 commit comments