Skip to content

Commit

Permalink
Add uk-UA credit card provider (#1999)
Browse files Browse the repository at this point in the history
* feat(uk_UA-credit-cards) Add Uk-UA credit card provider and tests

* remove duplicated function

---------

Co-authored-by: Flavio Curella <[email protected]>
  • Loading branch information
lozik4 and fcurella authored Mar 13, 2024
1 parent a8e137a commit 2251972
Show file tree
Hide file tree
Showing 4 changed files with 171 additions and 1 deletion.
76 changes: 76 additions & 0 deletions faker/providers/bank/uk_UA/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,83 @@ class Provider(BankProvider):
"""Implement bank provider for ``uk_UA`` locale.
Source for rules for bban format:
https://bank.gov.ua/en/iban
Banks list:
https://ubanks.com.ua/adr/
"""

bban_format = "#" * 27
country_code = "UA"
banks = (
'izibank',
'monobank',
'O.Bank',
'sportbank',
'А-Банк',
'Агропросперіс Банк',
'АкордБанк',
'Альтбанк',
'Асвіо Банк',
'Банк 3/4',
'Банк Авангард',
'Банк Альянс',
'Банк Власний Рахунок',
'Банк Восток',
'Банк інвестицій та заощаджень',
'Банк Кредит Дніпро',
'Банк Портал',
'Банк Український Капітал',
'Банк Фамільний',
'БТА Банк',
'Глобус',
'Грант',
'Дойче Банк ДБУ',
'Європейський Промисловий Банк',
'Ідея Банк',
'ІНГ Банк Україна',
'Індустріалбанк',
'Кліринговий Дім',
'Комінбанк',
'КомІнвестБанк',
'Кредит Європа Банк',
'Кредитвест Банк',
'Креді Агріколь',
'Кредобанк',
'Кристалбанк',
'Львів',
'МетаБанк',
'Міжнародний Інвестиційний Банк',
'Мотор-Банк',
'МТБ Банк',
'Національний банк України',
'Оксі Банк',
'ОТП Банк',
'Ощадбанк',
'Перший Інвестиційний Банк',
'Перший Український Міжнародний Банк',
'Південний',
'Піреус Банк',
'Полікомбанк',
'Полтава-Банк',
'Правекс Банк',
'ПриватБанк',
'ПроКредит Банк',
'Радабанк',
'Райффайзен Банк',
'РВС Банк',
'СЕБ Корпоративний Банк',
'Сенс Банк',
'Сітібанк',
'Скай Банк',
'ТАСкомбанк',
'Траст-капітал',
'Український банк реконструкції та розвитку',
'Укргазбанк',
'Укрексімбанк',
'УкрСиббанк',
'Універсал Банк',
'Юнекс Банк',
)

def bank(self) -> str:
"""Generate a bank name."""
return self.random_element(self.banks)
56 changes: 56 additions & 0 deletions faker/providers/credit_card/uk_UA/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
from collections import OrderedDict

Check failure on line 1 in faker/providers/credit_card/uk_UA/__init__.py

View workflow job for this annotation

GitHub Actions / isort

Imports are incorrectly sorted and/or formatted.
from typing import Optional

from faker.providers.person.uk_UA import translit
from .. import CardType, CreditCard
from .. import Provider as CreditCardProvider


class Provider(CreditCardProvider):
"""Implement credit card provider for ``uk_UA`` locale.
https://blog.ipay.ua/uk/sekrety-bankovskix-kart-kak-identificirovat-bank-po-nomeru-karty/
"""
prefix_visa = ["4"]
prefix_mastercard = ["51", "52", "53", "54"]
prefix_prostir = ["9"]
prefix_maestro = ["6762"]

credit_card_types = OrderedDict(
(
("visa", CreditCard("Visa", prefix_visa, security_code="CVV2")),
("mastercard", CreditCard("Mastercard", prefix_mastercard, security_code="CVC2")),
("prostir", CreditCard("ПРОСТІР", prefix_prostir, security_code="CVC2")),
("maestro", CreditCard("Maestro", prefix_maestro, security_code="CVV")),
)
)

def credit_card_full(self, card_type: Optional[CardType] = None) -> str:
""" Generate UA Credit Card:
Supported card types 'visa', 'mastercard', 'prostir', 'maestro'
:sample:
:sample: card_type="prostir"
:sample: card_type="mastercard"
"""
card = self._credit_card_type(card_type)
tpl = "{provider}\n" "{owner}\n" "{number} {expire_date}\n" "{security}: {security_nb}\n" "{issuer}"
tpl = tpl.format(
provider=card.name,
owner=translit(
self.generator.parse(
self.random_element(
[
"{{first_name_male}} {{last_name_male}}",
"{{first_name_female}} {{last_name_female}}",
]
)
)
),
number=self.credit_card_number(card),
expire_date=self.credit_card_expire(),
security=card.security_code,
security_nb=self.credit_card_security_code(card),
issuer=self.generator.parse("{{bank}}"),
)

return self.generator.parse(tpl)
3 changes: 2 additions & 1 deletion faker/providers/person/uk_UA/__init__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
from collections import OrderedDict
from typing import Dict, Optional

from ....typing import SexLiteral
from faker.typing import SexLiteral

from .. import ElementsType
from .. import Provider as PersonProvider

Expand Down
37 changes: 37 additions & 0 deletions tests/providers/test_credit_card.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

from faker.providers.bank.ru_RU import Provider as RuRuBankProvider
from faker.providers.credit_card import Provider as CreditCardProvider
from faker.providers.bank.uk_UA import Provider as UkUaBankProvider


class TestCreditCardProvider:
Expand Down Expand Up @@ -152,3 +153,39 @@ def test_maestro(self, faker, num_samples):
for _ in range(num_samples):
number = faker.credit_card_number("maestro")
assert self.maestro_pattern.fullmatch(number)


class TestUkUa:
mastercard_pattern: Pattern = re.compile(
r"(?:5[1-5][0-9]{2}|222[1-9]|22[3-9][0-9]|2[3-6][0-9]{2}|27[01][0-9]|2720)[0-9]{12}",
)
visa_pattern: Pattern = re.compile(r"4[0-9]{12}([0-9]{3}){0,2}")
maestro_pattern: Pattern = re.compile(r"(67)[0-9]{14}")
prostir_pattern: Pattern = re.compile(r"(9)[0-9]{15}")

def test_mastercard(self, faker, num_samples):
for _ in range(num_samples):
number = faker.credit_card_number("mastercard")
assert self.mastercard_pattern.fullmatch(number)

def test_visa(self, faker, num_samples):
for _ in range(num_samples):
number = faker.credit_card_number("visa")
assert self.visa_pattern.fullmatch(number)

def test_maestro(self, faker, num_samples):
for _ in range(num_samples):
number = faker.credit_card_number("maestro")
assert self.maestro_pattern.fullmatch(number)

def test_prostir(self, faker, num_samples):
for _ in range(num_samples):
number = faker.credit_card_number("prostir")
assert self.prostir_pattern.fullmatch(number)

def test_credit_card_full(self, faker, num_samples):
for _ in range(num_samples):
card_data = faker.credit_card_full('prostir').split("\n")
assert re.match("[A-Za-z]+", card_data[1])
assert card_data[4] in UkUaBankProvider.banks
assert card_data[0] == 'ПРОСТІР'

0 comments on commit 2251972

Please sign in to comment.