diff --git a/backend/benefit/applications/fixtures/test_applications.json b/backend/benefit/applications/fixtures/test_applications.json index 523916f375..a9d3070d29 100644 --- a/backend/benefit/applications/fixtures/test_applications.json +++ b/backend/benefit/applications/fixtures/test_applications.json @@ -1505,7 +1505,6 @@ "commission_description": "" } }, - { "model": "applications.attachment", "pk": "3a6fea3c-fbd6-4f04-a4b7-d9f9dcad801c", @@ -1670,7 +1669,7 @@ "fields": { "created_at": "2024-06-13T13:50:58.106Z", "modified_at": "2024-06-13T13:50:58.106Z", - "calculation": "a698bcb1-abea-4da1-a447-cb3742017afe", + "calculation": "aa52e56a-3d64-4129-ae7d-423585d47766", "row_type": "helsinki_benefit_monthly_eur", "ordering": 36, "description_fi": "Helsinki-lisä", @@ -1686,7 +1685,7 @@ "fields": { "created_at": "2024-06-13T13:50:58.109Z", "modified_at": "2024-06-13T13:50:58.109Z", - "calculation": "a698bcb1-abea-4da1-a447-cb3742017afe", + "calculation": "aa52e56a-3d64-4129-ae7d-423585d47766", "row_type": "helsinki_benefit_sub_total_eur", "ordering": 40, "description_fi": "Yhteensä ajanjaksolta", @@ -1775,5 +1774,339 @@ "end_date": "2025-03-01", "description_type": "deduction" } + }, + { + "model": "applications.application", + "pk": "5e586261-07d9-4900-ab27-842ac08910ca", + "fields": { + "created_at": "2024-11-04T10:06:33.596Z", + "modified_at": "2024-11-04T10:10:12.337Z", + "company": "746afc66-6f5a-4cb4-805f-4b58380b4745", + "status": "accepted", + "talpa_status": "rejected_by_talpa", + "application_origin": "applicant", + "application_number": 125000, + "company_name": "Demo I. Haanpää Oy", + "company_form": "OY", + "company_form_code": 16, + "company_department": "", + "official_company_street_address": "Vasaratie 4 A 3", + "official_company_city": "Vaasa", + "official_company_postcode": "65350", + "use_alternative_address": false, + "alternative_company_street_address": "", + "alternative_company_city": "", + "alternative_company_postcode": "", + "company_bank_account_number": "FI6033556370003404", + "company_contact_person_first_name": "Neo", + "company_contact_person_last_name": "Nönnönnöö", + "company_contact_person_phone_number": "+358501234", + "company_contact_person_email": "heips@example.com", + "association_has_business_activities": null, + "applicant_language": "fi", + "association_immediate_manager_check": null, + "co_operation_negotiations": false, + "co_operation_negotiations_description": "", + "pay_subsidy_granted": "not_granted", + "pay_subsidy_percent": null, + "additional_pay_subsidy_percent": null, + "apprenticeship_program": null, + "archived": false, + "application_step": "step_6", + "benefit_type": "salary_benefit", + "start_date": "2024-01-01", + "end_date": "2025-01-01", + "paper_application_date": null, + "de_minimis_aid": false, + "batch": "dde9461e-9580-4ad7-8438-3b9e5c8a616d", + "ahjo_case_id": "HEL 2024-234", + "ahjo_case_guid": "9c66ead0-25c4-4eba-952e-b44774c23056", + "handled_by_ahjo_automation": true, + "handler": "47ecedfa-351b-4815-bfac-96bdbc640178", + "bases": [] + } + }, + { + "model": "applications.employee", + "pk": "a9f04ff2-a45d-4213-b4fa-50d45858aa81", + "fields": { + "created_at": "2024-11-04T10:06:33.606Z", + "modified_at": "2024-11-04T10:10:12.344Z", + "application": "5e586261-07d9-4900-ab27-842ac08910ca", + "encrypted_first_name": "Milamassa", + "encrypted_last_name": "Saragossa", + "first_name": "Milamassa", + "last_name": "Saragossa", + "encrypted_social_security_number": "111111A111C", + "social_security_number": "111111A111C", + "phone_number": "", + "email": "", + "employee_language": "fi", + "job_title": "Taittaja", + "monthly_pay": "9999.00", + "vacation_money": "9999.00", + "other_expenses": "9999.00", + "working_hours": "32.00", + "collective_bargaining_agreement": "MEH", + "is_living_in_helsinki": true, + "commission_amount": null, + "commission_description": "" + } + }, + { + "model": "applications.attachment", + "pk": "af7fdd88-6a93-47ad-9867-fe3fb412d0a8", + "fields": { + "created_at": "2024-11-04T10:09:27.403Z", + "modified_at": "2024-11-04T10:09:27.403Z", + "application": "5e586261-07d9-4900-ab27-842ac08910ca", + "attachment_type": "employee_consent", + "content_type": "image/png", + "attachment_file": "1_6K4Jtln.png", + "ahjo_version_series_id": null, + "ahjo_hash_value": null, + "downloaded_by_ahjo": null + } + }, + { + "model": "applications.attachment", + "pk": "301b8fe0-ebe9-43d7-9dfe-29dc2729acd5", + "fields": { + "created_at": "2024-11-04T10:09:18.013Z", + "modified_at": "2024-11-04T10:09:18.013Z", + "application": "5e586261-07d9-4900-ab27-842ac08910ca", + "attachment_type": "employment_contract", + "content_type": "image/png", + "attachment_file": "1.png", + "ahjo_version_series_id": null, + "ahjo_hash_value": null, + "downloaded_by_ahjo": null + } + }, + { + "model": "applications.ahjostatus", + "pk": 1, + "fields": { + "created_at": "2024-11-04T10:10:12.358Z", + "modified_at": "2024-11-04T10:10:12.358Z", + "status": "details_received", + "application": "5e586261-07d9-4900-ab27-842ac08910ca", + "error_from_ahjo": null, + "ahjo_request_id": null, + "validation_error_from_ahjo": null + } + }, + { + "model": "applications.ahjodecisionproposaldraft", + "pk": 1, + "fields": { + "created_at": "2024-11-04T10:06:33.611Z", + "modified_at": "2024-11-04T10:06:33.611Z", + "application": "5e586261-07d9-4900-ab27-842ac08910ca", + "review_step": "1", + "status": null, + "log_entry_comment": null, + "granted_as_de_minimis_aid": false, + "handler_role": null, + "decision_text": null, + "justification_text": null, + "decision_maker_name": null, + "decision_maker_id": null + } + }, + { + "model": "applications.applicationlogentry", + "pk": "ade2ff63-03f9-493d-a7cb-fc81d7d94a0d", + "fields": { + "created_at": "2024-11-04T10:06:35.596Z", + "modified_at": "2024-11-04T10:06:35.596Z", + "application": "5e586261-07d9-4900-ab27-842ac08910ca", + "from_status": "draft", + "to_status": "received", + "comment": "" + } + }, + { + "model": "calculator.calculation", + "pk": "f9cd39ff-30b3-4a05-a0ec-8837aed98db1", + "fields": { + "created_at": "2024-11-04T10:10:12.357Z", + "modified_at": "2024-11-04T11:20:46.842Z", + "handler": "47ecedfa-351b-4815-bfac-96bdbc640178", + "application": "5e586261-07d9-4900-ab27-842ac08910ca", + "monthly_pay": "9999.00", + "vacation_money": "9999.00", + "other_expenses": "9999.00", + "start_date": "2024-01-01", + "end_date": "2025-03-01", + "state_aid_max_percentage": 100, + "calculated_benefit_amount": "11224.00", + "override_monthly_benefit_amount": null, + "granted_as_de_minimis_aid": false, + "target_group_check": false, + "override_monthly_benefit_amount_comment": "" + } + }, + { + "model": "applications.applicationbatch", + "pk": "dde9461e-9580-4ad7-8438-3b9e5c8a616d", + "fields": { + "created_at": "2024-06-13T14:02:03.208Z", + "modified_at": "2024-06-13T14:02:13.212Z", + "handler": "47ecedfa-351b-4815-bfac-96bdbc640178", + "status": "accepted", + "proposal_for_decision": "accepted", + "decision_maker_title": "Päätöksentekijä", + "decision_maker_name": "Malli Päättäjä", + "section_of_the_law": "§123", + "decision_date": "2024-11-04", + "p2p_inspector_name": null, + "p2p_inspector_email": null, + "p2p_checker_name": null, + "expert_inspector_name": "Malli Tarkastaja", + "expert_inspector_email": "malli.tarkastaja@example.com", + "expert_inspector_title": "Tarkastaja", + "auto_generated_by_ahjo": false + } + }, + { + "model": "calculator.paysubsidy", + "pk": "b5592c1b-80d9-46d3-b81f-a4b6a53e92e7", + "fields": { + "created_at": "2024-06-13T13:43:35.578Z", + "modified_at": "2024-06-13T13:50:58.054Z", + "application": "5e586261-07d9-4900-ab27-842ac08910ca", + "ordering": 0, + "start_date": "2024-06-17", + "end_date": "2024-08-14", + "pay_subsidy_percent": 50, + "work_time_percent": "65.00", + "disability_or_illness": false + } + }, + { + "model": "calculator.instalment", + "pk": "b1f58dab-3581-4ac2-9c15-facaa0bfff92", + "fields": { + "created_at": "2024-11-04T11:20:46.842Z", + "modified_at": "2024-11-04T11:20:46.842Z", + "calculation": "f9cd39ff-30b3-4a05-a0ec-8837aed98db1", + "instalment_number": 1, + "amount": "9600.00", + "due_date": "2024-11-04", + "status": "error_in_talpa" + } + }, + { + "model": "calculator.calculationrow", + "pk": "85fd6559-ae71-41b5-8bb6-830376962699", + "fields": { + "created_at": "2024-06-13T13:50:58.106Z", + "modified_at": "2024-06-13T13:50:58.106Z", + "calculation": "f9cd39ff-30b3-4a05-a0ec-8837aed98db1", + "row_type": "helsinki_benefit_monthly_eur", + "ordering": 36, + "description_fi": "Helsinki-lisä", + "amount": "250.00", + "start_date": null, + "end_date": null, + "description_type": null + } + }, + { + "model": "calculator.calculationrow", + "pk": "6fa38ae4-60ec-4128-b30f-164e64b796a7", + "fields": { + "created_at": "2024-06-13T13:50:58.109Z", + "modified_at": "2024-06-13T13:50:58.109Z", + "calculation": "f9cd39ff-30b3-4a05-a0ec-8837aed98db1", + "row_type": "helsinki_benefit_sub_total_eur", + "ordering": 40, + "description_fi": "Yhteensä ajanjaksolta", + "amount": "1575.00", + "start_date": "2024-08-15", + "end_date": "2024-10-17", + "description_type": null + } + }, + { + "model": "calculator.calculationrow", + "pk": "0625bfb0-17fa-42a8-a26c-70339204effe", + "fields": { + "created_at": "2024-11-04T11:20:46.838Z", + "modified_at": "2024-11-04T11:20:46.838Z", + "calculation": "f9cd39ff-30b3-4a05-a0ec-8837aed98db1", + "row_type": "salary_costs", + "ordering": 0, + "description_fi": "Palkkauskustannukset", + "amount": "29997.00", + "start_date": null, + "end_date": null, + "description_type": null + } + }, + { + "model": "calculator.calculationrow", + "pk": "b690cfc9-7286-4d3b-b71f-f7469fca5587", + "fields": { + "created_at": "2024-11-04T11:20:46.838Z", + "modified_at": "2024-11-04T11:20:46.838Z", + "calculation": "f9cd39ff-30b3-4a05-a0ec-8837aed98db1", + "row_type": "state_aid_max_monthly_eur", + "ordering": 1, + "description_fi": "Valtiotukimaksimi", + "amount": "29997.00", + "start_date": null, + "end_date": null, + "description_type": null + } + }, + { + "model": "calculator.calculationrow", + "pk": "b14209a8-3bdd-40e3-b224-dff55097eecb", + "fields": { + "created_at": "2024-11-04T11:20:46.839Z", + "modified_at": "2024-11-04T11:20:46.839Z", + "calculation": "f9cd39ff-30b3-4a05-a0ec-8837aed98db1", + "row_type": "helsinki_benefit_monthly_eur", + "ordering": 2, + "description_fi": "Helsinki-lisä", + "amount": "800.00", + "start_date": null, + "end_date": null, + "description_type": null + } + }, + { + "model": "calculator.calculationrow", + "pk": "c7f399ff-60d9-4560-8730-cec08355f31a", + "fields": { + "created_at": "2024-11-04T11:20:46.840Z", + "modified_at": "2024-11-04T11:20:46.840Z", + "calculation": "f9cd39ff-30b3-4a05-a0ec-8837aed98db1", + "row_type": "helsinki_benefit_sub_total_eur", + "ordering": 3, + "description_fi": "Yhteensä ajanjaksolta", + "amount": "11224.00", + "start_date": "2024-01-01", + "end_date": "2025-03-01", + "description_type": null + } + }, + { + "model": "calculator.calculationrow", + "pk": "0db9d408-404c-45bc-b71d-4d9ea309e172", + "fields": { + "created_at": "2024-11-04T11:20:46.841Z", + "modified_at": "2024-11-04T11:20:46.841Z", + "calculation": "f9cd39ff-30b3-4a05-a0ec-8837aed98db1", + "row_type": "helsinki_benefit_total_eur", + "ordering": 4, + "description_fi": "Helsinki-lisä yhteensä", + "amount": "11224.00", + "start_date": "2024-01-01", + "end_date": "2025-03-01", + "description_type": "deduction" + } } ] diff --git a/backend/benefit/calculator/api/v1/views.py b/backend/benefit/calculator/api/v1/views.py index 5cb19129aa..2ea4863f4b 100644 --- a/backend/benefit/calculator/api/v1/views.py +++ b/backend/benefit/calculator/api/v1/views.py @@ -5,7 +5,7 @@ from rest_framework.response import Response from rest_framework.views import APIView -from applications.enums import ApplicationTalpaStatus +from applications.enums import ApplicationBatchStatus, ApplicationTalpaStatus from calculator.api.v1.serializers import ( InstalmentSerializer, PreviousBenefitSerializer, @@ -58,7 +58,7 @@ def patch(self, request, instalment_id): instalment_count = instalment.calculation.instalments.count() if instalment.instalment_number == 1: - if instalment_status == InstalmentStatus.WAITING: + if instalment_status == InstalmentStatus.ACCEPTED: application.talpa_status = ( ApplicationTalpaStatus.NOT_PROCESSED_BY_TALPA ) @@ -69,14 +69,19 @@ def patch(self, request, instalment_id): application.talpa_status = ( ApplicationTalpaStatus.SUCCESSFULLY_SENT_TO_TALPA ) + application.batch.status = ApplicationBatchStatus.SENT_TO_TALPA else: application.talpa_status = ( ApplicationTalpaStatus.PARTIALLY_SENT_TO_TALPA ) + application.batch.status = ( + ApplicationBatchStatus.PARTIALLY_SENT_TO_TALPA + ) instalment.amount_paid = instalment.amount_after_recoveries application.archived = True instalment.save() application.save() + application.batch.save() return Response(serializer.data, status=status.HTTP_200_OK) if instalment.instalment_number == 2: first_instalment = instalment.calculation.instalments.get( diff --git a/frontend/benefit/handler/browser-tests/pages/10-talpa-error-handling.testcafe.ts b/frontend/benefit/handler/browser-tests/pages/10-talpa-error-handling.testcafe.ts new file mode 100644 index 0000000000..170304a5d1 --- /dev/null +++ b/frontend/benefit/handler/browser-tests/pages/10-talpa-error-handling.testcafe.ts @@ -0,0 +1,135 @@ +import { clearDataToPrintOnFailure } from '@frontend/shared/browser-tests/utils/testcafe.utils'; +import { ClientFunction, Selector } from 'testcafe'; + +import fi from '../../public/locales/fi/common.json'; +import MainIngress from '../page-model/MainIngress'; +import handlerUserAhjo from '../utils/handlerUserAhjo'; +import { getFrontendUrl } from '../utils/url.utils'; + +const url = getFrontendUrl(`/`); + +fixture('Talpa error resolution by handler') + .page(url) + .clientScripts({ + content: 'window.localStorage.setItem("newAhjoMode", "1");', + }) + .beforeEach(async (t) => { + clearDataToPrintOnFailure(t); + await t.useRole(handlerUserAhjo); + await ClientFunction(() => + window.localStorage.setItem('newAhjoMode', '1') + )(); + await t.navigateTo('/'); + }); + +test('Handler changes Talpa status to waiting', async (t: TestController) => { + const mainIngress = new MainIngress(fi.mainIngress.heading, 'h1'); + await mainIngress.isLoaded(); + + await t.click( + Selector('li').withText(fi.applications.list.headings.inPayment) + ); + + const errorTag = Selector('td') + .withText(`Juno Yucca-Palmu`) + .parent() + .find('#hds-tag span') + .withText(fi.applications.list.columns.talpaStatuses.rejected_by_talpa); + await t.expect(errorTag.visible).ok(); + await t.click(errorTag); + + await t + .expect( + Selector('h2').withText(fi.applications.dialog.talpaStatusChange.heading) + .visible + ) + .ok(); + + await t.click( + Selector('button').withText(fi.applications.list.actions.return_as_waiting) + ); + + await t + .expect( + Selector('#hds-tag').withText( + fi.applications.list.columns.talpaStatuses.not_sent_to_talpa + ).visible + ) + .ok(); +}); + +test('Handler changes Talpa status to paid', async (t: TestController) => { + const mainIngress = new MainIngress(fi.mainIngress.heading, 'h1'); + await mainIngress.isLoaded(); + + await t.click( + Selector('li').withText(fi.applications.list.headings.inPayment) + ); + + const errorTag = Selector('td') + .withText(`Milamassa Saragossa`) + .parent() + .find('#hds-tag span') + .withText(fi.applications.list.columns.talpaStatuses.rejected_by_talpa); + await t.expect(errorTag.visible).ok(); + await t.click(errorTag); + + await t + .expect( + Selector('h2').withText(fi.applications.dialog.talpaStatusChange.heading) + .visible + ) + .ok(); + + await t.click( + Selector('button').withText(fi.applications.list.actions.mark_as_paid) + ); + + await t.click(Selector('a').withText(fi.header.navigation.archive)); + await t.expect(Selector('td').withText(`Saragossa, Milamassa`).visible).ok(); +}); + +test('Handler changes 2nd instalment status waiting', async (t: TestController) => { + const mainIngress = new MainIngress(fi.mainIngress.heading, 'h1'); + await mainIngress.isLoaded(); + + await t.click( + Selector('li').withText(fi.applications.list.headings.instalments) + ); + + const checkbox = Selector('td[data-testid="applicationNum-0"]') + .withText(`125000`) + .parent() + .find('input[type="checkbox"]'); + await t.expect(checkbox.visible).ok(); + await t.click(checkbox); + + await t.click( + Selector('button').withText(fi.applications.list.actions.confirm) + ); + + await t.click( + Selector('button').withText(fi.applications.list.actions.return) + ); + + await t.click( + Selector('button').withText(fi.applications.list.actions.cancel) + ); + + await t + .expect( + Selector('h3').withText(fi.instalments.dialog.cancelInstalment.heading) + .visible + ) + .ok(); + + await t.click(Selector('button').withText(fi.utility.confirm)); + + await t + .expect( + Selector('td').withText( + fi.applications.list.columns.instalmentStatuses.cancelled + ).visible + ) + .ok(); +}); diff --git a/frontend/benefit/handler/src/components/applicationList/HandlerIndex.tsx b/frontend/benefit/handler/src/components/applicationList/HandlerIndex.tsx index a0a933f4b6..5ccb649dcf 100644 --- a/frontend/benefit/handler/src/components/applicationList/HandlerIndex.tsx +++ b/frontend/benefit/handler/src/components/applicationList/HandlerIndex.tsx @@ -49,6 +49,17 @@ export const isInPayment = ( application?.batch?.status ); +export const isPendingInstalment = ( + application: ApplicationListItemData | Application +): boolean => + [APPLICATION_STATUSES.ACCEPTED].includes(application.status) && + !isString(application.batch) && + [ + BATCH_STATUSES.DECIDED_ACCEPTED, + BATCH_STATUSES.REJECTED_BY_TALPA, + BATCH_STATUSES.PARTIALLY_SENT_TO_TALPA, + ].includes(application?.batch?.status); + const HandlerIndex: React.FC = ({ layoutBackgroundColor, list = [], @@ -292,7 +303,7 @@ const HandlerIndex: React.FC = ({ app.secondInstalment && isInPayment(app) + (app) => app.secondInstalment && isPendingInstalment(app) )} heading={t(`${translationBase}.instalments`)} /> diff --git a/frontend/benefit/handler/src/components/applicationList/TalpaStatusChangeDialog.tsx b/frontend/benefit/handler/src/components/applicationList/TalpaStatusChangeDialog.tsx index 84187938f7..1121b5c595 100644 --- a/frontend/benefit/handler/src/components/applicationList/TalpaStatusChangeDialog.tsx +++ b/frontend/benefit/handler/src/components/applicationList/TalpaStatusChangeDialog.tsx @@ -43,7 +43,7 @@ const TalpaStatusChangeModal: React.FC<{ diff --git a/frontend/benefit/shared/src/constants.ts b/frontend/benefit/shared/src/constants.ts index 4a64136299..aa4ebbd0fe 100644 --- a/frontend/benefit/shared/src/constants.ts +++ b/frontend/benefit/shared/src/constants.ts @@ -171,6 +171,7 @@ export enum BATCH_STATUSES { DECIDED_ACCEPTED = 'accepted', DECIDED_REJECTED = 'rejected', REJECTED_BY_TALPA = 'rejected_by_talpa', + PARTIALLY_SENT_TO_TALPA = 'partially_sent_to_talpa', SENT_TO_TALPA = 'sent_to_talpa', COMPLETED = 'completed', } diff --git a/frontend/shared/src/components/header/Header.tsx b/frontend/shared/src/components/header/Header.tsx index d54b551d21..aa6585a1ee 100644 --- a/frontend/shared/src/components/header/Header.tsx +++ b/frontend/shared/src/components/header/Header.tsx @@ -143,7 +143,7 @@ const Header: React.FC = ({ /> )} -
+
{login && login?.isAuthenticated && !hideLogin && (