diff --git a/libs/application/template-api-modules/src/lib/modules/templates/aosh/transfer-of-machine-ownership/emailGenerators/applicationDeleteEmail.ts b/libs/application/template-api-modules/src/lib/modules/templates/aosh/transfer-of-machine-ownership/emailGenerators/applicationDeleteEmail.ts new file mode 100644 index 000000000000..054a234a6957 --- /dev/null +++ b/libs/application/template-api-modules/src/lib/modules/templates/aosh/transfer-of-machine-ownership/emailGenerators/applicationDeleteEmail.ts @@ -0,0 +1,80 @@ +import { Message } from '@island.is/email-service' +import { EmailTemplateGeneratorProps } from '../../../../../types' +import { EmailRecipient } from '../types' +import { pathToAsset } from '../transfer-of-machine-ownership.utils' +import { ApplicationConfigurations } from '@island.is/application/types' +import { TransferOfMachineOwnershipAnswers } from '@island.is/application/templates/aosh/transfer-of-machine-ownership' + +export type ApplicationRejectedEmail = ( + props: EmailTemplateGeneratorProps, + recipient: EmailRecipient, + rejectedBy: EmailRecipient | undefined, +) => Message + +export const generateApplicationRejectedEmail: ApplicationRejectedEmail = ( + props, + recipient, + rejectedBy, +): Message => { + const { + application, + options: { email, clientLocationOrigin }, + } = props + const answers = application.answers as TransferOfMachineOwnershipAnswers + const regNumber = answers?.machine?.regNumber + + if (!recipient.email) throw new Error('Recipient email was undefined') + if (!regNumber) throw new Error('Registration Number was undefined') + if (!rejectedBy?.ssn) throw new Error('Rejected by ssn was undefined') + + const subject = 'Tilkynning um eigendaskipti - Umsókn afturkölluð' + + return { + from: { + name: email.sender, + address: email.address, + }, + to: [{ name: recipient.name, address: recipient.email }], + subject, + template: { + title: subject, + body: [ + { + component: 'Image', + context: { + src: pathToAsset('logo.jpg'), + alt: 'Ísland.is logo', + }, + }, + { + component: 'Image', + context: { + src: pathToAsset('computerIllustration.jpg'), + alt: 'Kaffi við skjá myndskreyting', + }, + }, + { + component: 'Heading', + context: { copy: subject }, + }, + { + component: 'Copy', + context: { + copy: + `Góðan dag,

` + + `Beiðni um eigendaskipti á tækinu ${regNumber} hefur verið afturkölluð þar sem eigandi ökutækis eyddi umsókninni.
` + + `Til þess að skrá eigendaskiptin rafrænt verður að byrja ferlið að upp á nýtt á umsóknarvef island.is: island.is/umsoknir, ásamt því að allir aðilar þurfa að staðfesta rafrænt innan gefins tímafrests.
` + + `Vinsamlegast hafið samband við Vinnueftirlitið vinnueftirlit@ver.is ef nánari upplýsinga er þörf.`, + }, + }, + { + component: 'Button', + context: { + copy: 'Skoða umsókn', + href: `${clientLocationOrigin}/${ApplicationConfigurations.TransferOfMachineOwnership.slug}/${application.id}`, + }, + }, + ], + }, + } +} diff --git a/libs/application/template-api-modules/src/lib/modules/templates/aosh/transfer-of-machine-ownership/transfer-of-machine-ownership.service.ts b/libs/application/template-api-modules/src/lib/modules/templates/aosh/transfer-of-machine-ownership/transfer-of-machine-ownership.service.ts index fba8b32860bb..6c0461d6d887 100644 --- a/libs/application/template-api-modules/src/lib/modules/templates/aosh/transfer-of-machine-ownership/transfer-of-machine-ownership.service.ts +++ b/libs/application/template-api-modules/src/lib/modules/templates/aosh/transfer-of-machine-ownership/transfer-of-machine-ownership.service.ts @@ -30,6 +30,7 @@ import { MachinesWithTotalCount, WorkMachinesClientService, } from '@island.is/clients/work-machines' +import { User } from '@island.is/auth-nest-tools' @Injectable() export class TransferOfMachineOwnershipTemplateService extends BaseTemplateApiService { constructor( @@ -270,6 +271,101 @@ export class TransferOfMachineOwnershipTemplateService extends BaseTemplateApiSe return null } + private async deleteOwnerChange( + auth: User, + applicationId: string, + ): Promise { + try { + const deleteChange = { + ownerchangeId: applicationId, + xCorrelationID: applicationId, + } + await this.workMachineClientService.deleteOwnerChange(auth, deleteChange) + } catch (error) { + this.logger.error( + `Failed to delete owner change for application ${applicationId}`, + error, + ) + throw error + } + } + + async deleteApplication({ + application, + auth, + }: TemplateApiModuleActionProps): Promise { + // 1. Delete charge so that the seller gets reimburshed + const chargeId = getPaymentIdFromExternalData(application) + try { + if (chargeId) { + await this.chargeFjsV2ClientService.deleteCharge(chargeId) + } + } catch (error) { + this.logger.error( + `Failed to delete charge ${chargeId} for application ${application.id}`, + error, + ) + throw error + } + + // 2. Delete owner change in work machines + await this.deleteOwnerChange(auth, application.id) + + // 3. Notify everyone in the process that the application has been withdrawn + + // 3a. Get list of users that need to be notified + const answers = application.answers as TransferOfMachineOwnershipAnswers + const recipientList = getRecipients(answers, [ + EmailRole.seller, + EmailRole.buyer, + ]) + + // 3b. Send email/sms individually to each recipient about success of withdrawing application + const deletedByRecipient = getRecipientBySsn(answers, auth.nationalId) + for (let i = 0; i < recipientList.length; i++) { + if (recipientList[i].email) { + await this.sharedTemplateAPIService + .sendEmail( + (props) => + generateApplicationRejectedEmail( + props, + recipientList[i], + deletedByRecipient, + ), + application, + ) + .catch((e) => { + this.logger.error( + `Error sending email about deleteApplication in application: ID: ${application.id}, + role: ${recipientList[i].role}`, + e, + ) + }) + } + + if (recipientList[i].phone) { + await this.sharedTemplateAPIService + .sendSms( + () => + generateApplicationRejectedSms( + application, + recipientList[i], + deletedByRecipient, + ), + application, + ) + .catch((e) => { + this.logger.error( + `Error sending sms about deleteApplication to + a phonenumber in application: ID: ${application.id}, + role: ${recipientList[i].role}`, + e, + ) + }) + } + } + } + async rejectApplication({ application, auth, @@ -280,16 +376,19 @@ export class TransferOfMachineOwnershipTemplateService extends BaseTemplateApiSe await this.chargeFjsV2ClientService.deleteCharge(chargeId) } - // 2. Notify everyone in the process that the application has been withdrawn + // 2. Delete owner change in work machines + await this.deleteOwnerChange(auth, application.id) + + // 3. Notify everyone in the process that the application has been withdrawn - // 2a. Get list of users that need to be notified + // 3a. Get list of users that need to be notified const answers = application.answers as TransferOfMachineOwnershipAnswers const recipientList = getRecipients(answers, [ EmailRole.seller, EmailRole.buyer, ]) - // 2b. Send email/sms individually to each recipient about success of withdrawing application + // 3b. Send email/sms individually to each recipient about success of withdrawing application const rejectedByRecipient = getRecipientBySsn(answers, auth.nationalId) for (let i = 0; i < recipientList.length; i++) { if (recipientList[i].email) { diff --git a/libs/application/templates/aosh/transfer-of-machine-ownership/src/dataProviders/index.ts b/libs/application/templates/aosh/transfer-of-machine-ownership/src/dataProviders/index.ts index 2eae2dfba990..9a1c83d1024c 100644 --- a/libs/application/templates/aosh/transfer-of-machine-ownership/src/dataProviders/index.ts +++ b/libs/application/templates/aosh/transfer-of-machine-ownership/src/dataProviders/index.ts @@ -1,6 +1,7 @@ import { defineTemplateApi, InstitutionNationalIds, + MockablePaymentCatalogApi, PaymentCatalogApi, } from '@island.is/application/types' @@ -13,6 +14,14 @@ export const VinnueftirlitidPaymentCatalogApi = PaymentCatalogApi.configure({ externalDataId: 'payment', }) +export const MockableVinnueftirlitidPaymentCatalogApi = + MockablePaymentCatalogApi.configure({ + params: { + organizationId: InstitutionNationalIds.VINNUEFTIRLITID, + }, + externalDataId: 'payment', + }) + export const MachinesApi = defineTemplateApi({ action: 'getMachines', externalDataId: 'machinesList', diff --git a/libs/application/templates/aosh/transfer-of-machine-ownership/src/forms/TransferOfMachineOwnershipForm/prerequisitesSection.ts b/libs/application/templates/aosh/transfer-of-machine-ownership/src/forms/TransferOfMachineOwnershipForm/prerequisitesSection.ts index c64528d5dd94..c8e665c5b23c 100644 --- a/libs/application/templates/aosh/transfer-of-machine-ownership/src/forms/TransferOfMachineOwnershipForm/prerequisitesSection.ts +++ b/libs/application/templates/aosh/transfer-of-machine-ownership/src/forms/TransferOfMachineOwnershipForm/prerequisitesSection.ts @@ -11,6 +11,7 @@ import { UserProfileApi, VinnueftirlitidPaymentCatalogApi, MachinesApi, + MockableVinnueftirlitidPaymentCatalogApi, } from '../../dataProviders' import { DefaultEvents } from '@island.is/application/types' @@ -56,6 +57,10 @@ export const prerequisitesSection = buildSection({ provider: VinnueftirlitidPaymentCatalogApi, title: '', }), + buildDataProviderItem({ + provider: MockableVinnueftirlitidPaymentCatalogApi, + title: '', + }), ], }), ], diff --git a/libs/application/templates/aosh/transfer-of-machine-ownership/src/lib/TransferOfMachineOwnershipTemplate.ts b/libs/application/templates/aosh/transfer-of-machine-ownership/src/lib/TransferOfMachineOwnershipTemplate.ts index f9ddc0ef0d61..e781e54c654c 100644 --- a/libs/application/templates/aosh/transfer-of-machine-ownership/src/lib/TransferOfMachineOwnershipTemplate.ts +++ b/libs/application/templates/aosh/transfer-of-machine-ownership/src/lib/TransferOfMachineOwnershipTemplate.ts @@ -30,6 +30,7 @@ import { UserProfileApi, VinnueftirlitidPaymentCatalogApi, MachinesApi, + MockableVinnueftirlitidPaymentCatalogApi, } from '../dataProviders' import { getChargeItemCodes, hasReviewerApproved } from '../utils' import { buildPaymentState } from '@island.is/application/utils' @@ -138,6 +139,7 @@ const template: ApplicationTemplate< api: [ IdentityApi, UserProfileApi, + MockableVinnueftirlitidPaymentCatalogApi, VinnueftirlitidPaymentCatalogApi, MachinesApi, ], @@ -214,6 +216,9 @@ const template: ApplicationTemplate< meta: { name: 'Tilkynning um eigendaskipti að ökutæki', status: 'inprogress', + onDelete: defineTemplateApi({ + action: ApiActions.deleteApplication, + }), actionCard: { tag: { label: applicationMessage.actionCardDraft, diff --git a/libs/application/templates/aosh/transfer-of-machine-ownership/src/shared/constants.ts b/libs/application/templates/aosh/transfer-of-machine-ownership/src/shared/constants.ts index 306b908dd811..f058593ec11e 100644 --- a/libs/application/templates/aosh/transfer-of-machine-ownership/src/shared/constants.ts +++ b/libs/application/templates/aosh/transfer-of-machine-ownership/src/shared/constants.ts @@ -2,4 +2,5 @@ export enum ApiActions { initReview = 'initReview', rejectApplication = 'rejectApplication', submitApplication = 'submitApplication', + deleteApplication = 'deleteApplication', } diff --git a/libs/clients/work-machines/src/clientConfig.json b/libs/clients/work-machines/src/clientConfig.json index ff3603c2a394..eec50c7450b0 100644 --- a/libs/clients/work-machines/src/clientConfig.json +++ b/libs/clients/work-machines/src/clientConfig.json @@ -256,16 +256,17 @@ } } }, - "/api/MachineParentCategories": { - "get": { - "tags": ["MachineParentCategories"], + "/api/MachineOwnerChange/{OwnerchangeId}": { + "delete": { + "tags": ["MachineOwnerChange"], "parameters": [ { - "name": "locale", - "in": "query", + "name": "OwnerchangeId", + "in": "path", + "required": true, "schema": { "type": "string", - "default": "is" + "format": "uuid" } }, { @@ -278,6 +279,27 @@ } } ], + "responses": { + "204": { + "description": "No Content" + } + } + } + }, + "/api/MachineParentCategories": { + "get": { + "tags": ["MachineParentCategories"], + "parameters": [ + { + "name": "X-Correlation-ID", + "in": "header", + "description": "Unique identifier associated with the request", + "schema": { + "type": "string", + "format": "uuid" + } + } + ], "responses": { "200": { "description": "OK", @@ -1266,14 +1288,6 @@ "type": "string" } }, - { - "name": "locale", - "in": "query", - "schema": { - "type": "string", - "default": "is" - } - }, { "name": "X-Correlation-ID", "in": "header", @@ -1419,28 +1433,6 @@ } } }, - "/api/Openapi": { - "get": { - "tags": ["Openapi"], - "summary": "Returns the openapi document as a json file", - "parameters": [ - { - "name": "X-Correlation-ID", - "in": "header", - "description": "Unique identifier associated with the request", - "schema": { - "type": "string", - "format": "uuid" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, "/api/TechnicalInfo/Inputs": { "get": { "tags": ["TechnicalInfo"], @@ -2157,12 +2149,10 @@ }, "MachineRegistrationCreateDto": { "required": [ - "containerNumber", "countryOfProduction", "importer", "isCECertified", "isPreRegistered", - "locationOfMachine", "model", "parentCategory", "serialNumber", @@ -2194,12 +2184,12 @@ "type": "string" }, "containerNumber": { - "minLength": 1, - "type": "string" + "type": "string", + "nullable": true }, "locationOfMachine": { - "minLength": 1, - "type": "string" + "type": "string", + "nullable": true }, "serialNumber": { "minLength": 1, @@ -2594,6 +2584,10 @@ "name": { "type": "string", "nullable": true + }, + "nameEn": { + "type": "string", + "nullable": true } }, "additionalProperties": false diff --git a/libs/clients/work-machines/src/lib/workMachines.service.ts b/libs/clients/work-machines/src/lib/workMachines.service.ts index 4c6cee1f4f50..ba1a730d4b75 100644 --- a/libs/clients/work-machines/src/lib/workMachines.service.ts +++ b/libs/clients/work-machines/src/lib/workMachines.service.ts @@ -2,6 +2,7 @@ import { Auth, AuthMiddleware, User } from '@island.is/auth-nest-tools' import { Injectable } from '@nestjs/common' import { ApiMachineModelsGetRequest, + ApiMachineOwnerChangeOwnerchangeIdDeleteRequest, ApiMachineParentCategoriesTypeModelGetRequest, ApiMachineRequestInspectionPostRequest, ApiMachineStatusChangePostRequest, @@ -247,6 +248,15 @@ export class WorkMachinesClientService { ) } + async deleteOwnerChange( + auth: Auth, + deleteChange: ApiMachineOwnerChangeOwnerchangeIdDeleteRequest, + ) { + await this.machineOwnerChangeApiWithAuth( + auth, + ).apiMachineOwnerChangeOwnerchangeIdDelete(deleteChange) + } + async changeMachineSupervisor( auth: Auth, supervisorChange: SupervisorChange,