Skip to content

Commit

Permalink
Management command to cleanup existing user phones
Browse files Browse the repository at this point in the history
  • Loading branch information
raphodn committed May 16, 2024
1 parent 2b6d03b commit 751ec89
Show file tree
Hide file tree
Showing 2 changed files with 84 additions and 0 deletions.
67 changes: 67 additions & 0 deletions lemarche/users/management/commands/cleanup_user_phone_field.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
from django.core.management.base import BaseCommand

from lemarche.users.models import User
from lemarche.utils.data import phone_number_is_valid


DEFAULT_COUNTRY_CODE = "+33"


class Command(BaseCommand):
"""
This script is used to validate existing user phone numbers
And cleanup / replace them with valid numbers (with +33)
Usage:
python manage.py cleanup_user_phone_field
python manage.py cleanup_user_phone_field --dry-run
"""

def add_arguments(self, parser):
parser.add_argument("--dry-run", dest="dry_run", action="store_true", help="Dry run (no changes to the DB)")

def handle(self, *args, **options): # noqa C901
self.stdout.write("-" * 80)
self.stdout.write(f"Users: {User.objects.count()}")
qs = User.objects.exclude(phone="")
self.stdout.write(f"Users with a phone: {qs.count()}")

stats = {"has_dot_count": 0, "has_space_count": 0, "valid_count": 0, "invalid_count": 0, "update_count": 0}
invalid_list = list()

for index, user in enumerate(qs):
user_phone = str(user.phone)

# cleanup phone number
# example: "06.06.06.06.06" -> "0606060606"
# example: "06 06 06 06 06" -> "0606060606"
if "." in user_phone:
stats["has_dot_count"] += 1
user_phone = user_phone.replace(".", "")
if " " in user_phone:
stats["has_space_count"] += 1
user_phone = user_phone.replace(" ", "")

# try to add +33 to phone numbers without country code
# check that the phone number is valid before saving it
# example: "0606060606" -> "+33606060606"
if user_phone.isdigit() and len(user_phone) == 10:
user_phone_tentative = f"{DEFAULT_COUNTRY_CODE}{user_phone[1:]}"
if phone_number_is_valid(user_phone_tentative):
user_phone = user_phone_tentative

# if the final phone number is valid, save it
if phone_number_is_valid(user_phone):
stats["valid_count"] += 1
if user.phone != user_phone:
stats["update_count"] += 1
if not options["dry_run"]:
user.phone = user_phone
user.save(update_fields=["phone"])
else:
stats["invalid_count"] += 1
invalid_list.append(user_phone)

print(stats)
# for num in invalid_list:
# print(num)
17 changes: 17 additions & 0 deletions lemarche/utils/data.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import io

import phonenumbers

# from phonenumber_field.phonenumber import PhoneNumber
from django.core.management import call_command
from django.db import connection

Expand Down Expand Up @@ -45,3 +48,17 @@ def date_to_string(date, format="%d/%m/%Y"):
if date:
return date.strftime(format)
return ""


def phone_number_is_valid(phone_number):
"""
Ways to check if a phone number is valid:
- phonenumbers.is_valid_number(number_string) / returns True or False
- PhoneNumber.from_string(number_string).is_valid() / returns True or NumberParseException.INVALID_COUNTRY_CODE # noqa
A number without a country code (example: +33) will be considered invalid.
"""
try:
return phonenumbers.is_valid_number(phonenumbers.parse(phone_number))
except phonenumbers.phonenumberutil.NumberParseException:
return False

0 comments on commit 751ec89

Please sign in to comment.