diff --git a/.InstallPackages b/.InstallPackages index bc3c5b89d9..2079c13aaa 100644 --- a/.InstallPackages +++ b/.InstallPackages @@ -10,4 +10,4 @@ swig imagemagick poppler-utils libsqlite3-dev -postgresql-client-14 + diff --git a/.copilot/config.yml b/.copilot/config.yml index 6a6bbf3bb7..b7f3f65a21 100644 --- a/.copilot/config.yml +++ b/.copilot/config.yml @@ -4,3 +4,4 @@ builder: version: 0.3.339 packs: - acodeninja/install + - acodeninja/psql diff --git a/Procfile b/Procfile index 7209272127..1d4f99dd64 100644 --- a/Procfile +++ b/Procfile @@ -1,5 +1,7 @@ web: SWIG_LIB=/home/vcap/deps/0/apt/usr/share/swig4.0 CFLAGS=-I/home/vcap/deps/1/python/include/python3.9.18m pip3 install endesive==1.5.9 && python manage.py migrate && gunicorn --worker-class gevent -c api/conf/gconfig.py -b 0.0.0.0:$PORT api.conf.wsgi web-dbt-platform: python manage.py migrate && gunicorn -c api/conf/gconfig-dbt-platform.py -b 0.0.0.0:$PORT api.conf.wsgi dump-and-anonymise: python manage.py dump_and_anonymise +rebuild-search-index: python manage.py search_index --rebuild -f +seed-internal-users: ./bin/seed_internal_users.sh celeryworker: celery -A api.conf worker -l info celeryscheduler: celery -A api.conf beat diff --git a/api/conf/settings.py b/api/conf/settings.py index d5d3a4cca4..f464eea9ed 100644 --- a/api/conf/settings.py +++ b/api/conf/settings.py @@ -491,7 +491,10 @@ def _build_redis_url(base_url, db_number, **query_args): LITE_API_ENABLE_ES = env.bool("LITE_API_ENABLE_ES", False) if LITE_API_ENABLE_ES: ELASTICSEARCH_DSL = { - "default": {"hosts": env.str("OPENSEARCH_ENDPOINT")}, + "default": { + "hosts": env.str("OPENSEARCH_ENDPOINT"), + "timeout": 30, + }, } ENABLE_SPIRE_SEARCH = env.bool("ENABLE_SPIRE_SEARCH", False) diff --git a/api/data_workspace/v2/serializers.py b/api/data_workspace/v2/serializers.py index 8f01866efa..3c2cd81aea 100644 --- a/api/data_workspace/v2/serializers.py +++ b/api/data_workspace/v2/serializers.py @@ -11,6 +11,8 @@ ) from api.cases.enums import LicenceDecisionType from api.cases.models import LicenceDecision +from api.licences.models import GoodOnLicence +from api.staticdata.control_list_entries.models import ControlListEntry from api.staticdata.countries.models import Country from api.staticdata.report_summaries.models import ReportSummary @@ -96,6 +98,15 @@ class Meta: ) +class GoodOnLicenceSerializer(serializers.ModelSerializer): + good_id = serializers.UUIDField() + licence_id = serializers.UUIDField() + + class Meta: + model = GoodOnLicence + fields = ("good_id", "licence_id") + + class ApplicationSerializer(serializers.ModelSerializer): licence_type = serializers.CharField(source="case_type.reference") status = serializers.CharField(source="status.status") @@ -136,3 +147,14 @@ class FootnoteSerializer(serializers.Serializer): team_name = serializers.CharField(source="team__name") application_id = serializers.CharField(source="case__pk") type = serializers.CharField() + + +class AssessmentSerializer(serializers.ModelSerializer): + good_id = serializers.UUIDField() + + class Meta: + model = ControlListEntry + fields = ( + "good_id", + "rating", + ) diff --git a/api/data_workspace/v2/tests/bdd/conftest.py b/api/data_workspace/v2/tests/bdd/conftest.py index 687a4b3e42..75521d3ad4 100644 --- a/api/data_workspace/v2/tests/bdd/conftest.py +++ b/api/data_workspace/v2/tests/bdd/conftest.py @@ -25,6 +25,10 @@ PartyOnApplicationFactory, StandardApplicationFactory, ) +from api.cases.enums import ( + AdviceType, +) +from api.cases.tests.factories import FinalAdviceFactory from api.cases.enums import CaseTypeEnum from api.cases.models import CaseType from api.core.constants import ( @@ -33,11 +37,16 @@ Roles, ) from api.goods.tests.factories import GoodFactory +from api.flags.enums import SystemFlags from api.documents.libraries.s3_operations import init_s3_client from api.letter_templates.models import LetterTemplate from api.parties.tests.factories import PartyDocumentFactory from api.organisations.tests.factories import OrganisationFactory from api.staticdata.letter_layouts.models import LetterLayout +from api.staticdata.report_summaries.models import ( + ReportSummaryPrefix, + ReportSummarySubject, +) from api.staticdata.statuses.enums import CaseStatusEnum from api.staticdata.statuses.models import CaseStatus from api.staticdata.units.enums import Units @@ -380,9 +389,75 @@ def check_rows(client, parse_table, unpage_data, table_name, rows): for row in parsed_rows[1:]: expected_data.append({key: value for key, value in zip(keys, row)}) expected_data = cast_to_types(expected_data, table_metadata["fields"]) + + actual_data = sorted(actual_data, key=lambda d, key=keys[0]: d[key]) + expected_data = sorted(expected_data, key=lambda d, key=keys[0]: d[key]) assert actual_data == expected_data +@given(parsers.parse("the application has the following goods:{goods}")) +def given_the_application_has_the_following_goods(parse_table, draft_standard_application, goods): + draft_standard_application.goods.all().delete() + good_attributes = parse_table(goods)[1:] + for id, name in good_attributes: + GoodOnApplicationFactory( + application=draft_standard_application, + id=id, + good__name=name, + ) + + +@when(parsers.parse("the goods are assessed by TAU as:{assessments}")) +def when_the_goods_are_assessed_by_tau( + parse_table, + submitted_standard_application, + assessments, + api_client, + lu_case_officer, + gov_headers, +): + assessments = parse_table(assessments)[1:] + url = reverse("assessments:make_assessments", kwargs={"case_pk": submitted_standard_application.pk}) + + assessment_payload = [] + for good_on_application_id, control_list_entry, report_summary_prefix, report_summary_subject in assessments: + data = { + "id": good_on_application_id, + "comment": "Some comment", + } + + if control_list_entry == "NLR": + data.update( + { + "control_list_entries": [], + "is_good_controlled": False, + } + ) + else: + if report_summary_prefix: + prefix = ReportSummaryPrefix.objects.get(name=report_summary_prefix) + else: + prefix = None + subject = ReportSummarySubject.objects.get(name=report_summary_subject) + data.update( + { + "control_list_entries": [control_list_entry], + "report_summary_prefix": prefix.pk if prefix else None, + "report_summary_subject": subject.pk, + "is_good_controlled": True, + "regime_entries": [], + } + ) + assessment_payload.append(data) + + response = api_client.put( + url, + assessment_payload, + **gov_headers, + ) + assert response.status_code == 200, response.content + + @pytest.fixture() def parse_attributes(parse_table): def _parse_attributes(attributes): @@ -412,3 +487,51 @@ def given_a_draft_standard_application_with_attributes(organisation, parse_attri ) return application + + +@pytest.fixture() +def issue_licence(api_client, lu_case_officer, gov_headers, siel_template): + def _issue_licence(application): + data = {"action": AdviceType.APPROVE, "duration": 24} + for good_on_app in application.goods.all(): + good_on_app.quantity = 100 + good_on_app.value = 10000 + good_on_app.save() + data[f"quantity-{good_on_app.id}"] = str(good_on_app.quantity) + data[f"value-{good_on_app.id}"] = str(good_on_app.value) + # create final advice for controlled goods; skip NLR goods + if good_on_app.is_good_controlled == False: + continue + FinalAdviceFactory(user=lu_case_officer, case=application, good=good_on_app.good) + + issue_date = datetime.datetime.now() + data.update({"year": issue_date.year, "month": issue_date.month, "day": issue_date.day}) + + application.flags.remove(SystemFlags.ENFORCEMENT_CHECK_REQUIRED) + + url = reverse("applications:finalise", kwargs={"pk": application.pk}) + response = api_client.put(url, data=data, **gov_headers) + assert response.status_code == 200, response.content + response = response.json() + + data = { + "template": str(siel_template.id), + "text": "", + "visible_to_exporter": False, + "advice_type": AdviceType.APPROVE, + } + url = reverse( + "cases:generated_documents:generated_documents", + kwargs={"pk": str(application.pk)}, + ) + response = api_client.post(url, data=data, **gov_headers) + assert response.status_code == 201, response.content + + url = reverse( + "cases:finalise", + kwargs={"pk": str(application.pk)}, + ) + response = api_client.put(url, data={}, **gov_headers) + assert response.status_code == 201 + + return _issue_licence diff --git a/api/data_workspace/v2/tests/bdd/scenarios/goods_descriptions.feature b/api/data_workspace/v2/tests/bdd/scenarios/goods_descriptions.feature index b5e70379a1..5e2197f00d 100644 --- a/api/data_workspace/v2/tests/bdd/scenarios/goods_descriptions.feature +++ b/api/data_workspace/v2/tests/bdd/scenarios/goods_descriptions.feature @@ -29,5 +29,5 @@ Scenario: Assess application | 4dad5dc6-38ef-4bf7-99fd-0c6bc5d86048 | NLR | | | Then the `goods_descriptions` table has the following rows: | good_id | description | - | 118a003c-7191-4a2c-97e9-be243722cbb2 | composite laminates | | 8fa8dc3c-c103-42f5-ba94-2d9098b8821d | accessories for composite laminates | + | 118a003c-7191-4a2c-97e9-be243722cbb2 | composite laminates | diff --git a/api/data_workspace/v2/tests/bdd/scenarios/goods_on_licences.feature b/api/data_workspace/v2/tests/bdd/scenarios/goods_on_licences.feature new file mode 100644 index 0000000000..3b67b6cded --- /dev/null +++ b/api/data_workspace/v2/tests/bdd/scenarios/goods_on_licences.feature @@ -0,0 +1,49 @@ +@db +Feature: Goods On Licences + +Scenario: Issue a licence + Given a standard application with the following goods: + | id | name | + | 61d193bd-a4d8-4f7d-8c07-1ac5e03ea2c7 | A controlled good | + And a draft licence with attributes: + | name | value | + | id | 962b4948-b87a-42fe-9c2b-61bdefd9cd21 | + When the licence is issued + Then the `goods_on_licences` table has the following rows: + | good_id | licence_id | + | 61d193bd-a4d8-4f7d-8c07-1ac5e03ea2c7 | 962b4948-b87a-42fe-9c2b-61bdefd9cd21 | + +Scenario: NLR goods not on licence + Given a standard application with the following goods: + | id | name | + | aa9736f9-48f5-4d44-ace9-e4b8738591a5 | Another controlled good | + | 56f562f6-b554-4bb3-923b-8695ab15afca | An NLR good | + And the goods are assessed by TAU as: + | id | Control list entry | Report summary prefix | Report summary subject | + | aa9736f9-48f5-4d44-ace9-e4b8738591a5 | ML5b | accessories for | network analysers | + | 56f562f6-b554-4bb3-923b-8695ab15afca | NLR | | | + And a draft licence with attributes: + | name | value | + | id | 847a9a03-c35f-4036-ab8c-8b58d13482ab | + When the licence is issued + Then the `goods_on_licences` table has the following rows: + | good_id | licence_id | + | aa9736f9-48f5-4d44-ace9-e4b8738591a5 | 847a9a03-c35f-4036-ab8c-8b58d13482ab | + +Scenario: Draft licences + Given a standard application with the following goods: + | id | name | + | f7c674b1-cd5e-4a6d-a1f5-d6ab58149d05 | A controlled good 2 | + And a draft licence with attributes: + | name | value | + | id | 297e89b9-fc93-4f38-be46-c2ab38914007 | + Then the `goods_on_licences` table is empty + +Scenario: Draft applications + Given a draft standard application with the following goods: + | id | name | + | 8262dcf7-d932-4a33-978d-b5aa8a7878ee | A controlled good 3 | + And a draft licence with attributes: + | name | value | + | id | 2078827b-6d67-406c-becc-41c423720cfc | + Then the `goods_on_licences` table is empty diff --git a/api/data_workspace/v2/tests/bdd/scenarios/goods_ratings.feature b/api/data_workspace/v2/tests/bdd/scenarios/goods_ratings.feature new file mode 100644 index 0000000000..df0202b1a5 --- /dev/null +++ b/api/data_workspace/v2/tests/bdd/scenarios/goods_ratings.feature @@ -0,0 +1,33 @@ +@db +Feature: goods_ratings Table + +Scenario: Draft application + Given a draft standard application + Then the `goods_ratings` table is empty + +Scenario: Submitted application + Given a draft standard application + And the application has the following goods: + | id | name | + | 8fa8dc3c-c103-42f5-ba94-2d9098b8821d | A controlled good | + | 4dad5dc6-38ef-4bf7-99fd-0c6bc5d86048 | An NLR good | + When the application is submitted + Then the `goods_ratings` table is empty + +Scenario: Assess application + Given a draft standard application + And the application has the following goods: + | id | name | + | 8fa8dc3c-c103-42f5-ba94-2d9098b8821d | A controlled good | + | 118a003c-7191-4a2c-97e9-be243722cbb2 | Another controlled good | + | 4dad5dc6-38ef-4bf7-99fd-0c6bc5d86048 | An NLR good | + When the application is submitted + And the goods are assessed by TAU as: + | id | Control list entry | Report summary prefix | Report summary subject | + | 8fa8dc3c-c103-42f5-ba94-2d9098b8821d | ML22a | accessories for | composite laminates | + | 118a003c-7191-4a2c-97e9-be243722cbb2 | PL9010 | | composite laminates | + | 4dad5dc6-38ef-4bf7-99fd-0c6bc5d86048 | NLR | | | + Then the `goods_ratings` table has the following rows: + | good_id | rating | + | 8fa8dc3c-c103-42f5-ba94-2d9098b8821d | ML22a | + | 118a003c-7191-4a2c-97e9-be243722cbb2 | PL9010 | diff --git a/api/data_workspace/v2/tests/bdd/test_applications.py b/api/data_workspace/v2/tests/bdd/test_applications.py index bad695de0f..fc2f6fef25 100644 --- a/api/data_workspace/v2/tests/bdd/test_applications.py +++ b/api/data_workspace/v2/tests/bdd/test_applications.py @@ -4,8 +4,6 @@ from freezegun import freeze_time -from moto import mock_aws - from pytest_bdd import ( given, parsers, @@ -13,7 +11,6 @@ when, ) -from django.conf import settings from django.urls import reverse from api.applications.enums import ApplicationExportType @@ -28,7 +25,6 @@ AdviceType, ) from api.cases.tests.factories import FinalAdviceFactory -from api.documents.libraries.s3_operations import init_s3_client from api.flags.enums import SystemFlags from api.licences.enums import LicenceStatus from api.parties.tests.factories import ( @@ -50,19 +46,6 @@ def run_processing_time_task(start, up_to): processing_time_task_run_date_time = processing_time_task_run_date_time + datetime.timedelta(days=1) -@pytest.fixture(autouse=True) -def mock_s3(): - with mock_aws(): - s3 = init_s3_client() - s3.create_bucket( - Bucket=settings.AWS_STORAGE_BUCKET_NAME, - CreateBucketConfiguration={ - "LocationConstraint": settings.AWS_REGION, - }, - ) - yield - - @pytest.fixture def submit_application(api_client, exporter_headers, mocker): def _submit_application(draft_application): @@ -91,51 +74,6 @@ def _submit_application(draft_application): return _submit_application -@pytest.fixture() -def issue_licence(api_client, lu_case_officer, gov_headers, siel_template): - def _issue_licence(application): - data = {"action": AdviceType.APPROVE, "duration": 24} - for good_on_app in application.goods.all(): - good_on_app.quantity = 100 - good_on_app.value = 10000 - good_on_app.save() - data[f"quantity-{good_on_app.id}"] = str(good_on_app.quantity) - data[f"value-{good_on_app.id}"] = str(good_on_app.value) - FinalAdviceFactory(user=lu_case_officer, case=application, good=good_on_app.good) - - issue_date = datetime.datetime.now() - data.update({"year": issue_date.year, "month": issue_date.month, "day": issue_date.day}) - - application.flags.remove(SystemFlags.ENFORCEMENT_CHECK_REQUIRED) - - url = reverse("applications:finalise", kwargs={"pk": application.pk}) - response = api_client.put(url, data=data, **gov_headers) - assert response.status_code == 200, response.content - response = response.json() - - data = { - "template": str(siel_template.id), - "text": "", - "visible_to_exporter": False, - "advice_type": AdviceType.APPROVE, - } - url = reverse( - "cases:generated_documents:generated_documents", - kwargs={"pk": str(application.pk)}, - ) - response = api_client.post(url, data=data, **gov_headers) - assert response.status_code == 201, response.content - - url = reverse( - "cases:finalise", - kwargs={"pk": str(application.pk)}, - ) - response = api_client.put(url, data={}, **gov_headers) - assert response.status_code == 201 - - return _issue_licence - - @pytest.fixture() def caseworker_change_status(api_client, lu_case_officer, lu_case_officer_headers): def _caseworker_change_status(application, status): diff --git a/api/data_workspace/v2/tests/bdd/test_goods_descriptions.py b/api/data_workspace/v2/tests/bdd/test_goods_descriptions.py index 88083a1278..8128fdd7f4 100644 --- a/api/data_workspace/v2/tests/bdd/test_goods_descriptions.py +++ b/api/data_workspace/v2/tests/bdd/test_goods_descriptions.py @@ -1,80 +1,4 @@ -from pytest_bdd import ( - given, - parsers, - scenarios, - when, -) - -from django.urls import reverse - -from api.applications.tests.factories import GoodOnApplicationFactory -from api.staticdata.report_summaries.models import ( - ReportSummaryPrefix, - ReportSummarySubject, -) +from pytest_bdd import scenarios scenarios("./scenarios/goods_descriptions.feature") - - -@given(parsers.parse("the application has the following goods:{goods}")) -def given_the_application_has_the_following_goods(parse_table, draft_standard_application, goods): - draft_standard_application.goods.all().delete() - good_attributes = parse_table(goods)[1:] - for id, name in good_attributes: - GoodOnApplicationFactory( - application=draft_standard_application, - id=id, - good__name=name, - ) - - -@when(parsers.parse("the goods are assessed by TAU as:{assessments}")) -def when_the_goods_are_assessed_by_tau( - parse_table, - submitted_standard_application, - assessments, - api_client, - lu_case_officer, - gov_headers, -): - assessments = parse_table(assessments)[1:] - url = reverse("assessments:make_assessments", kwargs={"case_pk": submitted_standard_application.pk}) - - assessment_payload = [] - for good_on_application_id, control_list_entry, report_summary_prefix, report_summary_subject in assessments: - data = { - "id": good_on_application_id, - "comment": "Some comment", - } - - if control_list_entry == "NLR": - data.update( - { - "control_list_entries": [], - "is_good_controlled": False, - } - ) - else: - if report_summary_prefix: - prefix = ReportSummaryPrefix.objects.get(name=report_summary_prefix) - else: - prefix = None - subject = ReportSummarySubject.objects.get(name=report_summary_subject) - data.update( - { - "control_list_entries": [control_list_entry], - "report_summary_prefix": prefix.pk if prefix else None, - "report_summary_subject": subject.pk, - "is_good_controlled": True, - "regime_entries": [], - } - ) - assessment_payload.append(data) - - response = api_client.put( - url, - assessment_payload, - **gov_headers, - ) - assert response.status_code == 200, response.content diff --git a/api/data_workspace/v2/tests/bdd/test_goods_on_licences.py b/api/data_workspace/v2/tests/bdd/test_goods_on_licences.py new file mode 100644 index 0000000000..9c51e66aa4 --- /dev/null +++ b/api/data_workspace/v2/tests/bdd/test_goods_on_licences.py @@ -0,0 +1,106 @@ +from django.urls import reverse +from pytest_bdd import given, parsers, scenarios, when + +from api.applications.tests.factories import GoodOnApplicationFactory +from api.licences.tests.factories import StandardLicenceFactory +from api.licences.enums import LicenceStatus +from api.staticdata.report_summaries.models import ( + ReportSummaryPrefix, + ReportSummarySubject, +) + +scenarios("./scenarios/goods_on_licences.feature") + + +@given(parsers.parse("a standard application with the following goods:{goods}"), target_fixture="standard_application") +def standard_application_with_following_goods(parse_table, goods, standard_application): + standard_application.goods.all().delete() + good_attributes = parse_table(goods)[1:] + for id, name in good_attributes: + GoodOnApplicationFactory( + application=standard_application, + id=id, + good__name=name, + ) + return standard_application + + +@given(parsers.parse("a draft licence with attributes:{attributes}"), target_fixture="draft_licence") +def draft_licence_with_attributes(parse_attributes, attributes, standard_application): + draft_licence = StandardLicenceFactory( + case=standard_application, status=LicenceStatus.DRAFT, **parse_attributes(attributes) + ) + return draft_licence + + +@when("the licence is issued") +def licence_is_issued(standard_application, issue_licence): + issue_licence(standard_application) + standard_application.refresh_from_db() + return standard_application + + +@given(parsers.parse("the goods are assessed by TAU as:{assessments}")) +def the_goods_are_assessed_by_tau_as( + parse_table, + standard_application, + assessments, + api_client, + lu_case_officer, + gov_headers, +): + assessments = parse_table(assessments)[1:] + url = reverse("assessments:make_assessments", kwargs={"case_pk": standard_application.pk}) + + assessment_payload = [] + for good_on_application_id, control_list_entry, report_summary_prefix, report_summary_subject in assessments: + data = { + "id": good_on_application_id, + "comment": "Some comment", + } + + if control_list_entry == "NLR": + data.update( + { + "control_list_entries": [], + "is_good_controlled": False, + } + ) + else: + if report_summary_prefix: + prefix = ReportSummaryPrefix.objects.get(name=report_summary_prefix) + else: + prefix = None + subject = ReportSummarySubject.objects.get(name=report_summary_subject) + data.update( + { + "control_list_entries": [control_list_entry], + "report_summary_prefix": prefix.pk if prefix else None, + "report_summary_subject": subject.pk, + "is_good_controlled": True, + "regime_entries": [], + } + ) + assessment_payload.append(data) + + response = api_client.put( + url, + assessment_payload, + **gov_headers, + ) + assert response.status_code == 200, response.content + + +@given( + parsers.parse("a draft standard application with the following goods:{goods}"), target_fixture="draft_application" +) +def draft_standard_application_with_following_goods(parse_table, goods, draft_application): + draft_application.goods.all().delete() + good_attributes = parse_table(goods)[1:] + for id, name in good_attributes: + GoodOnApplicationFactory( + application=draft_application, + id=id, + good__name=name, + ) + return draft_application diff --git a/api/data_workspace/v2/tests/bdd/test_goods_ratings.py b/api/data_workspace/v2/tests/bdd/test_goods_ratings.py new file mode 100644 index 0000000000..e1f3e17865 --- /dev/null +++ b/api/data_workspace/v2/tests/bdd/test_goods_ratings.py @@ -0,0 +1,4 @@ +from pytest_bdd import scenarios + + +scenarios("./scenarios/goods_ratings.feature") diff --git a/api/data_workspace/v2/urls.py b/api/data_workspace/v2/urls.py index 05817076f4..ed23ee8456 100644 --- a/api/data_workspace/v2/urls.py +++ b/api/data_workspace/v2/urls.py @@ -8,5 +8,7 @@ router_v2.register(views.DestinationViewSet) router_v2.register(views.GoodViewSet) router_v2.register(views.GoodDescriptionViewSet) +router_v2.register(views.GoodOnLicenceViewSet) router_v2.register(views.ApplicationViewSet) router_v2.register(views.FootnoteViewSet) +router_v2.register(views.AssessmentViewSet) diff --git a/api/data_workspace/v2/views.py b/api/data_workspace/v2/views.py index 086e455892..ac0affc2cb 100644 --- a/api/data_workspace/v2/views.py +++ b/api/data_workspace/v2/views.py @@ -29,13 +29,18 @@ from api.core.helpers import str_to_bool from api.data_workspace.v2.serializers import ( ApplicationSerializer, + AssessmentSerializer, CountrySerializer, DestinationSerializer, FootnoteSerializer, GoodDescriptionSerializer, GoodSerializer, LicenceDecisionSerializer, + GoodOnLicenceSerializer, ) +from api.licences.enums import LicenceStatus +from api.licences.models import GoodOnLicence +from api.staticdata.control_list_entries.models import ControlListEntry from api.staticdata.countries.models import Country from api.staticdata.report_summaries.models import ReportSummary from api.staticdata.statuses.enums import CaseStatusEnum @@ -118,6 +123,17 @@ def get_closed_statuses(): ) +class GoodOnLicenceViewSet(BaseViewSet): + serializer_class = GoodOnLicenceSerializer + queryset = GoodOnLicence.objects.exclude( + licence__case__status__status=CaseStatusEnum.DRAFT, + licence__status=LicenceStatus.DRAFT, + ) + + class DataWorkspace: + table_name = "goods_on_licences" + + class ApplicationViewSet(BaseViewSet): serializer_class = ApplicationSerializer queryset = ( @@ -155,3 +171,19 @@ class FootnoteViewSet(BaseViewSet): class DataWorkspace: table_name = "footnotes" + + +class AssessmentViewSet(BaseViewSet): + serializer_class = AssessmentSerializer + + def get_queryset(self): + return ( + ControlListEntry.objects.annotate( + good_id=F("goodonapplication__id"), + ) + .exclude(good_id__isnull=True) + .order_by("rating") + ) + + class DataWorkspace: + table_name = "goods_ratings" diff --git a/bin/seed_internal_users.sh b/bin/seed_internal_users.sh new file mode 100755 index 0000000000..f6517fc146 --- /dev/null +++ b/bin/seed_internal_users.sh @@ -0,0 +1,10 @@ +#!/bin/bash + +set -e + +if [[ "${ENV}" == "prod" ]]; then + echo "You can't seed users on prod" + exit 1 +fi + +python manage.py seedinternalusers diff --git a/pii-secret-exclude.txt b/pii-secret-exclude.txt index ecf8253680..03d87ef58b 100644 --- a/pii-secret-exclude.txt +++ b/pii-secret-exclude.txt @@ -117,3 +117,4 @@ api/staticdata/report_summaries/migrations/data/0002_add_report_summaries/report api/cases/generated_documents/tests/data/dummy.pdf api/cases/generated_documents/tests/data/signed.pdf api/data_workspace/v2/tests/bdd/scenarios/applications.feature +api/data_workspace/v2/tests/bdd/scenarios/goods_on_licences.feature