backend/server/routes/reports/localAuthorityReport/user.js
File `user.js` has 1148 lines of code (exceeds 250 allowed). Consider refactoring.// Local Authority user's report'use strict'; //external node modulesconst moment = require('moment');const fs = require('fs');const walk = require('walk');const JsZip = new require('jszip');const path = require('path');const cheerio = require('cheerio');const express = require('express');const router = express.Router(); //Constants string needed by this file in several placesconst folderName = 'template';const workplacesSheetName = path.join('xl', 'worksheets', 'sheet1.xml');const staffRecordsSheetName = path.join('xl', 'worksheets', 'sheet2.xml');const sharedStringsName = path.join('xl', 'sharedStrings.xml');const isNumberRegex = /^[0-9]+(\.[0-9]+)?$/; const reportLock = require('../../../utils/fileLock');//XML DOM manipulation helper functionsconst parseXML = (fileContent) => cheerio.load(fileContent, { xml: { normalizeWhitespace: true, }, }); //helper function to set a spreadsheet cell's valueconst putStringTemplate = (sheetDoc, stringsDoc, sst, sharedStringsUniqueCount, element, value) => { let vTag = element.children('v').first(); const hasVTag = element.children('v').length; const textValue = String(value); const isNumber = isNumberRegex.test(textValue); Identical blocks of code found in 2 locations. Consider refactoring. if (!hasVTag) { vTag = sheetDoc('<v></v>'); vTag.text(sharedStringsUniqueCount[0]); element.append(vTag); } else { vTag.text(sharedStringsUniqueCount[0]); } Identical blocks of code found in 2 locations. Consider refactoring. if (isNumber) { element.attr('t', ''); vTag.text(textValue); } else { element.attr('t', 's'); const si = stringsDoc('<si></si>'); const t = stringsDoc('<t></t>'); t.text(textValue); sst.append(si); si.append(t); sharedStringsUniqueCount[0] += 1; }}; // for databaseconst models = require('../../../models'); // for establishment entityconst Establishment = require('../../../models/classes/establishment').Establishment; // identifies the associated local authority of the establishment - code taken from establishment::restoreconst identifyLocalAuthority = async (postcode) => { // need to identify which, if any, of the shared authorities is attributed to the // primary Authority; that is the Local Authority associated with the physical area // of the given Establishment (using the postcode as the key) // lookup primary authority by trying to resolve on specific postcode code // We use the postcode to get local custodian code // and use this to get the Cssr record const cssrResults = await models.pcodedata.getLinkedCssrRecordsFromPostcode(postcode); if (cssrResults && !(cssrResults === undefined || cssrResults === null)) { return cssrResults[0].cssrRecord.name; } //Couldn't get local authority name. Just leave it blank? return '';}; const LAReport = {Function `run` has 58 lines of code (exceeds 25 allowed). Consider refactoring. run: async (date, thisEstablishment, fromDate, toDate) => { // for the report const establishmentId = thisEstablishment.id; // first run the report, which means running the `cqc.localAuthorityReport` function. // this function runs in a single transaction // the function returns true or false; encapsulating any SQL exceptions. const params = { replacements: { givenEstablishmentId: establishmentId, givenFromDate: fromDate, givenToDate: toDate, }, type: models.sequelize.QueryTypes.SELECT, }; const runReport = await models.sequelize.query( 'select cqc.localAuthorityReport(:givenEstablishmentId, :givenFromDate, :givenToDate);', params, ); // if report fails return no data if (!runReport || String(runReport[0].localauthorityreport) !== 'true') { return null; } //Construct the model data object for the report const reportData = { date: date.toISOString(), reportEstablishment: { name: thisEstablishment.name, nmdsId: thisEstablishment.nmdsId, localAuthority: await identifyLocalAuthority(thisEstablishment.postcode), }, establishments: [], workers: [], }; // now grab the establishments and format the report data const reportEstablishments = await models.localAuthorityReportEstablishment.findAll({ where: { establishmentFk: establishmentId, }, order: [['workplaceName', 'ASC']], }); if (reportEstablishments && Array.isArray(reportEstablishments)) { reportEstablishments.forEach(async (est) => { const establishmentDetails = await models.establishment.findOne({ where: { id: est.workplaceFk, }, attributes: ['id', 'ustatus'], }); if (establishmentDetails && establishmentDetails.ustatus !== 'PENDING') { reportData.establishments.push(est); } }); } // now grab the workers and format the report data const reportWorkers = await models.localAuthorityReportWorker.findAll({ where: { establishmentFk: establishmentId, }, order: [ ['workplaceName', 'ASC'], ['localId', 'ASC'], ], }); if (reportWorkers && Array.isArray(reportWorkers)) { reportData.workers = reportWorkers; } return reportData; },}; const styleLookup = {Similar blocks of code found in 2 locations. Consider refactoring. BLACK: { ESTFIRST: { A: 15, B: 16, C: 17, D: 16, E: 16, F: 16, G: 16, H: 18, I: 18, J: 16, K: 16, L: 16, M: 16, N: 16, O: 16, P: 17, Q: 16, R: 19, S: 18, T: 16, U: 20, V: 21, W: 22, X: 23, }, ESTLAST: { A: 30, B: 31, C: 32, D: 33, E: 31, F: 31, G: 31, H: 37, I: 37, J: 31, K: 31, L: 31, M: 31, N: 31, O: 31, P: 32, Q: 31, R: 36, S: 37, T: 31, U: 38, V: 39, W: 40, X: 38, }, ESTREGULAR: { A: 24, B: 8, C: 9, D: 8, E: 8, F: 8, G: 8, H: 10, I: 10, J: 8, K: 8, L: 8, M: 8, N: 8, O: 8, P: 9, Q: 8, R: 11, S: 10, T: 8, U: 11, V: 13, W: 14, X: 67, }, ESTTOTAL: { A: 7, B: 8, C: 9, D: 8, E: 8, F: 8, G: 8, H: 10, I: 10, J: 8, K: 8, L: 8, M: 8, N: 8, O: 8, P: 9, Q: 8, R: 11, S: 10, T: 8, U: 67, V: 13, W: 14, X: 67, }, WORKERREGULAR: { A: 24, B: 8, C: 8, D: 8, E: 8, F: 8, G: 8, H: 8, I: 8, J: 10, K: 10, L: 8, M: 42, N: 8, O: 8, P: 8, Q: 8, R: 57, }, WORKERLAST: { A: 30, B: 31, C: 31, D: 31, E: 31, F: 31, G: 31, H: 31, I: 31, J: 37, K: 37, L: 31, M: 44, N: 31, O: 31, P: 31, Q: 31, R: 56, }, },Similar blocks of code found in 2 locations. Consider refactoring. RED: { ESTFIRST: { A: 58, B: 59, C: 60, D: 59, E: 59, F: 59, G: 59, H: 61, I: 61, J: 59, K: 59, L: 59, M: 59, N: 59, O: 59, P: 60, Q: 59, R: 62, S: 61, T: 59, U: 63, V: 64, W: 65, X: 66, }, ESTLAST: { A: 30, B: 34, C: 70, D: 33, E: 34, F: 34, G: 34, H: 35, I: 35, J: 34, K: 34, L: 34, M: 34, N: 34, O: 34, P: 70, Q: 34, R: 68, S: 35, T: 34, U: 41, V: 34, W: 35, X: 41, }, ESTREGULAR: { A: 26, B: 26, C: 25, D: 26, E: 26, F: 26, G: 26, H: 27, I: 27, J: 26, K: 26, L: 26, M: 26, N: 26, O: 26, P: 25, Q: 26, R: 29, S: 27, T: 26, U: 12, V: 26, W: 27, X: 12, }, ESTTOTAL: { A: 7, B: 8, C: 9, D: 8, E: 8, F: 8, G: 8, H: 10, I: 10, J: 26, K: 26, L: 26, M: 26, N: 26, O: 26, P: 25, Q: 26, R: 29, S: 27, T: 26, U: 12, V: 26, W: 27, X: 12, }, WORKERREGULAR: { A: 24, B: 26, C: 26, D: 26, E: 26, F: 26, G: 26, H: 26, I: 26, J: 27, K: 27, L: 26, M: 27, N: 26, O: 26, P: 26, Q: 26, R: 25, }, WORKERLAST: { A: 30, B: 34, C: 34, D: 34, E: 34, F: 34, G: 34, H: 34, I: 34, J: 55, K: 55, L: 34, M: 55, N: 34, O: 34, P: 34, Q: 34, R: 70, }, },}; Identical blocks of code found in 2 locations. Consider refactoring.const setStyle = (cellToChange, columnText, rowType, isRed) => { cellToChange.attr('s', styleLookup[isRed ? 'RED' : 'BLACK'][rowType][columnText]);}; const basicValidationUpdate = (putString, cellToChange, value, columnText, rowType) => { let isRed = false; if (!isNumberRegex.test(String(value))) { value = 'Missing'; isRed = true; } putString(cellToChange, value); setStyle(cellToChange, columnText, rowType, isRed);}; Function `updateWorkplacesSheet` has 395 lines of code (exceeds 25 allowed). Consider refactoring.
Function `updateWorkplacesSheet` has a Cognitive Complexity of 77 (exceeds 5 allowed). Consider refactoring.const updateWorkplacesSheet = ( workplacesSheet, reportData, sharedStrings, sst, sharedStringsUniqueCount, fromDate, toDate,) => { const putString = putStringTemplate.bind(null, workplacesSheet, sharedStrings, sst, sharedStringsUniqueCount); //set headers putString(workplacesSheet("c[r='B5']"), moment(reportData.date).format('DD/MM/YYYY')); putString(workplacesSheet("c[r='B6']"), reportData.reportEstablishment.localAuthority); putString(workplacesSheet("c[r='B7']"), reportData.reportEstablishment.name); // clone the row the apropriate number of times const templateRow = workplacesSheet("row[r='13']"); let currentRow = templateRow; let rowIndex = 14; Similar blocks of code found in 2 locations. Consider refactoring. if (reportData.establishments.length > 1) { for (let i = 0; i < reportData.establishments.length - 1; i++) { const tempRow = templateRow.clone(true); tempRow.attr('r', rowIndex); tempRow.children('c').each((index, elem) => { workplacesSheet(elem).attr('r', String(workplacesSheet(elem).attr('r')).replace(/\d+$/, '') + rowIndex); }); currentRow.after(tempRow); currentRow = tempRow; rowIndex++; } currentRow = templateRow; } else if (reportData.establishments.length === 0) { templateRow.remove(); rowIndex = 13; } //fix the last row in the table workplacesSheet('sheetData row:last-child').attr('r', rowIndex); //fix the dimensions tag value const dimension = workplacesSheet('dimension'); dimension.attr('ref', String(dimension.attr('ref')).replace(/\d+$/, '') + rowIndex); //keep track of the totals for later const totals = { numberOfVacancies: 0, numberOfLeavers: 0, numberOfStarters: 0, numberOfStaffRecords: 0, numberOfIndividualStaffRecords: 0, numberOfStaffRecordsNotAgency: 0, numberOfCompleteStaffNotAgency: 0, numberOfAgencyStaffRecords: 0, numberOfCompleteAgencyStaffRecords: 0, workplaceComplete: true, }; //update the cell values for (let row = 0; row < reportData.establishments.length; row++) { const rowType = row === 0 ? 'ESTFIRST' : row === reportData.establishments.length - 1 ? 'ESTLAST' : 'ESTREGULAR'; for (let column = 0; column < 24; column++) { const columnText = String.fromCharCode(column + 65); let isRed = false; const cellToChange = currentRow.children(`c[r='${columnText}${row + 13}']`); switch (columnText) { case 'A': { putString(cellToChange, reportData.establishments[row].workplaceName); setStyle(cellToChange, columnText, rowType, isRed); } break; case 'B': { putString(cellToChange, reportData.establishments[row].workplaceId); setStyle(cellToChange, columnText, rowType, isRed); } break; case 'C': { putString(cellToChange, moment(reportData.establishments[row].lastUpdated).format('DD/MM/YYYY')); Similar blocks of code found in 2 locations. Consider refactoring. if ( !moment(reportData.establishments[row].lastUpdated).isBetween( moment(fromDate).subtract(1, 'd'), moment(toDate).add(1, 'd'), ) ) { isRed = true; } setStyle(cellToChange, columnText, rowType, isRed); } break; case 'E': { putString(cellToChange, reportData.establishments[row].establishmentType); if (!String(reportData.establishments[row].establishmentType).toLowerCase().includes('local authority')) { isRed = true; } setStyle(cellToChange, columnText, rowType, isRed); } break; case 'F': { putString(cellToChange, reportData.establishments[row].mainService); setStyle(cellToChange, columnText, rowType, isRed); } break; Similar blocks of code found in 3 locations. Consider refactoring. case 'G': { putString(cellToChange, reportData.establishments[row].serviceUserGroups); if (reportData.establishments[row].serviceUserGroups === 'Missing') { isRed = true; } setStyle(cellToChange, columnText, rowType, isRed); } break; Similar blocks of code found in 3 locations. Consider refactoring. case 'H': { putString(cellToChange, reportData.establishments[row].capacityOfMainService); if (reportData.establishments[row].capacityOfMainService === 'Missing') { isRed = true; } setStyle(cellToChange, columnText, rowType, isRed); } break; Similar blocks of code found in 3 locations. Consider refactoring. case 'I': { putString(cellToChange, reportData.establishments[row].utilisationOfMainService); if (reportData.establishments[row].utilisationOfMainService === 'Missing') { isRed = true; } setStyle(cellToChange, columnText, rowType, isRed); } break; Similar blocks of code found in 9 locations. Consider refactoring. case 'J': { basicValidationUpdate( putString, cellToChange, reportData.establishments[row].numberOfVacancies, columnText, rowType, ); totals.numberOfVacancies += parseInt(reportData.establishments[row].numberOfVacancies, 10) || 0; } break; Similar blocks of code found in 9 locations. Consider refactoring. case 'K': { basicValidationUpdate( putString, cellToChange, reportData.establishments[row].numberOfLeavers, columnText, rowType, ); totals.numberOfLeavers += parseInt(reportData.establishments[row].numberOfLeavers, 10) || 0; } break; Similar blocks of code found in 9 locations. Consider refactoring. case 'L': { basicValidationUpdate( putString, cellToChange, reportData.establishments[row].numberOfStarters, columnText, rowType, ); totals.numberOfStarters += parseInt(reportData.establishments[row].numberOfStarters, 10) || 0; } break; Similar blocks of code found in 9 locations. Consider refactoring. case 'M': { basicValidationUpdate( putString, cellToChange, reportData.establishments[row].numberOfStaffRecords, columnText, rowType, ); totals.numberOfStaffRecords += parseInt(reportData.establishments[row].numberOfStaffRecords, 10) || 0; } break; case 'N': case 'O': { putString(cellToChange, ''); setStyle(cellToChange, columnText, rowType, false); } break; case 'P': { putString(cellToChange, reportData.establishments[row].workplaceComplete ? 'Yes' : 'No'); if (!reportData.establishments[row].workplaceComplete) { isRed = true; totals.workplaceComplete = false; } setStyle(cellToChange, columnText, rowType, isRed); } break; Similar blocks of code found in 9 locations. Consider refactoring. case 'Q': { basicValidationUpdate( putString, cellToChange, reportData.establishments[row].numberOfIndividualStaffRecords, columnText, rowType, ); totals.numberOfIndividualStaffRecords += parseInt(reportData.establishments[row].numberOfIndividualStaffRecords, 10) || 0; } break; Similar blocks of code found in 3 locations. Consider refactoring. case 'R': { let value = reportData.establishments[row].percentageOfStaffRecords; if (!isNumberRegex.test(String(value))) { value = 'Missing'; } putString(cellToChange, value); if (value === 'Missing' || value < 90 || value > 100) { isRed = true; } setStyle(cellToChange, columnText, rowType, isRed); } break; Similar blocks of code found in 9 locations. Consider refactoring. case 'S': { basicValidationUpdate( putString, cellToChange, reportData.establishments[row].numberOfStaffRecordsNotAgency, columnText, rowType, ); totals.numberOfStaffRecordsNotAgency += parseInt(reportData.establishments[row].numberOfStaffRecordsNotAgency, 10) || 0; } break; Similar blocks of code found in 9 locations. Consider refactoring. case 'T': { basicValidationUpdate( putString, cellToChange, reportData.establishments[row].numberOfCompleteStaffNotAgency, columnText, rowType, ); totals.numberOfCompleteStaffNotAgency += parseInt(reportData.establishments[row].numberOfCompleteStaffNotAgency, 10) || 0; } break; Similar blocks of code found in 3 locations. Consider refactoring. case 'U': { let value = reportData.establishments[row].percentageOfCompleteStaffRecords; if (!isNumberRegex.test(String(value))) { value = 'Missing'; } putString(cellToChange, value); if (value === 'Missing' || value < 90 || value > 100) { isRed = true; } setStyle(cellToChange, columnText, rowType, isRed); } break; Similar blocks of code found in 9 locations. Consider refactoring. case 'V': { basicValidationUpdate( putString, cellToChange, reportData.establishments[row].numberOfAgencyStaffRecords, columnText, rowType, ); totals.numberOfAgencyStaffRecords += parseInt(reportData.establishments[row].numberOfAgencyStaffRecords, 10) || 0; } break; Similar blocks of code found in 9 locations. Consider refactoring. case 'W': { basicValidationUpdate( putString, cellToChange, reportData.establishments[row].numberOfCompleteAgencyStaffRecords, columnText, rowType, ); totals.numberOfCompleteAgencyStaffRecords += parseInt(reportData.establishments[row].numberOfCompleteAgencyStaffRecords, 10) || 0; } break; Similar blocks of code found in 3 locations. Consider refactoring. case 'X': { let value = reportData.establishments[row].percentageOfCompleteAgencyStaffRecords; if (!isNumberRegex.test(String(value))) { value = 'Missing'; } putString(cellToChange, value); if (value === 'Missing' || value < 90 || value > 100) { isRed = true; } setStyle(cellToChange, columnText, rowType, isRed); } break; } } currentRow = currentRow.next(); } //update totals const rowType = 'ESTTOTAL'; for (let column = 0; column < 24; column++) { const columnText = String.fromCharCode(column + 65); const cellToChange = workplacesSheet(`c[r='${columnText}12']`); switch (columnText) { case 'J': { basicValidationUpdate(putString, cellToChange, totals.numberOfVacancies, columnText, rowType); } break; case 'K': { basicValidationUpdate(putString, cellToChange, totals.numberOfLeavers, columnText, rowType); } break; case 'L': { basicValidationUpdate(putString, cellToChange, totals.numberOfStarters, columnText, rowType); } break; case 'M': { basicValidationUpdate(putString, cellToChange, totals.numberOfStaffRecords, columnText, rowType); } break; case 'N': case 'O': { putString(cellToChange, ''); setStyle(cellToChange, columnText, rowType, false); } break; case 'P': { let isRed = false; putString(cellToChange, totals.workplaceComplete ? 'Yes' : 'No'); if (!totals.workplaceComplete) { isRed = true; } setStyle(cellToChange, columnText, rowType, isRed); } break; case 'Q': { basicValidationUpdate(putString, cellToChange, totals.numberOfIndividualStaffRecords, columnText, rowType); } break; case 'R': { basicValidationUpdate( putString, cellToChange, (totals.numberOfIndividualStaffRecords / totals.numberOfStaffRecords) * 100, columnText, rowType, ); } break; case 'S': { basicValidationUpdate(putString, cellToChange, totals.numberOfStaffRecordsNotAgency, columnText, rowType); } break; case 'T': { basicValidationUpdate(putString, cellToChange, totals.numberOfCompleteStaffNotAgency, columnText, rowType); } break; case 'U': { basicValidationUpdate( putString, cellToChange, (totals.numberOfCompleteStaffNotAgency / totals.numberOfStaffRecordsNotAgency) * 100, columnText, rowType, ); } break; case 'V': { basicValidationUpdate(putString, cellToChange, totals.numberOfAgencyStaffRecords, columnText, rowType); } break; case 'W': { basicValidationUpdate( putString, cellToChange, totals.numberOfCompleteAgencyStaffRecords, columnText, rowType, ); } break; case 'X': { basicValidationUpdate( putString, cellToChange, (totals.numberOfCompleteAgencyStaffRecords / totals.numberOfAgencyStaffRecords) * 100, columnText, rowType, ); } break; } } return workplacesSheet;}; Function `redIifMissing` has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring.const redIifMissing = (putString, cellToChange, value, columnText, rowType, columnObj = {}) => { let isRed = false; if (String(value) === 'Missing') { isRed = true; } if (Object.keys(columnObj).length !== 0) { let currentRowObj = columnObj.reportObj[columnObj.index]; if (currentRowObj.employmentStatus === 'Pool/Bank' || currentRowObj.employmentStatus === 'Agency') { if (currentRowObj.sickDays === 'Missing') { isRed = false; } } } putString(cellToChange, value); setStyle(cellToChange, columnText, rowType, isRed);}; Function `updateStaffRecordsSheet` has 168 lines of code (exceeds 25 allowed). Consider refactoring.
Function `updateStaffRecordsSheet` has a Cognitive Complexity of 28 (exceeds 5 allowed). Consider refactoring.const updateStaffRecordsSheet = ( staffRecordsSheet, reportData, sharedStrings, sst, sharedStringsUniqueCount, fromDate, toDate,) => { const putString = putStringTemplate.bind(null, staffRecordsSheet, sharedStrings, sst, sharedStringsUniqueCount); putString(staffRecordsSheet("c[r='B5']"), moment(reportData.date).format('DD/MM/YYYY')); putString(staffRecordsSheet("c[r='B6']"), reportData.reportEstablishment.localAuthority); putString(staffRecordsSheet("c[r='B7']"), reportData.reportEstablishment.name); // clone the row the apropriate number of times const templateRow = staffRecordsSheet("row[r='11']"); let currentRow = templateRow; let rowIndex = 12; Similar blocks of code found in 2 locations. Consider refactoring. if (reportData.workers.length > 1) { for (let i = 0; i < reportData.workers.length - 1; i++) { const tempRow = templateRow.clone(true); tempRow.attr('r', rowIndex); tempRow.children('c').each((index, elem) => { staffRecordsSheet(elem).attr('r', String(staffRecordsSheet(elem).attr('r')).replace(/\d+$/, '') + rowIndex); }); currentRow.after(tempRow); currentRow = tempRow; rowIndex++; } currentRow = templateRow; } else if (reportData.workers.length === 0) { templateRow.remove(); rowIndex = 11; } //fix the last row in the table staffRecordsSheet('sheetData row:last-child').attr('r', rowIndex); //fix the dimensions tag value const dimension = staffRecordsSheet('dimension'); dimension.attr('ref', String(dimension.attr('ref')).replace(/\d+$/, '') + rowIndex); //update the cell values for (let row = 0; row < reportData.workers.length; row++) { const rowType = row === reportData.workers.length - 1 ? 'WORKERLAST' : 'WORKERREGULAR'; for (let column = 0; column < 18; column++) { const columnText = String.fromCharCode(column + 65); const cellToChange = currentRow.children(`c[r='${columnText}${row + 11}']`); switch (columnText) { case 'A': { redIifMissing(putString, cellToChange, reportData.workers[row].localId, columnText, rowType); } break; case 'B': { redIifMissing(putString, cellToChange, reportData.workers[row].workplaceName, columnText, rowType); } break; case 'D': { redIifMissing(putString, cellToChange, reportData.workers[row].workplaceId, columnText, rowType); } break; case 'E': { redIifMissing(putString, cellToChange, reportData.workers[row].gender, columnText, rowType); } break; case 'F': { redIifMissing(putString, cellToChange, reportData.workers[row].dateOfBirth, columnText, rowType); } break; case 'G': { redIifMissing(putString, cellToChange, reportData.workers[row].ethnicity, columnText, rowType); } break; case 'H': { redIifMissing(putString, cellToChange, reportData.workers[row].mainJob, columnText, rowType); } break; case 'I': { redIifMissing(putString, cellToChange, reportData.workers[row].employmentStatus, columnText, rowType); } break; case 'J': { redIifMissing(putString, cellToChange, reportData.workers[row].contractedAverageHours, columnText, rowType); } break; case 'K': { redIifMissing(putString, cellToChange, reportData.workers[row].sickDays, columnText, rowType, { reportObj: reportData.workers, index: row, }); } break; case 'L': { redIifMissing(putString, cellToChange, reportData.workers[row].payInterval, columnText, rowType); } break; case 'M': { redIifMissing(putString, cellToChange, reportData.workers[row].rateOfPay, columnText, rowType); } break; case 'N': { let isRed = false; let value = String(reportData.workers[row].relevantSocialCareQualification); switch (value.toLowerCase()) { case 'must be yes': { isRed = true; value = 'No'; } break; case 'missing': { isRed = true; } break; } putString(cellToChange, value); setStyle(cellToChange, columnText, rowType, isRed); } break; case 'O': { redIifMissing( putString, cellToChange, reportData.workers[row].highestSocialCareQualification, columnText, rowType, ); } break; case 'P': { redIifMissing( putString, cellToChange, reportData.workers[row].nonSocialCareQualification, columnText, rowType, ); } break; case 'Q': { let isRed = false; putString(cellToChange, moment(reportData.workers[row].lastUpdated).format('DD/MM/YYYY')); Similar blocks of code found in 2 locations. Consider refactoring. if ( !moment(reportData.workers[row].lastUpdated).isBetween( moment(fromDate).subtract(1, 'd'), moment(toDate).add(1, 'd'), ) ) { isRed = true; } setStyle(cellToChange, columnText, rowType, isRed); } break; case 'R': { let isRed = false; putString(cellToChange, reportData.workers[row].staffRecordComplete ? 'Yes' : 'No'); if (!reportData.workers[row].staffRecordComplete) { isRed = true; } setStyle(cellToChange, columnText, rowType, isRed); } break; } } currentRow = currentRow.next(); } return staffRecordsSheet;}; Function `getReport` has 86 lines of code (exceeds 25 allowed). Consider refactoring.const getReport = async (date, thisEstablishment) => { const laReturnStartDate = await models.AdminSettings.getValue('laReturnStartDate'); const laReturnEndDate = await models.AdminSettings.getValue('laReturnEndDate'); const fromDate = new Date(laReturnStartDate.Data.value); const toDate = new Date(laReturnEndDate.Data.value); let reportData = await LAReport.run(date, thisEstablishment, fromDate, toDate); if (reportData === null) { return null; } return new Promise((resolve) => { const thePath = path.join(__dirname, folderName); const walker = walk.walk(thePath); const outputZip = new JsZip(); let workplacesSheet, staffRecordsSheet, sharedStrings; walker.on('file', (root, fileStats, next) => { const pathName = root.replace(thePath, '').replace('\\', '/').replace(/^\//, ''); const zipPath = pathName === '' ? fileStats.name : path.join(pathName, fileStats.name); const readPath = path.join(thePath, zipPath); fs.readFile(`${readPath}`, (err, fileContent) => { if (!err) { switch (zipPath) { case workplacesSheetName: { workplacesSheet = parseXML(fileContent); } break; case staffRecordsSheetName: { staffRecordsSheet = parseXML(fileContent); } break; case sharedStringsName: { sharedStrings = parseXML(fileContent); } break; default: { outputZip.file(zipPath, fileContent); } break; } } next(); }); }); walker.on('end', () => { if (sharedStrings) { const sst = sharedStrings('sst'); const sharedStringsUniqueCount = [parseInt(sst.attr('uniqueCount'), 10)]; const sharedStringsCount = [parseInt(sst.attr('count'), 10)]; //update the workplaces sheet with the report data and add it to the zip outputZip.file( workplacesSheetName, updateWorkplacesSheet( workplacesSheet, reportData, sharedStrings, sst, sharedStringsUniqueCount, //pass unique count by reference rather than by value fromDate, toDate, ).xml(), ); //update the staff records sheet with the report data and add it to the zip outputZip.file( staffRecordsSheetName, updateStaffRecordsSheet( staffRecordsSheet, reportData, sharedStrings, sst, sharedStringsUniqueCount, //pass unique count by reference rather than by value fromDate, toDate, ).xml(), ); //update the shared strings counts we've been keeping track of sst.attr('uniqueCount', sharedStringsUniqueCount[0]); sst.attr('count', sharedStringsCount[0]); //add the updated shared strings to the zip outputZip.file(sharedStringsName, sharedStrings.xml()); } resolve(outputZip); }); }).then((outputZip) => outputZip.generateAsync({ type: 'nodebuffer', compression: 'DEFLATE', }), );}; // gets report// NOTE - the Local Authority report is driven mainly by pgsql (postgres functions) and therefore does not// pass through the Establishment/Worker entities. This is done for performance, as these reports// are expected to operate across large sets of data Function `reportGet` has a Cognitive Complexity of 11 (exceeds 5 allowed). Consider refactoring.
Function `reportGet` has 30 lines of code (exceeds 25 allowed). Consider refactoring.const reportGet = async (req, res) => { try { // first ensure this report can only be ran by those establishments with a Local Authority employer type const thisEstablishment = new Establishment(req.username); if (await thisEstablishment.restore(req.establishment.id, false)) { const theEmployerType = thisEstablishment.employerType; if (theEmployerType && theEmployerType.value.startsWith('Local Authority')) { const date = new Date(); const report = await getReport(date, thisEstablishment); if (report) {Similar blocks of code found in 2 locations. Consider refactoring. await reportLock.saveResponse(req, res, 200, report, { 'Content-Type': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', 'Content-disposition': `attachment; filename=${moment(date).format( 'YYYY-MM-DD', )}-SFC-Local-Authority-Report.xlsx`, }); } else { // only allow on those establishments being a parent console.error('report/localAuthority/user 500 response'); await reportLock.saveResponse(req, res, 500, {}); } } else { console.error('report/localAuthority/user 403 response'); await reportLock.saveResponse(req, res, 403, {}); } } else { // only allow on those establishments being a local authority console.error('report/localAuthority/user - failed restoring establishment'); await reportLock.saveResponse(req, res, 500, {}); } } catch (err) { console.error('report/localAuthority/user - failed', err); return res.status(500).send('ERR: Failed to retrieve report'); }}; router.route('/report').get(reportLock.acquireLock.bind(null, 'la', reportGet, false));router.route('/lockstatus').get(reportLock.lockStatusGet.bind(null, 'la', false));router.route('/unlock').get(reportLock.releaseLock.bind(null, 'la', false));router.route('/response/:buRequestId').get(reportLock.responseGet); module.exports = router;module.exports.identifyLocalAuthority = identifyLocalAuthority;