fix: import resource imporements

This commit is contained in:
Ahmed Bouhuolia
2024-03-27 04:01:01 +02:00
parent 973d1832bd
commit ad4e51d81d
59 changed files with 1508 additions and 211 deletions

View File

@@ -7,16 +7,16 @@ import { first } from 'lodash';
import { ImportFileDataValidator } from './ImportFileDataValidator';
import { Knex } from 'knex';
import {
ImportInsertError,
ImportOperError,
ImportOperSuccess,
ImportableContext,
} from './interfaces';
import { AccountsImportable } from '../Accounts/AccountsImportable';
import { ServiceError } from '@/exceptions';
import { trimObject } from './_utils';
import { ImportableResources } from './ImportableResources';
import ResourceService from '../Resource/ResourceService';
import HasTenancyService from '../Tenancy/TenancyService';
import Import from '@/models/Import';
@Service()
export class ImportFileCommon {
@@ -39,12 +39,12 @@ export class ImportFileCommon {
* @returns {Record<string, any>[]} - The mapped data objects.
*/
public parseXlsxSheet(buffer: Buffer): Record<string, unknown>[] {
const workbook = XLSX.read(buffer, { type: 'buffer' });
const workbook = XLSX.read(buffer, { type: 'buffer', raw: true });
const firstSheetName = workbook.SheetNames[0];
const worksheet = workbook.Sheets[firstSheetName];
return XLSX.utils.sheet_to_json(worksheet);
return XLSX.utils.sheet_to_json(worksheet, {});
}
/**
@@ -57,7 +57,7 @@ export class ImportFileCommon {
}
/**
* Imports the given parsed data to the resource storage through registered importable service.
* Imports the given parsed data to the resource storage through registered importable service.
* @param {number} tenantId -
* @param {string} resourceName - Resource name.
* @param {Record<string, any>} parsedData - Parsed data.
@@ -66,16 +66,16 @@ export class ImportFileCommon {
*/
public async import(
tenantId: number,
resourceName: string,
importFile: Import,
parsedData: Record<string, any>[],
trx?: Knex.Transaction
): Promise<[ImportOperSuccess[], ImportOperError[]]> {
const importableFields = this.resource.getResourceImportableFields(
tenantId,
resourceName
importFile.resource
);
const ImportableRegistry = this.importable.registry;
const importable = ImportableRegistry.getImportable(resourceName);
const importable = ImportableRegistry.getImportable(importFile.resource);
const concurrency = importable.concurrency || 10;
@@ -83,15 +83,25 @@ export class ImportFileCommon {
const failed: ImportOperError[] = [];
const importAsync = async (objectDTO, index: number): Promise<void> => {
const context: ImportableContext = {
rowIndex: index,
import: importFile,
};
const transformedDTO = importable.transform(objectDTO, context);
try {
// Validate the DTO object before passing it to the service layer.
await this.importFileValidator.validateData(
importableFields,
objectDTO
transformedDTO
);
try {
// Run the importable function and listen to the errors.
const data = await importable.importable(tenantId, objectDTO, trx);
const data = await importable.importable(
tenantId,
transformedDTO,
trx
);
success.push({ index, data });
} catch (err) {
if (err instanceof ServiceError) {
@@ -115,6 +125,60 @@ export class ImportFileCommon {
return [success, failed];
}
/**
*
* @param {string} resourceName
* @param {Record<string, any>} params
*/
public async validateParamsSchema(
resourceName: string,
params: Record<string, any>
) {
const ImportableRegistry = this.importable.registry;
const importable = ImportableRegistry.getImportable(resourceName);
const yupSchema = importable.paramsValidationSchema();
try {
await yupSchema.validate(params, { abortEarly: false });
} catch (validationError) {
const errors = validationError.inner.map((error) => ({
errorCode: 'ParamsValidationError',
errorMessage: error.errors,
}));
throw errors;
}
}
/**
*
* @param {string} resourceName
* @param {Record<string, any>} params
*/
public async validateParams(
tenantId: number,
resourceName: string,
params: Record<string, any>
) {
const ImportableRegistry = this.importable.registry;
const importable = ImportableRegistry.getImportable(resourceName);
await importable.validateParams(tenantId, params);
}
/**
*
* @param {string} resourceName
* @param {Record<string, any>} params
* @returns
*/
public transformParams(resourceName: string, params: Record<string, any>) {
const ImportableRegistry = this.importable.registry;
const importable = ImportableRegistry.getImportable(resourceName);
return importable.transformParams(params);
}
/**
* Retrieves the sheet columns from the given sheet data.
* @param {unknown[]} json