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

UAT Release #2200

Merged
merged 25 commits into from
Sep 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
9e6be57
new serializer and tests for party.name
Tllew Sep 17, 2024
6ed9e9d
Merge branch 'dev' into LTD-5432-party-name-validation
Tllew Sep 19, 2024
e6ec614
resolve existing dependabot alerts
markj0hnst0n Sep 19, 2024
d5fc14e
testing view
Tllew Sep 19, 2024
306446c
addressing git comments
Tllew Sep 19, 2024
8ee7553
Merge branch 'dev' into LTD-5432-party-name-validation
Tllew Sep 19, 2024
7deaa2a
removing cerfifi to check impact on e2e tests
markj0hnst0n Sep 20, 2024
8464f3a
Merge branch 'dev' into LTD-5432-party-name-validation
Tllew Sep 23, 2024
5cca1a5
Merge pull request #2189 from uktrade/LTD-5432-party-name-validation
Tllew Sep 23, 2024
9520b30
add certifi any pytz
markj0hnst0n Sep 23, 2024
63c7a3a
Merge branch 'dev' into LTD-5439-fix-dependabot-alerts
markj0hnst0n Sep 23, 2024
320a524
Rename GET param to include_non_selectable_for_assessment
currycoder Sep 16, 2024
3a6401a
Revert legacy control list entry endpoint to return all CLEs
currycoder Sep 16, 2024
7be7448
Add caseworker-specific CLE endpoint
currycoder Sep 16, 2024
b57fba2
Merge pull request #2190 from uktrade/LTD-5399-CLE-api-calls-visibility
currycoder Sep 23, 2024
b79283d
Merge branch 'dev' into LTD-5439-fix-dependabot-alerts
markj0hnst0n Sep 23, 2024
958165a
Bump lite_routing submodule sha to pull in ML13c* CLEs
currycoder Sep 23, 2024
cdcfe62
change team ownership
depsiatwal Sep 23, 2024
4a3aafb
Merge branch 'dev' into LTD-5435-change-refusal-letter-ownership
depsiatwal Sep 23, 2024
1931d55
Merge pull request #2197 from uktrade/LTD-5200_Add_new_ML13c_CLEs_to_…
currycoder Sep 23, 2024
9ed81d4
Merge branch 'dev' into LTD-5439-fix-dependabot-alerts
markj0hnst0n Sep 24, 2024
795aee4
Merge branch 'dev' into LTD-5435-change-refusal-letter-ownership
depsiatwal Sep 24, 2024
3d96210
Merge pull request #2196 from uktrade/LTD-5435-change-refusal-letter-…
depsiatwal Sep 24, 2024
c38e117
Merge branch 'dev' into LTD-5439-fix-dependabot-alerts
markj0hnst0n Sep 24, 2024
a5216c7
Merge pull request #2194 from uktrade/LTD-5439-fix-dependabot-alerts
markj0hnst0n Sep 24, 2024
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
6 changes: 4 additions & 2 deletions Pipfile
Original file line number Diff line number Diff line change
Expand Up @@ -50,13 +50,13 @@ notifications-python-client = "~=5.7.1"
dataclasses = "~=0.6"
# endesive = "~=1.5.9" (not included here as installed in a later jenkins step. Uncomment if working locally)
pypdf2 = "~=1.27.5"
cryptography = "~=42.0.0"
cryptography = "~=43.0.1"
sentry-sdk = "~=2.8.0"
elastic-apm = "~=6.7.2"
gunicorn = "~=22.0.0"
gevent = "~=23.9.1"
xmltodict = "~=0.12.0"
Pillow = "~=10.2.0"
Pillow = "~=10.3.0"
django-phonenumber-field = "==6.4.0"
phonenumbers = "~=8.13.1"
django-log-formatter-ecs = "==0.0.5"
Expand All @@ -76,6 +76,8 @@ psycopg = "~=3.1.18"
django-log-formatter-asim = "~=0.0.5"
dbt-copilot-python = "~=0.2.1"
dj-database-url = "~=2.2.0"
certifi = "~=2024.7.4"
pytz = "~=2024.1"

