From ae454a126690dda5b9217f97e3bc6df71644bf97 Mon Sep 17 00:00:00 2001 From: Michael Taylor Date: Tue, 8 Feb 2022 07:53:46 -0500 Subject: [PATCH] feat: assert child label existance when inserting or updating projects and units --- src/controllers/project.controller.js | 58 +++++++++++++++++++-------- src/controllers/units.controller.js | 41 ++++++++++++++----- src/models/index.js | 1 + src/utils/data-assertions.js | 7 ++++ 4 files changed, 79 insertions(+), 28 deletions(-) diff --git a/src/controllers/project.controller.js b/src/controllers/project.controller.js index 3192114c..6d2756f9 100644 --- a/src/controllers/project.controller.js +++ b/src/controllers/project.controller.js @@ -14,6 +14,7 @@ import { Organization, Rating, Estimation, + ModelKeys, } from '../models'; import { @@ -28,6 +29,7 @@ import { assertCsvFileInRequest, assertHomeOrgExists, assetNoPendingCommits, + assertRecordExistance, } from '../utils/data-assertions'; import { createProjectRecordsFromCsv } from '../utils/csv-utils'; @@ -55,7 +57,7 @@ export const create = async (req, res) => { const { orgUid } = await Organization.getHomeOrg(); newRecord.orgUid = orgUid; - const childRecords = [ + const childRecordsKeys = [ 'projectLocations', 'issuances', 'coBenefits', @@ -65,16 +67,28 @@ export const create = async (req, res) => { 'labels', ]; - childRecords.forEach((childRecordKey) => { - if (newRecord[childRecordKey]) { - newRecord[childRecordKey].map((childRecord) => { - childRecord.id = uuidv4(); + const existingChildRecordKeys = childRecordsKeys.filter((key) => + Boolean(newRecord[key]), + ); + + for (let i = 0; i < existingChildRecordKeys.length; i++) { + const key = existingChildRecordKeys[i]; + await Promise.all( + newRecord[key].map(async (childRecord) => { + if (childRecord.id) { + // If we are reusing an existing child record, + // Make sure it exists + await assertRecordExistance(ModelKeys[key], childRecord.id); + } else { + childRecord.id = uuidv4(); + } + childRecord.orgUid = orgUid; childRecord.warehouseProjectId = uuid; return childRecord; - }); - } - }); + }), + ); + } await Staging.create({ uuid, @@ -82,6 +96,7 @@ export const create = async (req, res) => { table: Project.stagingTableName, data: JSON.stringify([newRecord]), }); + res.json({ message: 'Project staged successfully' }); } catch (err) { res.status(400).json({ @@ -212,7 +227,7 @@ export const update = async (req, res) => { const newRecord = _.cloneDeep(req.body); const { orgUid } = await Organization.getHomeOrg(); - const childRecords = [ + const childRecordsKeys = [ 'projectLocations', 'issuances', 'coBenefits', @@ -222,10 +237,19 @@ export const update = async (req, res) => { 'labels', ]; - childRecords.forEach((childRecordKey) => { - if (newRecord[childRecordKey]) { - newRecord[childRecordKey].map((childRecord) => { - if (!childRecord.id) { + const existingChildRecordKeys = childRecordsKeys.filter((key) => + Boolean(newRecord[key]), + ); + + for (let i = 0; i < existingChildRecordKeys.length; i++) { + const key = existingChildRecordKeys[i]; + await Promise.all( + newRecord[key].map(async (childRecord) => { + if (childRecord.id) { + // If we are reusing an existing child record, + // Make sure it exists + await assertRecordExistance(ModelKeys[key], childRecord.id); + } else { childRecord.id = uuidv4(); } @@ -237,14 +261,14 @@ export const update = async (req, res) => { childRecord.warehouseProjectId = newRecord.warehouseProjectId; } - if (childRecordKey === 'labels' && childRecord.labelUnits) { + if (key === 'labels' && childRecord.labelUnits) { childRecord.labelUnits.orgUid = orgUid; } return childRecord; - }); - } - }); + }), + ); + } // merge the new record into the old record let stagedRecord = Array.isArray(newRecord) ? newRecord : [newRecord]; diff --git a/src/controllers/units.controller.js b/src/controllers/units.controller.js index a4afcef8..b0b95986 100644 --- a/src/controllers/units.controller.js +++ b/src/controllers/units.controller.js @@ -19,6 +19,7 @@ import { assertCsvFileInRequest, assertHomeOrgExists, assetNoPendingCommits, + assertRecordExistance, } from '../utils/data-assertions'; import { createUnitRecordsFromCsv } from '../utils/csv-utils'; @@ -48,8 +49,14 @@ export const create = async (req, res) => { newRecord.orgUid = orgUid; if (newRecord.labels) { - newRecord.labels.map((childRecord) => { - childRecord.id = uuidv4(); + const promises = newRecord.labels.map(async (childRecord) => { + if (childRecord.id) { + // if we are reusing a record, make sure it exists + await assertRecordExistance(Label, childRecord.id); + } else { + childRecord.id = uuidv4(); + } + childRecord.orgUid = orgUid; childRecord.label_unit = {}; childRecord.label_unit.id = uuidv4(); @@ -59,6 +66,8 @@ export const create = async (req, res) => { return childRecord; }); + + await Promise.all(promises); } if (newRecord.issuance) { @@ -80,7 +89,7 @@ export const create = async (req, res) => { }); } catch (error) { res.status(400).json({ - message: 'Batch Upload Failed.', + message: 'Unit Insert Failed to stage.', error: error.message, }); } @@ -178,12 +187,18 @@ export const findAll = async (req, res) => { }; export const findOne = async (req, res) => { - console.info('req.query', req.query); - res.json( - await Unit.findByPk(req.query.warehouseUnitId, { - include: Unit.getAssociatedModels(), - }), - ); + try { + res.json( + await Unit.findByPk(req.query.warehouseUnitId, { + include: Unit.getAssociatedModels(), + }), + ); + } catch (error) { + res.status(400).json({ + message: 'Cant find Unit.', + error: error.message, + }); + } }; export const updateFromXLS = async (req, res) => { @@ -230,8 +245,10 @@ export const update = async (req, res) => { updatedRecord.orgUid = orgUid; if (updatedRecord.labels) { - updatedRecord.labels.map((childRecord) => { - if (!childRecord.id) { + const promises = updatedRecord.labels.map(async (childRecord) => { + if (childRecord.id) { + await assertRecordExistance(Label, childRecord.id); + } else { childRecord.id = uuidv4(); } @@ -250,6 +267,8 @@ export const update = async (req, res) => { return childRecord; }); + + await Promise.all(promises); } if (updatedRecord.issuance) { diff --git a/src/models/index.js b/src/models/index.js index 0d79058b..96cf7ffe 100644 --- a/src/models/index.js +++ b/src/models/index.js @@ -37,6 +37,7 @@ export * from './estimations'; export const ModelKeys = { unit: Unit, units: Unit, + label: Label, labels: Label, label_unit: LabelUnit, label_units: LabelUnit, diff --git a/src/utils/data-assertions.js b/src/utils/data-assertions.js index c453a19b..d2bf5113 100644 --- a/src/utils/data-assertions.js +++ b/src/utils/data-assertions.js @@ -18,6 +18,13 @@ export const assetNoPendingCommits = async () => { } }; +export const assertRecordExistance = async (Model, pk) => { + const record = await Model.findByPk(pk); + if (!record) { + throw new Error(`${Model.name} does not have a record for ${pk}`); + } +}; + export const assertHomeOrgExists = async () => { const homeOrg = await Organization.getHomeOrg(); if (!homeOrg) {