Skip to content

Commit 9e35ceb

Browse files
committed
feat(eap): Add validation on operation timeframe and time_value
- Update test cases - Add timeframe values on enums
1 parent fea4344 commit 9e35ceb

5 files changed

Lines changed: 202 additions & 46 deletions

File tree

eap/enums.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,9 @@
55
"eap_type": models.EAPType,
66
"sector": models.PlannedOperation.Sector,
77
"timeframe": models.OperationActivity.TimeFrame,
8+
"years_timeframe_value": models.OperationActivity.YearsTimeFrameChoices,
9+
"months_timeframe_value": models.OperationActivity.MonthsTimeFrameChoices,
10+
"days_timeframe_value": models.OperationActivity.DaysTimeFrameChoices,
11+
"hours_timeframe_value": models.OperationActivity.HoursTimeFrameChoices,
812
"approach": models.EnableApproach.Approach,
913
}

eap/factories.py

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
from random import random
2-
31
import factory
42
from factory import fuzzy
53

@@ -66,7 +64,6 @@ class Meta:
6664

6765
activity = fuzzy.FuzzyText(length=50, prefix="Activity-")
6866
timeframe = fuzzy.FuzzyChoice(OperationActivity.TimeFrame)
69-
time_value = factory.LazyFunction(lambda: [random.randint(1, 12) for _ in range(3)])
7067

7168

7269
class EnableApproachFactory(factory.django.DjangoModelFactory):

eap/models.py

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,12 +233,76 @@ class Meta:
233233

234234

235235
class OperationActivity(models.Model):
236+
# NOTE: `timeframe` and `time_value` together represent the time span for an activity.
237+
# Make sure to keep them in sync.
236238
class TimeFrame(models.IntegerChoices):
237239
YEARS = 10, _("Years")
238240
MONTHS = 20, _("Months")
239241
DAYS = 30, _("Days")
240242
HOURS = 40, _("Hours")
241243

