Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Первые шаги к интернацианализации #15

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
83 changes: 76 additions & 7 deletions codes/models.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,45 @@
# -*- coding: utf-8 -*-
import re
from django.db import models
from utils.exceptions import InvalidNumberException, OperatorNotFoundException
from utils.exceptions import InvalidNumberException, OperatorNotFoundException, NotIdentifiedRegionException

from django.db.models import Max

class CountryNumberPolitics():
pass

INT_LINE_CODE = u'8'

DEFAULT_EXUSSR = {#to do : move this to db, and assign it at initialization with crawler spiders
'RegionName' : 'exUssr',
'FixedLength' : 11,
'RegionCode' : u'7',
'Countries' : ['RU', 'KZ']

}

number_rules = [
DEFAULT_EXUSSR,
{
'CountryCode' : 'Europe',
'RegionCode' : u'3',
'Countries' : ['UA', 'BLR']
},
]

@classmethod
def get_country_rule_by_number(cls, phone_number):

#special rule for international line code in russia
if phone_number.startswith(cls.INT_LINE_CODE):
return cls.DEFAULT_EXUSSR

for rule in cls.number_rules:
if phone_number.startswith(rule['RegionCode']):
return rule

raise NotIdentifiedRegionException



class Operator(models.Model):
Expand All @@ -16,20 +54,42 @@ class Operator(models.Model):
class Meta:
ordering = ['region_code', 'number_end_range']

def __unicode__(self):
return u'Operator object. name: {0}, region_code: {1}, number_start_range: {2}, number_end_range: {3}, country: {4}.'.format(self.name, self.region_code, self.number_start_range, self.number_end_range, self.country)




@staticmethod
def _get_cleaned_number(number):
cleaned = re.sub(r'\D', r'', number)

if len(cleaned) != 11:
if not cleaned.isdigit():
raise InvalidNumberException

return cleaned


@staticmethod
def _check_number_validity(number, region_number_politic):
number_length = region_number_politic.get('FixedLength')
if number_length:
if len(number) != number_length:
raise InvalidNumberException
return True


@classmethod
def find(cls, phone):
cleaned = cls._get_cleaned_number(phone)


region_number_politic = CountryNumberPolitics.get_country_rule_by_number(cleaned)
cls._check_number_validity(cleaned, region_number_politic)

region_code = int(cleaned[1:4])
number = int(cleaned[4:])
region_operators = cls.objects.filter(region_code=region_code)
region_operators = cls.objects.filter(region_code=region_code, country__in = region_number_politic['Countries'] )
try:
operator = region_operators.filter(number_end_range__gte=number)[0]
if not operator.number_start_range <= number:
Expand All @@ -40,12 +100,21 @@ def find(cls, phone):

@classmethod
def find_by_range(cls, phone):
number = cls._get_cleaned_number(phone)[1:] # Убираем 8 с начала
number = cls._get_cleaned_number(phone)


region_number_politic = CountryNumberPolitics.get_country_rule_by_number(number)
cls._check_number_validity(number, region_number_politic)



number = number[1:] # Убираем 8 с начала

try:
operator = cls.objects.raw(
'select *, max(region_code) from codes_operator where number_start_range <= %s and \
number_end_range >= %s;', [number, number])[0]

operator = cls.objects.filter(number_start_range__lte=number, number_end_range__gte=number, country__in = region_number_politic['Countries'] ).annotate(Max('region_code'))#mb assignment of aggregated value to operator object is needed here

operator = operator[0]
except IndexError:
raise OperatorNotFoundException

Expand Down
193 changes: 108 additions & 85 deletions codes/tests.py
Original file line number Diff line number Diff line change
@@ -1,85 +1,108 @@
# -*- coding: utf-8 -*-
import json
from django.test.client import Client as HTTPClient
from django.utils import unittest
from models import Operator
from utils.exceptions import *

class GetOperatorTestCase(unittest.TestCase):
def setUp(self):
self.client = HTTPClient()
Operator(
name=u"МагаданТелеком",
region_code=560,
number_start_range=2000000,
number_end_range=3999999,
mobile=False,
region=u"Магадан"
).save()
Operator(
name=u"КроссТелеком",
region_code=530,
number_start_range=1000000,
number_end_range=1999999,
mobile=True,
region=u"Владивосток"
).save()
Operator(
name=u"Магаданские Телесистемы",
region_code=560,
number_start_range=4000000,
number_end_range=8999999,
mobile=False,
region=u"Магадан"
).save()

def tearDown(self):
Operator.objects.all().delete()

def test_get_operator_ok(self):
resp = self.client.post('/', {'phone': '85602234567'})
self.assertEqual(resp.status_code, 200)
json_resp = json.loads(resp.content)
self.assertEqual(json_resp['operator'], u'МагаданТелеком')
self.assertEqual(json_resp['mobile'], False)
self.assertEqual(json_resp['region'], u'Магадан')

resp = self.client.get('/', {'phone': '+7 (530) 123-45-67'})
self.assertEqual(resp.status_code, 200)
json_resp = json.loads(resp.content)
self.assertEqual(json_resp['operator'], u'КроссТелеком')
self.assertEqual(json_resp['mobile'], True)
self.assertEqual(json_resp['region'], u'Владивосток')

