diff --git a/care/facility/api/viewsets/patient_otp.py b/care/facility/api/viewsets/patient_otp.py index d2efa9ddcd..af365533ce 100644 --- a/care/facility/api/viewsets/patient_otp.py +++ b/care/facility/api/viewsets/patient_otp.py @@ -11,7 +11,7 @@ from care.facility.api.serializers.patient_otp import PatientMobileOTPSerializer from care.facility.models.patient import PatientMobileOTP -from care.users.models import phone_number_regex +from care.utils.models.validators import mobile_validator from config.patient_otp_token import PatientToken @@ -32,7 +32,7 @@ def login(self, request): phone_number = request.data["phone_number"] otp = request.data["otp"] try: - phone_number_regex(phone_number) + mobile_validator(phone_number) except error: raise ValidationError({"phone_number": "Invalid phone number format"}) if len(otp) != settings.OTP_LENGTH: diff --git a/care/facility/models/ambulance.py b/care/facility/models/ambulance.py index 6db3dbf68a..e0b7a07751 100644 --- a/care/facility/models/ambulance.py +++ b/care/facility/models/ambulance.py @@ -2,8 +2,9 @@ from django.core.validators import RegexValidator from django.db import models -from care.facility.models.base import FacilityBaseModel, phone_number_regex +from care.facility.models.base import FacilityBaseModel from care.users.models import District +from care.utils.models.validators import mobile_or_landline_number_validator User = get_user_model() @@ -27,7 +28,7 @@ class Ambulance(FacilityBaseModel): owner_name = models.CharField(max_length=255) owner_phone_number = models.CharField( - max_length=14, validators=[phone_number_regex] + max_length=14, validators=[mobile_or_landline_number_validator] ) owner_is_smart_phone = models.BooleanField(default=True) @@ -135,7 +136,9 @@ class AmbulanceDriver(FacilityBaseModel): ambulance = models.ForeignKey(Ambulance, on_delete=models.CASCADE) name = models.CharField(max_length=255) - phone_number = models.CharField(max_length=14, validators=[phone_number_regex]) + phone_number = models.CharField( + max_length=14, validators=[mobile_or_landline_number_validator] + ) is_smart_phone = models.BooleanField() def __str__(self): diff --git a/care/facility/models/asset.py b/care/facility/models/asset.py index fdeaff4263..839362d6e1 100644 --- a/care/facility/models/asset.py +++ b/care/facility/models/asset.py @@ -7,10 +7,10 @@ from care.facility.models.facility import Facility from care.facility.models.json_schema.asset import ASSET_META from care.facility.models.mixins.permissions.asset import AssetsPermissionMixin -from care.users.models import User, phone_number_regex_11 +from care.users.models import User from care.utils.assetintegration.asset_classes import AssetClasses from care.utils.models.base import BaseModel -from care.utils.models.validators import JSONFieldSchemaValidator +from care.utils.models.validators import JSONFieldSchemaValidator, PhoneNumberValidator def get_random_asset_id(): @@ -84,7 +84,9 @@ class Status(enum.Enum): vendor_name = models.CharField(max_length=1024, blank=True, null=True) support_name = models.CharField(max_length=1024, blank=True, null=True) support_phone = models.CharField( - max_length=14, validators=[phone_number_regex_11], default="" + max_length=14, + validators=[PhoneNumberValidator(types=("mobile", "landline", "support"))], + default="", ) support_email = models.EmailField(blank=True, null=True) qr_code_id = models.CharField(max_length=1024, blank=True, default=None, null=True) diff --git a/care/facility/models/base.py b/care/facility/models/base.py index c255710b38..a8993980c9 100644 --- a/care/facility/models/base.py +++ b/care/facility/models/base.py @@ -1,14 +1,6 @@ -from django.core.validators import RegexValidator - from care.users.models import User from care.utils.models.base import BaseModel -phone_number_regex = RegexValidator( - regex=r"^((\+91|91|0)[\- ]{0,1})?[456789]\d{9}$", - message="Please Enter 10/11 digit mobile number or landline as 0", - code="invalid_mobile", -) - READ_ONLY_USER_TYPES = [ User.TYPE_VALUE_MAP["DistrictReadOnlyAdmin"], User.TYPE_VALUE_MAP["StateReadOnlyAdmin"], diff --git a/care/facility/models/facility.py b/care/facility/models/facility.py index 327a310ee7..16f4f0f39f 100644 --- a/care/facility/models/facility.py +++ b/care/facility/models/facility.py @@ -6,12 +6,13 @@ from multiselectfield.utils import get_max_length from simple_history.models import HistoricalRecords -from care.facility.models import FacilityBaseModel, phone_number_regex, reverse_choices +from care.facility.models import FacilityBaseModel, reverse_choices from care.facility.models.mixins.permissions.facility import ( FacilityPermissionMixin, FacilityRelatedPermissionMixin, ) from care.users.models import District, LocalBody, State, Ward +from care.utils.models.validators import mobile_or_landline_number_validator User = get_user_model() @@ -150,7 +151,7 @@ class Facility(FacilityBaseModel, FacilityPermissionMixin): expected_type_d_cylinders = models.IntegerField(default=0) phone_number = models.CharField( - max_length=14, blank=True, validators=[phone_number_regex] + max_length=14, blank=True, validators=[mobile_or_landline_number_validator] ) corona_testing = models.BooleanField(default=False) created_by = models.ForeignKey( diff --git a/care/facility/models/patient.py b/care/facility/models/patient.py index 4131fef636..0d751ac8da 100644 --- a/care/facility/models/patient.py +++ b/care/facility/models/patient.py @@ -34,13 +34,9 @@ ) from care.facility.models.patient_consultation import PatientConsultation from care.facility.static_data.icd11 import ICDDiseases -from care.users.models import ( - GENDER_CHOICES, - REVERSE_GENDER_CHOICES, - User, - phone_number_regex, -) +from care.users.models import GENDER_CHOICES, REVERSE_GENDER_CHOICES, User from care.utils.models.base import BaseManager, BaseModel +from care.utils.models.validators import mobile_or_landline_number_validator class PatientRegistration(PatientBaseModel, PatientPermissionMixin): @@ -115,11 +111,11 @@ class TestTypeEnum(enum.Enum): # phone_number_old = EncryptedCharField(max_length=14, validators=[phone_number_regex], default="") phone_number = models.CharField( - max_length=14, validators=[phone_number_regex], default="" + max_length=14, validators=[mobile_or_landline_number_validator], default="" ) emergency_phone_number = models.CharField( - max_length=14, validators=[phone_number_regex], default="" + max_length=14, validators=[mobile_or_landline_number_validator], default="" ) # address_old = EncryptedTextField(default="") @@ -672,7 +668,9 @@ class Meta: class PatientMobileOTP(BaseModel): is_used = models.BooleanField(default=False) - phone_number = models.CharField(max_length=14, validators=[phone_number_regex]) + phone_number = models.CharField( + max_length=14, validators=[mobile_or_landline_number_validator] + ) otp = models.CharField(max_length=10) diff --git a/care/facility/models/resources.py b/care/facility/models/resources.py index c9655d2fd2..492e893aff 100644 --- a/care/facility/models/resources.py +++ b/care/facility/models/resources.py @@ -6,7 +6,8 @@ pretty_boolean, reverse_choices, ) -from care.users.models import User, phone_number_regex +from care.users.models import User +from care.utils.models.validators import mobile_or_landline_number_validator RESOURCE_STATUS_CHOICES = ( (10, "PENDING"), @@ -58,7 +59,10 @@ class ResourceRequest(FacilityBaseModel): reason = models.TextField(default="", blank=True) refering_facility_contact_name = models.TextField(default="", blank=True) refering_facility_contact_number = models.CharField( - max_length=14, validators=[phone_number_regex], default="", blank=True + max_length=14, + validators=[mobile_or_landline_number_validator], + default="", + blank=True, ) status = models.IntegerField( choices=RESOURCE_STATUS_CHOICES, default=10, null=False, blank=False diff --git a/care/facility/models/shifting.py b/care/facility/models/shifting.py index 2e94d25ac7..4b88925b60 100644 --- a/care/facility/models/shifting.py +++ b/care/facility/models/shifting.py @@ -7,7 +7,8 @@ pretty_boolean, reverse_choices, ) -from care.users.models import User, phone_number_regex +from care.users.models import User +from care.utils.models.validators import mobile_or_landline_number_validator SHIFTING_STATUS_CHOICES = ( (10, "PENDING"), @@ -78,7 +79,10 @@ class ShiftingRequest(FacilityBaseModel): comments = models.TextField(default="", blank=True) refering_facility_contact_name = models.TextField(default="", blank=True) refering_facility_contact_number = models.CharField( - max_length=14, validators=[phone_number_regex], default="", blank=True + max_length=14, + validators=[mobile_or_landline_number_validator], + default="", + blank=True, ) is_kasp = models.BooleanField(default=False) status = models.IntegerField( @@ -98,7 +102,10 @@ class ShiftingRequest(FacilityBaseModel): ) ambulance_driver_name = models.TextField(default="", blank=True) ambulance_phone_number = models.CharField( - max_length=14, validators=[phone_number_regex], default="", blank=True + max_length=14, + validators=[mobile_or_landline_number_validator], + default="", + blank=True, ) ambulance_number = models.TextField(default="", blank=True) created_by = models.ForeignKey( diff --git a/care/users/models.py b/care/users/models.py index e5578e340d..b7b50b7ffc 100644 --- a/care/users/models.py +++ b/care/users/models.py @@ -2,12 +2,16 @@ from django.contrib.auth.models import AbstractUser, UserManager from django.contrib.auth.validators import UnicodeUsernameValidator -from django.core.validators import MaxValueValidator, MinValueValidator, RegexValidator +from django.core.validators import MaxValueValidator, MinValueValidator from django.db import models from django.urls import reverse from django.utils.translation import gettext_lazy as _ from care.utils.models.base import BaseModel +from care.utils.models.validators import ( + mobile_or_landline_number_validator, + mobile_validator, +) def reverse_choices(choices): @@ -20,19 +24,6 @@ def reverse_choices(choices): GENDER_CHOICES = [(1, "Male"), (2, "Female"), (3, "Non-binary")] REVERSE_GENDER_CHOICES = reverse_choices(GENDER_CHOICES) -phone_number_regex = RegexValidator( - regex=r"^(?:(?:(?:\+|0{0,2})91|0{0,2})(?:\()?\d{3}(?:\))?[\-]?\d{3}[\-]?\d{4})$", - message="Please Enter 10/11 digit mobile number or landline as 0", - code="invalid_mobile", -) - -phone_number_regex_11 = RegexValidator( - # allow 10 to 11 digit mobile numbers if the first 4 digits are 1800 - regex=r"^((\+91|91|0)[\- ]{0,1})?[456789]\d{9}|1800\d{6,7}$", - message="Please Enter 10/11 digit mobile/landline/tollfree number", - code="invalid_mobile", -) - DISTRICT_CHOICES = [ (1, "Thiruvananthapuram"), (2, "Kollam"), @@ -228,10 +219,12 @@ class User(AbstractUser): ) state = models.ForeignKey(State, on_delete=models.PROTECT, null=True, blank=True) - phone_number = models.CharField(max_length=14, validators=[phone_number_regex]) + phone_number = models.CharField( + max_length=14, validators=[mobile_or_landline_number_validator] + ) alt_phone_number = models.CharField( max_length=14, - validators=[phone_number_regex], + validators=[mobile_validator], default=None, blank=True, null=True, diff --git a/care/utils/sms/sendSMS.py b/care/utils/sms/sendSMS.py index 55d70459e6..dbf0fc9edd 100644 --- a/care/utils/sms/sendSMS.py +++ b/care/utils/sms/sendSMS.py @@ -1,7 +1,7 @@ import boto3 from django.conf import settings -from care.users.models import phone_number_regex +from care.utils.models.validators import mobile_validator def sendSMS(phone_numbers, message, many=False): @@ -10,7 +10,7 @@ def sendSMS(phone_numbers, message, many=False): phone_numbers = list(set(phone_numbers)) for phone in phone_numbers: try: - phone_number_regex(phone) + mobile_validator(phone) except Exception: continue client = boto3.client(