244+
class YearsTimeFrameChoices(models.IntegerChoices):
245+
ONE_YEAR = 1, _("1")
246+
TWO_YEARS = 2, _("2")
247+
THREE_YEARS = 3, _("3")
248+
FOUR_YEARS = 4, _("4")
249+
FIVE_YEARS = 5, _("5")
250+
251+
class MonthsTimeFrameChoices(models.IntegerChoices):
252+
ONE_MONTH = 1, _("1")
253+
TWO_MONTHS = 2, _("2")
254+
THREE_MONTHS = 3, _("3")
255+
FOUR_MONTHS = 4, _("4")
256+
FIVE_MONTHS = 5, _("5")
257+
SIX_MONTHS = 6, _("6")
258+
SEVEN_MONTHS = 7, _("7")
259+
EIGHT_MONTHS = 8, _("8")
260+
NINE_MONTHS = 9, _("9")
261+
TEN_MONTHS = 10, _("10")
262+
ELEVEN_MONTHS = 11, _("11")
263+
TWELVE_MONTHS = 12, _("12")
264+
265+
class DaysTimeFrameChoices(models.IntegerChoices):
266+
ONE_DAY = 1, _("1")
267+
TWO_DAYS = 2, _("2")
268+
THREE_DAYS = 3, _("3")
269+
FOUR_DAYS = 4, _("4")
270+
FIVE_DAYS = 5, _("5")
271+
SIX_DAYS = 6, _("6")
272+
SEVEN_DAYS = 7, _("7")
273+
EIGHT_DAYS = 8, _("8")
274+
NINE_DAYS = 9, _("9")
275+
TEN_DAYS = 10, _("10")
276+
ELEVEN_DAYS = 11, _("11")
277+
TWELVE_DAYS = 12, _("12")
278+
THIRTEEN_DAYS = 13, _("13")
279+
FOURTEEN_DAYS = 14, _("14")
280+
FIFTEEN_DAYS = 15, _("15")
281+
SIXTEEN_DAYS = 16, _("16")
282+
SEVENTEEN_DAYS = 17, _("17")
283+
EIGHTEEN_DAYS = 18, _("18")
284+
NINETEEN_DAYS = 19, _("19")
285+
TWENTY_DAYS = 20, _("20")
286+
TWENTY_ONE_DAYS = 21, _("21")
287+
TWENTY_TWO_DAYS = 22, _("22")
288+
TWENTY_THREE_DAYS = 23, _("23")
289+
TWENTY_FOUR_DAYS = 24, _("24")
290+
TWENTY_FIVE_DAYS = 25, _("25")
291+
TWENTY_SIX_DAYS = 26, _("26")
292+
TWENTY_SEVEN_DAYS = 27, _("27")
293+
TWENTY_EIGHT_DAYS = 28, _("28")
294+
TWENTY_NINE_DAYS = 29, _("29")
295+
THIRTY_DAYS = 30, _("30")
296+
THIRTY_ONE_DAYS = 31, _("31")
297+
298+
class HoursTimeFrameChoices(models.IntegerChoices):
299+
ZERO_TO_FIVE_HOURS = 5, _("0-5")
300+
FIVE_TO_TEN_HOURS = 10, _("5-10")
301+
TEN_TO_FIFTEEN_HOURS = 15, _("10-15")
302+
FIFTEEN_TO_TWENTY_HOURS = 20, _("15-20")
303+
TWENTY_TO_TWENTY_FIVE_HOURS = 25, _("20-25")
304+
TWENTY_FIVE_TO_THIRTY_HOURS = 30, _("25-30")
305+
242306
activity = models.CharField(max_length=255, verbose_name=_("Activity"))
243307
timeframe = models.IntegerField(choices=TimeFrame.choices, verbose_name=_("Timeframe"))
244308
time_value = ArrayField(

eap/serializers.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,15 +193,49 @@ def validate_file(self, file):
193193
return file
194194

195195

196+
ALLOWED_MAP_TIMEFRAMES_VALUE = {
197+
OperationActivity.TimeFrame.YEARS: list(OperationActivity.YearsTimeFrameChoices.values),
198+
OperationActivity.TimeFrame.MONTHS: list(OperationActivity.MonthsTimeFrameChoices.values),
199+
OperationActivity.TimeFrame.DAYS: list(OperationActivity.DaysTimeFrameChoices.values),
200+
OperationActivity.TimeFrame.HOURS: list(OperationActivity.HoursTimeFrameChoices.values),
201+
}
202+
203+
196204
class OperationActivitySerializer(
197205
serializers.ModelSerializer,
198206
):
199207
id = serializers.IntegerField(required=False)
208+
timeframe = serializers.ChoiceField(
209+
choices=OperationActivity.TimeFrame.choices,
210+
required=True,
211+
)
212+
time_value = serializers.ListField(
213+
child=serializers.IntegerField(),
214+
required=True,
215+
)
200216

201217
class Meta:
202218
model = OperationActivity
203219
fields = "__all__"
204220

221+
# NOTE: Custom validation for `timeframe` and `time_value`
222+
# Make sure time_value is within the allowed range for the selected timeframe
223+
def validate(self, validated_data: dict[str, typing.Any]) -> dict[str, typing.Any]:
224+
timeframe = validated_data["timeframe"]
225+
time_value = validated_data["time_value"]
226+
227+
allowed_values = ALLOWED_MAP_TIMEFRAMES_VALUE.get(timeframe, [])
228+
invalid_values = [value for value in time_value if value not in allowed_values]
229+
230+
if invalid_values:
231+
raise serializers.ValidationError(
232+
{
233+
"time_value": gettext("Invalid time_value(s) %s for the selected timeframe %s.")
234+
% (invalid_values, OperationActivity.TimeFrame(timeframe).label)
235+
}
236+
)
237+
return validated_data
238+
205239

206240
class PlannedOperationSerializer(
207241
NestedUpdateMixin,

0 commit comments

Comments
 (0)