Skip to content

Commit

Permalink
feat: finalize import/export
Browse files Browse the repository at this point in the history
  • Loading branch information
mkeen committed Jan 30, 2022
1 parent 5417a89 commit 52965eb
Show file tree
Hide file tree
Showing 6 changed files with 61 additions and 13 deletions.
4 changes: 2 additions & 2 deletions src/controllers/project.controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ import {
tableDataFromXlsx,
createXlsFromSequelizeResults,
sendXls,
updateTablesWithData,
updateTableWithData, collapseTablesData,
} from '../utils/xls';

export const create = async (req, res) => {
Expand Down Expand Up @@ -190,7 +190,7 @@ export const updateFromXLS = async (req, res) => {

const xlsxParsed = xlsx.parse(files.xlsx.data);
const stagedDataItems = tableDataFromXlsx(xlsxParsed, Project);
await updateTablesWithData(stagedDataItems);
await updateTableWithData(collapseTablesData(stagedDataItems, Project), Project);

res.json({
message: 'Updates from xlsx added to staging',
Expand Down
5 changes: 3 additions & 2 deletions src/controllers/units.controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,11 @@ import {

import { createUnitRecordsFromCsv } from '../utils/csv-utils';
import {
collapseTablesData,
createXlsFromSequelizeResults,
sendXls,
tableDataFromXlsx,
updateTablesWithData,
updateTableWithData,
} from '../utils/xls';
import xlsx from 'node-xlsx';

Expand Down Expand Up @@ -196,7 +197,7 @@ export const updateFromXLS = async (req, res) => {

const xlsxParsed = xlsx.parse(files.xlsx.data);
const stagedDataItems = tableDataFromXlsx(xlsxParsed, Unit);
await updateTablesWithData(stagedDataItems);
await updateTableWithData(collapseTablesData(stagedDataItems, Unit), Unit);

res.json({
message: 'Updates from xlsx added to staging',
Expand Down
2 changes: 2 additions & 0 deletions src/models/projects/projects.model.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ class Project extends Model {
static changes = new rxjs.Subject();
static defaultColumns = Object.keys(ModelTypes);
static validateImport = projectsUpdateSchema
static virtualFieldList = {};

static getAssociatedModels = () => [
ProjectLocation,
Label,
Expand Down
1 change: 1 addition & 0 deletions src/models/units/units.model.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ class Unit extends Model {
static stagingTableName = 'Units';
static changes = new rxjs.Subject();
static validateImport = unitsUpdateSchema;
static virtualFieldList = virtualFields;

static defaultColumns = Object.keys(
Object.assign({}, ModelTypes, virtualFields),
Expand Down
2 changes: 2 additions & 0 deletions src/models/units/units.stub.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
[
{
"warehouseUnitId": "5c960ac1-a180-45a4-9850-be177e26d2fb",
"projectLocationId": "89adcb9a-dc10-41aa-8606-c1ce1545dcbd",
"vintageYear": 2020,
"orgUid": "f1c54511-865e-4611-976c-7c3c1f704662",
"unitOwner": "f1c54511-865e-4611-976c-7c3c1f704662",
"countryJurisdictionOfOwner": "USA",
Expand Down
60 changes: 51 additions & 9 deletions src/utils/xls.js
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,9 @@ export const createXlsFromSequelizeResults = (
const initialReduceValue = {};
initialReduceValue[model.name] = {
name: model.name + 's',
data: [columnsInMainSheet],
data: [columnsInMainSheet.filter(colName => {
return !(excludeOrgUid && colName === 'orgUid');
})],
};

const xlsData = rows.reduce((sheets, row) => {
Expand All @@ -97,13 +99,17 @@ export const createXlsFromSequelizeResults = (
sheets[mainColName + 's'] = {
name: mainColName + 's',
data: [
Object.keys(row[mainColName].filter(colName => {
return !(excludeOrgUid && colName === 'orgUid');
})).concat([
Object.keys(row[mainColName]).concat([
model.name.split('_').join('') + 'Id',
]),
],
};
}

console.log(Object.keys(row[mainColName]).filter(colName => {
return !(excludeOrgUid && colName === 'orgUid');
}).concat([
model.name.split('_').join('') + 'Id',
]))
}
sheets[mainColName + 's'].data.push(
Object.values(row[mainColName])
Expand All @@ -116,7 +122,9 @@ export const createXlsFromSequelizeResults = (
if (row[mainColName] === null) {
row[mainColName] = 'null';
}
//console.log(mainColName, "//")
if (!(excludeOrgUid && mainColName === 'orgUid')) {
//console.log(mainColName, "!!!");
mainXlsRow.push(encodeValue(row[mainColName], hex));
}
}
Expand Down Expand Up @@ -210,7 +218,10 @@ export const tableDataFromXlsx = (xlsx, model) => {
if (columnData === 'null') {
columnData = null;
}
row[columnNames[columnIndex]] = columnData;
// Ignore virtual fields
if (!Object.keys(model.virtualFieldList).includes(columnNames[columnIndex])) {
row[columnNames[columnIndex]] = columnData;
}
}
delete row.orgUid;
stagingData[dataModel.name].data.push(row);
Expand All @@ -220,11 +231,42 @@ export const tableDataFromXlsx = (xlsx, model) => {
}, {});
};

export const updateTablesWithData = async (tableData) => {
export const collapseTablesData = (tableData, model) => {
const collapsed = {[model.name]: tableData[model.name]};

let associations = model.getAssociatedModels().map((model) => {
if (typeof model === 'object') {
return model.model;
} else {
return model;
}
});

for (const [i, data] of collapsed[model.name].data.entries()) {
for (const {name: association} of associations) {
if (['issuance'].includes(association)) {
collapsed[model.name].data[i][association] = tableData[association].data.find((row) => {
return row[model.name + 'Id'] === collapsed[model.name].data[i][association + 'Id'];
})
} else {
collapsed[model.name].data[i][association + 's'] = tableData[association].data.filter((row) => {
return row[model.name + 'Id'] === collapsed[model.name].data[i][tableData[model.name].model.primaryKeyAttributes[0]];
});
}
}
}

return collapsed;
}

export const updateTableWithData = async (tableData, model) => {
if (!['project', 'unit'].includes(model.name)) {
throw 'Bulk import is only supported for projects and units';
}
// using a transaction ensures either everything is uploaded or everything fails
await sequelize.transaction(async () => {
const { orgUid } = await Organization.getHomeOrg();

for (let [, { model, data }] of Object.values(tableData).entries()) {
for (let row of data) {
const existingRecord = await model.findByPk(
Expand All @@ -241,7 +283,7 @@ export const updateTablesWithData = async (tableData) => {
row.orgUid = orgUid;
}

const validation = model.validateImport.validate(row);
const validation = model.validateImport.validate(row, { stripUnknown: true });

if (!validation.error) {
await Staging.upsert({
Expand Down

0 comments on commit 52965eb

Please sign in to comment.