resp = self.client.get('/', {'phone': '8-560-5-23-45-67'})
self.assertEqual(resp.status_code, 200)
json_resp = json.loads(resp.content)
self.assertEqual(json_resp['operator'], u'Магаданские Телесистемы')
self.assertEqual(json_resp['mobile'], False)
self.assertEqual(json_resp['region'], u'Магадан')

def test_get_operator_fail(self):
resp = self.client.post('/', {'phone': '85609080808'})
self.assertEqual(resp.status_code, 200)
json_resp = json.loads(resp.content)
self.assertEqual(json_resp['status'], 1)
self.assertEqual(json_resp['message'], OperatorNotFoundException.msg)

resp = self.client.post('/', {'phone': '85601080808'})
self.assertEqual(resp.status_code, 200)
json_resp = json.loads(resp.content)
self.assertEqual(json_resp['status'], 1)
self.assertEqual(json_resp['message'], OperatorNotFoundException.msg)

def test_wrong_number(self):
resp = self.client.post('/', {'phone': '85601080808879475230345'})
self.assertEqual(resp.status_code, 200)
json_resp = json.loads(resp.content)
self.assertEqual(json_resp['status'], 1)
self.assertEqual(json_resp['message'], InvalidNumberException.msg)

resp = self.client.post('/', {'phone': 'PhoneNumber'})
self.assertEqual(resp.status_code, 200)
json_resp = json.loads(resp.content)
self.assertEqual(json_resp['status'], 1)
self.assertEqual(json_resp['message'], InvalidNumberException.msg)
# -*- coding: utf-8 -*-
import json
from django.test.client import Client as HTTPClient
from django.utils import unittest
from models import Operator
from utils.exceptions import *

class GetOperatorTestCase(unittest.TestCase):
def setUp(self):
self.client = HTTPClient()
Operator(
name=u"МагаданТелеком",
region_code=560,
number_start_range=2000000,
number_end_range=3999999,
mobile=False,
region=u"Магадан",
country=u"RU"
).save()
Operator(
name=u"КроссТелеком",
region_code=530,
number_start_range=1000000,
number_end_range=1999999,
mobile=True,
region=u"Владивосток",
country=u"RU"
).save()
Operator(
name=u"Магаданские Телесистемы",
region_code=560,
number_start_range=4000000,
number_end_range=8999999,
mobile=False,
region=u"Магадан",
country=u"RU"
).save()


Operator(
name=u"Мукачевский район",
region_code=803,
number_start_range= 13100000,
number_end_range= 13199999,
mobile=False,
region=u"Закарпатская область",
country=u"UA"
).save()

def tearDown(self):
Operator.objects.all().delete()

def test_get_operator_ok(self):
resp = self.client.post('/', {'phone': '85602234567'})
self.assertEqual(resp.status_code, 200)
json_resp = json.loads(resp.content)
self.assertEqual(json_resp['operator'], u'МагаданТелеком')
self.assertEqual(json_resp['mobile'], False)
self.assertEqual(json_resp['region'], u'Магадан')

resp = self.client.get('/', {'phone': '+7 (530) 123-45-67'})
self.assertEqual(resp.status_code, 200)
json_resp = json.loads(resp.content)
self.assertEqual(json_resp['operator'], u'КроссТелеком')
self.assertEqual(json_resp['mobile'], True)
self.assertEqual(json_resp['region'], u'Владивосток')

resp = self.client.get('/', {'phone': '8-560-5-23-45-67'})
self.assertEqual(resp.status_code, 200)
json_resp = json.loads(resp.content)
self.assertEqual(json_resp['operator'], u'Магаданские Телесистемы')
self.assertEqual(json_resp['mobile'], False)
self.assertEqual(json_resp['region'], u'Магадан')

def test_get_operator_fail(self):
resp = self.client.post('/', {'phone': '85609080808'})
self.assertEqual(resp.status_code, 200)
json_resp = json.loads(resp.content)
self.assertEqual(json_resp['status'], 1)
self.assertEqual(json_resp['message'], OperatorNotFoundException.msg)

resp = self.client.post('/', {'phone': '85601080808'})
self.assertEqual(resp.status_code, 200)
json_resp = json.loads(resp.content)
self.assertEqual(json_resp['status'], 1)
self.assertEqual(json_resp['message'], OperatorNotFoundException.msg)

def test_wrong_number(self):
resp = self.client.post('/', {'phone': '85601080808879475230345'})
self.assertEqual(resp.status_code, 200)
json_resp = json.loads(resp.content)
self.assertEqual(json_resp['status'], 1)
self.assertEqual(json_resp['message'], InvalidNumberException.msg)

resp = self.client.post('/', {'phone': 'PhoneNumber'})
self.assertEqual(resp.status_code, 200)
json_resp = json.loads(resp.content)
self.assertEqual(json_resp['status'], 1)
self.assertEqual(json_resp['message'], InvalidNumberException.msg)


def test_ukrainian_number(self):
resp = self.client.get('/', {'phone': '+380 31 31 62324'})
self.assertEqual(resp.status_code, 200)
json_resp = json.loads(resp.content)
self.assertEqual(json_resp['operator'], u'Мукачевский район')
self.assertEqual(json_resp['mobile'], False)
self.assertEqual(json_resp['region'], u'Закарпатская область')
5 changes: 5 additions & 0 deletions utils/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,8 @@ class OperatorNotFoundException(Exception):
code = 2
msg = 'Operator not found.'


class NotIdentifiedRegionException(Exception):
code = 3
msg = 'Region not found.'