class StaffListCreateSerializer(serializers.ModelSerializer): # OVERRIDE THE MODEL FIELDS AND ENFORCE THE FOLLOWING CUSTOM VALIDATION RULES. given_name = serializers.CharField( required=True, allow_blank=False, ) last_name = serializers.CharField( required=True, allow_blank=False, ) address_country = serializers.CharField( required=True, allow_blank=False, ) address_region = serializers.CharField( required=True, allow_blank=False, ) address_locality = serializers.CharField( required=True, allow_blank=False, ) postal_code = serializers.CharField( required=True, allow_blank=False, ) street_address = serializers.CharField( required=True, allow_blank=False, ) # We are overriding the `email` field to include unique email validation. email = serializers.EmailField( validators=[UniqueValidator(queryset=SharedUser.objects.all())], required=True, ) # All comments are created by our `create` function and not by # `django-rest-framework`. # comments = StaffCommentSerializer(many=True, read_only=True, allow_null=True) # This is a field used in the `create` function if the user enters a # comment. This field is *ONLY* to be used during the POST creation and # will be blank during GET. extra_comment = serializers.CharField(write_only=True, allow_null=True) # This field is used to assign the user to the group. account_type = serializers.CharField(write_only=True, allow_null=False, required=True) # Custom formatting of our telephone fields. fax_number = PhoneNumberField(allow_null=True, required=False) telephone = PhoneNumberField(allow_null=True, required=False) other_telephone = PhoneNumberField(allow_null=True, required=False) # Add password adding. password = serializers.CharField( write_only=True, required=True, allow_blank=False, max_length=63, style={'input_type': 'password'}, validators=[ MatchingDuelFieldsValidator( another_field='password_repeat', message=_("Inputted passwords fields do not match.")), EnhancedPasswordStrengthFieldValidator() ]) password_repeat = serializers.CharField(write_only=True, required=True, allow_blank=False, max_length=63, style={'input_type': 'password'}) is_active = serializers.BooleanField( write_only=True, required=True, error_messages={ "invalid": _("Please pick either 'Yes' or 'No' choice.") }) # Meta Information. class Meta: model = Staff fields = ( # Thing 'id', 'created', 'last_modified', 'account_type', 'description', # Person 'given_name', 'middle_name', 'last_name', 'birthdate', 'join_date', 'gender', # Misc (Read/Write) 'tags', 'is_active', # # Misc (Read Only) # 'comments', # Misc (Write Only) 'extra_comment', 'password', 'password_repeat', # Contact Point 'area_served', 'available_language', 'contact_type', 'email', 'personal_email', 'fax_number', # 'hours_available', #TODO: FIX 'telephone', 'telephone_extension', 'telephone_type_of', 'other_telephone', 'other_telephone_extension', 'other_telephone_type_of', # Postal Address 'address_country', 'address_locality', 'address_region', 'post_office_box_number', 'postal_code', 'street_address', 'street_address_extra', # Geo-coordinate 'elevation', 'latitude', 'longitude', # 'location' #TODO: FIX ) def validate_telephone(self, value): """ Include validation on no-blanks """ if value is None: raise serializers.ValidationError("This field may not be blank.") return value def validate_account_type(self, value): """ Include validation for valid choices. """ if int_or_none(value) is None: raise serializers.ValidationError("Please select a valid choice.") return value def setup_eager_loading(cls, queryset): """ Perform necessary eager loading of data. """ queryset = queryset.prefetch_related( 'owner', 'created_by', 'last_modified_by', # 'comments' 'tags', ) return queryset def create(self, validated_data): """ Override the `create` function to add extra functinality: - Create a `User` object in the public database. - Create a `SharedUser` object in the public database. - Create a `Staff` object in the tenant database. - If user has entered text in the 'extra_comment' field then we will a `Comment` object and attach it to the `Staff` object. - We will attach the staff user whom created this `Staff` object. """ # Format our telephone(s) fax_number = validated_data.get('fax_number', None) if fax_number: fax_number = phonenumbers.parse(fax_number, "CA") telephone = validated_data.get('telephone', None) if telephone: telephone = phonenumbers.parse(telephone, "CA") other_telephone = validated_data.get('other_telephone', None) if other_telephone: other_telephone = phonenumbers.parse(other_telephone, "CA") validated_data['fax_number'] = fax_number validated_data['telephone'] = telephone validated_data['other_telephone'] = other_telephone # Extract our "email" field. email = validated_data.get('email', None) personal_email = validated_data.get('personal_email', None) #------------------- # Create our user. #------------------- owner = SharedUser.objects.create( first_name=validated_data['given_name'], last_name=validated_data['last_name'], email=email, is_active=validated_data['is_active'], franchise=self.context['franchise'], was_email_activated=True) logger.info("Created shared user.") # Attach the user to the `group` group. account_type = int_or_none(validated_data.get('account_type', None)) if account_type: owner.groups.set([account_type]) # Update the password. password = validated_data.get('password', None) owner.set_password(password) owner.save() #--------------------------------------------------- # Create our `Staff` object in our tenant schema. #--------------------------------------------------- # Create an "Staff". staff = Staff.objects.create( created_by=self.context['created_by'], last_modified_by=self.context['created_by'], description=validated_data.get('description', None), # Person given_name=validated_data['given_name'], last_name=validated_data['last_name'], middle_name=validated_data['middle_name'], birthdate=validated_data.get('birthdate', None), join_date=validated_data.get('join_date', None), gender=validated_data.get('gender', None), # Misc created_from=self.context['created_from'], created_from_is_public=self.context['created_from_is_public'], # . . . # Contact Point area_served=validated_data.get('area_served', None), available_language=validated_data.get('available_language', None), contact_type=validated_data.get('contact_type', None), email=email, personal_email=personal_email, fax_number=fax_number, # 'hours_available', #TODO: IMPLEMENT. telephone=telephone, telephone_extension=validated_data.get('telephone_extension', None), telephone_type_of=validated_data.get('telephone_type_of', None), other_telephone=other_telephone, other_telephone_extension=validated_data.get( 'other_telephone_extension', None), other_telephone_type_of=validated_data.get( 'other_telephone_type_of', None), # Postal Address address_country=validated_data.get('address_country', None), address_locality=validated_data.get('address_locality', None), address_region=validated_data.get('address_region', None), post_office_box_number=validated_data.get('post_office_box_number', None), postal_code=validated_data.get('postal_code', None), street_address=validated_data.get('street_address', None), street_address_extra=validated_data.get('street_address_extra', None), # Geo-coordinate elevation=validated_data.get('elevation', None), latitude=validated_data.get('latitude', None), longitude=validated_data.get('longitude', None), # 'location' #TODO: IMPLEMENT. ) logger.info("Created staff member.") # Update our staff again. staff.owner = owner staff.email = email staff.save() logger.info("Attached user object to staff member.") #------------------------ # Set our `Tag` objects. #------------------------ tags = validated_data.get('tags', None) if tags is not None: if len(tags) > 0: staff.tags.set(tags) #----------------------------- # Create our `Comment` object. #----------------------------- extra_comment = validated_data.get('extra_comment', None) if extra_comment is not None: comment = Comment.objects.create( created_by=self.context['created_by'], last_modified_by=self.context['created_by'], text=extra_comment, created_from=self.context['created_from'], created_from_is_public=self.context['created_from_is_public']) staff_comment = StaffComment.objects.create( about=staff, comment=comment, ) # Update validation data. # validated_data['comments'] = StaffComment.objects.filter(staff=staff) validated_data['created_by'] = self.context['created_by'] validated_data['last_modified_by'] = self.context['created_by'] validated_data['extra_comment'] = None validated_data['id'] = staff.id # Return our validated data. return validated_data
class StaffRetrieveUpdateDestroySerializer(serializers.ModelSerializer): # owner = serializers.PrimaryKeyRelatedField(many=False, read_only=True) # We are overriding the `email` field to include unique email validation. email = serializers.EmailField( validators=[UniqueValidator(queryset=Staff.objects.all())], required=False) personal_email = serializers.EmailField( validators=[UniqueValidator(queryset=Staff.objects.all())], required=False) # Add password adding. password = serializers.CharField( write_only=True, required=False, allow_blank=True, max_length=63, style={'input_type': 'password'}, validators=[ MatchingDuelFieldsValidator( another_field='password_repeat', message=_("Inputted passwords fields do not match.")), EnhancedPasswordStrengthFieldValidator() ]) password_repeat = serializers.CharField(write_only=True, required=False, allow_blank=True, max_length=63, style={'input_type': 'password'}) is_active = serializers.BooleanField( write_only=True, required=True, error_messages={ "invalid": _("Please pick either 'Yes' or 'No' choice.") }) # This field is used to assign the user to the group. account_type = serializers.CharField(write_only=True, allow_null=False, required=True) # All comments are created by our `create` function and not by # # `django-rest-framework`. # comments = StaffCommentSerializer(many=True, read_only=True) # # # This is a field used in the `create` function if the user enters a # # comment. This field is *ONLY* to be used during the POST creation and # # will be blank during GET. # extra_comment = serializers.CharField(write_only=True, allow_null=True) # Custom formatting of our telephone fields. fax_number = PhoneNumberField(allow_null=True, required=False) telephone = PhoneNumberField(allow_null=True, required=False) other_telephone = PhoneNumberField(allow_null=True, required=False) # Meta Information. class Meta: model = Staff fields = ( # Thing 'id', 'created', 'last_modified', # 'owner', 'description', 'account_type', # Person 'given_name', 'middle_name', 'last_name', 'birthdate', 'join_date', 'gender', # Misc (Read/Write) 'tags', 'is_active', # # 'is_senior', # # 'is_support', # # 'job_info_read', # 'how_hear', # # # Misc (Read Only) # 'comments', # # # Misc (Write Only) 'password', 'password_repeat', # 'extra_comment', # Contact Point 'area_served', 'available_language', 'contact_type', 'email', 'personal_email', 'fax_number', # 'hours_available', #TODO: FIX 'telephone', 'telephone_extension', 'telephone_type_of', 'other_telephone', 'other_telephone_extension', 'other_telephone_type_of', # Postal Address 'address_country', 'address_locality', 'address_region', 'post_office_box_number', 'postal_code', 'street_address', 'street_address_extra', # Geo-coordinate 'elevation', 'latitude', 'longitude', # 'location' #TODO: FIX ) def setup_eager_loading(cls, queryset): """ Perform necessary eager loading of data. """ queryset = queryset.prefetch_related( 'owner', 'created_by', 'last_modified_by', # 'comments' 'tags', ) return queryset def validate_account_type(self, value): """ Include validation for valid choices. """ if int_or_none(value) is None: raise serializers.ValidationError("Please select a valid choice.") return value def validate_personal_email(self, value): """ Include validation for valid choices. """ if value is None or value == '': raise serializers.ValidationError("This field may not be blank.") return value def update(self, instance, validated_data): """ Override this function to include extra functionality. """ # For debugging purposes only. # print(validated_data) # Get our inputs. email = validated_data.get('email', instance.email) personal_email = validated_data.get('personal_email', None) #------------------------------------- # Bugfix: Created `SharedUser` object. #------------------------------------- if instance.owner is None: owner = SharedUser.objects.filter(email=email).first() if owner: instance.owner = owner instance.save() logger.info("BUGFIX: Attached existing shared user to staff.") else: instance.owner = SharedUser.objects.create( first_name=validated_data['given_name'], last_name=validated_data['last_name'], email=email, is_active=validated_data['is_active'], franchise=self.context['franchise'], was_email_activated=True) instance.save() logger.info( "BUGFIX: Created shared user and attached to staff.") #--------------------------- # Update `SharedUser` object. #--------------------------- # Update the password if required. password = validated_data.get('password', None) if password: instance.owner.set_password(password) logger.info("Updated the password.") # Update the account. if email: instance.owner.email = email instance.owner.username = get_unique_username_from_email(email) instance.owner.first_name = validated_data.get( 'given_name', instance.owner.first_name) instance.owner.last_name = validated_data.get('last_name', instance.owner.last_name) instance.owner.is_active = validated_data.get('is_active', instance.owner.is_active) instance.owner.save() logger.info("Updated the shared user.") # Attach the user to the `group` group. account_type = validated_data.get('account_type', None) if account_type != "NaN": account_type = int(account_type) instance.owner.groups.set([account_type]) logger.info("Updated the group membership.") #--------------------------- # Update `Staff` object. #--------------------------- # Person instance.description = validated_data.get('description', None) instance.given_name = validated_data.get('given_name', None) instance.last_name = validated_data.get('last_name', None) instance.middle_name = validated_data.get('middle_name', None) instance.birthdate = validated_data.get('birthdate', None) instance.join_date = validated_data.get('join_date', None) instance.gender = validated_data.get('gender', None) # Misc instance.hourly_salary_desired = validated_data.get( 'hourly_salary_desired', 0.00) instance.limit_special = validated_data.get('limit_special', None) instance.dues_date = validated_data.get('dues_date', None) instance.commercial_insurance_expiry_date = validated_data.get( 'commercial_insurance_expiry_date', None) instance.police_check = validated_data.get('police_check', None) instance.drivers_license_class = validated_data.get( 'drivers_license_class', None) instance.how_hear = validated_data.get('how_hear', None) instance.last_modified_by = self.context['last_modified_by'] instance.last_modified_from = self.context['last_modified_from'] instance.last_modified_from_is_public = self.context[ 'last_modified_from_is_public'] # 'organizations', #TODO: IMPLEMENT. # Contact Point instance.area_served = validated_data.get('area_served', None) instance.available_language = validated_data.get( 'available_language', None) instance.contact_type = validated_data.get('contact_type', None) instance.email = email instance.personal_email = personal_email instance.fax_number = validated_data.get('fax_number', None) # 'hours_available', #TODO: IMPLEMENT. instance.telephone = validated_data.get('telephone', None) instance.telephone_extension = validated_data.get( 'telephone_extension', None) instance.telephone_type_of = validated_data.get( 'telephone_type_of', None) instance.other_telephone = validated_data.get('other_telephone', None) instance.other_telephone_extension = validated_data.get( 'other_telephone_extension', None) instance.other_telephone_type_of = validated_data.get( 'other_telephone_type_of', None) # Postal Address instance.address_country = validated_data.get('address_country', None) instance.address_locality = validated_data.get('address_locality', None) instance.address_region = validated_data.get('address_region', None) instance.post_office_box_number = validated_data.get( 'post_office_box_number', None) instance.postal_code = validated_data.get('postal_code', None) instance.street_address = validated_data.get('street_address', None) instance.street_address_extra = validated_data.get( 'street_address_extra', None) # Geo-coordinate instance.elevation = validated_data.get('elevation', None) instance.latitude = validated_data.get('latitude', None) instance.longitude = validated_data.get('longitude', None) # 'location' #TODO: IMPLEMENT. # Save our instance. instance.save() logger.info("Updated the staff member.") #------------------------ # Set our `Tag` objects. #------------------------ tags = validated_data.get('tags', None) if tags is not None: if len(tags) > 0: instance.tags.set(tags) #--------------------------- # Attach our comment. #--------------------------- extra_comment = validated_data.get('extra_comment', None) if extra_comment is not None: comment = Comment.objects.create( created_by=self.context['last_modified_by'], last_modified_by=self.context['last_modified_by'], text=extra_comment, created_from=self.context['last_modified_from'], created_from_is_public=self. context['last_modified_from_is_public']) staff_comment = StaffComment.objects.create( staff=instance, comment=comment, ) #--------------------------- # Update validation data. #--------------------------- # validated_data['comments'] = StaffComment.objects.filter(staff=instance) validated_data['last_modified_by'] = self.context['last_modified_by'] # validated_data['extra_comment'] = None # Return our validated data. return validated_data
class AssociateRetrieveUpdateDestroySerializer(serializers.ModelSerializer): # We are overriding the `email` field to include unique email validation. email = serializers.EmailField( validators=[UniqueValidator(queryset=Associate.objects.all())], required=True, allow_blank=False, ) # All comments are created by our `create` function and not by # `django-rest-framework`. # comments = AssociateCommentSerializer(many=True, read_only=True) # # This is a field used in the `create` function if the user enters a # # comment. This field is *ONLY* to be used during the POST creation and # # will be blank during GET. # extra_comment = serializers.CharField(write_only=True, allow_null=True) # The skill_sets that this associate belongs to. We will return primary # keys only. This field is read/write accessible. skill_sets = serializers.PrimaryKeyRelatedField( many=True, queryset=SkillSet.objects.all(), allow_null=True) insurance_requirements = serializers.PrimaryKeyRelatedField( many=True, queryset=InsuranceRequirement.objects.all(), allow_null=True) # assigned_skill_sets = SkillSetListCreateSerializer(many=True, read_only=True) # Custom formatting of our telephone fields. fax_number = PhoneNumberField(allow_null=True, required=False) telephone = PhoneNumberField() other_telephone = PhoneNumberField(allow_null=True, required=False) is_active = serializers.BooleanField( write_only=True, required=True, ) join_date = serializers.DateField(required=True, ) class Meta: model = Associate fields = ( # Thing 'id', 'created', 'last_modified', 'description', # Person 'given_name', 'middle_name', 'last_name', 'birthdate', 'join_date', 'gender', 'description', 'tax_id', # Misc (Read/Write) 'is_active', 'is_ok_to_email', 'is_ok_to_text', 'hourly_salary_desired', 'limit_special', 'dues_date', 'commercial_insurance_expiry_date', 'auto_insurance_expiry_date', 'wsib_number', 'wsib_insurance_date', 'police_check', 'drivers_license_class', 'vehicle_types', # many-to-many 'how_hear', 'how_hear_other', 'skill_sets', # many-to-many 'tags', # many-to-many 'insurance_requirements', # many-to-many # Misc (Read Only) # 'comments', # 'assigned_skill_sets', # 'organizations', #TODO: FIX # # Misc (Write Only) # 'extra_comment', # Contact Point 'area_served', 'available_language', 'contact_type', 'email', 'fax_number', # 'hours_available', #TODO: FIX 'telephone', 'telephone_extension', 'telephone_type_of', 'other_telephone', 'other_telephone_extension', 'other_telephone_type_of', # Postal Address 'address_country', 'address_locality', 'address_region', 'post_office_box_number', 'postal_code', 'street_address', 'street_address_extra', # Geo-coordinate 'elevation', 'latitude', 'longitude', # 'location' #TODO: FIX ) extra_kwargs = { "is_ok_to_email": { "error_messages": { "invalid": _("Please pick either 'Yes' or 'No' choice.") } }, "is_ok_to_text": { "error_messages": { "invalid": _("Please pick either 'Yes' or 'No' choice.") } }, "hourly_salary_desired": { "error_messages": { "min_value": _("Ensure this value is greater than or equal to 0."), "invalid": _("Please enter a value with no $, such as 20") } } } def setup_eager_loading(cls, queryset): """ Perform necessary eager loading of data. """ queryset = queryset.prefetch_related('owner', 'created_by', 'last_modified_by', 'skill_sets', 'tags', 'vehicle_types' 'comments', 'insurance_requirements') return queryset def update(self, instance, validated_data): """ Override this function to include extra functionality. """ # For debugging purposes only. # logger.info(validated_data) # Get our inputs. email = validated_data.get('email', instance.email) skill_sets = validated_data.get('skill_sets', None) vehicle_types = validated_data.get('vehicle_types', None) insurance_requirements = validated_data.get('insurance_requirements', None) # Update telephone numbers. fax_number = validated_data.get('fax_number', instance.fax_number) if fax_number is not None: validated_data['fax_number'] = phonenumbers.parse(fax_number, "CA") telephone = validated_data.get('telephone', instance.telephone) if telephone is not None: validated_data['telephone'] = phonenumbers.parse(telephone, "CA") other_telephone = validated_data.get('other_telephone', instance.other_telephone) if other_telephone is not None: validated_data['other_telephone'] = phonenumbers.parse( other_telephone, "CA") #--------------------------- # Update `SharedUser` object. #--------------------------- instance.owner, created = SharedUser.objects.update_or_create( email=email, defaults={ 'email': email, 'first_name': validated_data.get('given_name', instance.given_name), 'last_name': validated_data.get('last_name', instance.last_name), 'is_active': validated_data.get('is_active', False) }) logger.info("Updated shared user.") # Update the password. password = validated_data.get('password', None) if password: instance.owner.set_password(password) # Save the model. instance.owner.save() logger.info("Password was updated.") #--------------------------- # Update `Associate` object. #--------------------------- instance.email = email # Profile instance.given_name = validated_data.get('given_name', instance.given_name) instance.last_name = validated_data.get('last_name', instance.last_name) instance.middle_name = validated_data.get('middle_name', instance.middle_name) instance.birthdate = validated_data.get('birthdate', instance.birthdate) instance.join_date = validated_data.get('join_date', instance.join_date) instance.gender = validated_data.get('gender', instance.gender) instance.description = validated_data.get('description', instance.description) instance.tax_id = validated_data.get('tax_id', instance.tax_id) # Misc instance.is_ok_to_email = validated_data.get('is_ok_to_email', instance.is_ok_to_email) instance.is_ok_to_text = validated_data.get('is_ok_to_text', instance.is_ok_to_text) instance.hourly_salary_desired = validated_data.get( 'hourly_salary_desired', instance.hourly_salary_desired) instance.limit_special = validated_data.get('limit_special', instance.limit_special) instance.dues_date = validated_data.get('dues_date', instance.dues_date) instance.commercial_insurance_expiry_date = validated_data.get( 'commercial_insurance_expiry_date', instance.commercial_insurance_expiry_date) instance.auto_insurance_expiry_date = validated_data.get( 'auto_insurance_expiry_date', instance.auto_insurance_expiry_date) instance.wsib_insurance_date = validated_data.get( 'wsib_insurance_date', instance.wsib_insurance_date) instance.wsib_number = validated_data.get('wsib_number', instance.wsib_number) instance.police_check = validated_data.get('police_check', instance.police_check) instance.drivers_license_class = validated_data.get( 'drivers_license_class', instance.drivers_license_class) instance.how_hear = validated_data.get('how_hear', instance.how_hear) instance.how_hear_other = validated_data.get('how_hear_other', instance.how_hear_other) instance.last_modified_from = self.context['last_modified_from'] instance.last_modified_from_is_public = self.context[ 'last_modified_from_is_public'] instance.last_modified_by = self.context['last_modified_by'] # 'organizations', #TODO: IMPLEMENT. # Contact Point instance.area_served = validated_data.get('area_served', instance.area_served) instance.available_language = validated_data.get( 'available_language', instance.available_language) instance.contact_type = validated_data.get('contact_type', instance.contact_type) instance.fax_number = validated_data.get('fax_number', instance.fax_number) # 'hours_available', #TODO: IMPLEMENT. instance.telephone = validated_data.get('telephone', instance.telephone) instance.telephone_extension = validated_data.get( 'telephone_extension', instance.telephone_extension) instance.telephone_type_of = validated_data.get( 'telephone_type_of', TELEPHONE_CONTACT_POINT_TYPE_OF_ID) instance.other_telephone = validated_data.get('other_telephone', instance.other_telephone) instance.other_telephone_extension = validated_data.get( 'other_telephone_extension', instance.other_telephone_extension) instance.other_telephone_type_of = validated_data.get( 'other_telephone_type_of', TELEPHONE_CONTACT_POINT_TYPE_OF_ID) # Postal Address instance.address_country = validated_data.get('address_country', instance.address_country) instance.address_locality = validated_data.get( 'address_locality', instance.address_locality) instance.address_region = validated_data.get('address_region', instance.address_region) instance.post_office_box_number = validated_data.get( 'post_office_box_number', instance.post_office_box_number) instance.postal_code = validated_data.get('postal_code', instance.postal_code) instance.street_address = validated_data.get('street_address', instance.street_address) instance.street_address_extra = validated_data.get( 'street_address_extra', instance.street_address_extra) # Geo-coordinate instance.elevation = validated_data.get('elevation', instance.elevation) instance.latitude = validated_data.get('latitude', instance.latitude) instance.longitude = validated_data.get('longitude', instance.longitude) # 'location' #TODO: IMPLEMENT. # Save our instance. instance.save() logger.info("Updated the associate.") #----------------------------- # Set our `SkillSet` objects. #----------------------------- if skill_sets is not None: if len(skill_sets) > 0: instance.skill_sets.set(skill_sets) logger.info("Set associate skill sets.") #------------------------------- # Set our `VehicleType` objects. #------------------------------- if vehicle_types is not None: if len(vehicle_types) > 0: instance.vehicle_types.set(vehicle_types) logger.info("Set associate vehicle types.") #------------------------ # Set our `Tag` objects. #------------------------ tags = validated_data.get('tags', None) if tags is not None: if len(tags) > 0: instance.tags.set(tags) logger.info("Set associate tags.") #--------------------------- # Attach our comment. #--------------------------- extra_comment = validated_data.get('extra_comment', None) if extra_comment is not None: comment = Comment.objects.create( created_by=self.context['last_modified_by'], last_modified_by=self.context['last_modified_by'], text=extra_comment, created_from=self.context['last_modified_from'], created_from_is_public=self. context['last_modified_from_is_public']) AssociateComment.objects.create( about=instance, comment=comment, ) logger.info("Set associate comments.") #---------------------------------------- # Set our `InsuranceRequirement` objects. #---------------------------------------- if insurance_requirements is not None: if len(insurance_requirements) > 0: instance.insurance_requirements.set(insurance_requirements) logger.info("Set associate insurance requirements.") #--------------------------- # Update validation data. #--------------------------- # validated_data['comments'] = AssociateComment.objects.filter(associate=instance) validated_data['last_modified_by'] = self.context['last_modified_by'] # validated_data['extra_comment'] = None # validated_data['assigned_skill_sets'] = instance.skill_sets.all() # Return our validated data. return validated_data
class AssociateListCreateSerializer(serializers.ModelSerializer): # OVERRIDE THE MODEL FIELDS AND ENFORCE THE FOLLOWING CUSTOM VALIDATION RULES. given_name = serializers.CharField( required=True, allow_blank=False, ) last_name = serializers.CharField( required=True, allow_blank=False, ) address_country = serializers.CharField( required=True, allow_blank=False, ) address_region = serializers.CharField( required=True, allow_blank=False, ) address_locality = serializers.CharField( required=True, allow_blank=False, ) postal_code = serializers.CharField( required=True, allow_blank=False, ) street_address = serializers.CharField( required=True, allow_blank=False, ) join_date = serializers.DateField(required=True, ) # We are overriding the `email` field to include unique email validation. email = serializers.EmailField( validators=[UniqueValidator(queryset=SharedUser.objects.all())], required=True, ) # All comments are created by our `create` function and not by # `django-rest-framework`. # comments = AssociateCommentSerializer(many=True, read_only=True, allow_null=True) # This is a field used in the `create` function if the user enters a # comment. This field is *ONLY* to be used during the POST creation and # will be blank during GET. extra_comment = serializers.CharField(write_only=True, allow_null=True) # # The skill_sets that this associate belongs to. We will return primary # # keys only. This field is read/write accessible. # skill_sets = serializers.PrimaryKeyRelatedField(many=True, queryset=SkillSet.objects.all(), allow_null=True) # assigned_skill_sets = SkillSetListCreateSerializer(many=True, read_only=True) # Custom formatting of our telephone fields. fax_number = PhoneNumberField(allow_null=True, required=False) telephone = PhoneNumberField( allow_null=False, required=True, ) other_telephone = PhoneNumberField(allow_null=True, required=False) # Add password adding. password = serializers.CharField( write_only=True, required=True, allow_blank=False, max_length=63, style={'input_type': 'password'}, validators=[ MatchingDuelFieldsValidator( another_field='password_repeat', message=_("Inputted passwords fields do not match.")), EnhancedPasswordStrengthFieldValidator() ]) password_repeat = serializers.CharField(write_only=True, required=True, allow_blank=False, max_length=63, style={'input_type': 'password'}) is_active = serializers.BooleanField( write_only=True, required=True, error_messages={"invalid": "Please pick either 'Yes' or 'No' choice."}) # Meta Information. class Meta: model = Associate fields = ( # Thing 'id', 'created', 'last_modified', # Person 'given_name', 'middle_name', 'last_name', 'birthdate', 'join_date', 'gender', 'description', 'tax_id', # Misc (Read/Write) 'is_active', 'is_ok_to_email', 'is_ok_to_text', 'hourly_salary_desired', 'limit_special', 'dues_date', 'commercial_insurance_expiry_date', 'auto_insurance_expiry_date', 'wsib_number', 'wsib_insurance_date', 'police_check', 'drivers_license_class', 'vehicle_types', # many-to-many 'how_hear', 'how_hear_other', 'skill_sets', # many-to-many 'tags', # many-to-many 'insurance_requirements', # many-to-many # Misc (Read Only) # 'comments', 'password', 'password_repeat', # # Misc (Write Only) 'extra_comment', # Contact Point 'area_served', 'available_language', 'contact_type', 'email', 'fax_number', # 'hours_available', #TODO: FIX 'telephone', 'telephone_extension', 'telephone_type_of', 'other_telephone', 'other_telephone_extension', 'other_telephone_type_of', # Postal Address 'address_country', 'address_locality', 'address_region', 'post_office_box_number', 'postal_code', 'street_address', 'street_address_extra', # Geo-coordinate 'elevation', 'latitude', 'longitude', # 'location' #TODO: FIX ) extra_kwargs = { "is_ok_to_email": { "error_messages": { "invalid": _("Please pick either 'Yes' or 'No' choice.") } }, "is_ok_to_text": { "error_messages": { "invalid": _("Please pick either 'Yes' or 'No' choice.") } }, "hourly_salary_desired": { "error_messages": { "min_value": _("Ensure this value is greater than or equal to 0."), "invalid": _("Please enter a value with no $, such as 20") } } } def validate_telephone(self, value): """ Include validation on no-blanks """ if value is None: raise serializers.ValidationError("This field may not be blank.") return value def setup_eager_loading(cls, queryset): """ Perform necessary eager loading of data. """ queryset = queryset.prefetch_related( 'owner', 'created_by', 'last_modified_by', 'tags', 'skill_sets', 'vehicle_types' 'comments', 'insurance_requirements', ) return queryset def create(self, validated_data): """ Override the `create` function to add extra functinality: - Create a `User` object in the public database. - Create a `SharedUser` object in the public database. - Create a `Associate` object in the tenant database. - If user has entered text in the 'extra_comment' field then we will a `Comment` object and attach it to the `Associate` object. - We will attach the staff user whom created this `Associate` object. """ # Format our telephone(s) fax_number = validated_data.get('fax_number', None) if fax_number: fax_number = phonenumbers.parse(fax_number, "CA") telephone = validated_data.get('telephone', None) if telephone: telephone = phonenumbers.parse(telephone, "CA") other_telephone = validated_data.get('other_telephone', None) if other_telephone: other_telephone = phonenumbers.parse(other_telephone, "CA") validated_data['fax_number'] = fax_number validated_data['telephone'] = telephone validated_data['other_telephone'] = other_telephone #------------------- # Create our user. #------------------- email = validated_data.get('email', None) # Extract our "email" field. owner = SharedUser.objects.create( first_name=validated_data['given_name'], last_name=validated_data['last_name'], email=email, franchise=self.context['franchise'], was_email_activated=True, is_active=validated_data['is_active'], ) # Attach the user to the `Associate` group. owner.groups.add(ASSOCIATE_GROUP_ID) # Update the password. password = validated_data.get('password', None) owner.set_password(password) owner.save() logger.info("Created shared user.") #--------------------------------------------------- # Create our `Associate` object in our tenant schema. #--------------------------------------------------- # Create an "Associate". associate = Associate.objects.create( owner=owner, created_by=self.context['created_by'], last_modified_by=self.context['created_by'], description=validated_data['description'], # Profile given_name=validated_data['given_name'], last_name=validated_data['last_name'], middle_name=validated_data['middle_name'], birthdate=validated_data.get('birthdate', None), join_date=validated_data.get('join_date', None), gender=validated_data.get('gender', None), tax_id=validated_data.get('tax_id', None), # Misc is_ok_to_email=validated_data.get('is_ok_to_email', None), is_ok_to_text=validated_data.get('is_ok_to_text', None), hourly_salary_desired=validated_data.get('hourly_salary_desired', 0.00), limit_special=validated_data.get('limit_special', None), dues_date=validated_data.get('dues_date', None), commercial_insurance_expiry_date=validated_data.get( 'commercial_insurance_expiry_date', None), auto_insurance_expiry_date=validated_data.get( 'auto_insurance_expiry_date', None), wsib_number=validated_data.get('wsib_number', None), wsib_insurance_date=validated_data.get('wsib_insurance_date', None), police_check=validated_data.get('police_check', None), drivers_license_class=validated_data.get('drivers_license_class', None), how_hear=validated_data.get('how_hear', None), how_hear_other=validated_data.get('how_hear_other', None), created_from=self.context['created_from'], created_from_is_public=self.context['created_from_is_public'], # 'organizations', #TODO: IMPLEMENT. # Contact Point area_served=validated_data.get('area_served', None), available_language=validated_data.get('available_language', None), contact_type=validated_data.get('contact_type', None), email=email, fax_number=fax_number, # 'hours_available', #TODO: IMPLEMENT. telephone=telephone, telephone_extension=validated_data.get('telephone_extension', None), telephone_type_of=validated_data.get('telephone_type_of', None), other_telephone=other_telephone, other_telephone_extension=validated_data.get( 'other_telephone_extension', None), other_telephone_type_of=validated_data.get( 'other_telephone_type_of', None), # Postal Address address_country=validated_data.get('address_country', None), address_locality=validated_data.get('address_locality', None), address_region=validated_data.get('address_region', None), post_office_box_number=validated_data.get('post_office_box_number', None), postal_code=validated_data.get('postal_code', None), street_address=validated_data.get('street_address', None), street_address_extra=validated_data.get('street_address_extra', None), # Geo-coordinate elevation=validated_data.get('elevation', None), latitude=validated_data.get('latitude', None), longitude=validated_data.get('longitude', None), # 'location' #TODO: IMPLEMENT. ) logger.info("Created associate.") #----------------------------- # Set our `SkillSet` objects. #----------------------------- skill_sets = validated_data.get('skill_sets', None) if skill_sets is not None: if len(skill_sets) > 0: associate.skill_sets.set(skill_sets) logger.info("Set associate skill sets.") #------------------------------- # Set our `VehicleType` objects. #------------------------------- vehicle_types = validated_data.get('vehicle_types', None) if vehicle_types is not None: if len(vehicle_types) > 0: associate.vehicle_types.set(vehicle_types) logger.info("Set associate vehicle types.") #------------------------ # Set our `Tag` objects. #------------------------ tags = validated_data.get('tags', None) if tags is not None: if len(tags) > 0: associate.tags.set(tags) logger.info("Set associate tags.") #----------------------------- # Create our `Comment` object. #----------------------------- extra_comment = validated_data.get('extra_comment', None) if extra_comment is not None: comment = Comment.objects.create( created_by=self.context['created_by'], last_modified_by=self.context['created_by'], text=extra_comment, created_from=self.context['created_from'], created_from_is_public=self.context['created_from_is_public']) AssociateComment.objects.create( about=associate, comment=comment, ) logger.info("Set associate comments.") #---------------------------------------- # Set our `InsuranceRequirement` objects. #---------------------------------------- insurance_requirements = validated_data.get('insurance_requirements', None) if insurance_requirements is not None: if len(insurance_requirements) > 0: associate.insurance_requirements.set(insurance_requirements) logger.info("Set associate insurance requirements.") # Update validation data. # validated_data['comments'] = AssociateComment.objects.filter(associate=associate) validated_data['created_by'] = self.context['created_by'] validated_data['last_modified_by'] = self.context['created_by'] validated_data['extra_comment'] = None validated_data['id'] = associate.id # validated_data['assigned_skill_sets'] = associate.skill_sets.all() # Return our validated data. return validated_data
class CustomerRetrieveUpdateDestroySerializer(serializers.ModelSerializer): # owner = serializers.PrimaryKeyRelatedField(many=False, read_only=True) # We are overriding the `email` field to include unique email validation. email = serializers.EmailField( validators=[UniqueValidator(queryset=Customer.objects.all())], required=False ) # All comments are created by our `create` function and not by # `django-rest-framework`. # comments = CustomerCommentSerializer(many=True, read_only=True) # This is a field used in the `create` function if the user enters a # comment. This field is *ONLY* to be used during the POST creation and # will be blank during GET. extra_comment = serializers.CharField(write_only=True, allow_null=True) # Custom formatting of our telephone fields. fax_number = PhoneNumberField(allow_null=True, required=False) telephone = PhoneNumberField(allow_null=True, required=False) other_telephone = PhoneNumberField(allow_null=True, required=False) # Add password adding. password = serializers.CharField( write_only=True, required=False, allow_blank=True, max_length=63, style={'input_type': 'password'}, validators = [ MatchingDuelFieldsValidator( another_field='password_repeat', message=_("Inputted passwords fields do not match.") ), EnhancedPasswordStrengthFieldValidator() ] ) password_repeat = serializers.CharField( write_only=True, required=False, allow_blank=True, max_length=63, style={'input_type': 'password'} ) # # Fields used for mapping to organizations. # organization_name = serializers.CharField( write_only=True, required=False, allow_blank=False, allow_null=False, max_length=63, # validators=[ # UniqueValidator( # queryset=Organization.objects.all(), # ) # ], ) organization_type_of = serializers.CharField( write_only=True, required=True, allow_blank=True, max_length=63, ) organization_address_country = serializers.CharField( write_only=True, required=False, allow_blank=True, max_length=127, ) organization_address_locality = serializers.CharField( write_only=True, required=False, allow_blank=True, max_length=127, ) organization_address_region = serializers.CharField( write_only=True, required=False, allow_blank=True, max_length=127, ) organization_post_office_box_number = serializers.CharField( write_only=True, required=False, allow_blank=True, max_length=255, ) organization_postal_code = serializers.CharField( write_only=True, required=False, allow_blank=True, max_length=127, ) organization_street_address = serializers.CharField( write_only=True, required=False, allow_blank=True, max_length=255, ) organization_street_address_extra = serializers.CharField( write_only=True, required=False, allow_blank=True, max_length=255, ) class Meta: model = Customer fields = ( # Thing 'id', 'created', 'last_modified', # 'owner', 'description', # Person 'given_name', 'middle_name', 'last_name', 'birthdate', 'join_date', 'gender', # Misc (Read/Write) 'is_ok_to_email', 'is_ok_to_text', 'is_senior', 'is_support', 'job_info_read', 'type_of', 'tags', 'how_hear', 'how_hear_other', # Misc (Read Only) 'extra_comment', # Misc (Write Only) 'password', 'password_repeat', # Organization 'organization_name', 'organization_type_of', 'organization_address_country', 'organization_address_locality', 'organization_address_region', 'organization_post_office_box_number', 'organization_postal_code', 'organization_street_address', 'organization_street_address_extra', # Contact Point 'area_served', 'available_language', 'contact_type', 'email', 'fax_number', # 'hours_available', #TODO: FIX 'telephone', 'telephone_extension', 'telephone_type_of', 'other_telephone', 'other_telephone_extension', 'other_telephone_type_of', # Postal Address 'address_country', 'address_locality', 'address_region', 'post_office_box_number', 'postal_code', 'street_address', 'street_address_extra', # Geo-coordinate 'elevation', 'latitude', 'longitude', # 'location' #TODO: FIX ) def setup_eager_loading(cls, queryset): """ Perform necessary eager loading of data. """ queryset = queryset.prefetch_related( 'owner', 'created_by', 'last_modified_by', 'tags', 'comments', 'organization' ) return queryset def validate(self, data): """ Override the validator to provide additional custom validation based on our custom logic. 1. If 'type_of' == Commercial then make sure 'email' was inputted. """ # CASE 1 - Other reason if data.get('type_of', None) == COMMERCIAL_CUSTOMER_TYPE_OF_ID: email = data.get('email', None) if email is None: raise serializers.ValidationError(_("Please provide an email if client is commercial.")) # Return our data. return data def update(self, instance, validated_data): """ Override this function to include extra functionality. """ # Get our inputs. email = validated_data.get('email', instance.email) type_of_customer = validated_data.get('type_of', UNASSIGNED_CUSTOMER_TYPE_OF_ID) #----------------------------------------------------------- # Bugfix: Created `SharedUser` object if not created before. #----------------------------------------------------------- if instance.owner is None and email: owner = SharedUser.objects.filter(email=email).first() if owner: instance.owner = owner instance.save() logger.info("BUGFIX: Attached existing shared user to staff.") else: instance.owner = SharedUser.objects.create( first_name=validated_data['given_name'], last_name=validated_data['last_name'], email=email, is_active=True, franchise=self.context['franchise'], was_email_activated=True ) instance.save() logger.info("BUGFIX: Created shared user and attached to staff.") #--------------------------- # Update `SharedUser` object. #--------------------------- if instance.owner: # Update details. instance.owner.first_name = validated_data.get('given_name', instance.owner.first_name) instance.owner.last_name = validated_data.get('last_name', instance.owner.last_name) if email: instance.owner.email = email instance.owner.username = get_unique_username_from_email(email) # Update the password. password = validated_data.get('password', None) instance.owner.set_password(password) # Save the model to the database. instance.owner.save() logger.info("Updated shared user.") #--------------------------- # Update `Customer` object. #--------------------------- # Update email instance. instance.description = validated_data.get('description', instance.description) if email: instance.email = email # Profile instance.given_name = validated_data.get('given_name', instance.given_name) instance.middle_name = validated_data.get('middle_name', instance.middle_name) instance.last_name = validated_data.get('last_name', instance.last_name) instance.last_modified_by = self.context['last_modified_by'] instance.birthdate = validated_data.get('birthdate', instance.birthdate) instance.join_date = validated_data.get('join_date', instance.join_date) instance.gender = validated_data.get('gender', instance.gender) # Misc (Read/Write) instance.is_ok_to_email = validated_data.get('is_ok_to_email', instance.is_ok_to_email) instance.is_ok_to_text = validated_data.get('is_ok_to_text', instance.is_ok_to_text) instance.is_senior = validated_data.get('is_ok_to_text', instance.is_ok_to_text) instance.is_senior = validated_data.get('is_senior', instance.is_senior) instance.is_support = validated_data.get('is_support', instance.is_support) instance.job_info_read = validated_data.get('job_info_read', instance.job_info_read) instance.how_hear = validated_data.get('how_hear', instance.how_hear) instance.how_hear_other = validated_data.get('how_hear_other', instance.how_hear_other) instance.type_of=validated_data.get('type_of', instance.type_of) # # Misc (Read Only) instance.last_modified_by = self.context['last_modified_by'] instance.last_modified_from = self.context['last_modified_from'] instance.last_modified_from_is_public = self.context['last_modified_from_is_public'] # 'organizations', #TODO: FIX # Contact Point instance.area_served = validated_data.get('area_served', instance.area_served) instance.available_language = validated_data.get('available_language', instance.available_language) instance.contact_type = validated_data.get('contact_type', instance.contact_type) instance.email = validated_data.get('email', instance.contact_type) instance.fax_number = validated_data.get('fax_number', instance.fax_number) # 'hours_available', #TODO: FIX instance.telephone=validated_data.get('telephone', None) instance.telephone_extension=validated_data.get('telephone_extension', None) instance.telephone_type_of=validated_data.get('telephone_type_of', None) instance.other_telephone=validated_data.get('other_telephone', None) instance.other_telephone_extension=validated_data.get('other_telephone_extension', None) instance.other_telephone_type_of=validated_data.get('other_telephone_type_of', None) # Postal Address instance.address_country = validated_data.get('address_country', instance.address_country) instance.address_locality = validated_data.get('address_locality', instance.address_locality) instance.address_region = validated_data.get('address_region', instance.address_region) instance.post_office_box_number = validated_data.get('post_office_box_number', instance.post_office_box_number) instance.postal_code = validated_data.get('postal_code', instance.postal_code) instance.street_address = validated_data.get('street_address', instance.street_address) instance.street_address_extra = validated_data.get('street_address_extra', instance.street_address_extra) # Geo-coordinate instance.elevation = validated_data.get('elevation', instance.elevation) instance.latitude = validated_data.get('latitude', instance.latitude) instance.longitude = validated_data.get('longitude', instance.longitude) # 'location' #TODO: FIX # Save instance.save() logger.info("Updated the customer.") #------------------------ # Set our `Tag` objects. #------------------------ tags = validated_data.get('tags', instance.tags) if tags is not None: if len(tags) > 0: instance.tags.set(tags) #--------------------------- # Attach our comment. #--------------------------- extra_comment = validated_data.get('extra_comment', None) if extra_comment is not None: comment = Comment.objects.create( created_by=self.context['last_modified_by'], last_modified_by=self.context['last_modified_by'], text=extra_comment, created_from = self.context['last_modified_from'], created_from_is_public = self.context['last_modified_from_is_public'] ) CustomerComment.objects.create( about=instance, comment=comment, ) #---------------------------------------- # Update or create `Organization` object. #---------------------------------------- if type_of_customer == COMMERCIAL_CUSTOMER_TYPE_OF_ID: logger.info("Detected commercial customer...") organization_name = validated_data.get('organization_name', None) organization_type_of = validated_data.get('organization_type_of', None) organization_address_country = validated_data.get('organization_address_country', None) organization_address_locality = validated_data.get('organization_address_locality', None) organization_address_region = validated_data.get('organization_address_region', None) organization_post_office_box_number = validated_data.get('organization_post_office_box_number', None) organization_postal_code = validated_data.get('organization_postal_code', None) organization_street_address = validated_data.get('organization_street_address', None) organization_street_address_extra = validated_data.get('organization_street_address_extra', None) if organization_name and organization_type_of: organization, created = Organization.objects.update_or_create( name=organization_name, type_of=organization_type_of, defaults={ 'type_of': organization_type_of, 'name': organization_name, 'address_country': organization_address_country, 'address_locality': organization_address_locality, 'address_region': organization_address_region, 'post_office_box_number': organization_post_office_box_number, 'postal_code': organization_postal_code, 'street_address': organization_street_address, 'street_address_extra': organization_street_address_extra, } ) logger.info("Created organization.") if created: logger.info("Created organization.") organization.owner = instance.owner organization.save() instance.organization = organization instance.save() logger.info("Attached created organization to customer.") #--------------------------- # Update validation data. #--------------------------- # validated_data['comments'] = CustomerComment.objects.filter(customer=instance) validated_data['last_modified_by'] = self.context['last_modified_by'] validated_data['extra_comment'] = None # Return our validated data. return validated_data
class CustomerListCreateSerializer(serializers.ModelSerializer): # OVERRIDE THE MODEL FIELDS AND ENFORCE THE FOLLOWING CUSTOM VALIDATION RULES. given_name = serializers.CharField( required=True, allow_blank=False, ) last_name = serializers.CharField( required=True, allow_blank=False, ) address_country = serializers.CharField( required=True, allow_blank=False, ) address_region = serializers.CharField( required=True, allow_blank=False, ) address_locality = serializers.CharField( required=True, allow_blank=False, ) postal_code = serializers.CharField( required=True, allow_blank=False, ) street_address = serializers.CharField( required=True, allow_blank=False, ) # We are overriding the `email` field to include unique email validation. email = serializers.EmailField( validators=[UniqueValidator(queryset=SharedUser.objects.all())], required=False, ) # All comments are created by our `create` function and not by # `django-rest-framework`. # comments = CustomerCommentSerializer(many=True, read_only=True, allow_null=True) # This is a field used in the `create` function if the user enters a # comment. This field is *ONLY* to be used during the POST creation and # will be blank during GET. extra_comment = serializers.CharField(write_only=True, allow_null=True) # Custom formatting of our telephone fields. fax_number = PhoneNumberField(allow_null=True, required=False) telephone = PhoneNumberField(allow_null=False, required=True,) other_telephone = PhoneNumberField(allow_null=True, required=False) # Add password adding. password = serializers.CharField( write_only=True, required=True, allow_blank=False, max_length=63, style={'input_type': 'password'}, validators = [ MatchingDuelFieldsValidator( another_field='password_repeat', message=_("Inputted passwords fields do not match.") ), EnhancedPasswordStrengthFieldValidator() ] ) password_repeat = serializers.CharField( write_only=True, required=True, allow_blank=False, max_length=63, style={'input_type': 'password'} ) # # Fields used for mapping to organizations. # organization_name = serializers.CharField( write_only=True, required=False, allow_blank=False, allow_null=False, max_length=63, # validators=[ # UniqueValidator( # queryset=Organization.objects.all(), # ) # ], ) organization_type_of = serializers.CharField( write_only=True, required=True, allow_blank=True, max_length=63, ) organization_address_country = serializers.CharField( write_only=True, required=False, allow_blank=True, max_length=127, ) organization_address_locality = serializers.CharField( write_only=True, required=False, allow_blank=True, max_length=127, ) organization_address_region = serializers.CharField( write_only=True, required=False, allow_blank=True, max_length=127, ) organization_post_office_box_number = serializers.CharField( write_only=True, required=False, allow_blank=True, max_length=255, ) organization_postal_code = serializers.CharField( write_only=True, required=False, allow_blank=True, max_length=127, ) organization_street_address = serializers.CharField( write_only=True, required=False, allow_blank=True, max_length=255, ) organization_street_address_extra = serializers.CharField( write_only=True, required=False, allow_blank=True, max_length=255, ) # Meta Information. class Meta: model = Customer fields = ( # Thing 'id', 'created', 'last_modified', # 'owner', 'description', # Person 'given_name', 'middle_name', 'last_name', 'birthdate', 'join_date', 'gender', 'nationality', # Misc (Read/Write) 'is_ok_to_email', 'is_ok_to_text', 'is_senior', 'is_support', 'job_info_read', 'type_of', 'tags', 'how_hear', 'how_hear_other', # Misc (Read Only) # 'comments', 'password', 'password_repeat', # Organization 'organization_name', 'organization_type_of', 'organization_address_country', 'organization_address_locality', 'organization_address_region', 'organization_post_office_box_number', 'organization_postal_code', 'organization_street_address', 'organization_street_address_extra', # Misc (Write Only) 'extra_comment', # Contact Point 'area_served', 'available_language', 'contact_type', 'email', 'fax_number', # 'hours_available', #TODO: FIX 'telephone', 'telephone_extension', 'telephone_type_of', 'other_telephone', 'other_telephone_extension', 'other_telephone_type_of', # Postal Address 'address_country', 'address_locality', 'address_region', 'post_office_box_number', 'postal_code', 'street_address', 'street_address_extra', # Geo-coordinate 'elevation', 'latitude', 'longitude', # 'location' #TODO: FIX ) extra_kwargs = { "is_ok_to_email": { "error_messages": { "invalid": "Please pick either 'Yes' or 'No' choice." } }, "is_ok_to_text": { "error_messages": { "invalid": "Please pick either 'Yes' or 'No' choice." } } } def validate_telephone(self, value): """ Include validation on no-blanks """ if value is None: raise serializers.ValidationError("This field may not be blank.") return value def setup_eager_loading(cls, queryset): """ Perform necessary eager loading of data. """ queryset = queryset.prefetch_related( 'owner', 'created_by', 'last_modified_by', 'tags', 'comments' ) return queryset def create(self, validated_data): """ Override the `create` function to add extra functinality. """ type_of_customer = validated_data.get('type_of', UNASSIGNED_CUSTOMER_TYPE_OF_ID) # Format our telephone(s) fax_number = validated_data.get('fax_number', None) if fax_number: fax_number = phonenumbers.parse(fax_number, "CA") telephone = validated_data.get('telephone', None) if telephone: telephone = phonenumbers.parse(telephone, "CA") other_telephone = validated_data.get('other_telephone', None) if other_telephone: other_telephone = phonenumbers.parse(other_telephone, "CA") #------------------- # Create our user. #------------------- # Extract our "email" field. email = validated_data.get('email', None) # If an email exists then owner = None if email: owner = SharedUser.objects.create( first_name=validated_data['given_name'], last_name=validated_data['last_name'], email=email, is_active=True, franchise=self.context['franchise'], was_email_activated=True ) # Attach the user to the `Customer` group. owner.groups.add(CUSTOMER_GROUP_ID) # Update the password. password = validated_data.get('password', None) owner.set_password(password) owner.save() logger.info("Created shared user.") #--------------------------------------------------- # Create our `Customer` object in our tenant schema. #--------------------------------------------------- customer = Customer.objects.create( owner=owner, created_by=self.context['created_by'], last_modified_by=self.context['created_by'], description=validated_data.get('description', None), # Profile given_name=validated_data['given_name'], last_name=validated_data['last_name'], middle_name=validated_data['middle_name'], birthdate=validated_data.get('birthdate', None), join_date=validated_data.get('join_date', None), # Misc is_senior=validated_data.get('is_senior', False), is_support=validated_data.get('is_support', False), job_info_read=validated_data.get('job_info_read', False), how_hear=validated_data.get('how_hear', 1), how_hear_other=validated_data.get('how_hear_other', "Not answered"), type_of=type_of_customer, created_from = self.context['created_from'], created_from_is_public = self.context['created_from_is_public'], # Contact Point email=email, area_served=validated_data.get('area_served', None), available_language=validated_data.get('available_language', None), contact_type=validated_data.get('contact_type', None), fax_number=fax_number, # 'hours_available', #TODO: IMPLEMENT. telephone=telephone, telephone_extension=validated_data.get('telephone_extension', None), telephone_type_of=validated_data.get('telephone_type_of', None), other_telephone=other_telephone, other_telephone_extension=validated_data.get('other_telephone_extension', None), other_telephone_type_of=validated_data.get('other_telephone_type_of', None), # Postal Address address_country=validated_data.get('address_country', None), address_locality=validated_data.get('address_locality', None), address_region=validated_data.get('address_region', None), post_office_box_number=validated_data.get('post_office_box_number', None), postal_code=validated_data.get('postal_code', None), street_address=validated_data.get('street_address', None), street_address_extra=validated_data.get('street_address_extra', None), # Geo-coordinate elevation=validated_data.get('elevation', None), latitude=validated_data.get('latitude', None), longitude=validated_data.get('longitude', None), # 'location' #TODO: IMPLEMENT. ) logger.info("Created customer.") #----------------------------------- # Create or update our Organization. #----------------------------------- type_of_customer = validated_data.get('type_of', UNASSIGNED_CUSTOMER_TYPE_OF_ID) if type_of_customer == COMMERCIAL_JOB_TYPE_OF_ID: logger.info("Detected commercial customer...") organization_name = validated_data.get('organization_name', None) organization_type_of = validated_data.get('organization_type_of', None) organization_address_country = validated_data.get('organization_address_country', None) organization_address_locality = validated_data.get('organization_address_locality', None) organization_address_region = validated_data.get('organization_address_region', None) organization_post_office_box_number = validated_data.get('organization_post_office_box_number', None) organization_postal_code = validated_data.get('organization_postal_code', None) organization_street_address = validated_data.get('organization_street_address', None) organization_street_address_extra = validated_data.get('organization_street_address_extra', None) if organization_name and organization_type_of: organization, created = Organization.objects.update_or_create( name=organization_name, type_of=organization_type_of, defaults={ 'type_of': organization_type_of, 'name': organization_name, 'address_country': organization_address_country, 'address_locality': organization_address_locality, 'address_region': organization_address_region, 'post_office_box_number': organization_post_office_box_number, 'postal_code': organization_postal_code, 'street_address': organization_street_address, 'street_address_extra': organization_street_address_extra, } ) logger.info("Created organization.") if created: logger.info("Created organization.") organization.owner = owner organization.save() customer.organization = organization customer.save() logger.info("Attached created organization to customer.") #------------------------ # Set our `Tag` objects. #------------------------ tags = validated_data.get('tags', None) if tags is not None: if len(tags) > 0: customer.tags.set(tags) #----------------------------- # Create our `Comment` object. #----------------------------- extra_comment = validated_data.get('extra_comment', None) if extra_comment is not None: comment = Comment.objects.create( created_by=self.context['created_by'], last_modified_by=self.context['created_by'], text=extra_comment, created_from = self.context['created_from'], created_from_is_public = self.context['created_from_is_public'] ) CustomerComment.objects.create( about=customer, comment=comment, ) # Update validation data. # validated_data['comments'] = CustomerComment.objects.filter(customer=customer) validated_data['created_by'] = self.context['created_by'] validated_data['last_modified_by'] = self.context['created_by'] validated_data['extra_comment'] = None validated_data['telephone'] = telephone validated_data['fax_number'] = fax_number validated_data['other_telephone'] = other_telephone validated_data['id'] = customer.id # Return our validated data. return validated_data
class PartnerRetrieveUpdateDestroySerializer(serializers.ModelSerializer): # owner = serializers.PrimaryKeyRelatedField(many=False, read_only=True) # We are overriding the `email` field to include unique email validation. email = serializers.EmailField( validators=[UniqueValidator(queryset=Partner.objects.all())], required=True, allow_blank=False, ) # All comments are created by our `create` function and not by # `django-rest-framework`. # comments = PartnerCommentSerializer(many=True, read_only=True) # # This is a field used in the `create` function if the user enters a # # comment. This field is *ONLY* to be used during the POST creation and # # will be blank during GET. # extra_comment = serializers.CharField(write_only=True, allow_null=True) # Custom formatting of our telephone fields. fax_number = PhoneNumberField(allow_null=True, required=False) telephone = PhoneNumberField() other_telephone = PhoneNumberField(allow_null=True, required=False) is_active = serializers.BooleanField( write_only=True, required=True, ) class Meta: model = Partner fields = ( # Thing 'id', 'created', 'last_modified', # 'owner', 'description', # Profile 'given_name', 'middle_name', 'last_name', 'birthdate', 'join_date', # Misc (Read/Write) 'is_active', 'is_ok_to_email', 'is_ok_to_text', # 'is_senior', # 'is_support', # 'job_info_read', 'gender', # Misc (Read Only) # 'comments', # 'organizations', #TODO: FIX # Misc (Write Only) # 'extra_comment', # Contact Point 'area_served', 'available_language', 'contact_type', 'email', 'fax_number', # 'hours_available', #TODO: FIX 'telephone', 'telephone_extension', 'telephone_type_of', 'other_telephone', 'other_telephone_extension', 'other_telephone_type_of', # Postal Address 'address_country', 'address_locality', 'address_region', 'post_office_box_number', 'postal_code', 'street_address', 'street_address_extra', # Geo-coordinate 'elevation', 'latitude', 'longitude', # 'location' #TODO: FIX ) def setup_eager_loading(cls, queryset): """ Perform necessary eager loading of data. """ queryset = queryset.prefetch_related( 'owner', 'created_by', 'last_modified_by', # 'comments' ) return queryset def update(self, instance, validated_data): """ Override this function to include extra functionality. """ # For debugging purposes only. # print(validated_data) # Get our inputs. email = validated_data.get('email', instance.email) # Update telephone numbers. fax_number = validated_data.get('fax_number', instance.fax_number) if fax_number is not None: validated_data['fax_number'] = phonenumbers.parse(fax_number, "CA") telephone = validated_data.get('telephone', instance.telephone) if telephone is not None: validated_data['telephone'] = phonenumbers.parse(telephone, "CA") other_telephone = validated_data.get('other_telephone', instance.other_telephone) if other_telephone is not None: validated_data['other_telephone'] = phonenumbers.parse(other_telephone, "CA") #--------------------------- # Update `SharedUser` object. #--------------------------- instance.owner, created = SharedUser.objects.update_or_create( email=email, defaults={ 'email': email, 'first_name': validated_data.get('given_name', instance.given_name), 'last_name': validated_data.get('last_name', instance.last_name), 'is_active': validated_data.get('is_active', False) } ) logger.info("Updated shared user.") # Update the password. password = validated_data.get('password', None) if password: instance.owner.set_password(password) # Save the model. instance.owner.save() #--------------------------- # Update `Partner` object. #--------------------------- instance.email = email # Profile instance.given_name=validated_data.get('given_name', instance.given_name) instance.last_name=validated_data.get('last_name', instance.last_name) instance.middle_name=validated_data.get('middle_name', instance.middle_name) instance.birthdate=validated_data.get('birthdate', instance.birthdate) instance.join_date=validated_data.get('join_date', instance.join_date) instance.gender = validated_data.get('gender', instance.gender) instance.description = validated_data.get('description', instance.description) # Misc instance.is_ok_to_email=validated_data.get('is_ok_to_email', None) instance.is_ok_to_text=validated_data.get('is_ok_to_text', None) instance.hourly_salary_desired=validated_data.get('hourly_salary_desired', 0.00) instance.limit_special=validated_data.get('limit_special', None) instance.dues_date=validated_data.get('dues_date', None) instance.commercial_insurance_expiry_date=validated_data.get('commercial_insurance_expiry_date', None) instance.police_check=validated_data.get('police_check', None) instance.drivers_license_class=validated_data.get('drivers_license_class', None) instance.how_hear=validated_data.get('how_hear', None) instance.last_modified_by = self.context['last_modified_by'] instance.last_modified_from = self.context['last_modified_from'] instance.last_modified_from_is_public = self.context['last_modified_from_is_public'] # 'organizations', #TODO: IMPLEMENT. # Contact Point instance.area_served=validated_data.get('area_served', None) instance.available_language=validated_data.get('available_language', None) instance.contact_type=validated_data.get('contact_type', None) instance.fax_number=validated_data.get('fax_number', None) # 'hours_available', #TODO: IMPLEMENT. instance.telephone=validated_data.get('telephone', None) instance.telephone_extension=validated_data.get('telephone_extension', None) instance.telephone_type_of=validated_data.get('telephone_type_of', TELEPHONE_CONTACT_POINT_TYPE_OF_ID) instance.other_telephone=validated_data.get('other_telephone', None) instance.other_telephone_extension=validated_data.get('other_telephone_extension', None) instance.other_telephone_type_of=validated_data.get('other_telephone_type_of', TELEPHONE_CONTACT_POINT_TYPE_OF_ID) # Postal Address instance.address_country=validated_data.get('address_country', None) instance.address_locality=validated_data.get('address_locality', None) instance.address_region=validated_data.get('address_region', None) instance.post_office_box_number=validated_data.get('post_office_box_number', None) instance.postal_code=validated_data.get('postal_code', None) instance.street_address=validated_data.get('street_address', None) instance.street_address_extra=validated_data.get('street_address_extra', None) # Geo-coordinate instance.elevation=validated_data.get('elevation', None) instance.latitude=validated_data.get('latitude', None) instance.longitude=validated_data.get('longitude', None) # 'location' #TODO: IMPLEMENT. # Save our instance. instance.save() logger.info("Updated the partner.") # #--------------------------- # # Attach our comment. # #--------------------------- # extra_comment = validated_data.get('extra_comment', None) # if extra_comment is not None: # comment = Comment.objects.create( # created_by=self.context['last_modified_by'], # last_modified_by=self.context['last_modified_by'], # text=extra_comment # ) # partner_comment = PartnerComment.objects.create( # partner=instance, # comment=comment, # created_from = self.context['last_modified_from'], # created_from_is_public = self.context['last_modified_from_is_public'] # ) #--------------------------- # Update validation data. #--------------------------- # validated_data['comments'] = PartnerComment.objects.filter(partner=instance) validated_data['last_modified_by'] = self.context['last_modified_by'] # validated_data['extra_comment'] = None # Return our validated data. return validated_data