[requires]
python_version = "3.9"
Expand Down
1,361 changes: 700 additions & 661 deletions Pipfile.lock

Large diffs are not rendered by default.

109 changes: 109 additions & 0 deletions api/applications/views/tests/test_parties.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
from parameterized import parameterized
from django.urls import reverse
from rest_framework import status

from api.applications.tests.factories import (
StandardApplicationFactory,
PartyOnApplicationFactory,
DraftStandardApplicationFactory,
)
from api.parties.models import Party
from api.staticdata.statuses.models import CaseStatus
Expand Down Expand Up @@ -72,3 +74,110 @@ def test_other_status_cannot_update_party_detail(self):
]
},
)


class TestApplicationPartyViewValues(DataTestClient):

def setUp(self):
super().setUp()
self.application = DraftStandardApplicationFactory(organisation=self.organisation)

self.party_on_application = PartyOnApplicationFactory(application=self.application)

@parameterized.expand(
[
(
{"name": "end_user", "address": "1 Example Street"},
True,
{
"name": [
"Party name must only include letters, numbers, and common special characters such as hyphens, brackets and apostrophes"
]
},
),
(
{"name": "end\auser", "address": "1 Example Street"},
True,
{
"name": [
"Party name must only include letters, numbers, and common special characters such as hyphens, brackets and apostrophes"
]
},
),
(
{"name": "end£user", "address": "1 Example Street"},
True,
{
"name": [
"Party name must only include letters, numbers, and common special characters such as hyphens, brackets and apostrophes"
]
},
),
(
{"name": "end user", "address": "1_Example Street"},
True,
{
"address": [
"Address must only include letters, numbers, and common special characters such as hyphens, brackets and apostrophes"
]
},
),
(
{"name": "end user", "address": "1\aExample Street"},
True,
{
"address": [
"Address must only include letters, numbers, and common special characters such as hyphens, brackets and apostrophes"
]
},
),
(
{"name": "end_user", "address": "1\aExample Street"},
True,
{
"name": [
"Party name must only include letters, numbers, and common special characters such as hyphens, brackets and apostrophes"
],
"address": [
"Address must only include letters, numbers, and common special characters such as hyphens, brackets and apostrophes"
],
},
),
]
)
def test_party_post_invalid(self, data, error, error_message):
data["country"] = {"id": "FR", "name": "France"}
self.url = reverse(
"applications:party",
kwargs={"pk": str(self.application.pk), "party_pk": str(self.party_on_application.party.pk)},
)
party = Party.objects.get(id=self.party_on_application.party.pk)
versions = Version.objects.get_for_object(party)
self.assertEqual(versions.count(), 0)

self.application.status = CaseStatus.objects.get(status="draft")
self.application.save()

response = self.client.put(self.url, **self.exporter_headers, data=data)
if error:
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
self.assertEqual(response.json()["errors"], error_message)

@parameterized.expand(
[
({"name": "end user", "address": "1 Example Street"},),
({"name": "end/!user", "address": "1 Example Street"},),
({"name": "end-user", "address": "1 Example Street"},),
({"name": "end-user", "address": "1 \r\nExample Street"},),
]
)
def test_party_post_valid(self, data):
data["country"] = {"id": "FR", "name": "France"}
self.url = reverse(
"applications:party",
kwargs={"pk": str(self.application.pk), "party_pk": str(self.party_on_application.party.pk)},
)

response = self.client.put(self.url, **self.exporter_headers, data=data)

