import { deleteImportFile, getResourceColumns, readImportFile, sanitizeResourceName, validateSheetEmpty, } from './_utils'; import { ResourceService } from '../Resource/ResourceService'; import { ImportFileCommon } from './ImportFileCommon'; import { ImportFileDataValidator } from './ImportFileDataValidator'; import { ImportFileUploadPOJO } from './interfaces'; import { Import } from '@/system/models'; import { parseSheetData } from './sheet_utils'; import { Injectable } from '@nestjs/common'; @Injectable() export class ImportFileUploadService { constructor( private resourceService: ResourceService, private importFileCommon: ImportFileCommon, private importValidator: ImportFileDataValidator, ) {} /** * Imports the specified file for the given resource. * Deletes the file if an error occurs during the import process. * @param {number} tenantId * @param {string} resourceName * @param {string} filename * @param {Record} params * @returns {Promise} */ public async import( resourceName: string, filename: string, params: Record, ): Promise { try { return await this.importUnhandled( tenantId, resourceName, filename, params, ); } catch (err) { deleteImportFile(filename); throw err; } } /** * Reads the imported file and stores the import file meta under unqiue id. * @param {number} tenantId - Tenant id. * @param {string} resource - Resource name. * @param {string} filePath - File path. * @param {string} fileName - File name. * @returns {Promise} */ public async importUnhandled( resourceName: string, filename: string, params: Record, ): Promise { const resource = sanitizeResourceName(resourceName); const resourceMeta = this.resourceService.getResourceMeta(resource); // Throw service error if the resource does not support importing. this.importValidator.validateResourceImportable(resourceMeta); // Reads the imported file into buffer. const buffer = await readImportFile(filename); // Parse the buffer file to array data. const [sheetData, sheetColumns] = parseSheetData(buffer); const coumnsStringified = JSON.stringify(sheetColumns); // Throws service error if the sheet data is empty. validateSheetEmpty(sheetData); try { // Validates the params Yup schema. await this.importFileCommon.validateParamsSchema(resource, params); // Validates importable params asyncly. await this.importFileCommon.validateParams(tenantId, resource, params); } catch (error) { throw error; } const _params = this.importFileCommon.transformParams(resource, params); const paramsStringified = JSON.stringify(_params); // Store the import model with related metadata. const importFile = await Import.query().insert({ filename, resource, tenantId, importId: filename, columns: coumnsStringified, params: paramsStringified, }); const resourceColumnsMap = this.resourceService.getResourceFields2( tenantId, resource, ); const resourceColumns = getResourceColumns(resourceColumnsMap); return { import: { importId: importFile.importId, resource: importFile.resource, }, sheetColumns, resourceColumns, }; } }