A confusing task!
Tags: backend, django, djangorest, webdev
Published: 2024-06-28 15:44:46

Have you ever felt a requirement was either impossible or atmost unrealistic? Like utterly confusing and you can't wrap your head as to why such a task was given?

I'm helping a friend out on a task; he has this particularly intersting criteria he wants sorted out. Apparently he an expense tracker app he uses to store information concerning budgets, expenses made and contributions. These data are stored and obviously validation are carried out on each input to ensure amounts are floated digits, emails are emails, ... and I'm sure you know the rest. 

So far everything is going well and he just received a load of information to save. The problem with this information is that more than half of the data have no phone numbers yet (yet as it could be gotten later and updated).

As we discussed on the possible solutions, I suggested leaving the phone number fields blank but he didn't want that. I suggested randomizing the phone numbers if they are blank but he didn't want that because he mentioned he would find it difficult locating them later incase he needs to update the records.

After a while, he mentioned he would love to enter the numbers himself with he pattern he would recognize. He suggested prefixing the phone number with the country code, fixed double digits and remaining 7 numbers
i.e., **(+233 (99) 1234567)**. This makes sense as he would always recognize the **99**.

Now here's the kicker, our Phone Number Serializer refused to accept this pattern and I thought it was impossible. The reason was, +233 is the Ghanian country code and **99** cannot be the first two digits after it (Ghanians should understand this). 

I won't lie, I honestly told him this was impossible as to achieve this, I had to remove the **PhoneNumber **Serializer field and use a normal **CharField** and this was unacceptable professionally as other countries could be registered and we needed a validation engine avaliable. 

After my brief moment of doubt, I decided to research and see how possible this was and I suprised when I found out I could actually manipulate the process to allow numbers following the pattern **+23399** and to ensure every other number entered was properly checked. 

This brings me to one of the reasons I'm making this public. Apart from the fact that I'm a programmer with over 10 years of development experience trying to come into the light and make myself public, (I've hidden myself for a while. I don't know why) one other major reason is this is a task from **HNG**. I have to talk about a recent task I found difficult (in my case disturbing because I actually felt it was unrealistic). 

**HNG** is a company with a mission `to empower the next generation of tech talent.` They work with the brightest technologists (programmers, designers, project managers, social media managers etc) to help them improve their skills and expand their professional network. Here's their link ([awesome link taking you to the HNG Tech official website](https://hng.tech/)). 

In case you want to join their network as an intern (trust me it's awesome), you can click this **link** too ([This link, not the previous one that's bold and shouty](https://hng.tech/internship)). 

They also have a love channel where they share job opportunites, you get to meet more awesome people (**like me**) and expand your professional network. Click the next link to visit ([Yes, this awesome link](https://hng.tech/premium)).


So, back to our solution. It's actually simple. I can manipulate the **Field** method of the **serializer** class and modify the expected serializer field. Like i mentioned earlier, the solution is quite simple; the **CharField** serializer field would be used for any number that is prefixed with **+23399** and any other number would have to deal with the strict validation process of the **PhoneNumberField**. 

The first block of code below is the DynamicPhoneNumberField class created to handle my request. 

`    class DynamicPhoneNumberField(serializers.Field):
        """
            Custom serializer field to handle phone numbers dynamically.
            Uses CharField for Ghanaian numbers prefixed with +23399
            and PhoneNumberField for others.
        """
        default_error_messages = {
            'invalid': 'Enter a valid phone number.',
        }

    def to_internal_value(self, data):
        # Check if it's a prefixed Ghanaian number and use 
        # CharField for it.
        if data.startswith("+23399") and len(data) == 13:
            return serializers.CharField().to_internal_value(data)
        else:
            try:
                # Try to parse the number using PhoneNumberField
                parsed = phonenumbers_parse(data, None)
                return PhoneNumberField().to_internal_value(data)
            except Exception:
                self.fail("invalid")`


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qm3hp8r0i4ixr8a0dvjk.png)




And the code below is the serializer class where I used this life saver in the form of a codebase

`
class ContributionSerializer(serializers.ModelSerializer):
    phonenumber = DynamicPhoneNumberField(required=False)
    first_name = serializers.CharField(required=False)
    last_name = serializers.CharField(required=False)
    ...
`

I smiled like a kid who found a new toy when this actually worked. I felt like a superhero (Batman to be precise) ...

If you made it this far, `Thank you for sticking around`. 

Here's a link to my [github profile](https://github.com/kramstyles)