self.assertEqual(response.status_code, status.HTTP_200_OK)
1 change: 1 addition & 0 deletions api/conf/caseworker_urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@
urlpatterns = [
path("applications/", include("api.applications.caseworker.urls")),
path("organisations/", include("api.organisations.caseworker.urls")),
path("static/", include("api.staticdata.caseworker.urls")),
]
4 changes: 4 additions & 0 deletions api/core/validators.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,3 +42,7 @@ class GoodNameValidator(EdifactStringValidator):
class PartyAddressValidator(EdifactStringValidator):
regex_string = re.compile(r"^[a-zA-Z0-9 .,\-\)\(\/'+:=\?\!\"%&\*;\<\>\r\n]+$")
message = "Address must only include letters, numbers, and common special characters such as hyphens, brackets and apostrophes"


class PartyNameValidator(EdifactStringValidator):
message = "Party name must only include letters, numbers, and common special characters such as hyphens, brackets and apostrophes"
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
from django.db import migrations

LICENSING_UNIT_TEAM_ID = "58e77e47-42c8-499f-a58d-94f94541f8c6"


def refusal_letter_picklist_update_team_ownership(apps, schema_editor):

PicklistItem = apps.get_model("picklists", "PicklistItem")
refusal_letter_content = PicklistItem.objects.get(name="Refusal letter content")
refusal_letter_content.team_id = LICENSING_UNIT_TEAM_ID
refusal_letter_content.save()


class Migration(migrations.Migration):

dependencies = [
("letter_templates", "0009_refusal_letter_update_fix"),
]

operations = [
migrations.RunPython(refusal_letter_picklist_update_team_ownership, migrations.RunPython.noop),
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import pytest
from django_test_migrations.contrib.unittest_case import MigratorTestCase


@pytest.mark.django_db()
class TestChangeTeamRefusalPickList(MigratorTestCase):
migrate_from = ("letter_templates", "0009_refusal_letter_update_fix")
migrate_to = ("letter_templates", "0010_refusal_letter_picklist_update_team_ownership")

def test_refusal_letter_picklist_update_team_ownership(self):
LICENSING_UNIT_TEAM_ID = "58e77e47-42c8-499f-a58d-94f94541f8c6" # /PS-IGNORE

PicklistItem = self.new_state.apps.get_model("picklists", "PicklistItem")

assert str(PicklistItem.objects.get(name="Refusal letter content").team_id) == LICENSING_UNIT_TEAM_ID
4 changes: 2 additions & 2 deletions api/parties/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

from api.cases.enums import CaseTypeSubTypeEnum
from api.core.serializers import KeyValueChoiceField, CountrySerializerField
from api.core.validators import PartyAddressValidator
from api.core.validators import PartyAddressValidator, PartyNameValidator
from api.documents.libraries.process_document import process_document
from api.flags.serializers import FlagSerializer
from api.goods.enums import PvGrading
Expand All @@ -15,7 +15,7 @@


class PartySerializer(serializers.ModelSerializer):
name = serializers.CharField(error_messages=PartyErrors.NAME)
name = serializers.CharField(error_messages=PartyErrors.NAME, validators=[PartyNameValidator()])
address = serializers.CharField(error_messages=PartyErrors.ADDRESS, validators=[PartyAddressValidator()])
country = CountrySerializerField()
website = serializers.CharField(required=False, allow_blank=True)
Expand Down
52 changes: 52 additions & 0 deletions api/parties/tests/test_serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,3 +92,55 @@ def test_validate_party_address_invalid(self, address, error_message):
str(address_errors[0]),
error_message,
)

@parameterized.expand(
[
"random name",
"party-name",
"party!name",
"party-!.<>/%&*;+'(),.name",
]
)
def test_validate_party_name_valid(self, name):
serializer = PartySerializer(
data={"name": name},
partial=True,
)
self.assertTrue(serializer.is_valid())

