Skip to content

Commit

Permalink
feat: statistiques sur la validité des numéros de téléphone (#1219)
Browse files Browse the repository at this point in the history
  • Loading branch information
raphodn authored May 21, 2024
1 parent ec96cb6 commit 8279dab
Show file tree
Hide file tree
Showing 2 changed files with 93 additions and 0 deletions.
19 changes: 19 additions & 0 deletions lemarche/utils/data.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import io

import phonenumbers
from django.core.management import call_command
from django.db import connection

Expand Down Expand Up @@ -45,3 +46,21 @@ 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:
- with phonenumbers
import phonenumbers
phonenumbers.is_valid_number(number_string) / returns True or False
- with PhoneNumber
from phonenumber_field.phonenumber import PhoneNumber
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
74 changes: 74 additions & 0 deletions lemarche/utils/management/commands/cleanup_phone_field.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
from django.apps import apps
from django.core.management.base import BaseCommand

from lemarche.utils.data import phone_number_is_valid


DEFAULT_COUNTRY_CODE = "+33"


class Command(BaseCommand):
"""
This script is used to validate existing phone numbers
And cleanup / replace them with valid numbers (with +33)
Usage:
python manage.py cleanup_phone_field --model users.User --field phone --dry-run
python manage.py cleanup_phone_field --model tenders.Tender --field contact_phone --dry-run
python manage.py cleanup_phone_field --model siaes.Siae --field contact_phone --dry-run
python manage.py cleanup_phone_field --model siaes.SiaeGroup --field contact_phone --dry-run
"""

def add_arguments(self, parser):
parser.add_argument("--model", dest="model", default="users.User", help="Model to update")
parser.add_argument("--field", dest="field", default="phone", help="Field where the phone number is stored")
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)
model_name = options["model"].split(".")[1]
field_name = options["field"]
Model = apps.get_model(options["model"].split(".")[0], model_name)
self.stdout.write(f"{model_name}: {Model.objects.count()}")
qs = Model.objects.exclude(**{field_name: ""})
self.stdout.write(f"{model_name} with a {field_name}: {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, item in enumerate(qs):
item_phone = item_phone_cleaned = str(getattr(item, field_name))

# cleanup phone number
# example: "06.06.06.06.06" -> "0606060606"
# example: "06 06 06 06 06" -> "0606060606"
if "." in item_phone_cleaned:
stats["has_dot_count"] += 1
item_phone_cleaned = item_phone_cleaned.replace(".", "")
if " " in item_phone:
stats["has_space_count"] += 1
item_phone_cleaned = item_phone_cleaned.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 item_phone_cleaned.isdigit() and len(item_phone_cleaned) == 10:
item_phone_cleaned_with_prefix = f"{DEFAULT_COUNTRY_CODE}{item_phone_cleaned[1:]}"
if phone_number_is_valid(item_phone_cleaned_with_prefix):
item_phone_cleaned = item_phone_cleaned_with_prefix

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

print(stats)
# for num in invalid_list:
# print(num)

0 comments on commit 8279dab

Please sign in to comment.