From 99090a5982b68ba4d4a0827f5581ed10e827a7b9 Mon Sep 17 00:00:00 2001 From: obmagnusson Date: Tue, 29 Oct 2024 09:34:36 +0000 Subject: [PATCH] on delete --- .../application/application.controller.ts | 77 ++++++++++++++++--- .../core/src/lib/ApplicationTemplateHelper.ts | 9 +++ .../application/types/src/lib/StateMachine.ts | 1 + .../ApplicationList/ApplicationList.tsx | 8 +- .../src/hooks/useDeleteApplication.ts | 6 ++ 5 files changed, 90 insertions(+), 11 deletions(-) diff --git a/apps/application-system/api/src/app/modules/application/application.controller.ts b/apps/application-system/api/src/app/modules/application/application.controller.ts index d8d3180484aa..15139315064b 100644 --- a/apps/application-system/api/src/app/modules/application/application.controller.ts +++ b/apps/application-system/api/src/app/modules/application/application.controller.ts @@ -1079,6 +1079,7 @@ export class ApplicationController { async delete( @Param('id', new ParseUUIDPipe()) id: string, @CurrentUser() user: User, + @CurrentLocale() locale: Locale, ) { const { nationalId } = user const existingApplication = @@ -1097,19 +1098,75 @@ export class ApplicationController { ) } - // delete charge in FJS - await this.applicationChargeService.deleteCharge(existingApplication) + const template = await getApplicationTemplateByTypeId( + existingApplication.typeId, + ) + if (template === null) { + throw new BadRequestException( + `No application template exists for type: ${existingApplication.typeId}`, + ) + } + + let onDeleteActions = new ApplicationTemplateHelper( + existingApplication, + template, + ).getOnDeleteStateAPIAction() + if (onDeleteActions) { + const namespaces = await getApplicationTranslationNamespaces( + existingApplication, + ) + if (!Array.isArray(onDeleteActions)) { + onDeleteActions = [onDeleteActions] + } + + const intl = await this.intlService.useIntl(namespaces, locale) + const deletingApplication = await this.templateApiActionRunner.run( + existingApplication, + onDeleteActions, + user, + locale, + intl.formatMessage, + ) + + for (const api of onDeleteActions) { + const result = + deletingApplication.externalData[api.externalDataId || api.action] + + this.logger.debug( + `Performing action ${api.action} on ${JSON.stringify( + template.name, + )} ended with ${result.status}`, + ) - // delete the entry in Payment table to prevent FK error - await this.paymentService.delete(existingApplication.id, user) + if (result.status === 'failure' && api.throwOnError) { + const reason = result.reason ?? 'Unknown error' + throw new TemplateApiError(reason, 500) + } + } - await this.fileService.deleteAttachmentsForApplication(existingApplication) + // delete charge in FJS + await this.applicationChargeService.deleteCharge(existingApplication) - // delete history for application - await this.historyService.deleteHistoryByApplicationId( - existingApplication.id, - ) + // delete the entry in Payment table to prevent FK error + await this.paymentService.delete(existingApplication.id, user) - await this.applicationService.delete(existingApplication.id) + await this.fileService.deleteAttachmentsForApplication( + existingApplication, + ) + + // delete history for application + await this.historyService.deleteHistoryByApplicationId( + existingApplication.id, + ) + + await this.applicationService.delete(existingApplication.id) + + this.auditService.audit({ + auth: user, + action: 'delete', + resources: existingApplication.id, + meta: { type: existingApplication.typeId }, + }) + } } } diff --git a/libs/application/core/src/lib/ApplicationTemplateHelper.ts b/libs/application/core/src/lib/ApplicationTemplateHelper.ts index f7d35edcd394..7af4692c2cfd 100644 --- a/libs/application/core/src/lib/ApplicationTemplateHelper.ts +++ b/libs/application/core/src/lib/ApplicationTemplateHelper.ts @@ -118,6 +118,15 @@ export class ApplicationTemplateHelper< return this.getTemplateAPIAction(action) } + getOnDeleteStateAPIAction( + stateKey: string = this.application.state, + ): TemplateApi | TemplateApi[] | null { + const action = + this.template.stateMachineConfig.states[stateKey]?.meta?.onDelete ?? null + + return this.getTemplateAPIAction(action) + } + getApplicationStateInformation( stateKey: string = this.application.state, ): ApplicationStateMeta | undefined { diff --git a/libs/application/types/src/lib/StateMachine.ts b/libs/application/types/src/lib/StateMachine.ts index cad79844abe8..8dd8c370cc7d 100644 --- a/libs/application/types/src/lib/StateMachine.ts +++ b/libs/application/types/src/lib/StateMachine.ts @@ -131,6 +131,7 @@ export interface ApplicationStateMeta< roles?: RoleInState[] onExit?: TemplateApi[] | TemplateApi onEntry?: TemplateApi[] | TemplateApi + onDelete?: TemplateApi[] | TemplateApi } export interface ApplicationStateSchema diff --git a/libs/application/ui-components/src/components/ApplicationList/ApplicationList.tsx b/libs/application/ui-components/src/components/ApplicationList/ApplicationList.tsx index 5a2c56984266..682899678b9a 100644 --- a/libs/application/ui-components/src/components/ApplicationList/ApplicationList.tsx +++ b/libs/application/ui-components/src/components/ApplicationList/ApplicationList.tsx @@ -1,5 +1,10 @@ import React, { useCallback, useState } from 'react' -import { Box, Pagination, Stack } from '@island.is/island-ui/core' +import { + Box, + Pagination, + Stack, + ToastContainer, +} from '@island.is/island-ui/core' import { Application, ApplicationTypes, @@ -95,6 +100,7 @@ const ApplicationList = ({ /> ) : null} + ) } diff --git a/libs/application/ui-components/src/hooks/useDeleteApplication.ts b/libs/application/ui-components/src/hooks/useDeleteApplication.ts index a30fec5fcba8..6171c56ee2e7 100644 --- a/libs/application/ui-components/src/hooks/useDeleteApplication.ts +++ b/libs/application/ui-components/src/hooks/useDeleteApplication.ts @@ -1,13 +1,19 @@ import { useMutation } from '@apollo/client' import { DELETE_APPLICATION } from '@island.is/application/graphql' +import { handleServerError } from '../utilities/handleServerError' +import { useLocale } from '@island.is/localization' export const useDeleteApplication = (refetch?: (() => void) | undefined) => { + const { formatMessage } = useLocale() const [deleteApplicationMutation, { error, loading }] = useMutation( DELETE_APPLICATION, { onCompleted: () => { refetch?.() }, + onError: (error) => { + handleServerError(error, formatMessage) + }, }, )