From 62c805d38c5482176f6a54c3a33b717846fbf61d Mon Sep 17 00:00:00 2001 From: rupali-inflection Date: Thu, 25 Sep 2025 17:26:28 +0530 Subject: [PATCH 1/2] Implementation of the form template export --- .../form.template/form.template.controller.ts | 24 +++++ src/api/form.template/form.template.router.ts | 2 + .../services/form.template.service.ts | 91 +++++++++++++++++++ .../form.template.domain.types.ts | 2 +- 4 files changed, 118 insertions(+), 1 deletion(-) diff --git a/src/api/form.template/form.template.controller.ts b/src/api/form.template/form.template.controller.ts index d63953d..a5f3d27 100644 --- a/src/api/form.template/form.template.controller.ts +++ b/src/api/form.template/form.template.controller.ts @@ -209,6 +209,28 @@ export class FormTemplateController { } }; + export = async (request: express.Request, response: express.Response) => { + try { + var id: uuid = await this._validator.requestParamAsUUID( + request, + 'id' + ); + const exportData = await this._service.export(id); + + const { filename, sourceFileLocation } + = await Helper.storeTemplateToFileLocally(exportData); + + var mimeType = Helper.getMimeType(sourceFileLocation); + response.setHeader('Content-type', mimeType); + response.setHeader('Content-disposition', 'attachment; filename=' + filename); + + var filestream = fs.createReadStream(sourceFileLocation); + filestream.pipe(response); + } catch (error) { + ResponseHandler.handleError(request, response, error); + } + }; + //#region Private Helper Methods @@ -373,5 +395,7 @@ export class FormTemplateController { } } + + //#endregion } diff --git a/src/api/form.template/form.template.router.ts b/src/api/form.template/form.template.router.ts index c44b4e2..9ab8457 100644 --- a/src/api/form.template/form.template.router.ts +++ b/src/api/form.template/form.template.router.ts @@ -15,6 +15,8 @@ export const register = (app: express.Application): void => { router.get('/:id', context(`${contextBase}.GetById`), controller.getById); router.delete('/:id', context(`${contextBase}.Delete`), controller.delete); router.get('/:id/details', context(`${contextBase}.GetDetailsById`), controller.getDetailsById); + router.get('/:id/export', context(`${contextBase}.Export`), controller.export); + app.use('/api/v1/form-templates', router); }; diff --git a/src/database/services/form.template.service.ts b/src/database/services/form.template.service.ts index e1f28d0..84e7180 100644 --- a/src/database/services/form.template.service.ts +++ b/src/database/services/form.template.service.ts @@ -304,6 +304,97 @@ export class FormTemplateService extends BaseService { } }; + public export = async (id: uuid): Promise => { + try { + const template = await this._formTemplateRepository.findOne({ + where: { + id: id, + DeletedAt: IsNull(), + }, + relations: { + FormSections: { + FormFields: { + SkipLogic: { + Rules: { + FallbackRule: true, + BaseFallbackRuleEntity: true, + }, + }, + CalculateLogic: { + Rules: { + FallbackRule: true, + }, + }, + ValidateLogic: { + Rules: { + FallbackRule: true, + }, + }, + }, + }, + }, + order: { + FormSections: { + CreatedAt: "ASC", + FormFields: { + CreatedAt: "ASC", + }, + }, + }, + }); + + if (!template) { + ErrorHandler.throwNotFoundError('Form template not found!'); + } + + // Filter out deleted sections and fields + if (template.FormSections) { + template.FormSections = template.FormSections.filter( + (section) => section.DeletedAt === null + ); + + template.FormSections.forEach((section) => { + if (section.FormFields) { + section.FormFields = section.FormFields.filter( + (field) => field.DeletedAt === null + ); + } + }); + } + + // Map sections to hierarchical structure + const mappedSections = await this.mapSections(template.FormSections); + + // Populate operations for all form fields + await this.populateFormFieldsOperations(mappedSections); + + // Create export DTO + const exportDto: ExportFormTemplateDto = { + Template: { + id: template.id, + Title: template.Title, + Description: template.Description, + CurrentVersion: template.Version, + TenantCode: template.TenantId, + Type: template.Type as any, + DisplayCode: template.DisplayCode, + OwnerUserId: template.OwnerUserId, + RootSectionId: template.RootSectionId, + DefaultSectionNumbering: template.DefaultSectionNumbering, + CreatedAt: template.CreatedAt, + UpdatedAt: template.UpdatedAt, + Sections: mappedSections, + }, + Sections: mappedSections, + }; + + return exportDto; + } catch (error) { + logger.error(`Error exporting form template: ${error.message}`); + ErrorHandler.throwInternalServerError(error.message, error); + } + }; + //#region Privates diff --git a/src/domain.types/form.template.domain.types.ts b/src/domain.types/form.template.domain.types.ts index adedf1e..ddd4534 100644 --- a/src/domain.types/form.template.domain.types.ts +++ b/src/domain.types/form.template.domain.types.ts @@ -80,7 +80,7 @@ export interface FormTemplateSearchResponseDto extends BaseSearchResults { } export interface ExportFormTemplateDto { - Sections: any; + Sections: SectionDto[]; Template: TemplateDto; } From 6e187285984ed98b845452bf32ebdcc3202dff6e Mon Sep 17 00:00:00 2001 From: RupaliD Date: Fri, 26 Sep 2025 14:41:27 +0530 Subject: [PATCH 2/2] FIxed the assessment duplicate data issue --- src/database/services/form.template.service.ts | 1 - src/domain.types/form.template.domain.types.ts | 1 - 2 files changed, 2 deletions(-) diff --git a/src/database/services/form.template.service.ts b/src/database/services/form.template.service.ts index 84e7180..bebdf65 100644 --- a/src/database/services/form.template.service.ts +++ b/src/database/services/form.template.service.ts @@ -385,7 +385,6 @@ export class FormTemplateService extends BaseService { UpdatedAt: template.UpdatedAt, Sections: mappedSections, }, - Sections: mappedSections, }; return exportDto; diff --git a/src/domain.types/form.template.domain.types.ts b/src/domain.types/form.template.domain.types.ts index ddd4534..ea35f35 100644 --- a/src/domain.types/form.template.domain.types.ts +++ b/src/domain.types/form.template.domain.types.ts @@ -80,7 +80,6 @@ export interface FormTemplateSearchResponseDto extends BaseSearchResults { } export interface ExportFormTemplateDto { - Sections: SectionDto[]; Template: TemplateDto; }