From 170861a77366fdd4848429215200d2c288a38ecc Mon Sep 17 00:00:00 2001
From: Agustin <agusr1999@gmail.com>
Date: Fri, 17 Sep 2021 13:12:39 -0300
Subject: [PATCH] Swagger updated with calculator path, parameter path not done
 yet

Calculator controller now also logs errors.
---
 src/Controllers/CalculatorController.ts |   2 +
 src/Controllers/SheetController.ts      |  48 +++---
 src/Logger/logger.ts                    |  64 +++----
 src/Services/SheetService.ts            | 216 ++++++++++++------------
 src/index.ts                            |  78 ++++-----
 swagger.yaml                            |  27 +++
 6 files changed, 232 insertions(+), 203 deletions(-)

diff --git a/src/Controllers/CalculatorController.ts b/src/Controllers/CalculatorController.ts
index d178be2..51a0f43 100644
--- a/src/Controllers/CalculatorController.ts
+++ b/src/Controllers/CalculatorController.ts
@@ -4,6 +4,7 @@ import {
 import AgeGroupJSON from '../DTOs/AgeGroupJSON';
 import CalculatorService from '../Services/CalculatorService';
 import CalculatorResponse from '../DTOs/CalculatorResponseDTO';
+import logger from '../Logger/logger';
 
 const router = Router();
 
@@ -14,6 +15,7 @@ const getREP: Handler = async (req: Request, res: Response) => {
     return res.status(200).send(EnergyReq);
   } catch (error) {
     const e = error as Error;
+    logger.info(e.message);
     return res.status(400).json({ error: e.message });
   }
 };
