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..734796589e4a 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,6 +1098,53 @@ export class ApplicationController { ) } + 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}`, + ) + + if (result.status === 'failure' && api.throwOnError) { + const reason = result.reason ?? 'Unknown error' + throw new TemplateApiError(reason, 500) + } + } + } + // delete charge in FJS await this.applicationChargeService.deleteCharge(existingApplication) @@ -1111,5 +1159,12 @@ export class ApplicationController { ) 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) + }, }, )