@parameterized.expand(
[
(
"party\aname",
"Party name must only include letters, numbers, and common special characters such as hyphens, brackets and apostrophes",
),
(
"party-\wname",
"Party name must only include letters, numbers, and common special characters such as hyphens, brackets and apostrophes",
),
(
"party_name",
"Party name must only include letters, numbers, and common special characters such as hyphens, brackets and apostrophes",
),
(
"party$name",
"Party name must only include letters, numbers, and common special characters such as hyphens, brackets and apostrophes",
),
(
"party@name",
"Party name must only include letters, numbers, and common special characters such as hyphens, brackets and apostrophes",
),
]
)
def test_party_name_invalid(self, name, error_message):
serializer = PartySerializer(
data={"name": name},
partial=True,
)
self.assertFalse(serializer.is_valid())
serializer_error = serializer.errors["name"]
self.assertEqual(len(serializer_error), 1)
self.assertEqual(
str(serializer_error[0]),
error_message,
)
6 changes: 2 additions & 4 deletions api/picklists/tests/test_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,7 @@ def test_gov_user_can_see_all_their_teams_picklist_items(self):
response_data = response.json()

self.assertEqual(response.status_code, status.HTTP_200_OK)
# New migration will create a new PicklistItem if base does not exist so its becoming 5
# api/letter_templates/migrations/0008_refusal_letter_update.py
self.assertEqual(len(response_data["results"]), 5)
self.assertEqual(len(response_data["results"]), 4)

def test_gov_user_can_see_all_their_teams_picklist_items_excluding_deactivated(
self,
Expand All @@ -34,7 +32,7 @@ def test_gov_user_can_see_all_their_teams_picklist_items_excluding_deactivated(
response_data = response.json()

self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(len(response_data["results"]), 4)
self.assertEqual(len(response_data["results"]), 3)

def test_gov_user_can_see_all_their_teams_picklist_items_filter_by_name(
self,
Expand Down
Empty file.
Empty file.
9 changes: 9 additions & 0 deletions api/staticdata/caseworker/control_list_entries/serializers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
from rest_framework import serializers

from api.staticdata.control_list_entries.models import ControlListEntry


class ControlListEntriesListSerializer(serializers.ModelSerializer):
class Meta:
model = ControlListEntry
fields = ("rating", "text", "parent")
Empty file.
67 changes: 67 additions & 0 deletions api/staticdata/caseworker/control_list_entries/tests/test_views.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
from rest_framework import status
from rest_framework.reverse import reverse

from api.staticdata.control_list_entries.models import ControlListEntry
from api.staticdata.control_list_entries.factories import ControlListEntriesFactory
from test_helpers.clients import DataTestClient


class ControlListEntriesListTests(DataTestClient):
def setUp(self):
self.url = reverse("caseworker_staticdata:control_list_entries:control_list_entries")
super().setUp()
ControlListEntry.objects.all().delete()
self.parent_cle = ControlListEntriesFactory(
rating="ML1",
selectable_for_assessment=False,
text="some ML1 text",
)
self.child_cle = ControlListEntriesFactory(
rating="ML1a",
parent=self.parent_cle,
selectable_for_assessment=True,
text="some ML1a text",
)

def test_GET_success(self):
response = self.client.get(self.url, **self.gov_headers)

self.assertEqual(response.status_code, status.HTTP_200_OK)

self.assertEqual(
response.json(),
[
{
"rating": "ML1a",
"text": "some ML1a text",
"parent": str(self.parent_cle.id),
}
],
)

def test_GET_exporter_forbidden(self):
response = self.client.get(self.url, **self.exporter_headers)

self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)

def test_GET_include_non_selectable_for_assessment_param(self):
url = self.url + "?include_non_selectable_for_assessment=True"
response = self.client.get(url, **self.gov_headers)

self.assertEqual(response.status_code, status.HTTP_200_OK)

self.assertEqual(
response.json(),
[
{
"rating": "ML1",
"text": "some ML1 text",
"parent": None,
},
{
"rating": "ML1a",
"text": "some ML1a text",
"parent": str(self.parent_cle.id),
},
],
)
9 changes: 9 additions & 0 deletions api/staticdata/caseworker/control_list_entries/urls.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
from django.urls import path

from api.staticdata.caseworker.control_list_entries import views

app_name = "control_list_entries"

urlpatterns = [
path("", views.ControlListEntriesList.as_view(), name="control_list_entries"),
]
Loading