diff --git a/src/Controllers/SheetController.ts b/src/Controllers/SheetController.ts
index 8d784ec..8658d81 100644
--- a/src/Controllers/SheetController.ts
+++ b/src/Controllers/SheetController.ts
@@ -1,24 +1,24 @@
-import {
-  Handler, Request, Response, Router,
-} from 'express';
-import { SheetParserResponse } from '../Models/SheetParserResponse';
-import SheetService from '../Services/SheetService';
-import logger from '../Logger/logger';
-
-const router = Router();
-
-const parseSheet: Handler = async (req: Request, res: Response) => {
-  const sheet: Buffer = req.body;
-  try {
-    const parsedSheet: SheetParserResponse = SheetService.parseSheetService(sheet);
-    return res.status(200).send(parsedSheet);
-  } catch (error) {
-    const e = error as Error;
-    logger.info(e.message);
-    return res.status(400).json({ error: e.message });
-  }
-};
-
-router.post('/', parseSheet);
-
-export default router;
+import {
+  Handler, Request, Response, Router,
+} from 'express';
+import { SheetParserResponse } from '../Models/SheetParserResponse';
+import SheetService from '../Services/SheetService';
+import logger from '../Logger/logger';
+
+const router = Router();
+
+const parseSheet: Handler = async (req: Request, res: Response) => {
+  const sheet: Buffer = req.body;
+  try {
+    const parsedSheet: SheetParserResponse = SheetService.parseSheetService(sheet);
+    return res.status(200).send(parsedSheet);
+  } catch (error) {
+    const e = error as Error;
+    logger.info(e.message);
+    return res.status(400).json({ error: e.message });
+  }
+};
+
+router.post('/', parseSheet);
+
+export default router;
diff --git a/src/Logger/logger.ts b/src/Logger/logger.ts
index 1771549..e14b731 100644
--- a/src/Logger/logger.ts
+++ b/src/Logger/logger.ts
@@ -1,32 +1,32 @@
-import {
-  createLogger, format, transports, Logger,
-} from 'winston';
-
-const {
-  combine, timestamp,
-} = format;
-
-const logger: Logger = createLogger({
-  level: 'info',
-  format: combine(
-    timestamp(),
-    format.errors({ stack: true }),
-    format.json(),
-  ),
-  transports: [
-    new transports.File({
-      level: 'error',
-      filename: 'logs/error-logs',
-      maxsize: 104857600, // 100Mb
-      maxFiles: 3,
-    }),
-    new transports.File({
-      level: 'info',
-      filename: 'logs/info-logs',
-      maxsize: 104857600, // 100Mb
-      maxFiles: 3,
-    }),
-  ],
-});
-
-export default logger;
+import {
+  createLogger, format, transports, Logger,
+} from 'winston';
+
+const {
+  combine, timestamp,
+} = format;
+
+const logger: Logger = createLogger({
+  level: 'info',
+  format: combine(
+    timestamp(),
+    format.errors({ stack: true }),
+    format.json(),
+  ),
+  transports: [
+    new transports.File({
+      level: 'error',
+      filename: 'logs/error-logs',
+      maxsize: 104857600, // 100Mb
+      maxFiles: 3,
+    }),
+    new transports.File({
+      level: 'info',
+      filename: 'logs/info-logs',
+      maxsize: 104857600, // 100Mb
+      maxFiles: 3,
+    }),
+  ],
+});
+
+export default logger;
diff --git a/src/Services/SheetService.ts b/src/Services/SheetService.ts
index 947b1b0..e30e75a 100644
--- a/src/Services/SheetService.ts
+++ b/src/Services/SheetService.ts
@@ -1,108 +1,108 @@
-import * as XLSX from 'xlsx';
-import { SheetNames } from '../Config/Constants';
-import {
-  SheetParserResponse, Menores, Mayores, MenoresSheet, MayoresSheet,
-} from '../Models/SheetParserResponse';
-
-/* PRIVATE FUNCTIONS */
-// const ec = (r: number, c: number): string => XLSX.utils.encode_cell({ r, c });
-// const deleteRow = (ws: XLSX.WorkSheet, rowIndex: number): XLSX.WorkSheet => {
-//   const work = ws;
-//   if (work['!ref'] === undefined) throw new Error('An error has ocurred in deleteRow');
-//   const variable = XLSX.utils.decode_range(work['!ref']);
-//   for (let R = rowIndex; R < variable.e.r; R += 1) {
-//     for (let C = variable.s.c; C <= variable.e.c; C += 1) {
-//       work[ec(R, C)] = work[ec(R + 1, C)];
-//     }
-//   }
-//   variable.e.r -= 1;
-//   work['!ref'] = XLSX.utils.encode_range(variable.s, variable.e);
-//   return work;
-// };
-
-const parseAdults = (worksheet: XLSX.WorkSheet): Mayores[] => {
-  const res: Mayores[] = [];
-  const ref = worksheet['!ref'];
-  if (ref === undefined) throw new Error('An error ocurred');
-  const range = XLSX.utils.decode_range(ref);
-  range.s.c = 0;
-  range.e.c = 2;
-  const newRange = XLSX.utils.encode_range(range);
-
-  const aux = XLSX.utils.sheet_to_json(worksheet, { range: newRange }) as unknown as MayoresSheet[];
-
-  aux.forEach((element: MayoresSheet) => {
-    res.push(
-      {
-        edad: element['Edad (años)'],
-        peso: element['Peso (Kg)'],
-        talla: element['Talla (cm)'],
-      },
-    );
-  });
-  return res;
-};
-
-const parseBabies = (worksheet: XLSX.WorkSheet): Menores[] => {
-  const res: Menores[] = [];
-  const aux = XLSX.utils.sheet_to_json(worksheet) as unknown as MenoresSheet[];
-  aux.forEach((element: MenoresSheet) => {
-    res.push(
-      {
-        edad: element['Edad (meses)'],
-        peso: element['Peso (Kg)'],
-      },
-    );
-  });
-  return res;
-};
-
-/* EXPORT FUNCTIONS */
-
-const parseSheetService = (data: Buffer): SheetParserResponse => {
-  const workbook: XLSX.WorkBook = XLSX.read(data);
-  let parsed: SheetParserResponse = null;
-  let hombresMenores: Menores[] = [];
-  let hombres: Mayores[] = [];
-  let mujeresMenores: Menores[] = [];
-  let mujeres: Mayores[] = [];
-
-  const sheetNames: string[] = workbook.SheetNames;
-  // Check there are 4 sheets, no more, no less
-  if (sheetNames.length !== 4) {
-    throw new Error('File does not respect scheme, there are more or less than 4 sheets');
-  }
-  sheetNames.forEach((name) => {
-    const worksheet: XLSX.WorkSheet = workbook.Sheets[name];
-    switch (name) {
-      case SheetNames.HOMBRES_MENORES:
-        hombresMenores = parseBabies(worksheet);
-        break;
-      case SheetNames.HOMBRES:
-        hombres = parseAdults(worksheet);
-        break;
-      case SheetNames.MUJERES_MENORES:
-        mujeresMenores = parseBabies(worksheet);
-        break;
-      case SheetNames.MUJERES:
-        mujeres = parseAdults(worksheet);
-        break;
-
-      default:
-        throw new Error(`Sheet name ${name} is not part of the scheme `);
-    }
-  });
-  parsed = {
-    hombresMenores,
-    hombres,
-    mujeresMenores,
-    mujeres,
-  };
-
-  return parsed;
-  // TODO: depends on sheet layout what to do
-};
-
-export default {
-  parseSheetService,
-};
+import * as XLSX from 'xlsx';
+import { SheetNames } from '../Config/Constants';
+import {
+  SheetParserResponse, Menores, Mayores, MenoresSheet, MayoresSheet,
+} from '../Models/SheetParserResponse';
+
+/* PRIVATE FUNCTIONS */
+// const ec = (r: number, c: number): string => XLSX.utils.encode_cell({ r, c });
+// const deleteRow = (ws: XLSX.WorkSheet, rowIndex: number): XLSX.WorkSheet => {
+//   const work = ws;
+//   if (work['!ref'] === undefined) throw new Error('An error has ocurred in deleteRow');
+//   const variable = XLSX.utils.decode_range(work['!ref']);
+//   for (let R = rowIndex; R < variable.e.r; R += 1) {
+//     for (let C = variable.s.c; C <= variable.e.c; C += 1) {
+//       work[ec(R, C)] = work[ec(R + 1, C)];
+//     }
+//   }
+//   variable.e.r -= 1;
+//   work['!ref'] = XLSX.utils.encode_range(variable.s, variable.e);
+//   return work;
+// };
+
+const parseAdults = (worksheet: XLSX.WorkSheet): Mayores[] => {
+  const res: Mayores[] = [];
+  const ref = worksheet['!ref'];
+  if (ref === undefined) throw new Error('An error ocurred');
+  const range = XLSX.utils.decode_range(ref);
+  range.s.c = 0;
+  range.e.c = 2;
+  const newRange = XLSX.utils.encode_range(range);
+
+  const aux = XLSX.utils.sheet_to_json(worksheet, { range: newRange }) as unknown as MayoresSheet[];
+
+  aux.forEach((element: MayoresSheet) => {
+    res.push(
+      {
+        edad: element['Edad (años)'],
+        peso: element['Peso (Kg)'],
+        talla: element['Talla (cm)'],
+      },
+    );
+  });
+  return res;
+};
+
+const parseBabies = (worksheet: XLSX.WorkSheet): Menores[] => {
+  const res: Menores[] = [];
+  const aux = XLSX.utils.sheet_to_json(worksheet) as unknown as MenoresSheet[];
+  aux.forEach((element: MenoresSheet) => {
+    res.push(
+      {
+        edad: element['Edad (meses)'],
+        peso: element['Peso (Kg)'],
+      },
+    );
+  });
+  return res;
+};
+
+/* EXPORT FUNCTIONS */
+
+const parseSheetService = (data: Buffer): SheetParserResponse => {
+  const workbook: XLSX.WorkBook = XLSX.read(data);
+  let parsed: SheetParserResponse = null;
+  let hombresMenores: Menores[] = [];
+  let hombres: Mayores[] = [];
+  let mujeresMenores: Menores[] = [];
+  let mujeres: Mayores[] = [];
+
+  const sheetNames: string[] = workbook.SheetNames;
+  // Check there are 4 sheets, no more, no less
+  if (sheetNames.length !== 4) {
+    throw new Error('File does not respect scheme, there are more or less than 4 sheets');
+  }
+  sheetNames.forEach((name) => {
+    const worksheet: XLSX.WorkSheet = workbook.Sheets[name];
+    switch (name) {
+      case SheetNames.HOMBRES_MENORES:
+        hombresMenores = parseBabies(worksheet);
+        break;
+      case SheetNames.HOMBRES:
+        hombres = parseAdults(worksheet);
+        break;
+      case SheetNames.MUJERES_MENORES:
+        mujeresMenores = parseBabies(worksheet);
+        break;
+      case SheetNames.MUJERES:
+        mujeres = parseAdults(worksheet);
+        break;
+
+      default:
+        throw new Error(`Sheet name ${name} is not part of the scheme `);
+    }
+  });
+  parsed = {
+    hombresMenores,
+    hombres,
+    mujeresMenores,
+    mujeres,
+  };
+
+  return parsed;
+  // TODO: depends on sheet layout what to do
+};
+
+export default {
+  parseSheetService,
+};
diff --git a/src/index.ts b/src/index.ts
index 30dad1b..6198782 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -1,39 +1,39 @@
-/* eslint-disable no-console */
-import express, { Application } from 'express';
-import 'dotenv/config';
-import cors from 'cors';
-import swaggerUi from 'swagger-ui-express';
-import helmet from 'helmet';
-import YAML from 'yamljs';
-import Routes from './routes';
-import logger from './Logger/logger';
-
-const app: Application = express();
-const PORT = process.env.PORT || 8000;
-app.use(helmet.hidePoweredBy());
-// swagger init
-const swaggerDocument = YAML.load('./swagger.yaml');
-// middlewares
-app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(swaggerDocument));
-
-app.use(express.json({
-  limit: '50mb',
-}));
-app.use(express.urlencoded({ extended: false }));
-app.use(cors({
-  origin: '*',
-  methods: 'GET,HEAD,PUT,PATCH,POST,DELETE',
-  preflightContinue: false,
-  optionsSuccessStatus: 204,
-}));
-
-app.use(express.raw({
-  limit: '50mb',
-}));
-
-app.use(Routes);
-
-app.listen(PORT, (): void => {
-  console.log(`REPP Backend running here 👉 https://localhost:${PORT}`);
-  logger.info('Server initiated');
-});
+/* eslint-disable no-console */
+import express, { Application } from 'express';
+import 'dotenv/config';
+import cors from 'cors';
+import swaggerUi from 'swagger-ui-express';
+import helmet from 'helmet';
+import YAML from 'yamljs';
+import Routes from './routes';
+import logger from './Logger/logger';
+
+const app: Application = express();
+const PORT = process.env.PORT || 8000;
+app.use(helmet.hidePoweredBy());
+// swagger init
+const swaggerDocument = YAML.load('./swagger.yaml');
+// middlewares
+app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(swaggerDocument));
+
+app.use(express.json({
+  limit: '50mb',
+}));
+app.use(express.urlencoded({ extended: false }));
+app.use(cors({
+  origin: '*',
+  methods: 'GET,HEAD,PUT,PATCH,POST,DELETE',
+  preflightContinue: false,
+  optionsSuccessStatus: 204,
+}));
+
+app.use(express.raw({
+  limit: '50mb',
+}));
+
+app.use(Routes);
+
+app.listen(PORT, (): void => {
+  console.log(`REPP Backend running here 👉 https://localhost:${PORT}`);
+  logger.info('Server initiated');
+});
diff --git a/swagger.yaml b/swagger.yaml
index b424dc7..a531d9d 100644
--- a/swagger.yaml
+++ b/swagger.yaml
@@ -44,6 +44,23 @@ paths:
           description: Ok.
       security:
         - BearerAuth: []
+
+  /repCalculator:
+      post:
+        tags:
+          - Calculation
+      summary: Given population data calculates its energetic requirement
+      requestBody:
+        content: 
+          application/json:
+            schema:
+              $ref: '#/components/schemas/AgeGroupJSON'
+        required: true
+      responses:
+        '200':
+          description: Ok.
+      security:
+        - BearerAuth: []
 components:
   securitySchemes:
     BearerAuth:
@@ -88,3 +105,13 @@ components:
           type: string
         pass:
           type: string
+    AgeGroupJSON:
+      properties:
+        edad:
+          type: string
+        sexo:
+          type: string
+        pesoMediano:
+          type: string
+        cantidad:
+          type: string
\ No newline at end of file
-- 
GitLab