-
-
Notifications
You must be signed in to change notification settings - Fork 24
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
8909b82
commit ff6db1f
Showing
24 changed files
with
881 additions
and
443 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Empty file.
106 changes: 106 additions & 0 deletions
106
backend/donations/common/validation/registration_number.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
import re | ||
from typing import Dict, List, Optional, Tuple | ||
|
||
from django.conf import settings | ||
from django.core.exceptions import ValidationError | ||
from django.utils.translation import gettext_lazy as _ | ||
|
||
ALLOWED_CHARACTERS_REGEX = r"[^RO0-9]" | ||
REGISTRATION_NUMBER_REGEX = r"^([A-Z]{2}|)\d{2,10}$" | ||
REGISTRATION_NUMBER_REGEX_SANS_VAT = r"^\d{2,10}$" | ||
REGISTRATION_NUMBER_REGEX_WITH_VAT = r"^[A-Z]{2}\d{2,10}$" | ||
|
||
|
||
def extract_vat_id(registration_number: str) -> Dict[str, str]: | ||
""" | ||
Extract the VAT ID and the registration number from a valid registration number. | ||
:param registration_number: | ||
A registration number that may or may not contain a VAT ID. | ||
The registration number must have a valid format. | ||
:return: A dictionary containing the VAT ID and the registration number. | ||
{ | ||
"vat_id": "RO", | ||
"registration_number": "1234567890", | ||
} | ||
""" | ||
|
||
result = { | ||
"vat_id": "", | ||
"registration_number": registration_number, | ||
} | ||
|
||
if re.match(REGISTRATION_NUMBER_REGEX_SANS_VAT, registration_number): | ||
return result | ||
|
||
result["vat_id"] = registration_number[:2] | ||
result["registration_number"] = registration_number[2:] | ||
|
||
return result | ||
|
||
|
||
def clean_registration_number(registration_number: str) -> Optional[str]: | ||
""" | ||
Clean up a registration number by uppercasing the string, then removing any whitespace or forbidden characters. | ||
:param registration_number: The registration number to clean. | ||
:return: The cleaned registration number. | ||
""" | ||
if re.match(REGISTRATION_NUMBER_REGEX, registration_number): | ||
return registration_number | ||
|
||
# uppercase the string and strip of any whitespace | ||
registration_number = registration_number.upper().strip() | ||
|
||
# remove all the whitespace | ||
registration_number = re.sub(r"\s+", "", registration_number) | ||
|
||
# remove any forbidden characters | ||
registration_number = re.sub(ALLOWED_CHARACTERS_REGEX, "", registration_number) | ||
|
||
return registration_number | ||
|
||
|
||
def ngo_id_number_validator(value): | ||
""" | ||
Validate a registration number for an NGO. | ||
:param value: The registration number to validate. | ||
:return: None | ||
""" | ||
|
||
reg_num: str = "".join([char for char in value.upper() if char.isalnum()]) | ||
|
||
if reg_num == len(reg_num) * "0": | ||
raise ValidationError(_("The ID number cannot be all zeros")) | ||
|
||
if not re.match(REGISTRATION_NUMBER_REGEX, reg_num): | ||
raise ValidationError(_("The ID number format is not valid")) | ||
|
||
if re.match(REGISTRATION_NUMBER_REGEX_WITH_VAT, reg_num): | ||
reg_num = value[2:] | ||
|
||
if not reg_num.isdigit(): | ||
raise ValidationError(_("The ID number must contain only digits")) | ||
|
||
if 2 > len(reg_num) or len(reg_num) > 10: | ||
raise ValidationError(_("The ID number must be between 2 and 10 digits long")) | ||
|
||
if not settings.ENABLE_FULL_CUI_VALIDATION: | ||
return | ||
|
||
control_key: str = "753217532" | ||
|
||
reversed_key: List[int] = [int(digit) for digit in control_key[::-1]] | ||
reversed_cif: List[int] = [int(digit) for digit in reg_num[::-1]] | ||
|
||
cif_control_digit: int = reversed_cif.pop(0) | ||
|
||
cif_key_pairs: Tuple[int, ...] = tuple( | ||
cif_digit * key_digit for cif_digit, key_digit in zip(reversed_cif, reversed_key) | ||
) | ||
control_result: int = sum(cif_key_pairs) * 10 % 11 | ||
|
||
if control_result == cif_control_digit: | ||
return | ||
elif control_result == 10 and cif_control_digit == 0: | ||
return | ||
|
||
raise ValidationError(_("The ID number is not valid")) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.