def case_activity_json(audit, case_type): """ Creates an activity stream compatible record for an application activity """ case = audit.target or audit.action_object if not case: # Some applications in draft status are being deleted return {} data_type = TYPE_MAPPING[AuditType(audit.verb)] verb = VERB_MAPPING[AuditType(audit.verb)] object_data = { "type": [ "dit:lite:case:change", "dit:lite:activity", "dit:lite:case:change:{data_type}".format(data_type=data_type), ], "attributedTo": { "id": "dit:lite:case:{case_type}:{id}".format(case_type=case_type, id=case.id) }, "id": "dit:lite:case:change:{data_type}:{id}:{audit_id}".format( data_type=data_type, id=case.id, audit_id=audit.id), }
def test_change_next_review_date_success(self): old_date = "2025-01-01" request = self.client.put(self.url, data={"next_review_date": old_date}, **self.gov_headers) self.assertEqual(request.status_code, status.HTTP_200_OK) self.case.refresh_from_db() case_review_date = self.case.case_review_date.all()[0] self.assertEqual(len(self.case.case_review_date.all()), 1) self.assertEqual(str(case_review_date.next_review_date), old_date) self.assertEqual(case_review_date.team_id, self.team.id) self.assertEqual(case_review_date.case_id, self.case.id) audit_qs = Audit.objects.all() self.assertEqual(audit_qs.count(), 2) self.assertEqual(AuditType(audit_qs.first().verb), AuditType.ADDED_NEXT_REVIEW_DATE) self.assertEqual( audit_qs.first().payload, { "next_review_date": convert_date_to_string(old_date), "team_name": self.team.name }, ) new_date = "2026-05-06" request = self.client.put(self.url, data={"next_review_date": new_date}, **self.gov_headers) self.assertEqual(request.status_code, status.HTTP_200_OK) self.case.refresh_from_db() case_review_date = self.case.case_review_date.all()[0] self.assertEqual(len(self.case.case_review_date.all()), 1) self.assertEqual(str(case_review_date.next_review_date), new_date) self.assertEqual(case_review_date.team_id, self.team.id) self.assertEqual(case_review_date.case_id, self.case.id) audit_qs = Audit.objects.all() self.assertEqual(audit_qs.count(), 3) self.assertEqual(AuditType(audit_qs.first().verb), AuditType.EDITED_NEXT_REVIEW_DATE) self.assertEqual( audit_qs.first().payload, { "old_date": convert_date_to_string(old_date), "new_date": convert_date_to_string(new_date), "team_name": self.team.name, }, )
def test_respond_to_control_list_classification_query_nlr(self): """ Ensure that a gov user can respond to a control list classification query with no licence required. """ control_list_entries = self.query.good.control_list_entries.set( [get_control_list_entry("ML1a")]) data = { "comment": "I Am Easy to Find", "report_summary": self.report_summary.pk, "is_good_controlled": "no" } response = self.client.put(self.url, data, **self.gov_headers) self.query.refresh_from_db() self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual( list( self.query.good.control_list_entries.values_list("rating", flat=True)), ["ML1a"]) self.assertEqual(self.query.good.is_good_controlled, False) self.assertEqual(self.query.good.status, GoodStatus.VERIFIED) # Check that an activity item has been added qs = Audit.objects.filter( target_object_id=self.query.id, target_content_type=ContentType.objects.get_for_model(self.query)) for audit in qs: verb = AuditType.GOOD_REVIEWED if audit.payload else AuditType.CLC_RESPONSE self.assertEqual(AuditType(audit.verb), verb)
def test_respond_to_control_list_classification_query_update_control_list_entries_success( self): previous_query_control_list_entries = self.query.good.control_list_entries.all( ) response = self.client.put(self.url, self.data, **self.gov_headers) self.query.refresh_from_db() self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual( [clc.rating for clc in self.query.good.control_list_entries.all()], self.data["control_list_entries"]) self.assertNotEqual(self.query.good.control_list_entries, previous_query_control_list_entries) self.assertEqual(self.query.good.is_good_controlled, True) self.assertEqual(self.query.good.status, GoodStatus.VERIFIED) audit_qs = Audit.objects.all() self.assertEqual(audit_qs.count(), 2) for audit in audit_qs: verb = AuditType.GOOD_REVIEWED if audit.payload else AuditType.CLC_RESPONSE self.assertEqual(AuditType(audit.verb), verb) if verb == AuditType.GOOD_REVIEWED: payload = { "good_name": self.query.good.description, "old_control_list_entry": ["No control code"], "new_control_list_entry": self.data["control_list_entries"], } self.assertEqual(audit.payload, payload)
def test_resubmit_same_next_review_date_success(self): date = "2025-01-01" request = self.client.put(self.url, data={"next_review_date": date}, **self.gov_headers) self.assertEqual(request.status_code, status.HTTP_200_OK) self.case.refresh_from_db() case_review_date = self.case.case_review_date.all()[0] self.assertEqual(len(self.case.case_review_date.all()), 1) self.assertEqual(str(case_review_date.next_review_date), date) self.assertEqual(case_review_date.team_id, self.team.id) self.assertEqual(case_review_date.case_id, self.case.id) audit_qs = Audit.objects.all() self.assertEqual(audit_qs.count(), 2) self.assertEqual(AuditType(audit_qs.first().verb), AuditType.ADDED_NEXT_REVIEW_DATE) self.assertEqual( audit_qs.first().payload, { "next_review_date": convert_date_to_string(date), "team_name": self.team.name }) request = self.client.put(self.url, data={"next_review_date": date}, **self.gov_headers) self.assertEqual(request.status_code, status.HTTP_200_OK) self.case.refresh_from_db() case_review_date = self.case.case_review_date.all()[0] self.assertEqual(len(self.case.case_review_date.all()), 1) self.assertEqual(str(case_review_date.next_review_date), date) self.assertEqual(case_review_date.team_id, self.team.id) self.assertEqual(case_review_date.case_id, self.case.id) audit_qs = Audit.objects.all() # Resubmitting the same date shouldn't created an new edited audit self.assertEqual(audit_qs.count(), 2) self.assertNotEqual(AuditType(audit_qs.first().verb), AuditType.EDITED_NEXT_REVIEW_DATE)
def test_set_org_details_success(self): """ Internal users can change an organisation's information """ organisation = OrganisationFactory(type=OrganisationType.COMMERCIAL) previous_eori_number = organisation.eori_number previous_sic_number = organisation.sic_number previous_vat_number = organisation.vat_number previous_registration_number = organisation.registration_number self.gov_user.role.permissions.set([GovPermissions.MANAGE_ORGANISATIONS.name]) data = { "eori_number": self.faker.eori_number(), "sic_number": self.faker.sic_number(), "vat_number": self.faker.vat_number(), "registration_number": self.faker.registration_number(), } response = self.client.put(self._get_url(organisation.id), data, **self.gov_headers) organisation.refresh_from_db() self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(organisation.eori_number, data["eori_number"]) self.assertEqual(organisation.sic_number, data["sic_number"]) self.assertEqual(organisation.vat_number, data["vat_number"]) self.assertEqual(organisation.registration_number, data["registration_number"]) audit_qs = Audit.objects.all() self.assertEqual(audit_qs.count(), 4) for audit in audit_qs: verb = AuditType.UPDATED_ORGANISATION self.assertEqual(AuditType(audit.verb), verb) if audit.payload["key"] == "registration number": org_field = "registration number" previous_value = previous_registration_number new_value = organisation.registration_number elif audit.payload["key"] == "VAT number": org_field = "VAT number" previous_value = previous_vat_number new_value = organisation.vat_number elif audit.payload["key"] == "SIC number": org_field = "SIC number" previous_value = previous_sic_number new_value = organisation.sic_number elif audit.payload["key"] == "EORI number": org_field = "EORI number" previous_value = previous_eori_number new_value = organisation.eori_number payload = { "key": org_field, "old": previous_value, "new": new_value, } self.assertEqual(audit.payload, payload)
def test_add_past_next_review_date_failure(self): date = "2000-01-01" request = self.client.put(self.url, data={"next_review_date": date}, **self.gov_headers) self.assertEqual(request.status_code, status.HTTP_400_BAD_REQUEST) self.assertEqual(str(request.data["errors"]["next_review_date"][0]), strings.Cases.NextReviewDate.Errors.DATE_IN_PAST) self.assertEqual(len(self.case.case_review_date.all()), 0) audit_qs = Audit.objects.all() self.assertEqual(audit_qs.count(), 1) self.assertNotEqual(AuditType(audit_qs.first().verb), AuditType.ADDED_NEXT_REVIEW_DATE)
def get_filters(data: QueryDict) -> Dict: return { "user_id": data.get("user_id"), "team": data.get("team_id"), "user_type": UserType(data["user_type"]) if data.get("user_type") else None, "audit_type": AuditType(data["activity_type"]) if data.get("activity_type") else None, "date_from": make_date_from_params("from", data), "date_to": make_date_from_params("to", data), }
def get_objects_activity_filters(object_id, object_content_type): audit_qs = Audit.objects.filter( Q(action_object_object_id=object_id, action_object_content_type=object_content_type) | Q(target_object_id=object_id, target_content_type=object_content_type)) activity_types = (audit_qs.order_by("verb").exclude( verb=AuditType.CREATED_CASE_NOTE).values_list("verb", flat=True).distinct()) # Add the created case note audit type if an audit entry exists with additional text if audit_qs.filter(payload__contains="additional_text").exists(): activity_types = list(activity_types) activity_types.append(AuditType.CREATED_CASE_NOTE) activity_types = sorted(activity_types) user_ids = audit_qs.order_by("actor_object_id").values_list( "actor_object_id", flat=True).distinct() users = BaseUser.objects.filter(id__in=list(user_ids)).values( "id", "first_name", "last_name") teams = Team.objects.filter( users__pk__in=list(user_ids)).order_by("id").values("name", "id").distinct() filters = { "activity_types": [{ "key": verb, "value": AuditType(verb).human_readable() } for verb in activity_types], "teams": [{ "key": str(team["id"]), "value": team["name"] } for team in teams], "user_types": [ { "key": UserType.INTERNAL.value, "value": UserType.INTERNAL.human_readable() }, { "key": UserType.EXPORTER.value, "value": UserType.EXPORTER.human_readable() }, ], "users": [{ "key": str(user["id"]), "value": f"{user['first_name']} {user['last_name']}" } for user in users], } return filters
def test_add_blank_next_review_date_success(self): date = None request = self.client.put(self.url, data={"next_review_date": date}, **self.gov_headers) self.assertEqual(request.status_code, status.HTTP_200_OK) self.case.refresh_from_db() case_review_date = self.case.case_review_date.all()[0] self.assertEqual(len(self.case.case_review_date.all()), 1) self.assertEqual(case_review_date.next_review_date, date) self.assertEqual(case_review_date.team_id, self.team.id) self.assertEqual(case_review_date.case_id, self.case.id) audit_qs = Audit.objects.all() self.assertEqual(audit_qs.count(), 1) self.assertNotEqual(AuditType(audit_qs.first().verb), AuditType.ADDED_NEXT_REVIEW_DATE)
def test_edit_submitted_application_clearance_type_major_success(self): application = self.create_mod_clearance_application( self.organisation, CaseTypeEnum.F680) url = reverse("applications:application", kwargs={"pk": application.id}) self.submit_application(application) application.status = get_case_status_by_status( CaseStatusEnum.APPLICANT_EDITING) application.save() data = { "types": [ F680ClearanceTypeEnum. DEMONSTRATION_IN_THE_UK_TO_OVERSEAS_CUSTOMERS ] } response = self.client.put(url, data=data, **self.exporter_headers) application.refresh_from_db() self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual( application.types.get().name, F680ClearanceTypeEnum. DEMONSTRATION_IN_THE_UK_TO_OVERSEAS_CUSTOMERS) # Check add audit self.assertEqual(Audit.objects.all().count(), 2) audit = Audit.objects.all().first() self.assertEqual(AuditType(audit.verb), AuditType.UPDATE_APPLICATION_F680_CLEARANCE_TYPES) self.assertEqual( audit.payload, { "old_types": [ F680ClearanceTypeEnum.get_text( F680ClearanceTypeEnum.MARKET_SURVEY) ], "new_types": [ F680ClearanceTypeEnum.get_text(type) for type in data["types"] ], }, )
def get_text(self, instance): verb = AuditType(instance.verb) payload = deepcopy(instance.payload) if verb == AuditType.REGISTER_ORGANISATION: payload["email"] = "" for key in payload: # If value is a list, join by comma. try: if isinstance(payload[key], list): payload[key] = ", ".join(payload[key]) except KeyError as e: logging.error(f"Audit serialization exception skipped: {e}") # TODO: standardise payloads across all audits and remove below if key == "status" and "new" in payload[key]: # Handle new payload format payload[key] = payload[key]["new"] return format_payload(verb, payload)
def test_add_present_next_review_date_success(self): date = timezone.now().date() request = self.client.put(self.url, data={"next_review_date": str(date)}, **self.gov_headers) self.assertEqual(request.status_code, status.HTTP_200_OK) self.case.refresh_from_db() case_review_date = self.case.case_review_date.all()[0] self.assertEqual(len(self.case.case_review_date.all()), 1) self.assertEqual(case_review_date.next_review_date, date) self.assertEqual(case_review_date.team_id, self.team.id) self.assertEqual(case_review_date.case_id, self.case.id) audit_qs = Audit.objects.all() self.assertEqual(audit_qs.count(), 2) self.assertEqual(AuditType(audit_qs.first().verb), AuditType.ADDED_NEXT_REVIEW_DATE) self.assertEqual( audit_qs.first().payload, { "next_review_date": convert_date_to_string(date), "team_name": self.team.name })
def test_edit_submitted_application_reference_number(self): """ Test successful editing of an application's reference number when the application's status is non read-only. """ application = self.create_draft_standard_application(self.organisation) self.submit_application(application) application.status = get_case_status_by_status( CaseStatusEnum.APPLICANT_EDITING) application.save() url = reverse("applications:application", kwargs={"pk": application.id}) updated_at = application.updated_at audit_qs = Audit.objects.all() new_ref = "35236246" update_ref = "13124124" # Add ref data = { "reference_number_on_information_form": new_ref, "have_you_been_informed": "yes" } response = self.client.put(url, data, **self.exporter_headers) application.refresh_from_db() self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual( application.reference_number_on_information_form, data["reference_number_on_information_form"], ) self.assertNotEqual(application.updated_at, updated_at) # Check add audit self.assertEqual(audit_qs.count(), 2) self.assertEqual(AuditType(audit_qs.first().verb), AuditType.UPDATE_APPLICATION_LETTER_REFERENCE) self.assertEqual(audit_qs.first().payload, { "old_ref_number": "no reference", "new_ref_number": new_ref }) # Update ref data = { "reference_number_on_information_form": update_ref, "have_you_been_informed": "yes" } response = self.client.put(url, data, **self.exporter_headers) # Check update audit self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(audit_qs.count(), 3) self.assertEqual(AuditType(audit_qs.first().verb), AuditType.UPDATE_APPLICATION_LETTER_REFERENCE) self.assertEqual(audit_qs.first().payload, { "old_ref_number": new_ref, "new_ref_number": update_ref }) # Update ref with no reference data = { "reference_number_on_information_form": "", "have_you_been_informed": "yes" } response = self.client.put(url, data, **self.exporter_headers) # Check update self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(audit_qs.count(), 4) self.assertEqual(AuditType(audit_qs.first().verb), AuditType.UPDATE_APPLICATION_LETTER_REFERENCE) self.assertEqual(audit_qs.first().payload, { "old_ref_number": update_ref, "new_ref_number": "no reference" }) # Remove ref data = { "reference_number_on_information_form": "", "have_you_been_informed": "no" } response = self.client.put(url, data, **self.exporter_headers) # Check update self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(audit_qs.count(), 5) self.assertEqual(AuditType(audit_qs.first().verb), AuditType.REMOVED_APPLICATION_LETTER_REFERENCE) self.assertEqual(audit_qs.first().payload, {"old_ref_number": "no reference"})
"dit:lite:case:change", "dit:lite:activity", "dit:lite:case:change:{data_type}".format(data_type=data_type), ], "attributedTo": { "id": "dit:lite:case:{case_type}:{id}".format(case_type=case_type, id=case.id) }, "id": "dit:lite:case:change:{data_type}:{id}:{audit_id}".format( data_type=data_type, id=case.id, audit_id=audit.id), } # TODO: standardize audit payloads and clean if AuditType(audit.verb) == AuditType.CREATED: if not audit.payload: audit.payload = { "status": { "new": "clc_review" if case_type == "end_user_advisory" else "submitted" } } audit.save() object_data["dit:to"] = { "dit:lite:case:status": audit.payload["status"]["new"] } object_data["type"] = [ "dit:lite:case:create", "dit:lite:activity",