feat(nestjs): migrate to NestJS

This commit is contained in:
Ahmed Bouhuolia
2025-04-07 11:51:24 +02:00
parent f068218a16
commit 55fcc908ef
3779 changed files with 631 additions and 195332 deletions

View File

@@ -0,0 +1,143 @@
import { Injectable } from '@nestjs/common';
import { fromPairs, isUndefined } from 'lodash';
import {
ImportDateFormats,
ImportFileMapPOJO,
ImportMappingAttr,
} from './interfaces';
import { ResourceService } from '../Resource/ResourceService';
import { ServiceError } from '../Items/ServiceError';
import { ERRORS } from './_utils';
import { Import } from './models/Import';
@Injectable()
export class ImportFileMapping {
constructor(private readonly resource: ResourceService) {}
/**
* Mapping the excel sheet columns with resource columns.
* @param {number} tenantId
* @param {number} importId
* @param {ImportMappingAttr} maps
*/
public async mapping(
importId: string,
maps: ImportMappingAttr[],
): Promise<ImportFileMapPOJO> {
const importFile = await Import.query()
.findOne('filename', importId)
.throwIfNotFound();
// Invalidate the from/to map attributes.
this.validateMapsAttrs(importFile, maps);
// @todo validate the required fields.
// Validate the diplicated relations of map attrs.
this.validateDuplicatedMapAttrs(maps);
// Validate the date format mapping.
this.validateDateFormatMapping(importFile.resource, maps);
const mappingStringified = JSON.stringify(maps);
await Import.query().findById(importFile.id).patch({
mapping: mappingStringified,
});
return {
import: {
importId: importFile.importId,
resource: importFile.resource,
},
};
}
/**
* Validate the mapping attributes.
* @param {number} tenantId -
* @param {} importFile -
* @param {ImportMappingAttr[]} maps
* @throws {ServiceError(ERRORS.INVALID_MAP_ATTRS)}
*/
private validateMapsAttrs(importFile: any, maps: ImportMappingAttr[]) {
const fields = this.resource.getResourceFields2(importFile.resource);
const columnsMap = fromPairs(
importFile.columnsParsed.map((field) => [field, '']),
);
const invalid = [];
// is not empty, is not undefined or map.group
maps.forEach((map) => {
let _invalid = true;
if (!map.group && fields[map.to]) {
_invalid = false;
}
if (map.group && fields[map.group] && fields[map.group]?.fields[map.to]) {
_invalid = false;
}
if (columnsMap[map.from]) {
_invalid = false;
}
if (_invalid) {
invalid.push(map);
}
});
if (invalid.length > 0) {
throw new ServiceError(ERRORS.INVALID_MAP_ATTRS);
}
}
/**
* Validate the map attrs relation should be one-to-one relation only.
* @param {ImportMappingAttr[]} maps
*/
private validateDuplicatedMapAttrs(maps: ImportMappingAttr[]) {
const fromMap = {};
const toMap = {};
maps.forEach((map) => {
if (fromMap[map.from]) {
throw new ServiceError(ERRORS.DUPLICATED_FROM_MAP_ATTR);
} else {
fromMap[map.from] = true;
}
const toPath = !isUndefined(map?.group)
? `${map.group}.${map.to}`
: map.to;
if (toMap[toPath]) {
throw new ServiceError(ERRORS.DUPLICATED_TO_MAP_ATTR);
} else {
toMap[toPath] = true;
}
});
}
/**
* Validates the date format mapping.
* @param {number} tenantId
* @param {string} resource
* @param {ImportMappingAttr[]} maps
*/
private validateDateFormatMapping(
resource: string,
maps: ImportMappingAttr[],
) {
const fields = this.resource.getResourceImportableFields(resource);
// @todo Validate date type of the nested fields.
maps.forEach((map) => {
if (
typeof fields[map.to] !== 'undefined' &&
fields[map.to].fieldType === 'date'
) {
if (
typeof map.dateFormat !== 'undefined' &&
ImportDateFormats.indexOf(map.dateFormat) === -1
) {
throw new ServiceError(ERRORS.INVALID_MAP_DATE_FORMAT);
}
}
});
}
}