From 6800c392848e5c0e0221abad55e6153ba4d85968 Mon Sep 17 00:00:00 2001 From: Sampo Tawast <5328394+sirtawast@users.noreply.github.com> Date: Tue, 16 Jan 2024 10:21:34 +0200 Subject: [PATCH] fix: an array of fixes for HL-1053 (#2726) * refactor: rename private function * fix: issue with setting inspection data with rejected applications * feat: add possibility to reorder batches differently on each tab * fix: swap column order for title and name field * fix: bunch of translation issues * feat: conditionally load table headers; improve typing; use helper * feat: useState to update batch count on heading for each tab * fix: use smaller margin for listing batches --- .../api/v1/application_batch_views.py | 114 ++++++++++-------- .../tests/test_application_batch_api.py | 24 ++-- .../handler/public/locales/en/common.json | 39 ++++-- .../handler/public/locales/fi/common.json | 39 ++++-- .../handler/public/locales/sv/common.json | 39 ++++-- .../batchProcessing/BatchApplicationList.tsx | 63 ++++++---- .../batchProcessing/BatchProposals.tsx | 13 +- .../batchFooter/BatchFooterCompletion.tsx | 4 +- .../useBatchActionsInspected.ts | 5 +- .../components/batchProcessing/useBatches.ts | 11 +- .../src/components/table/TableExtras.sc.ts | 2 +- .../handler/src/hooks/useBatchInspected.ts | 11 +- .../handler/src/hooks/useBatchQuery.ts | 4 +- .../handler/src/hooks/useBatchStatus.ts | 4 +- .../handler/src/pages/batches/index.tsx | 22 +++- .../handler/src/types/applicationList.d.ts | 1 + .../benefit/handler/src/types/batchList.d.ts | 13 ++ 17 files changed, 272 insertions(+), 136 deletions(-) create mode 100644 frontend/benefit/handler/src/types/batchList.d.ts diff --git a/backend/benefit/applications/api/v1/application_batch_views.py b/backend/benefit/applications/api/v1/application_batch_views.py index 813d917aa8..104fad2d34 100755 --- a/backend/benefit/applications/api/v1/application_batch_views.py +++ b/backend/benefit/applications/api/v1/application_batch_views.py @@ -70,6 +70,14 @@ class ApplicationBatchViewSet(AuditLoggingModelViewSet): "applications__company_contact_person_email", ] + def get_queryset(self): + order_by = self.request.query_params.get("order_by") or None + + if order_by: + self.queryset = self.queryset.order_by(order_by) + + return self.queryset + def get_serializer_class(self): """ ApplicationBatchSerializer for default behaviour on mutation functions, @@ -80,7 +88,7 @@ def get_serializer_class(self): return ApplicationBatchListSerializer - def get_batch(self, id: str) -> ApplicationBatch: + def _get_batch(self, id: str) -> ApplicationBatch: """ Just a wrapper for Django's get_object_or_404 function """ @@ -91,7 +99,7 @@ def destroy(self, request, pk=None): """ Override default destroy(), batch can only be deleted if it's status is "draft" """ - batch = self.get_batch(pk) + batch = self._get_batch(pk) if batch.status == ApplicationBatchStatus.DRAFT: batch.delete() return Response(status=status.HTTP_204_NO_CONTENT) @@ -272,7 +280,7 @@ def deassign_applications(self, request, pk=None): Remove one or more applications from a specific batch """ application_ids = request.data.get("application_ids") - batch = self.get_batch(pk) + batch = self._get_batch(pk) deassign_apps = Application.objects.filter( batch=batch, @@ -302,57 +310,22 @@ def status(self, request, pk=None): Assign a new status for batch: as pending for Ahjo proposal or switch back to draft """ new_status = request.data["status"] - batch = self.get_batch(pk) - if new_status not in [ - ApplicationBatchStatus.DRAFT, - ApplicationBatchStatus.AHJO_REPORT_CREATED, - ApplicationBatchStatus.AWAITING_AHJO_DECISION, - ApplicationBatchStatus.DECIDED_ACCEPTED, - ApplicationBatchStatus.DECIDED_REJECTED, - ApplicationBatchStatus.SENT_TO_TALPA, - ApplicationBatchStatus.COMPLETED, - ]: + + if _unallowed_status_change(new_status): return Response(status=status.HTTP_400_BAD_REQUEST) - # Patch all required fields after batch inspection - if new_status in [ - ApplicationBatchStatus.DECIDED_ACCEPTED, - ApplicationBatchStatus.DECIDED_REJECTED, - ]: - for key in request.data: - setattr(batch, key, request.data.get(key)) + batch = self._get_batch(pk) + previous_status = batch.status - # Archive all applications if this batch will be completed - if new_status in [ - ApplicationBatchStatus.COMPLETED, - ]: - Application.objects.filter(batch=batch).update(archived=True) + _save_batch_or_raise(batch, new_status, request.data) - batch.status = new_status + # Decided on rejection, can set status to completed + if new_status == ApplicationBatchStatus.DECIDED_REJECTED: + _save_batch_or_raise(batch, ApplicationBatchStatus.COMPLETED, request.data) - try: - batch.save() - except BatchCompletionDecisionDateError: - return Response( - {"errorKey": "batchInvalidDecisionDate"}, - status=status.HTTP_400_BAD_REQUEST, - ) - except BatchTooManyDraftsError: - return Response( - {"errorKey": "batchInvalidDraftAlreadyExists"}, - status=status.HTTP_400_BAD_REQUEST, - ) - except BatchCompletionRequiredFieldsError: - return Response( - {"errorKey": "batchInvalidCompletionRequiredFieldsMissing"}, - status=status.HTTP_400_BAD_REQUEST, - ) - except ValidationError: - return Response( - status=status.HTTP_400_BAD_REQUEST, - ) - - previous_status = batch.status + # Archive all applications if this batch will be completed + if batch.status == ApplicationBatchStatus.COMPLETED: + Application.objects.filter(batch=batch).update(archived=True) return Response( { @@ -363,3 +336,46 @@ def status(self, request, pk=None): }, status=status.HTTP_200_OK, ) + + +def _save_batch_or_raise(batch, new_status, data): + # Patch all required fields after batch inspection + if new_status in [ + ApplicationBatchStatus.DECIDED_ACCEPTED, + ApplicationBatchStatus.DECIDED_REJECTED, + ]: + for key in data: + setattr(batch, key, data.get(key)) + try: + batch.status = new_status + batch.save() + except BatchCompletionDecisionDateError: + return Response( + {"errorKey": "batchInvalidDecisionDate"}, + status=status.HTTP_400_BAD_REQUEST, + ) + except BatchTooManyDraftsError: + return Response( + {"errorKey": "batchInvalidDraftAlreadyExists"}, + status=status.HTTP_400_BAD_REQUEST, + ) + except BatchCompletionRequiredFieldsError: + return Response( + {"errorKey": "batchInvalidCompletionRequiredFieldsMissing"}, + status=status.HTTP_400_BAD_REQUEST, + ) + except ValidationError: + return Response( + status=status.HTTP_400_BAD_REQUEST, + ) + + +def _unallowed_status_change(new_status): + return new_status not in [ + ApplicationBatchStatus.DRAFT, + ApplicationBatchStatus.AHJO_REPORT_CREATED, + ApplicationBatchStatus.AWAITING_AHJO_DECISION, + ApplicationBatchStatus.DECIDED_ACCEPTED, + ApplicationBatchStatus.DECIDED_REJECTED, + ApplicationBatchStatus.COMPLETED, + ] diff --git a/backend/benefit/applications/tests/test_application_batch_api.py b/backend/benefit/applications/tests/test_application_batch_api.py index db2b165e6d..ad35d8da22 100755 --- a/backend/benefit/applications/tests/test_application_batch_api.py +++ b/backend/benefit/applications/tests/test_application_batch_api.py @@ -39,6 +39,15 @@ def get_valid_batch_completion_data(): } +def get_valid_rejected_batch_completion_data(): + return { + "decision_maker_title": get_faker().job(), + "decision_maker_name": get_faker().name(), + "section_of_the_law": "$1234", + "decision_date": date.today(), + } + + def get_valid_p2p_batch_completion_data(): return { "decision_maker_title": get_faker().job(), @@ -270,7 +279,7 @@ def test_deassign_applications_from_batch_all(handler_api_client, application_ba "batch_status,status_code,changed_status", [ (ApplicationBatchStatus.COMPLETED, 200, None), - (ApplicationBatchStatus.SENT_TO_TALPA, 200, None), + (ApplicationBatchStatus.SENT_TO_TALPA, 400, None), (ApplicationBatchStatus.RETURNED, 400, None), (ApplicationBatchStatus.DECIDED_ACCEPTED, 200, None), (ApplicationBatchStatus.DECIDED_REJECTED, 200, None), @@ -347,15 +356,12 @@ def remove_inspection_data_from_batch(batch): batch.save() url = get_batch_detail_url(application_batch, "status/") - payload = get_valid_batch_completion_data() - payload["status"] = batch_status - - # With months and a day over the range - payload["decision_date"] = date.today() + relativedelta( - days=delta_days, months=delta_months + payload = ( + get_valid_batch_completion_data() + if batch_status == ApplicationBatchStatus.DECIDED_ACCEPTED + else get_valid_rejected_batch_completion_data() ) - response = handler_api_client.patch(url, payload) - assert response.status_code == 400 + payload["status"] = batch_status # With exact months payload["decision_date"] = date.today() + relativedelta(months=(delta_months)) diff --git a/frontend/benefit/handler/public/locales/en/common.json b/frontend/benefit/handler/public/locales/en/common.json index 3274959f0c..e08a2974b1 100644 --- a/frontend/benefit/handler/public/locales/en/common.json +++ b/frontend/benefit/handler/public/locales/en/common.json @@ -1092,12 +1092,27 @@ } }, "statusChange": { - "awaiting_ahjo_decision": "Koonti merkitty Ahjoon viedyksi", - "exported_ahjo_report": "Ahjo-valmistelu aloitettu, koonti lukittu", - "completed": "Koonti käsitelty ja arkistoitu", - "draft": "Koonti palautettu takaisin odottamaan päätösvalmistelua", - "accepted": "Tarkastustiedot tallennettu", - "rejected": "Koonti arkistoitu" + "awaiting_ahjo_decision": { + "heading": "Koonti merkitty Ahjoon viedyksi", + "text": "" + }, + "exported_ahjo_report": { + "heading": "Ahjo-valmistelu aloitettu, koonti lukittu", + "text": "" + }, + "completed": { + "heading": "Koonti käsitelty ja arkistoitu", + "text": "" + }, + "draft": { + "heading": "Koonti palautettu takaisin odottamaan päätösvalmistelua", + "text": "" + }, + "accepted": { + "heading": "Hakemuksia siirretty maksuun", + "text": "Olet lähettänyt {{ count }} myönteistä hakemusta maksuun. Hakemukset siirtyvät automaattisesti maksuun tänään klo 23.00." + }, + "rejected": { "heading": "Koonti arkistoitu", "text": "" } }, "errors": { "batchInvalidDraftAlreadyExists": { @@ -1120,10 +1135,10 @@ "markAsReadyForAhjo": "Aloita Ahjo-valmistelu", "markAsRegisteredToAhjo": "Merkitse Ahjoon viedyksi", "markedAsRegisteredToAhjo": "Viety Ahjoon", - "markToTalpa": "Hyväksy tarkastustiedot", + "markToTalpa": "Siirrä maksuun", "markToArchive": "Arkistoi", "markAsWaitingForAhjo": "Palauta odottamaan Ahjoon vientiä", - "returnToInspection": "Muokkaa tarkastustietoja", + "returnToInspection": "Palauta odottamaan maksuun vientiä", "downloadFiles": "Lataa liitteet", "downloadP2PFile": "Lataa Talpa-tiedosto", "deleteBatch": "Tyhjennä koonti", @@ -1151,11 +1166,11 @@ "text": "Oletko varma, että haluat palauttaa koonnin odottamaan Ahjoon vientiä?" }, "fromInspectionToCompletion": { - "heading": "Hyväksy tarkastustiedot", - "text": "Haluatko merkitä koonnin tarkastetuksi?" + "heading": "Siirrä koonti maksuun", + "text": "Haluatko siirtää koonnin maksuun?" }, "fromCompletionToInspection": { - "heading": "Palauta koonti aiempaan vaiheeseen", + "heading": "Palauta koonti odottamaan maksuun vientiä", "text": "Haluatko palata aiempaan vaiheeseen ja tehdä muutoksia asiantarkastajien nimiin?" }, "fromCompletionToArchive": { @@ -1168,7 +1183,7 @@ "decisionMakerName": "Päättäjän nimi", "decisionMakerTitle": "Päättäjän titteli", "sectionOfTheLaw": "Pykälä", - "decisionDate": "Päätöksen päivämäärä", + "decisionDate": "Päätöspäivä", "expertInspectorName": "Asiantarkistajan nimi, Ahjo", "expertInspectorTitle": "Asiantarkistajan titteli, Ahjo", "p2pInspectorName": "Tarkastajan nimi, P2P", diff --git a/frontend/benefit/handler/public/locales/fi/common.json b/frontend/benefit/handler/public/locales/fi/common.json index 40412c1f17..ba3bffb228 100644 --- a/frontend/benefit/handler/public/locales/fi/common.json +++ b/frontend/benefit/handler/public/locales/fi/common.json @@ -1092,12 +1092,27 @@ } }, "statusChange": { - "awaiting_ahjo_decision": "Koonti merkitty Ahjoon viedyksi", - "exported_ahjo_report": "Ahjo-valmistelu aloitettu, koonti lukittu", - "completed": "Koonti käsitelty ja arkistoitu", - "draft": "Koonti palautettu takaisin odottamaan päätösvalmistelua", - "accepted": "Tarkastustiedot tallennettu", - "rejected": "Koonti arkistoitu" + "awaiting_ahjo_decision": { + "heading": "Koonti merkitty odottamaan maksuun vientiä", + "text": "" + }, + "exported_ahjo_report": { + "heading": "Ahjo-valmistelu aloitettu, koonti lukittu", + "text": "" + }, + "completed": { + "heading": "Koonti käsitelty ja arkistoitu", + "text": "" + }, + "draft": { + "heading": "Koonti palautettu takaisin odottamaan päätösvalmistelua", + "text": "" + }, + "accepted": { + "heading": "Hakemuksia siirretty maksuun", + "text": "Olet lähettänyt {{ count }} myönteistä hakemusta maksuun. Hakemukset siirtyvät automaattisesti maksuun tänään klo 23.00." + }, + "rejected": { "heading": "Koonti arkistoitu", "text": "" } }, "errors": { "batchInvalidDraftAlreadyExists": { @@ -1120,10 +1135,10 @@ "markAsReadyForAhjo": "Aloita Ahjo-valmistelu", "markAsRegisteredToAhjo": "Merkitse Ahjoon viedyksi", "markedAsRegisteredToAhjo": "Viety Ahjoon", - "markToTalpa": "Hyväksy tarkastustiedot", + "markToTalpa": "Siirrä maksuun", "markToArchive": "Arkistoi", "markAsWaitingForAhjo": "Palauta odottamaan Ahjoon vientiä", - "returnToInspection": "Muokkaa tarkastustietoja", + "returnToInspection": "Palauta odottamaan maksuun vientiä", "downloadFiles": "Lataa liitteet", "downloadP2PFile": "Lataa Talpa-tiedosto", "deleteBatch": "Tyhjennä koonti", @@ -1151,11 +1166,11 @@ "text": "Oletko varma, että haluat palauttaa koonnin odottamaan Ahjoon vientiä?" }, "fromInspectionToCompletion": { - "heading": "Hyväksy tarkastustiedot", - "text": "Haluatko merkitä koonnin tarkastetuksi?" + "heading": "Siirrä koonti maksuun", + "text": "Haluatko siirtää koonnin maksuun?" }, "fromCompletionToInspection": { - "heading": "Palauta koonti aiempaan vaiheeseen", + "heading": "Palauta koonti odottamaan maksuun vientiä", "text": "Haluatko palata aiempaan vaiheeseen ja tehdä muutoksia asiantarkastajien nimiin?" }, "fromCompletionToArchive": { @@ -1168,7 +1183,7 @@ "decisionMakerName": "Päättäjän nimi", "decisionMakerTitle": "Päättäjän titteli", "sectionOfTheLaw": "Pykälä", - "decisionDate": "Päätöksen päivämäärä", + "decisionDate": "Päätöspäivä", "expertInspectorName": "Asiantarkistajan nimi, Ahjo", "expertInspectorTitle": "Asiantarkistajan titteli, Ahjo", "p2pInspectorName": "Tarkastajan nimi, P2P", diff --git a/frontend/benefit/handler/public/locales/sv/common.json b/frontend/benefit/handler/public/locales/sv/common.json index 3274959f0c..e08a2974b1 100644 --- a/frontend/benefit/handler/public/locales/sv/common.json +++ b/frontend/benefit/handler/public/locales/sv/common.json @@ -1092,12 +1092,27 @@ } }, "statusChange": { - "awaiting_ahjo_decision": "Koonti merkitty Ahjoon viedyksi", - "exported_ahjo_report": "Ahjo-valmistelu aloitettu, koonti lukittu", - "completed": "Koonti käsitelty ja arkistoitu", - "draft": "Koonti palautettu takaisin odottamaan päätösvalmistelua", - "accepted": "Tarkastustiedot tallennettu", - "rejected": "Koonti arkistoitu" + "awaiting_ahjo_decision": { + "heading": "Koonti merkitty Ahjoon viedyksi", + "text": "" + }, + "exported_ahjo_report": { + "heading": "Ahjo-valmistelu aloitettu, koonti lukittu", + "text": "" + }, + "completed": { + "heading": "Koonti käsitelty ja arkistoitu", + "text": "" + }, + "draft": { + "heading": "Koonti palautettu takaisin odottamaan päätösvalmistelua", + "text": "" + }, + "accepted": { + "heading": "Hakemuksia siirretty maksuun", + "text": "Olet lähettänyt {{ count }} myönteistä hakemusta maksuun. Hakemukset siirtyvät automaattisesti maksuun tänään klo 23.00." + }, + "rejected": { "heading": "Koonti arkistoitu", "text": "" } }, "errors": { "batchInvalidDraftAlreadyExists": { @@ -1120,10 +1135,10 @@ "markAsReadyForAhjo": "Aloita Ahjo-valmistelu", "markAsRegisteredToAhjo": "Merkitse Ahjoon viedyksi", "markedAsRegisteredToAhjo": "Viety Ahjoon", - "markToTalpa": "Hyväksy tarkastustiedot", + "markToTalpa": "Siirrä maksuun", "markToArchive": "Arkistoi", "markAsWaitingForAhjo": "Palauta odottamaan Ahjoon vientiä", - "returnToInspection": "Muokkaa tarkastustietoja", + "returnToInspection": "Palauta odottamaan maksuun vientiä", "downloadFiles": "Lataa liitteet", "downloadP2PFile": "Lataa Talpa-tiedosto", "deleteBatch": "Tyhjennä koonti", @@ -1151,11 +1166,11 @@ "text": "Oletko varma, että haluat palauttaa koonnin odottamaan Ahjoon vientiä?" }, "fromInspectionToCompletion": { - "heading": "Hyväksy tarkastustiedot", - "text": "Haluatko merkitä koonnin tarkastetuksi?" + "heading": "Siirrä koonti maksuun", + "text": "Haluatko siirtää koonnin maksuun?" }, "fromCompletionToInspection": { - "heading": "Palauta koonti aiempaan vaiheeseen", + "heading": "Palauta koonti odottamaan maksuun vientiä", "text": "Haluatko palata aiempaan vaiheeseen ja tehdä muutoksia asiantarkastajien nimiin?" }, "fromCompletionToArchive": { @@ -1168,7 +1183,7 @@ "decisionMakerName": "Päättäjän nimi", "decisionMakerTitle": "Päättäjän titteli", "sectionOfTheLaw": "Pykälä", - "decisionDate": "Päätöksen päivämäärä", + "decisionDate": "Päätöspäivä", "expertInspectorName": "Asiantarkistajan nimi, Ahjo", "expertInspectorTitle": "Asiantarkistajan titteli, Ahjo", "p2pInspectorName": "Tarkastajan nimi, P2P", diff --git a/frontend/benefit/handler/src/components/batchProcessing/BatchApplicationList.tsx b/frontend/benefit/handler/src/components/batchProcessing/BatchApplicationList.tsx index c2359a75c0..289e43b4b3 100644 --- a/frontend/benefit/handler/src/components/batchProcessing/BatchApplicationList.tsx +++ b/frontend/benefit/handler/src/components/batchProcessing/BatchApplicationList.tsx @@ -1,3 +1,4 @@ +import { ROUTES } from 'benefit/handler/constants'; import useRemoveAppFromBatch from 'benefit/handler/hooks/useRemoveAppFromBatch'; import { BATCH_STATUSES, @@ -22,6 +23,7 @@ import noop from 'lodash/noop'; import { useTranslation } from 'next-i18next'; import React from 'react'; import Modal from 'shared/components/modal/Modal'; +import { $Link } from 'shared/components/table/Table.sc'; import theme from 'shared/styles/theme'; import { convertToUIDateAndTimeFormat, @@ -52,10 +54,11 @@ const $BatchStatusValue = styled.span` margin-top: 4px; `; +// eslint-disable-next-line sonarjs/cognitive-complexity const BatchApplicationList: React.FC = ({ batch }: BatchProps) => { const { t } = useTranslation(); const { - id, + id: batchId, status, created_at, applications: apps, @@ -65,14 +68,15 @@ const BatchApplicationList: React.FC = ({ batch }: BatchProps) => { const applications = React.useMemo(() => apps, [apps]); - const IS_WAITING_FOR_AHJO = [ + const IS_WAITING_FOR_INSPECTION = [ BATCH_STATUSES.DRAFT, BATCH_STATUSES.AHJO_REPORT_CREATED, ].includes(status); + const [isCollapsed, setIsCollapsed] = React.useState( - !IS_WAITING_FOR_AHJO + !IS_WAITING_FOR_INSPECTION ); - const [isConfirmAppRemoval, setConfirmAppRemoval] = React.useState(false); + const [isConfirmAppRemoval, setIsConfirmAppRemoval] = React.useState(false); const [appToRemove, setAppToRemove] = React.useState(null); const [batchCloseAnimation, setBatchCloseAnimation] = React.useState(false); @@ -81,20 +85,26 @@ const BatchApplicationList: React.FC = ({ batch }: BatchProps) => { const openAppRemovalDialog = (appId: string): void => { const selectedApp = apps.find((app) => app.id === appId); setAppToRemove(selectedApp); - setConfirmAppRemoval(true); + setIsConfirmAppRemoval(true); }; const onAppRemovalSubmit = (): void => { - removeApp({ appIds: [appToRemove.id], batchId: id }); - setConfirmAppRemoval(false); + removeApp({ appIds: [appToRemove.id], batchId }); + setIsConfirmAppRemoval(false); setAppToRemove(null); }; - const cols = [ + const cols: BatchTableColumns[] = [ { headerName: t('common:applications.list.columns.companyName'), key: 'company_name', isSortable: true, + transform: ({ id, company_name: companyName }: BatchTableTransforms) => ( + // eslint-disable-next-line @typescript-eslint/restrict-template-expressions + <$Link href={`${ROUTES.APPLICATION}?id=${id}`} target="_blank"> + {companyName} + + ), }, { headerName: t('common:applications.list.columns.companyId'), @@ -119,30 +129,36 @@ const BatchApplicationList: React.FC = ({ batch }: BatchProps) => { isSortable: true, customSortCompareFunction: sortFinnishDate, }, - { + ]; + + if (proposalForDecision === PROPOSALS_FOR_DECISION.ACCEPTED) { + cols.push({ headerName: t('common:applications.list.columns.benefitAmount'), key: 'total_amount', isSortable: true, - transform: ({ benefitAmount: amount }: { benefitAmount: number | 0 }) => + transform: ({ benefitAmount: amount }: { benefitAmount: number }) => formatFloatToCurrency(amount, 'EUR', 'fi-FI', 0), - }, - { - transform: ({ id: appId }: { id: string }) => - IS_WAITING_FOR_AHJO ? ( + }); + } + + if (IS_WAITING_FOR_INSPECTION) { + cols.push({ + headerName: '', + key: 'remove', + transform: ({ id }: { id: string }) => + IS_WAITING_FOR_INSPECTION ? ( ) : null, - headerName: '', - key: 'remove', - }, - ]; + }); + } const proposalForDecisionHeader = (): JSX.Element => { if (proposalForDecision === PROPOSALS_FOR_DECISION.ACCEPTED) { @@ -183,7 +199,7 @@ const BatchApplicationList: React.FC = ({ batch }: BatchProps) => { } > = ({ batch }: BatchProps) => { text={t('common:batches.dialog.removeApplication.text', { applicationNumber: `${appToRemove.company_name} / ${appToRemove.employee_name} (${appToRemove.application_number})`, })} - onClose={() => setConfirmAppRemoval(false)} + onClose={() => setIsConfirmAppRemoval(false)} onSubmit={onAppRemovalSubmit} /> ) : null @@ -271,10 +287,7 @@ const BatchApplicationList: React.FC = ({ batch }: BatchProps) => { : theme.colors.infoLight } > - {[ - BATCH_STATUSES.DRAFT, - BATCH_STATUSES.AHJO_REPORT_CREATED, - ].includes(status) && ( + {IS_WAITING_FOR_INSPECTION && ( >; }; -const BatchProposals: React.FC = ({ status }: BatchProps) => { +const BatchProposals: React.FC = ({ + status, + setBatchCount, +}: BatchProps) => { const { t, batches, shouldShowSkeleton, shouldHideList }: BatchListProps = useBatchProposal(status); const list = React.useMemo(() => batches, [batches]); + React.useEffect(() => { + setBatchCount(`(${list.length})`); + if (shouldShowSkeleton) { + setBatchCount('(0)'); + } + }, [list, setBatchCount, shouldShowSkeleton]); + if (shouldShowSkeleton) { return ; } diff --git a/frontend/benefit/handler/src/components/batchProcessing/batchFooter/BatchFooterCompletion.tsx b/frontend/benefit/handler/src/components/batchProcessing/batchFooter/BatchFooterCompletion.tsx index 52f2c38e60..851be63a85 100644 --- a/frontend/benefit/handler/src/components/batchProcessing/batchFooter/BatchFooterCompletion.tsx +++ b/frontend/benefit/handler/src/components/batchProcessing/batchFooter/BatchFooterCompletion.tsx @@ -170,14 +170,14 @@ const BatchFooterCompletion: React.FC = ({ <$ViewFieldBold> {t('common:batches.form.fields.decisionMakerName')} - <$ViewField>{decision_maker_title} + <$ViewField>{decision_maker_name} <$GridCell $colSpan={3}> <$ViewFieldBold> {t('common:batches.form.fields.decisionMakerTitle')} - <$ViewField>{decision_maker_name} + <$ViewField>{decision_maker_title} <$GridCell $colSpan={2}> diff --git a/frontend/benefit/handler/src/components/batchProcessing/useBatchActionsInspected.ts b/frontend/benefit/handler/src/components/batchProcessing/useBatchActionsInspected.ts index bf6c65d3bd..aba6f6e52e 100644 --- a/frontend/benefit/handler/src/components/batchProcessing/useBatchActionsInspected.ts +++ b/frontend/benefit/handler/src/components/batchProcessing/useBatchActionsInspected.ts @@ -37,6 +37,7 @@ const useBatchActionsInspected = ( setBatchCloseAnimation?: React.Dispatch> ): ApplicationListProps => { const { + applications, proposal_for_decision: proposalForDecision, id, decision_maker_name, @@ -54,7 +55,7 @@ const useBatchActionsInspected = ( isSuccess, isError, mutate: setBatchDecided, - } = useBatchInspected(setBatchCloseAnimation); + } = useBatchInspected(setBatchCloseAnimation, applications.length); const parseLocalizedDateString = ( _: string, @@ -192,7 +193,7 @@ const useBatchActionsInspected = ( markBatchAs( proposalForDecision === PROPOSALS_FOR_DECISION.ACCEPTED ? BATCH_STATUSES.DECIDED_ACCEPTED - : BATCH_STATUSES.COMPLETED, + : BATCH_STATUSES.DECIDED_REJECTED, values ), }; diff --git a/frontend/benefit/handler/src/components/batchProcessing/useBatches.ts b/frontend/benefit/handler/src/components/batchProcessing/useBatches.ts index cbc08c3340..d8fa5fb1bd 100644 --- a/frontend/benefit/handler/src/components/batchProcessing/useBatches.ts +++ b/frontend/benefit/handler/src/components/batchProcessing/useBatches.ts @@ -21,7 +21,14 @@ const translationsBase = 'common:applications.list'; const useBatchProposal = (filterByStatus: BATCH_STATUSES[]): BatchListProps => { const { t } = useTranslation(); - const query = useBatchQuery(filterByStatus); + const orderBy = filterByStatus.filter( + (status: BATCH_STATUSES) => + status === BATCH_STATUSES.DECIDED_ACCEPTED || + status === BATCH_STATUSES.SENT_TO_TALPA + ) + ? '-modified_at' + : undefined; + const query = useBatchQuery(filterByStatus, orderBy); let batches: BatchProposal[] = []; if (query.data) { @@ -61,7 +68,7 @@ const useBatchProposal = (filterByStatus: BATCH_STATUSES[]): BatchListProps => { }); } - const shouldShowSkeleton = query.isLoading; + const shouldShowSkeleton = query.isLoading || query.isFetching; const shouldHideList = Boolean(query.error) || diff --git a/frontend/benefit/handler/src/components/table/TableExtras.sc.ts b/frontend/benefit/handler/src/components/table/TableExtras.sc.ts index d6c9737057..16e29b4989 100644 --- a/frontend/benefit/handler/src/components/table/TableExtras.sc.ts +++ b/frontend/benefit/handler/src/components/table/TableExtras.sc.ts @@ -57,7 +57,7 @@ export const $TableGrid = styled.div` transition: all 0.65s ease-out; grid-template-rows: ${(props) => (props.animateClose ? '0fr' : '1fr')}; opacity: ${(props) => (props.animateClose ? '0' : '1')}; - margin-bottom: ${(props) => (props.animateClose ? '0' : 'var(--spacing-l)')}; + margin-bottom: ${(props) => (props.animateClose ? '0' : 'var(--spacing-xs)')}; `; type TableWrapperProps = { diff --git a/frontend/benefit/handler/src/hooks/useBatchInspected.ts b/frontend/benefit/handler/src/hooks/useBatchInspected.ts index d82cd44b6a..2f80b77f71 100644 --- a/frontend/benefit/handler/src/hooks/useBatchInspected.ts +++ b/frontend/benefit/handler/src/hooks/useBatchInspected.ts @@ -35,7 +35,8 @@ type Response = { }; const useBatchInspected = ( - setBatchCloseAnimation: React.Dispatch> + setBatchCloseAnimation: React.Dispatch>, + numberOfApplications?: number ): UseMutationResult => { const { axios, handleResponse } = useBackendAPI(); const { t } = useTranslation(); @@ -76,8 +77,12 @@ const useBatchInspected = ( { onSuccess: ({ status: backendStatus }: Response) => { showSuccessToast( - t(`common:batches.notifications.statusChange.${backendStatus}`), - '' + t( + `common:batches.notifications.statusChange.${backendStatus}.heading` + ), + t(`common:batches.notifications.statusChange.${backendStatus}.text`, { + count: numberOfApplications, + }) ); if ( diff --git a/frontend/benefit/handler/src/hooks/useBatchQuery.ts b/frontend/benefit/handler/src/hooks/useBatchQuery.ts index 6383a38697..afc942d554 100644 --- a/frontend/benefit/handler/src/hooks/useBatchQuery.ts +++ b/frontend/benefit/handler/src/hooks/useBatchQuery.ts @@ -7,7 +7,8 @@ import showErrorToast from 'shared/components/toast/show-error-toast'; import useBackendAPI from 'shared/hooks/useBackendAPI'; const useBatchQuery = ( - status: BATCH_STATUSES[] + status: BATCH_STATUSES[], + orderBy?: string ): UseQueryResult => { const { axios, handleResponse } = useBackendAPI(); const { t } = useTranslation(); @@ -21,6 +22,7 @@ const useBatchQuery = ( const params = { status: status.join(','), + order_by: orderBy || '-created_at', }; return useQuery( diff --git a/frontend/benefit/handler/src/hooks/useBatchStatus.ts b/frontend/benefit/handler/src/hooks/useBatchStatus.ts index eb6f1fa3dd..b2e2854857 100644 --- a/frontend/benefit/handler/src/hooks/useBatchStatus.ts +++ b/frontend/benefit/handler/src/hooks/useBatchStatus.ts @@ -75,7 +75,9 @@ const useBatchStatus = ( { onSuccess: ({ status: backendStatus, previousStatus }: Response) => { showSuccessToast( - t(`common:batches.notifications.statusChange.${backendStatus}`), + t( + `common:batches.notifications.statusChange.${backendStatus}.heading` + ), '' ); if ( diff --git a/frontend/benefit/handler/src/pages/batches/index.tsx b/frontend/benefit/handler/src/pages/batches/index.tsx index eef5b6b6b8..842de762ee 100644 --- a/frontend/benefit/handler/src/pages/batches/index.tsx +++ b/frontend/benefit/handler/src/pages/batches/index.tsx @@ -21,6 +21,9 @@ const BatchIndex: NextPage = () => { } = React.useContext(AppContext); const { t } = useTranslation(); + const [batchPendingCount, setBatchPendingCount] = React.useState(''); + const [batchInspectionCount, setBatchInspectionCount] = React.useState(''); + const [batchCompletionCount, setBatchCompletionCount] = React.useState(''); useEffect(() => { setIsNavigationVisible(true); @@ -48,8 +51,11 @@ const BatchIndex: NextPage = () => { - <$Heading>{t('common:batches.tabs.pending')} + <$Heading> + {t('common:batches.tabs.pending')} {batchPendingCount} + { - <$Heading>{t('common:batches.tabs.inspection')} - + <$Heading> + {t('common:batches.tabs.inspection')} {batchInspectionCount} + + - <$Heading>{t('common:batches.tabs.completion')} + <$Heading> + {t('common:batches.tabs.completion')} {batchCompletionCount} + string | JSX.Element; + customSortCompareFunction?: (a: string, b: string) => void; +};