Skip to content
This repository has been archived by the owner on Mar 6, 2023. It is now read-only.

Commit

Permalink
feat(api): import individuel #1801
Browse files Browse the repository at this point in the history
  • Loading branch information
Toub committed May 19, 2020
1 parent 83dfcd9 commit f104ddc
Show file tree
Hide file tree
Showing 23 changed files with 641 additions and 109 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ describe("POST /hasura/events/email-reservation", () => {
const response = await request(server)
.post("/hasura/events/email-reservation")
.set("hasura_web_hook_secret", process.env.HASURA_WEB_HOOK_SECRET)
.set("Accept", "application/json")
.send(createHasuraTriggerEvent(global.mesure));

expect(response.status).toBe(200);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
const enqueteExcelParser = require("./enqueteExcelParser");
const logger = require("../../../utils/logger");

const actionsEnqueteImporter = {
importEnqueteFile
};

async function importEnqueteFile({
file: { base64str },
importContext: {
enqueteId,
// mandataireUserId & serviceId are mutually exclusive
mandataireUserId,
serviceId
}
}) {
const start = Date.now();
logger.info(`[IMPORT ENQUETE] START ${enqueteId}`);

const enqueteToImport = enqueteExcelParser.parse({
base64str
});

logger.info(`[IMPORT ENQUETE] enqueteToImport: ${enqueteToImport.length}`);

const importSummary = {
errors: [],
mandataireUserId,
serviceId
};

const durationInSeconds = Math.ceil((Date.now() - start) / 1000);

const errors = importSummary.errors;
if (errors.length) {
logger.info(
`[IMPORT ENQUETE] ERROR (duration: ${durationInSeconds}s, errors: ${errors.length}, to create: ${importSummary.create.length}, to update: ${importSummary.update.length})`
);
} else {
logger.info(
`[IMPORT ENQUETE] SUCCESS (duration: ${durationInSeconds}s, created: ${importSummary.create.length}, updated: ${importSummary.update.length})`
);
}

return {
errors: importSummary.errors,
creationNumber: importSummary.create.length,
updateNumber: importSummary.update.length,
invalidAntenneNames:
importSummary.errors.length === 0 ? importSummary.invalidAntenneNames : []
};
}

module.exports = actionsEnqueteImporter;
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
const HttpError = require("../../../utils/error/HttpError");
// const { Service } = require("../../../models/Service");

async function checkImportEnqueteParameters(req) {
const { role, userId } = req.user;

const inputParameters = req.body.input;

const { base64str, enqueteId, serviceId, mandataireUserId } = inputParameters;

if (!serviceId && !mandataireUserId) {
throw new HttpError(
422,
"Invalid parameters: serviceId or mandataireUserId is required"
);
}

let importContext;
if (role === "admin") {
// ADMIN
throw new HttpError(400, "Not supported yet (admin)");
// importContext = serviceId ? { enqueteId, serviceId } : { enqueteId, mandataireUserId };
} else if (role === "service") {
// SERVICE
throw new HttpError(400, "Not supported yet (service)");
// if (!serviceId) {
// throw new HttpError(422, "Invalid parameters: serviceId is required");
// }
// const service = await Service.query().findById(serviceId);
// if (!service || service.id !== serviceId) {
// throw new HttpError(403, "Access denied: invalid serviceId");
// }
// importContext = { enqueteId, serviceId };
} else if (role === "individuel") {
// MANDATAIRE INDIVIDUEL
if (!mandataireUserId) {
throw new HttpError(
422,
"Invalid parameters: mandataireUserId is required"
);
}
if (userId !== mandataireUserId) {
throw new HttpError(403, "Access denied: invalid mandataireUserId");
}
importContext = { enqueteId, mandataireUserId };
} else {
throw new HttpError(403, "Unexpected user");
}

const importEnqueteParameters = {
file: {
base64str
},
importContext
};
return importEnqueteParameters;
}

module.exports = checkImportEnqueteParameters;
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
var XLSX = require("xlsx");

const parse = ({ base64str }) => {
const workbook = XLSX.read(base64str, {
cellDates: true,
dateNF: "dd/mm/yyyy",
locale: "fr-FR",
type: "base64",
raw: false
});

const worksheet = workbook.Sheets["info mandataire-exerc. activité"];
if (worksheet) {
console.log("test");
console.log("test:", worksheet["A2"]);
}

return [];
};

const enqueteExcelParser = {
parse
};

module.exports = enqueteExcelParser;
81 changes: 21 additions & 60 deletions packages/api/src/routes/hasura-actions/hasura-actions.routes.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
const express = require("express");
const router = express.Router();
const actionsMesuresImporter = require("./mesures-import/actionsMesuresImporter");
const checkImportMesuresParameters = require("./mesures-import/checkImportMesuresParameters");
const actionsEnqueteImporter = require("./enquete-import/actionsEnqueteImporter");
const checkImportEnqueteParameters = require("./enquete-import/checkImportEnqueteParameters");
const hasuraActionErrorHandler = require("../../middlewares/hasura-error-handler");
const HttpError = require("../../utils/error/HttpError");
const { Service } = require("../../models/Service");

// Hasura handler associated to `upload_mesures_file` hasura action
// hasura action: `upload_mesures_file`
router.post(
"/mesures/upload",
async (req, res, next) => {
Expand All @@ -26,65 +27,25 @@ router.post(
hasuraActionErrorHandler("Unexpected error processing file")
);

async function checkImportMesuresParameters(req) {
const { role, userId } = req.user;

const inputParameters = req.body.input;

const {
name,
base64str,
serviceId,
mandataireUserId,
antennesMap
} = inputParameters;

if (!serviceId && !mandataireUserId) {
throw new HttpError(
422,
"Invalid parameters: serviceId or mandataireUserId is required"
);
}
// hasura action: `upload_enquete_file`
router.post(
"/enquetes/upload",
async (req, res, next) => {
try {
const importEnqueteParameters = await checkImportEnqueteParameters(req);

let importContext;
if (role === "admin") {
// ADMIN
importContext = serviceId ? { serviceId } : { mandataireUserId };
} else if (role === "service") {
// SERVICE
if (!serviceId) {
throw new HttpError(422, "Invalid parameters: serviceId is required");
}
const service = await Service.query().findById(serviceId);
if (!service || service.id !== serviceId) {
throw new HttpError(403, "Access denied: invalid serviceId");
}
importContext = { serviceId };
} else if (role === "individuel") {
// MANDATAIRE INDIVIDUEL
if (!mandataireUserId) {
throw new HttpError(
422,
"Invalid parameters: mandataireUserId is required"
const importSummary = await actionsEnqueteImporter.importEnqueteFile(
importEnqueteParameters
);
}
if (userId !== mandataireUserId) {
throw new HttpError(403, "Access denied: invalid mandataireUserId");
}
importContext = { mandataireUserId };
} else {
throw new HttpError(403, "Unexpected user");
}

const importMesuresParameters = {
file: {
base64str,
type: name.endsWith(".xls") || name.endsWith(".xlsx") ? "xls" : "csv"
},
importContext,
antennesMap: antennesMap ? JSON.parse(antennesMap) : undefined
};
return importMesuresParameters;
}
return res.status(201).json({
data: JSON.stringify(importSummary)
});
} catch (err) {
return next(err);
}
},
hasuraActionErrorHandler("Unexpected error processing file")
);

module.exports = router;
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,19 @@ async function importMesuresFile({
antennesMap
}) {
const start = Date.now();
logger.info(`[IMPORT] START`);

const mesuresToImport = excelParser.toJson({ base64str, type });
logger.info(`[IMPORT MESURES] START`);

const mesuresToImport = excelParser.parseSheetByIndex({
sheetIndex: 0,
base64str,
parseOptions: {
cellDates: true,
dateNF: "dd/mm/yyyy",
locale: "fr-FR",
type: "base64",
raw: type === "csv" ? true : false
}
});

mesuresToImport.forEach(data => {
if (data.type) {
Expand All @@ -40,7 +50,7 @@ async function importMesuresFile({
}
});

logger.info(`[IMPORT] mesuresToImport: ${mesuresToImport.length}`);
logger.info(`[IMPORT MESURES] mesuresToImport: ${mesuresToImport.length}`);

const {
errors,
Expand All @@ -61,15 +71,15 @@ async function importMesuresFile({

if (errors.length) {
logger.info(
`[IMPORT] ERROR (duration: ${durationInSeconds}s, errors: ${errors.length}, to create: ${importSummary.create.length}, to update: ${importSummary.update.length})`
`[IMPORT MESURES] ERROR (duration: ${durationInSeconds}s, errors: ${errors.length}, to create: ${importSummary.create.length}, to update: ${importSummary.update.length})`
);
} else if (importSummary.invalidAntenneNames.length) {
logger.info(
`[IMPORT] WARNING (duration: ${durationInSeconds}s, invalid antennes: ${importSummary.invalidAntenneNames.length}, to create: ${importSummary.create.length}, to update: ${importSummary.update.length})`
`[IMPORT MESURES] WARNING (duration: ${durationInSeconds}s, invalid antennes: ${importSummary.invalidAntenneNames.length}, to create: ${importSummary.create.length}, to update: ${importSummary.update.length})`
);
} else {
logger.info(
`[IMPORT] SUCCESS (duration: ${durationInSeconds}s, created: ${importSummary.create.length}, updated: ${importSummary.update.length})`
`[IMPORT MESURES] SUCCESS (duration: ${durationInSeconds}s, created: ${importSummary.create.length}, updated: ${importSummary.update.length})`
);
}

Expand Down Expand Up @@ -119,7 +129,7 @@ const importMesures = async ({
const size = mesuresWithLine.length;
for (const { mesure, line } of mesuresWithLine) {
if (counter === 1 || counter === size || counter % 100 === 0) {
logger.info(`[IMPORT] mesure ${counter} / ${size}`);
logger.info(`[IMPORT MESURES] mesure ${counter} / ${size}`);
}
const mesureDatas = {
...mesure,
Expand All @@ -145,15 +155,15 @@ const importMesures = async ({
// persist changes
if (importSummary.create.length) {
logger.info(
`[IMPORT] creating ${importSummary.create.length} mesures...`
`[IMPORT MESURES] creating ${importSummary.create.length} mesures...`
);
// batch insert
await Mesure.query().insert(importSummary.create);
}

if (importSummary.update.length) {
logger.info(
`[IMPORT] updating ${importSummary.update.length} mesures...`
`[IMPORT MESURES] updating ${importSummary.update.length} mesures...`
);
for (const { id, data } of importSummary.update) {
await Mesure.query()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
const HttpError = require("../../../utils/error/HttpError");
const { Service } = require("../../../models/Service");

async function checkImportMesuresParameters(req) {
const { role, userId } = req.user;

const inputParameters = req.body.input;

const {
name,
base64str,
serviceId,
mandataireUserId,
antennesMap
} = inputParameters;

if (!serviceId && !mandataireUserId) {
throw new HttpError(
422,
"Invalid parameters: serviceId or mandataireUserId is required"
);
}

let importContext;
if (role === "admin") {
// ADMIN
importContext = serviceId ? { serviceId } : { mandataireUserId };
} else if (role === "service") {
// SERVICE
if (!serviceId) {
throw new HttpError(422, "Invalid parameters: serviceId is required");
}
const service = await Service.query().findById(serviceId);
if (!service || service.id !== serviceId) {
throw new HttpError(403, "Access denied: invalid serviceId");
}
importContext = { serviceId };
} else if (role === "individuel") {
// MANDATAIRE INDIVIDUEL
if (!mandataireUserId) {
throw new HttpError(
422,
"Invalid parameters: mandataireUserId is required"
);
}
if (userId !== mandataireUserId) {
throw new HttpError(403, "Access denied: invalid mandataireUserId");
}
importContext = { mandataireUserId };
} else {
throw new HttpError(403, "Unexpected user");
}

const importMesuresParameters = {
file: {
base64str,
type: name.endsWith(".xls") || name.endsWith(".xlsx") ? "xls" : "csv"
},
importContext,
antennesMap: antennesMap ? JSON.parse(antennesMap) : undefined
};
return importMesuresParameters;
}

module.exports = checkImportMesuresParameters;
Loading

0 comments on commit f104ddc

Please sign in to comment.