From 2306c732decbe3e44fb5d411847cc9654fd729a5 Mon Sep 17 00:00:00 2001 From: Matthew Date: Wed, 11 Sep 2024 11:11:17 +0200 Subject: [PATCH 1/3] fixing for precommit-6 --- .pre-commit-config.yaml | 8 +- config/settings/base.py | 4 +- config/urls.py | 1 + setup.cfg | 2 +- setup.py | 2 +- timezone_utils/__init__.py | 0 timezone_utils/admin.py | 3 + timezone_utils/apps.py | 6 ++ timezone_utils/migrations/__init__.py | 0 timezone_utils/models.py | 3 + timezone_utils/tests.py | 143 ++++++++++++++++++++++++++ timezone_utils/urls.py | 11 ++ timezone_utils/views.py | 66 ++++++++++++ 13 files changed, 242 insertions(+), 7 deletions(-) create mode 100644 timezone_utils/__init__.py create mode 100644 timezone_utils/admin.py create mode 100644 timezone_utils/apps.py create mode 100644 timezone_utils/migrations/__init__.py create mode 100644 timezone_utils/models.py create mode 100644 timezone_utils/tests.py create mode 100644 timezone_utils/urls.py create mode 100644 timezone_utils/views.py diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index b3ee27a..0815b93 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -2,7 +2,7 @@ exclude: ^(ve/|venv/) repos: - repo: https://github.com/ambv/black - rev: 1fbf7251ccdb58ba93301622388615633ecc348a + rev: 24.8.0 hooks: - id: black language_version: python3.9 @@ -16,17 +16,17 @@ repos: additional_dependencies: ['flake8-print'] - repo: https://github.com/adrienverge/yamllint - rev: v1.16.0 + rev: v1.35.1 hooks: - id: yamllint files: ^.*\.(yml|yaml)$ - repo: https://github.com/asottile/seed-isort-config - rev: v1.9.1 + rev: v2.2.0 hooks: - id: seed-isort-config - repo: https://github.com/pre-commit/mirrors-isort - rev: v4.3.20 + rev: v5.10.1 hooks: - id: isort diff --git a/config/settings/base.py b/config/settings/base.py index e987a38..81f8558 100644 --- a/config/settings/base.py +++ b/config/settings/base.py @@ -47,6 +47,7 @@ "rp_interceptors", "rp_yal", "randomisation", + "timezone_utils", ] MIDDLEWARE = [ @@ -72,7 +73,8 @@ DATABASES = { "default": dj_database_url.config( default=os.environ.get( - "RP_SIDEKICK_DATABASE", "postgres://postgres@localhost/rp_sidekick" + "RP_SIDEKICK_DATABASE", + "postgres://postgres:dev_secret_key@localhost/rp_sidekick", ), engine="django_prometheus.db.backends.postgresql", ) diff --git a/config/urls.py b/config/urls.py index 81dac58..0e2ff8b 100644 --- a/config/urls.py +++ b/config/urls.py @@ -10,4 +10,5 @@ path("dtone/", include("rp_dtone.urls")), path("randomisation/", include("randomisation.urls")), path("yal/", include("rp_yal.urls"), name="rp_yal"), + path("timezone_utils/", include("timezone_utils.urls")), ] diff --git a/setup.cfg b/setup.cfg index 534c8a4..806f247 100644 --- a/setup.cfg +++ b/setup.cfg @@ -16,4 +16,4 @@ line_length = 88 multi_line_output = 3 include_trailing_comma = True skip = ve/,env/ -known_third_party = boto3,celery,dj_database_url,django,environ,freezegun,hashids,json2html,kombu,moto,phonenumber_field,pkg_resources,prometheus_client,pytest,raven,recommonmark,requests,responses,rest_framework,sentry_sdk,setuptools,six,temba_client +known_third_party = celery,dj_database_url,django,environ,freezegun,hashids,json2html,jsonschema,kombu,phonenumber_field,phonenumbers,pkg_resources,prometheus_client,pytest,pytz,raven,recommonmark,redis,requests,responses,rest_framework,sentry_sdk,setuptools,six,temba_client diff --git a/setup.py b/setup.py index 4cedc1c..25c35ca 100644 --- a/setup.py +++ b/setup.py @@ -18,7 +18,7 @@ "django-prometheus==2.2.0", "djangorestframework==3.15.2", "json2html==1.3.0", - "phonenumbers==8.10.23", + "phonenumbers==8.13.45", "psycopg2-binary==2.8.6", "rapidpro-python==2.6.1", "redis==4.5.4", diff --git a/timezone_utils/__init__.py b/timezone_utils/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/timezone_utils/admin.py b/timezone_utils/admin.py new file mode 100644 index 0000000..4185d36 --- /dev/null +++ b/timezone_utils/admin.py @@ -0,0 +1,3 @@ +# from django.contrib import admin + +# Register your models here. diff --git a/timezone_utils/apps.py b/timezone_utils/apps.py new file mode 100644 index 0000000..037a354 --- /dev/null +++ b/timezone_utils/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class TimezoneUtilsConfig(AppConfig): + default_auto_field = "django.db.models.BigAutoField" + name = "timezone_utils" diff --git a/timezone_utils/migrations/__init__.py b/timezone_utils/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/timezone_utils/models.py b/timezone_utils/models.py new file mode 100644 index 0000000..0b4331b --- /dev/null +++ b/timezone_utils/models.py @@ -0,0 +1,3 @@ +# from django.db import models + +# Create your models here. diff --git a/timezone_utils/tests.py b/timezone_utils/tests.py new file mode 100644 index 0000000..9ce3cad --- /dev/null +++ b/timezone_utils/tests.py @@ -0,0 +1,143 @@ +import json +from datetime import datetime +from unittest.mock import patch + +from django.contrib.auth.models import User +from rest_framework.test import APITestCase + + +class GetMsisdnTimezonesTest(APITestCase): + def setUp(self): + self.admin_user = User.objects.create_superuser("adminuser", "admin_password") + + def test_auth_required_to_get_timezones(self): + response = self.client.post( + "/timezone_utils/timezones/", + data={"contacts": [{"msisdn": "something"}]}, + content_type="application/json", + ) + + self.assertEqual(response.status_code, 401) + + def test_no_msisdn_returns_400(self): + self.client.force_authenticate(user=self.admin_user) + response = self.client.post( + "/timezone_utils/timezones/", + data=json.dumps({"contact": {"urn": "something"}}), + content_type="application/json", + ) + + self.assertEqual(response.data, {"msisdn": ["This field is required."]}) + self.assertEqual(response.status_code, 400) + + def test_phonenumber_unparseable_returns_400(self): + self.client.force_authenticate(user=self.admin_user) + response = self.client.post( + "/timezone_utils/timezones/", + data=json.dumps({"msisdn": "something"}), + content_type="application/json", + ) + + self.assertEqual( + response.data, + {"msisdn": ["This value must be a phone number with a region prefix."]}, + ) + self.assertEqual(response.status_code, 400) + + def test_not_possible_phonenumber_returns_400(self): + # If the length of a number doesn't match accepted length for it's region + self.client.force_authenticate(user=self.admin_user) + response = self.client.post( + "/timezone_utils/timezones/", + data=json.dumps({"msisdn": "120012301"}), + content_type="application/json", + ) + + self.assertEqual( + response.data, + {"msisdn": ["This value must be a phone number with a region prefix."]}, + ) + self.assertEqual(response.status_code, 400) + + def test_invalid_phonenumber_returns_400(self): + # If a phone number is invalid for it's region + self.client.force_authenticate(user=self.admin_user) + response = self.client.post( + "/timezone_utils/timezones/", + data=json.dumps({"msisdn": "12001230101"}), + content_type="application/json", + ) + + self.assertEqual( + response.data, + {"msisdn": ["This value must be a phone number with a region prefix."]}, + ) + self.assertEqual(response.status_code, 400) + + def test_phonenumber_with_plus(self): + self.client.force_authenticate(user=self.admin_user) + response = self.client.post( + "/timezone_utils/timezones/", + data=json.dumps({"msisdn": "+27345678910"}), + content_type="application/json", + ) + + self.assertEqual( + response.data, {"success": True, "timezones": ["Africa/Johannesburg"]} + ) + self.assertEqual(response.status_code, 200) + + def test_single_timezone_number(self): + self.client.force_authenticate(user=self.admin_user) + response = self.client.post( + "/timezone_utils/timezones/", + data=json.dumps({"msisdn": "27345678910"}), + content_type="application/json", + ) + + self.assertEqual( + response.data, {"success": True, "timezones": ["Africa/Johannesburg"]} + ) + self.assertEqual(response.status_code, 200) + + def test_multiple_timezone_number_returns_all(self): + self.client.force_authenticate(user=self.admin_user) + response = self.client.post( + "/timezone_utils/timezones/", + data=json.dumps({"msisdn": "61498765432"}), + content_type="application/json", + ) + + self.assertEqual( + response.data, + { + "success": True, + "timezones": [ + "Australia/Adelaide", + "Australia/Brisbane", + "Australia/Eucla", + "Australia/Lord_Howe", + "Australia/Perth", + "Australia/Sydney", + "Indian/Christmas", + "Indian/Cocos", + ], + }, + ) + self.assertEqual(response.status_code, 200) + + def test_return_one_flag_gives_middle_timezone(self): + self.client.force_authenticate(user=self.admin_user) + + with patch("timezone_utils.views.datetime") as mock_datetime: + mock_datetime.utcnow.return_value = datetime(2022, 8, 8) + response = self.client.post( + "/timezone_utils/timezones/?return_one=true", + data=json.dumps({"msisdn": "61498765432"}), + content_type="application/json", + ) + + self.assertEqual( + response.data, {"success": True, "timezones": ["Australia/Adelaide"]} + ) + self.assertEqual(response.status_code, 200) diff --git a/timezone_utils/urls.py b/timezone_utils/urls.py new file mode 100644 index 0000000..dbf76e7 --- /dev/null +++ b/timezone_utils/urls.py @@ -0,0 +1,11 @@ +from django.urls import path + +from . import views + +urlpatterns = [ + path( + "timezones/", + views.GetMsisdnTimezones.as_view(), + name="get-timezones", + ), +] diff --git a/timezone_utils/views.py b/timezone_utils/views.py new file mode 100644 index 0000000..0fc7609 --- /dev/null +++ b/timezone_utils/views.py @@ -0,0 +1,66 @@ +import logging +from datetime import datetime +from math import floor + +import phonenumbers +import pytz +from phonenumbers import timezone as ph_timezone +from rest_framework import authentication, permissions +from rest_framework.exceptions import ValidationError +from rest_framework.response import Response +from rest_framework.views import APIView + +LOGGER = logging.getLogger(__name__) + + +def get_middle_tz(zones): + timezones = [] + for zone in zones: + offset = pytz.timezone(zone).utcoffset(datetime.utcnow()) + offset_seconds = (offset.days * 86400) + offset.seconds + timezones.append({"name": zone, "offset": offset_seconds / 3600}) + ordered_tzs = sorted(timezones, key=lambda k: k["offset"]) + + approx_tz = ordered_tzs[floor(len(ordered_tzs) / 2)]["name"] + + LOGGER.info( + "Available timezones: {}. Returned timezone: {}".format(ordered_tzs, approx_tz) + ) + return approx_tz + + +class GetMsisdnTimezones(APIView): + authentication_classes = [authentication.BasicAuthentication] + permission_classes = [permissions.IsAdminUser] + + def post(self, request, *args, **kwargs): + try: + msisdn = request.data["msisdn"] + except KeyError: + raise ValidationError({"msisdn": ["This field is required."]}) + + msisdn = msisdn if msisdn.startswith("+") else "+" + msisdn + + try: + msisdn = phonenumbers.parse(msisdn) + except phonenumbers.phonenumberutil.NumberParseException: + raise ValidationError( + {"msisdn": ["This value must be a phone number with a region prefix."]} + ) + + if not ( + phonenumbers.is_possible_number(msisdn) + and phonenumbers.is_valid_number(msisdn) + ): + raise ValidationError( + {"msisdn": ["This value must be a phone number with a region prefix."]} + ) + + zones = list(ph_timezone.time_zones_for_number(msisdn)) + if ( + len(zones) > 1 + and request.query_params.get("return_one", "false").lower() == "true" + ): + zones = [get_middle_tz(zones)] + + return Response({"success": True, "timezones": zones}, status=200) From 90708b2d57683debbf92fb7f3faf24daeeed334c Mon Sep 17 00:00:00 2001 From: Matthew Date: Wed, 11 Sep 2024 21:23:06 +0200 Subject: [PATCH 2/3] Adding token verification, so that it functions more like rp-randomization-isort --- timezone_utils/tests.py | 50 ++++++++++++++++++++++++++++------------- timezone_utils/views.py | 16 +++++++++---- 2 files changed, 47 insertions(+), 19 deletions(-) diff --git a/timezone_utils/tests.py b/timezone_utils/tests.py index 9ce3cad..6587c4b 100644 --- a/timezone_utils/tests.py +++ b/timezone_utils/tests.py @@ -3,17 +3,25 @@ from unittest.mock import patch from django.contrib.auth.models import User -from rest_framework.test import APITestCase +from rest_framework.authtoken.models import Token +from rest_framework.test import APIClient, APITestCase class GetMsisdnTimezonesTest(APITestCase): def setUp(self): + self.api_client = APIClient() + self.admin_user = User.objects.create_superuser("adminuser", "admin_password") + token = Token.objects.get(user=self.admin_user) + self.token = token.key + + self.api_client.credentials(HTTP_AUTHORIZATION="Token " + self.token) + def test_auth_required_to_get_timezones(self): - response = self.client.post( + response = self.api_client.post( "/timezone_utils/timezones/", - data={"contacts": [{"msisdn": "something"}]}, + data=json.dumps({"whatsapp_id": "something"}), content_type="application/json", ) @@ -23,24 +31,28 @@ def test_no_msisdn_returns_400(self): self.client.force_authenticate(user=self.admin_user) response = self.client.post( "/timezone_utils/timezones/", - data=json.dumps({"contact": {"urn": "something"}}), + data=json.dumps({}), content_type="application/json", ) - self.assertEqual(response.data, {"msisdn": ["This field is required."]}) + self.assertEqual(response.data, {"whatsapp_id": ["This field is required."]}) self.assertEqual(response.status_code, 400) def test_phonenumber_unparseable_returns_400(self): self.client.force_authenticate(user=self.admin_user) response = self.client.post( "/timezone_utils/timezones/", - data=json.dumps({"msisdn": "something"}), + data=json.dumps({"whatsapp_id": "something"}), content_type="application/json", ) self.assertEqual( response.data, - {"msisdn": ["This value must be a phone number with a region prefix."]}, + { + "whatsapp_id": [ + "This value must be a phone number with a region prefix." + ] + }, ) self.assertEqual(response.status_code, 400) @@ -49,13 +61,17 @@ def test_not_possible_phonenumber_returns_400(self): self.client.force_authenticate(user=self.admin_user) response = self.client.post( "/timezone_utils/timezones/", - data=json.dumps({"msisdn": "120012301"}), + data=json.dumps({"whatsapp_id": "120012301"}), content_type="application/json", ) self.assertEqual( response.data, - {"msisdn": ["This value must be a phone number with a region prefix."]}, + { + "whatsapp_id": [ + "This value must be a phone number with a region prefix." + ] + }, ) self.assertEqual(response.status_code, 400) @@ -64,13 +80,17 @@ def test_invalid_phonenumber_returns_400(self): self.client.force_authenticate(user=self.admin_user) response = self.client.post( "/timezone_utils/timezones/", - data=json.dumps({"msisdn": "12001230101"}), + data=json.dumps({"whatsapp_id": "12001230101"}), content_type="application/json", ) self.assertEqual( response.data, - {"msisdn": ["This value must be a phone number with a region prefix."]}, + { + "whatsapp_id": [ + "This value must be a phone number with a region prefix." + ] + }, ) self.assertEqual(response.status_code, 400) @@ -78,7 +98,7 @@ def test_phonenumber_with_plus(self): self.client.force_authenticate(user=self.admin_user) response = self.client.post( "/timezone_utils/timezones/", - data=json.dumps({"msisdn": "+27345678910"}), + data=json.dumps({"whatsapp_id": "+27345678910"}), content_type="application/json", ) @@ -91,7 +111,7 @@ def test_single_timezone_number(self): self.client.force_authenticate(user=self.admin_user) response = self.client.post( "/timezone_utils/timezones/", - data=json.dumps({"msisdn": "27345678910"}), + data=json.dumps({"whatsapp_id": "27345678910"}), content_type="application/json", ) @@ -104,7 +124,7 @@ def test_multiple_timezone_number_returns_all(self): self.client.force_authenticate(user=self.admin_user) response = self.client.post( "/timezone_utils/timezones/", - data=json.dumps({"msisdn": "61498765432"}), + data=json.dumps({"whatsapp_id": "61498765432"}), content_type="application/json", ) @@ -133,7 +153,7 @@ def test_return_one_flag_gives_middle_timezone(self): mock_datetime.utcnow.return_value = datetime(2022, 8, 8) response = self.client.post( "/timezone_utils/timezones/?return_one=true", - data=json.dumps({"msisdn": "61498765432"}), + data=json.dumps({"whatsapp_id": "61498765432"}), content_type="application/json", ) diff --git a/timezone_utils/views.py b/timezone_utils/views.py index 0fc7609..2024842 100644 --- a/timezone_utils/views.py +++ b/timezone_utils/views.py @@ -35,9 +35,9 @@ class GetMsisdnTimezones(APIView): def post(self, request, *args, **kwargs): try: - msisdn = request.data["msisdn"] + msisdn = request.data["whatsapp_id"] except KeyError: - raise ValidationError({"msisdn": ["This field is required."]}) + raise ValidationError({"whatsapp_id": ["This field is required."]}) msisdn = msisdn if msisdn.startswith("+") else "+" + msisdn @@ -45,7 +45,11 @@ def post(self, request, *args, **kwargs): msisdn = phonenumbers.parse(msisdn) except phonenumbers.phonenumberutil.NumberParseException: raise ValidationError( - {"msisdn": ["This value must be a phone number with a region prefix."]} + { + "whatsapp_id": [ + "This value must be a phone number with a region prefix." + ] + } ) if not ( @@ -53,7 +57,11 @@ def post(self, request, *args, **kwargs): and phonenumbers.is_valid_number(msisdn) ): raise ValidationError( - {"msisdn": ["This value must be a phone number with a region prefix."]} + { + "whatsapp_id": [ + "This value must be a phone number with a region prefix." + ] + } ) zones = list(ph_timezone.time_zones_for_number(msisdn)) From a8752d4636fefaf723aa1a10c5fbe6a6886a92cf Mon Sep 17 00:00:00 2001 From: Matthew Date: Thu, 12 Sep 2024 11:05:04 +0200 Subject: [PATCH 3/3] changing app name from timezone_utils to msisdn_utils --- config/settings/base.py | 2 +- config/urls.py | 2 +- {timezone_utils => msisdn_utils}/__init__.py | 0 {timezone_utils => msisdn_utils}/admin.py | 0 {timezone_utils => msisdn_utils}/apps.py | 2 +- .../migrations/__init__.py | 0 {timezone_utils => msisdn_utils}/models.py | 0 {timezone_utils => msisdn_utils}/tests.py | 20 +++++++++---------- {timezone_utils => msisdn_utils}/urls.py | 0 {timezone_utils => msisdn_utils}/views.py | 0 10 files changed, 13 insertions(+), 13 deletions(-) rename {timezone_utils => msisdn_utils}/__init__.py (100%) rename {timezone_utils => msisdn_utils}/admin.py (100%) rename {timezone_utils => msisdn_utils}/apps.py (82%) rename {timezone_utils => msisdn_utils}/migrations/__init__.py (100%) rename {timezone_utils => msisdn_utils}/models.py (100%) rename {timezone_utils => msisdn_utils}/tests.py (91%) rename {timezone_utils => msisdn_utils}/urls.py (100%) rename {timezone_utils => msisdn_utils}/views.py (100%) diff --git a/config/settings/base.py b/config/settings/base.py index 81f8558..53c71b6 100644 --- a/config/settings/base.py +++ b/config/settings/base.py @@ -47,7 +47,7 @@ "rp_interceptors", "rp_yal", "randomisation", - "timezone_utils", + "msisdn_utils", ] MIDDLEWARE = [ diff --git a/config/urls.py b/config/urls.py index 0e2ff8b..4e57c18 100644 --- a/config/urls.py +++ b/config/urls.py @@ -10,5 +10,5 @@ path("dtone/", include("rp_dtone.urls")), path("randomisation/", include("randomisation.urls")), path("yal/", include("rp_yal.urls"), name="rp_yal"), - path("timezone_utils/", include("timezone_utils.urls")), + path("msisdn_utils/", include("msisdn_utils.urls")), ] diff --git a/timezone_utils/__init__.py b/msisdn_utils/__init__.py similarity index 100% rename from timezone_utils/__init__.py rename to msisdn_utils/__init__.py diff --git a/timezone_utils/admin.py b/msisdn_utils/admin.py similarity index 100% rename from timezone_utils/admin.py rename to msisdn_utils/admin.py diff --git a/timezone_utils/apps.py b/msisdn_utils/apps.py similarity index 82% rename from timezone_utils/apps.py rename to msisdn_utils/apps.py index 037a354..e64e9fa 100644 --- a/timezone_utils/apps.py +++ b/msisdn_utils/apps.py @@ -3,4 +3,4 @@ class TimezoneUtilsConfig(AppConfig): default_auto_field = "django.db.models.BigAutoField" - name = "timezone_utils" + name = "msisdn_utils" diff --git a/timezone_utils/migrations/__init__.py b/msisdn_utils/migrations/__init__.py similarity index 100% rename from timezone_utils/migrations/__init__.py rename to msisdn_utils/migrations/__init__.py diff --git a/timezone_utils/models.py b/msisdn_utils/models.py similarity index 100% rename from timezone_utils/models.py rename to msisdn_utils/models.py diff --git a/timezone_utils/tests.py b/msisdn_utils/tests.py similarity index 91% rename from timezone_utils/tests.py rename to msisdn_utils/tests.py index 6587c4b..6e66553 100644 --- a/timezone_utils/tests.py +++ b/msisdn_utils/tests.py @@ -20,7 +20,7 @@ def setUp(self): def test_auth_required_to_get_timezones(self): response = self.api_client.post( - "/timezone_utils/timezones/", + "/msisdn_utils/timezones/", data=json.dumps({"whatsapp_id": "something"}), content_type="application/json", ) @@ -30,7 +30,7 @@ def test_auth_required_to_get_timezones(self): def test_no_msisdn_returns_400(self): self.client.force_authenticate(user=self.admin_user) response = self.client.post( - "/timezone_utils/timezones/", + "/msisdn_utils/timezones/", data=json.dumps({}), content_type="application/json", ) @@ -41,7 +41,7 @@ def test_no_msisdn_returns_400(self): def test_phonenumber_unparseable_returns_400(self): self.client.force_authenticate(user=self.admin_user) response = self.client.post( - "/timezone_utils/timezones/", + "/msisdn_utils/timezones/", data=json.dumps({"whatsapp_id": "something"}), content_type="application/json", ) @@ -60,7 +60,7 @@ def test_not_possible_phonenumber_returns_400(self): # If the length of a number doesn't match accepted length for it's region self.client.force_authenticate(user=self.admin_user) response = self.client.post( - "/timezone_utils/timezones/", + "/msisdn_utils/timezones/", data=json.dumps({"whatsapp_id": "120012301"}), content_type="application/json", ) @@ -79,7 +79,7 @@ def test_invalid_phonenumber_returns_400(self): # If a phone number is invalid for it's region self.client.force_authenticate(user=self.admin_user) response = self.client.post( - "/timezone_utils/timezones/", + "/msisdn_utils/timezones/", data=json.dumps({"whatsapp_id": "12001230101"}), content_type="application/json", ) @@ -97,7 +97,7 @@ def test_invalid_phonenumber_returns_400(self): def test_phonenumber_with_plus(self): self.client.force_authenticate(user=self.admin_user) response = self.client.post( - "/timezone_utils/timezones/", + "/msisdn_utils/timezones/", data=json.dumps({"whatsapp_id": "+27345678910"}), content_type="application/json", ) @@ -110,7 +110,7 @@ def test_phonenumber_with_plus(self): def test_single_timezone_number(self): self.client.force_authenticate(user=self.admin_user) response = self.client.post( - "/timezone_utils/timezones/", + "/msisdn_utils/timezones/", data=json.dumps({"whatsapp_id": "27345678910"}), content_type="application/json", ) @@ -123,7 +123,7 @@ def test_single_timezone_number(self): def test_multiple_timezone_number_returns_all(self): self.client.force_authenticate(user=self.admin_user) response = self.client.post( - "/timezone_utils/timezones/", + "/msisdn_utils/timezones/", data=json.dumps({"whatsapp_id": "61498765432"}), content_type="application/json", ) @@ -149,10 +149,10 @@ def test_multiple_timezone_number_returns_all(self): def test_return_one_flag_gives_middle_timezone(self): self.client.force_authenticate(user=self.admin_user) - with patch("timezone_utils.views.datetime") as mock_datetime: + with patch("msisdn_utils.views.datetime") as mock_datetime: mock_datetime.utcnow.return_value = datetime(2022, 8, 8) response = self.client.post( - "/timezone_utils/timezones/?return_one=true", + "/msisdn_utils/timezones/?return_one=true", data=json.dumps({"whatsapp_id": "61498765432"}), content_type="application/json", ) diff --git a/timezone_utils/urls.py b/msisdn_utils/urls.py similarity index 100% rename from timezone_utils/urls.py rename to msisdn_utils/urls.py diff --git a/timezone_utils/views.py b/msisdn_utils/views.py similarity index 100% rename from timezone_utils/views.py rename to msisdn_utils/views.py