@@ -154,20 +154,16 @@ class TargetSerializer(rest_framework.serializers.Serializer):
154154 min_value = 0 ,
155155 max_value = 100 ,
156156 required = False ,
157- allow_null = True ,
158157 )
159158 age_until = rest_framework .serializers .IntegerField (
160159 min_value = 0 ,
161160 max_value = 100 ,
162161 required = False ,
163- allow_null = True ,
164162 )
165163 country = rest_framework .serializers .CharField (
166164 max_length = 2 ,
167165 min_length = 2 ,
168166 required = False ,
169- allow_null = True ,
170- allow_blank = True ,
171167 )
172168 categories = rest_framework .serializers .ListField (
173169 child = rest_framework .serializers .CharField (
@@ -193,9 +189,8 @@ def validate(self, data):
193189
194190 country = data .get ('country' )
195191 if country :
196- country = country .strip ().upper ()
197192 try :
198- pycountry .countries .lookup (country )
193+ pycountry .countries .lookup (country . strip (). upper () )
199194 data ['country' ] = country
200195 except LookupError :
201196 raise rest_framework .serializers .ValidationError (
@@ -218,7 +213,7 @@ class PromoCreateSerializer(rest_framework.serializers.ModelSerializer):
218213 django .core .validators .URLValidator (schemes = ['http' , 'https' ]),
219214 ],
220215 )
221- target = TargetSerializer (required = True )
216+ target = TargetSerializer (required = True , allow_null = True )
222217 promo_common = rest_framework .serializers .CharField (
223218 min_length = 5 ,
224219 max_length = 30 ,
@@ -446,3 +441,141 @@ def to_representation(self, instance):
446441 data .pop ('promo_common' , None )
447442
448443 return data
444+
445+
446+ class PromoDetailSerializer (rest_framework .serializers .ModelSerializer ):
447+ promo_id = rest_framework .serializers .UUIDField (
448+ source = 'id' ,
449+ read_only = True ,
450+ )
451+ target = TargetSerializer (allow_null = True , required = False )
452+ promo_unique = rest_framework .serializers .SerializerMethodField ()
453+ company_name = rest_framework .serializers .CharField (
454+ source = 'company.name' ,
455+ read_only = True ,
456+ )
457+ like_count = rest_framework .serializers .SerializerMethodField ()
458+ used_count = rest_framework .serializers .SerializerMethodField ()
459+
460+ class Meta :
461+ model = business_models .Promo
462+ fields = (
463+ 'promo_id' ,
464+ 'description' ,
465+ 'image_url' ,
466+ 'target' ,
467+ 'max_count' ,
468+ 'active_from' ,
469+ 'active_until' ,
470+ 'mode' ,
471+ 'promo_common' ,
472+ 'promo_unique' ,
473+ 'company_name' ,
474+ 'like_count' ,
475+ 'used_count' ,
476+ )
477+
478+ def get_promo_unique (self , obj ):
479+ if obj .mode == business_models .Promo .MODE_UNIQUE :
480+ return [code .code for code in obj .unique_codes .all ()]
481+
482+ return None
483+
484+ def update (self , instance , validated_data ):
485+ target_data = validated_data .pop ('target' , None )
486+ for attr , value in validated_data .items ():
487+ setattr (instance , attr , value )
488+
489+ if target_data is not None :
490+ instance .target = target_data
491+
492+ instance .save ()
493+ return instance
494+
495+ def validate (self , data ):
496+ instance = self .instance
497+ full_data = {
498+ 'mode' : instance .mode ,
499+ 'promo_common' : instance .promo_common ,
500+ 'promo_unique' : None ,
501+ 'max_count' : instance .max_count ,
502+ 'active_from' : instance .active_from ,
503+ 'active_until' : instance .active_until ,
504+ 'target' : instance .target if instance .target is not None else {},
505+ }
506+ full_data .update (data )
507+ mode = full_data .get ('mode' )
508+ promo_common = full_data .get ('promo_common' )
509+ promo_unique = full_data .get ('promo_unique' )
510+ max_count = full_data .get ('max_count' )
511+
512+ if mode == business_models .Promo .MODE_COMMON :
513+ if not promo_common :
514+ raise rest_framework .serializers .ValidationError (
515+ {
516+ 'promo_common' : (
517+ 'This field is required for COMMON mode.'
518+ ),
519+ },
520+ )
521+
522+ if promo_unique is not None :
523+ raise rest_framework .serializers .ValidationError (
524+ {
525+ 'promo_unique' : (
526+ 'This field is not allowed for COMMON mode.'
527+ ),
528+ },
529+ )
530+
531+ if max_count < 0 or max_count > 100000000 :
532+ raise rest_framework .serializers .ValidationError (
533+ {'max_count' : 'Must be between 0 and 100,000,000.' },
534+ )
535+
536+ elif mode == business_models .Promo .MODE_UNIQUE :
537+ if not promo_unique :
538+ raise rest_framework .serializers .ValidationError (
539+ {
540+ 'promo_unique' : (
541+ 'This field is required for UNIQUE mode.'
542+ ),
543+ },
544+ )
545+
546+ if promo_common is not None :
547+ raise rest_framework .serializers .ValidationError (
548+ {
549+ 'promo_common' : (
550+ 'This field is not allowed for UNIQUE mode.'
551+ ),
552+ },
553+ )
554+
555+ if max_count != 1 :
556+ raise rest_framework .serializers .ValidationError (
557+ {'max_count' : 'Must be 1 for UNIQUE mode.' },
558+ )
559+ else :
560+ raise rest_framework .serializers .ValidationError (
561+ {'mode' : 'Invalid mode.' },
562+ )
563+
564+ active_from = full_data .get ('active_from' )
565+ active_until = full_data .get ('active_until' )
566+
567+ if active_from and active_until and active_from > active_until :
568+ raise rest_framework .serializers .ValidationError (
569+ {'active_until' : 'Must be after or equal to active_from.' },
570+ )
571+
572+ return data
573+
574+ def get_like_count (self , obj ):
575+ return 0
576+
577+ def get_used_count (self , obj ):
578+ if obj .mode == business_models .Promo .MODE_UNIQUE :
579+ return obj .unique_codes .filter (is_used = True ).count ()
580+
581+ return 0
0 commit comments