diff --git a/src/routes/upload/index.ts b/src/routes/upload/index.ts index 945688b1a..7c761c694 100644 --- a/src/routes/upload/index.ts +++ b/src/routes/upload/index.ts @@ -16,7 +16,7 @@ import { Types } from 'mongoose'; import { getUploadColumns, loadRow, uploadFile } from '@utils/files'; import { getNextId, getOwnership } from '@utils/form'; import i18next from 'i18next'; -import get from 'lodash/get'; +import { get, isString } from 'lodash'; import { logger } from '@services/logger.service'; import { accessibleBy } from '@casl/mongoose'; import { insertRecords as insertRecordsPulljob } from '@server/pullJobScheduler'; @@ -123,7 +123,39 @@ async function insertRecords( const versionsToCreate: Version[] = []; const recordsToCreate: Record[] = []; const recordToUpdate: Record[] = []; - worksheet.eachRow({ includeEmpty: false }, function (row) { + + // Get resource questions that are linked to a unique field + const linkedResourceQuestion = ( + await Promise.all( + columns.map(async (question, index) => { + // Extract all the question info from the form structure + const fullQuestion = form.fields.find( + (field) => field.name === question.name + ); + + if (fullQuestion && fullQuestion.type === 'resource') { + // Verify if the question field is equal to any form import field of the resource + const forms = await Form.find({ resource: fullQuestion.resource }); + for (const resForm of forms) { + if (resForm.importField === fullQuestion.displayField) { + // Saving the associated import field name and the column index to retrieve the corresponding data + question.importField = resForm.importField; + question.excelColumnIndex = index; + // Get the question type to avoid formatting issues with numeric values + const resQuestion = resForm.fields.find( + (field) => field.name === fullQuestion.displayField + ); + question.type = resQuestion?.type; + return question; + } + } + } + }) + ) + ).filter(Boolean); // Remove undefined values + + for (let i = 1; i <= worksheet.rowCount; i++) { + const row = worksheet.getRow(i); const { data, positionAttributes } = loadRow(columns, row.values); const oldRecord = oldRecords.find((rec) => importField === DEFAULT_IMPORT_FIELD.incID @@ -131,6 +163,20 @@ async function insertRecords( : rec.data[importField] === row.getCell(importFieldIndex).value ); + // Change the import field value to the object ID if the record exists + await Promise.all( + linkedResourceQuestion.map(async (field) => { + if (!isString(data[field.name]) && field.type !== 'numeric') { + data[field.name] = JSON.stringify(data[field.name]); + } + const record = await Record.findOne({ + [`data.${field.importField}`]: data[field.name], + }); + if (record) { + data[field.name] = record._id.toString(); + } + }) + ); // If the record already exists, update it and create a new version if (oldRecord) { const updatedRecord = cloneDeep(oldRecord); @@ -185,7 +231,7 @@ async function insertRecords( }) ); } - }); + } // Set the incrementalIDs of new records for (let i = 0; i < recordsToCreate.length; i += 1) { diff --git a/src/utils/form/getFieldType.ts b/src/utils/form/getFieldType.ts index 49dbbb3a2..b273db7d7 100644 --- a/src/utils/form/getFieldType.ts +++ b/src/utils/form/getFieldType.ts @@ -85,6 +85,8 @@ export const getFieldType = async (question: { return 'owner'; case 'geospatial': return 'geospatial'; + case 'expression': + return 'expression'; default: return 'text'; }