@@ -285,81 +285,67 @@ class Meta:
285
285
)
286
286
287
287
def validate (self , data ):
288
- full_data = self ._get_full_data (data )
288
+ """
289
+ Main validation method.
290
+ Determines the mode and calls the corresponding validation method.
291
+ """
289
292
290
- mode = full_data .get ('mode' )
293
+ mode = data .get ('mode' , getattr ( self . instance , 'mode' , None ) )
291
294
292
295
if mode == business .constants .PROMO_MODE_COMMON :
293
- self ._validate_common (full_data )
294
-
296
+ self ._validate_common (data )
295
297
elif mode == business .constants .PROMO_MODE_UNIQUE :
296
- self ._validate_unique (full_data )
297
-
298
+ self ._validate_unique (data )
299
+ elif mode is None :
300
+ raise rest_framework .serializers .ValidationError (
301
+ {'mode' : 'This field is required.' },
302
+ )
298
303
else :
299
304
raise rest_framework .serializers .ValidationError (
300
305
{'mode' : 'Invalid mode.' },
301
306
)
302
307
303
308
return data
304
309
305
- def to_representation (self , instance ):
306
- """
307
- Controls the display of fields in the response.
308
- """
309
- data = super ().to_representation (instance )
310
-
311
- if not instance .image_url :
312
- data .pop ('image_url' , None )
313
-
314
- if instance .mode == business .constants .PROMO_MODE_UNIQUE :
315
- data .pop ('promo_common' , None )
316
- if 'promo_unique' in self .fields and isinstance (
317
- self .fields ['promo_unique' ],
318
- rest_framework .serializers .SerializerMethodField ,
319
- ):
320
- data ['promo_unique' ] = self .get_promo_unique (instance )
321
- else :
322
- data ['promo_unique' ] = [
323
- code .code for code in instance .unique_codes .all ()
324
- ]
325
- else :
326
- data .pop ('promo_unique' , None )
327
-
328
- return data
329
-
330
- def _get_full_data (self , data ):
331
- """
332
- Build the full data dict by merging existing instance data
333
- with new input.
334
- """
335
- if self .instance :
336
- full_data = self .to_representation (self .instance )
337
- full_data .update (data )
338
- else :
339
- full_data = data
340
- return full_data
341
-
342
- def _validate_common (self , full_data ):
310
+ def _validate_common (self , data ):
343
311
"""
344
312
Validations for COMMON promo mode.
345
313
"""
346
- promo_common = full_data .get ('promo_common' )
347
- promo_unique = full_data .get ('promo_unique' )
348
- max_count = full_data .get ('max_count' )
349
314
350
- if not promo_common :
315
+ if 'promo_unique' in data and data [ 'promo_unique' ] is not None :
351
316
raise rest_framework .serializers .ValidationError (
352
- {'promo_common ' : 'This field is required for COMMON mode.' },
317
+ {'promo_unique ' : 'This field is not allowed for COMMON mode.' },
353
318
)
354
319
355
- if promo_unique is not None :
320
+ if self . instance is None and not data . get ( 'promo_common' ) :
356
321
raise rest_framework .serializers .ValidationError (
357
- {'promo_unique ' : 'This field is not allowed for COMMON mode.' },
322
+ {'promo_common ' : 'This field is required for COMMON mode.' },
358
323
)
359
324
325
+ new_max_count = data .get ('max_count' )
326
+ if self .instance and new_max_count is not None :
327
+ used_count = self .instance .get_used_codes_count
328
+ if used_count > new_max_count :
329
+ raise rest_framework .serializers .ValidationError (
330
+ {
331
+ 'max_count' : (
332
+ f'max_count ({ new_max_count } ) cannot be less than '
333
+ f'used_count ({ used_count } ).'
334
+ ),
335
+ },
336
+ )
337
+
338
+ effective_max_count = (
339
+ new_max_count
340
+ if new_max_count is not None
341
+ else getattr (self .instance , 'max_count' , None )
342
+ )
343
+
360
344
min_c = business .constants .PROMO_COMMON_MIN_COUNT
361
345
max_c = business .constants .PROMO_COMMON_MAX_COUNT
362
- if not (min_c <= max_count <= max_c ):
346
+ if effective_max_count is not None and not (
347
+ min_c <= effective_max_count <= max_c
348
+ ):
363
349
raise rest_framework .serializers .ValidationError (
364
350
{
365
351
'max_count' : (
@@ -368,35 +354,67 @@ def _validate_common(self, full_data):
368
354
},
369
355
)
370
356
371
- def _validate_unique (self , full_data ):
357
+ def _validate_unique (self , data ):
372
358
"""
373
359
Validations for UNIQUE promo mode.
374
360
"""
375
- promo_common = full_data .get ('promo_common' )
376
- promo_unique = full_data .get ('promo_unique' )
377
- max_count = full_data .get ('max_count' )
378
361
379
- if not promo_unique :
362
+ if 'promo_common' in data and data [ 'promo_common' ] is not None :
380
363
raise rest_framework .serializers .ValidationError (
381
- {'promo_unique ' : 'This field is required for UNIQUE mode.' },
364
+ {'promo_common ' : 'This field is not allowed for UNIQUE mode.' },
382
365
)
383
366
384
- if promo_common is not None :
367
+ if self . instance is None and not data . get ( 'promo_unique' ) :
385
368
raise rest_framework .serializers .ValidationError (
386
- {'promo_common ' : 'This field is not allowed for UNIQUE mode.' },
369
+ {'promo_unique ' : 'This field is required for UNIQUE mode.' },
387
370
)
388
371
389
- if max_count != business .constants .PROMO_UNIQUE_MAX_COUNT :
372
+ effective_max_count = data .get (
373
+ 'max_count' ,
374
+ getattr (self .instance , 'max_count' , None ),
375
+ )
376
+
377
+ if (
378
+ effective_max_count is not None
379
+ and effective_max_count
380
+ != business .constants .PROMO_UNIQUE_MAX_COUNT
381
+ ):
390
382
raise rest_framework .serializers .ValidationError (
391
383
{
392
384
'max_count' : (
393
385
'Must be equal to '
394
- f'{ business .constants .PROMO_UNIQUE_MAX_COUNT } '
386
+ f'{ business .constants .PROMO_UNIQUE_MAX_COUNT } '
395
387
'for UNIQUE mode.'
396
388
),
397
389
},
398
390
)
399
391
392
+ def to_representation (self , instance ):
393
+ """
394
+ Controls the display of fields in the response.
395
+ """
396
+
397
+ data = super ().to_representation (instance )
398
+
399
+ if not instance .image_url :
400
+ data .pop ('image_url' , None )
401
+
402
+ if instance .mode == business .constants .PROMO_MODE_UNIQUE :
403
+ data .pop ('promo_common' , None )
404
+ if 'promo_unique' in self .fields and isinstance (
405
+ self .fields ['promo_unique' ],
406
+ rest_framework .serializers .SerializerMethodField ,
407
+ ):
408
+ data ['promo_unique' ] = self .get_promo_unique (instance )
409
+ else :
410
+ data ['promo_unique' ] = [
411
+ code .code for code in instance .unique_codes .all ()
412
+ ]
413
+ else :
414
+ data .pop ('promo_unique' , None )
415
+
416
+ return data
417
+
400
418
401
419
class PromoCreateSerializer (BasePromoSerializer ):
402
420
url = rest_framework .serializers .HyperlinkedIdentityField (
0 commit comments