From 28319c2cdc949ada42b5456c62f42d20703f499e Mon Sep 17 00:00:00 2001 From: Ahmed Bouhuolia Date: Sat, 14 Sep 2024 16:26:34 +0200 Subject: [PATCH] feat: cannot delete a predefined branding template --- .../services/PdfTemplate/DeletePdfTemplate.ts | 20 ++++++++-- .../server/src/services/PdfTemplate/types.ts | 3 ++ .../alerts/DeleteBrandingTemplateAlert.tsx | 39 ++++++++++++------- 3 files changed, 46 insertions(+), 16 deletions(-) diff --git a/packages/server/src/services/PdfTemplate/DeletePdfTemplate.ts b/packages/server/src/services/PdfTemplate/DeletePdfTemplate.ts index e15bea1de..246d12636 100644 --- a/packages/server/src/services/PdfTemplate/DeletePdfTemplate.ts +++ b/packages/server/src/services/PdfTemplate/DeletePdfTemplate.ts @@ -1,8 +1,10 @@ import { Inject, Service } from 'typedi'; import HasTenancyService from '../Tenancy/TenancyService'; import UnitOfWork from '../UnitOfWork'; -import { EventPublisher } from '@/lib/EventPublisher/EventPublisher'; import events from '@/subscribers/events'; +import { EventPublisher } from '@/lib/EventPublisher/EventPublisher'; +import { ServiceError } from '@/exceptions'; +import { ERRORS } from './types'; @Service() export class DeletePdfTemplate { @@ -18,16 +20,26 @@ export class DeletePdfTemplate { /** * Deletes a pdf template. * @param {number} tenantId - * @param {number} templateId + * @param {number} templateId - Pdf template id. */ - public deletePdfTemplate(tenantId: number, templateId: number) { + public async deletePdfTemplate(tenantId: number, templateId: number) { const { PdfTemplate } = this.tenancy.models(tenantId); + const oldPdfTemplate = await PdfTemplate.query() + .findById(templateId) + .throwIfNotFound(); + + // Cannot delete the predefined pdf templates. + if (oldPdfTemplate.predefined) { + throw new ServiceError(ERRORS.CANNOT_DELETE_PREDEFINED_PDF_TEMPLATE); + } return this.uow.withTransaction(tenantId, async (trx) => { // Triggers `onPdfTemplateDeleting` event. await this.eventPublisher.emitAsync(events.pdfTemplate.onDeleting, { tenantId, templateId, + oldPdfTemplate, + trx, }); await PdfTemplate.query(trx).deleteById(templateId); @@ -35,6 +47,8 @@ export class DeletePdfTemplate { await this.eventPublisher.emitAsync(events.pdfTemplate.onDeleted, { tenantId, templateId, + oldPdfTemplate, + trx, }); }); } diff --git a/packages/server/src/services/PdfTemplate/types.ts b/packages/server/src/services/PdfTemplate/types.ts index 98cf1d214..b27c87f0a 100644 --- a/packages/server/src/services/PdfTemplate/types.ts +++ b/packages/server/src/services/PdfTemplate/types.ts @@ -1,3 +1,6 @@ +export enum ERRORS { + CANNOT_DELETE_PREDEFINED_PDF_TEMPLATE = 'CANNOT_DELETE_PREDEFINED_PDF_TEMPLATE', +} export interface ICreateInvoicePdfTemplateDTO { // Colors primaryColor?: string; diff --git a/packages/webapp/src/containers/BrandingTemplates/alerts/DeleteBrandingTemplateAlert.tsx b/packages/webapp/src/containers/BrandingTemplates/alerts/DeleteBrandingTemplateAlert.tsx index a044d5fbe..58358b0de 100644 --- a/packages/webapp/src/containers/BrandingTemplates/alerts/DeleteBrandingTemplateAlert.tsx +++ b/packages/webapp/src/containers/BrandingTemplates/alerts/DeleteBrandingTemplateAlert.tsx @@ -3,7 +3,7 @@ import React from 'react'; import intl from 'react-intl-universal'; import { AppToaster } from '@/components'; import { Alert, Intent } from '@blueprintjs/core'; -import { useDeletePdfTemplate} from '@/hooks/query/pdf-templates'; +import { useDeletePdfTemplate } from '@/hooks/query/pdf-templates'; import withAlertStoreConnect from '@/containers/Alert/withAlertStoreConnect'; import withAlertActions from '@/containers/Alert/withAlertActions'; @@ -35,13 +35,30 @@ function DeleteBrandingTemplateAlert({ }); closeAlert(name); }) - .catch((error) => { - AppToaster.show({ - message: 'Something went wrong.', - intent: Intent.DANGER, - }); - closeAlert(name); - }); + .catch( + ({ + response: { + data: { errors }, + }, + }) => { + if ( + errors.find( + (error) => error.type === 'CANNOT_DELETE_PREDEFINED_PDF_TEMPLATE', + ) + ) { + AppToaster.show({ + message: 'Cannot delete a predefined branding template.', + intent: Intent.DANGER, + }); + } else { + AppToaster.show({ + message: 'Something went wrong.', + intent: Intent.DANGER, + }); + } + closeAlert(name); + }, + ); }; const handleCancel = () => { @@ -57,9 +74,7 @@ function DeleteBrandingTemplateAlert({ onCancel={handleCancel} onConfirm={handleConfirmDelete} > -

- Are you sure want to delete branding template? -

+

Are you sure want to delete branding template?

); } @@ -68,5 +83,3 @@ export default compose( withAlertStoreConnect(), withAlertActions, )(DeleteBrandingTemplateAlert); - -