Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat : added themes in generate template #773

Merged
merged 2 commits into from
Jun 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion utilities/project-factory/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
"axios": "1.6.8",
"body-parser": "1.20.2",
"compression": "1.7.4",
"exceljs": "^4.4.0",
"express": "4.18.3",
"hash-sum": "2.0.0",
"helmet": "7.1.0",
Expand Down Expand Up @@ -57,4 +58,4 @@
"ts-node-dev": "2.0.0",
"typescript": "5.4.2"
}
}
}
51 changes: 12 additions & 39 deletions utilities/project-factory/src/server/api/genericApis.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import { extractCodesFromBoundaryRelationshipResponse, generateFilteredBoundaryD
import { getFiltersFromCampaignSearchResponse, getHierarchy } from './campaignApis';
import { validateMappingId } from '../utils/campaignMappingUtils';
import { campaignStatuses } from '../config/constants';
import { getBoundaryTabName } from '../utils/boundaryUtils';
const _ = require('lodash'); // Import lodash library

// Function to retrieve workbook from Excel file URL and sheet name
Expand Down Expand Up @@ -391,15 +390,12 @@ const getCount: any = async (

// Function to create Excel sheet and upload it
async function createAndUploadFile(
updatedWorkbook: XLSX.WorkBook,
updatedWorkbook: any,
request: any,
tenantId?: any
) {
// Write the updated workbook to a buffer
const buffer = XLSX.write(updatedWorkbook, {
bookType: "xlsx",
type: "buffer",
});
const buffer = await updatedWorkbook.xlsx.writeBuffer();

// Create form data for file upload
const formData = new FormData();
Expand All @@ -426,11 +422,8 @@ async function createAndUploadFile(
// Extract response data
const responseData = fileCreationResult?.files;
if (!responseData) {
throwError(
"COMMON",
500,
"INTERNAL_SERVER_ERROR",
"Error while uploading excel file"
throw new Error(
"Error while uploading excel file: INTERNAL_SERVER_ERROR"
);
}

Expand Down Expand Up @@ -499,28 +492,9 @@ function traverseChildren(parent: any, parentMap: any, hierarchyList: any[]) {
}

// Function to create an Excel sheet
async function createExcelSheet(
data: any,
headers: any,
sheetName: string = "Sheet1"
) {
// Create a new Excel workbook
const workbook = XLSX.utils.book_new();

// Combine headers and data into sheet data
const sheetData = [headers, ...data];
const ws = XLSX.utils.aoa_to_sheet(sheetData);

// Define column widths (in pixels)
const columnWidths = headers.map(() => ({ width: 30 }));

// Apply column widths to the sheet
ws["!cols"] = columnWidths;

// Append sheet to the workbook
XLSX.utils.book_append_sheet(workbook, ws, sheetName);

return { wb: workbook, ws: ws, sheetName: sheetName }; // Return the workbook, worksheet, and sheet name
async function createExcelSheet(data: any, headers: any) {
var rows = [headers, ...data];
return rows;
}

// Function to handle getting boundary codes
Expand Down Expand Up @@ -648,15 +622,14 @@ async function getBoundarySheetData(
localizationMap
);
// create empty sheet if no boundary present in system
const localizedBoundaryTab = getLocalizedName(
getBoundaryTabName(),
localizationMap
);
// const localizedBoundaryTab = getLocalizedName(
// getBoundaryTabName(),
// localizationMap
// );
logger.info(`generated a empty template for boundary`);
return await createExcelSheet(
boundaryData,
localizedHeaders,
localizedBoundaryTab
localizedHeaders
);
} else {
// logger.info("boundaryData for sheet " + JSON.stringify(boundaryData))
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
import express from "express";
import { processGenericRequest } from "../api/campaignApis";
import { createAndUploadFile, getBoundarySheetData } from "../api/genericApis";
import { processDataSearchRequest } from "../utils/campaignUtils";
import { enrichResourceDetails, getLocalizedMessagesHandler, getResponseFromDb, processGenerate, throwError } from "../utils/genericUtils";
import { getLocalizedName, processDataSearchRequest } from "../utils/campaignUtils";
import { addDataToSheet, enrichResourceDetails, getLocalizedMessagesHandler, getResponseFromDb, processGenerate, throwError } from "../utils/genericUtils";
import { logger } from "../utils/logger";
import { validateCreateRequest, validateDownloadRequest, validateSearchRequest } from "../validators/campaignValidators";
import { validateGenerateRequest } from "../validators/genericValidator";
import { getLocalisationModuleName } from "../utils/localisationUtils";
import { getBoundaryTabName } from "../utils/boundaryUtils";
const ExcelJS = require('exceljs');


const generateDataService = async (request: express.Request) => {
// Validate the generate request
Expand Down Expand Up @@ -37,15 +40,18 @@ const downloadDataService = async (request: express.Request) => {
const getBoundaryDataService = async (
request: express.Request
) => {
const workbook = new ExcelJS.Workbook();
const { hierarchyType } = request?.query;
const localizationMapHierarchy = hierarchyType && await getLocalizedMessagesHandler(request, request?.query?.tenantId, getLocalisationModuleName(hierarchyType));
const localizationMapModule = await getLocalizedMessagesHandler(request, request?.query?.tenantId);
const localizationMap = { ...localizationMapHierarchy, ...localizationMapModule };
// const localizationMap = await getLocalizedMessagesHandler(request, request?.body?.ResourceDetails?.tenantId || request?.query?.tenantId || 'mz');
// Retrieve boundary sheet data
const boundarySheetData: any = await getBoundarySheetData(request, localizationMap);
ashish-egov marked this conversation as resolved.
Show resolved Hide resolved
// Create and upload file
const BoundaryFileDetails: any = await createAndUploadFile(boundarySheetData?.wb, request);

const localizedBoundaryTab = getLocalizedName(getBoundaryTabName(), localizationMap);
const boundarySheet = workbook.addWorksheet(localizedBoundaryTab);
addDataToSheet(boundarySheet, boundarySheetData);
const BoundaryFileDetails: any = await createAndUploadFile(workbook, request);
// Return boundary file details
logger.info("RETURNS THE BOUNDARY RESPONSE");
return BoundaryFileDetails;
Expand Down
123 changes: 86 additions & 37 deletions utilities/project-factory/src/server/utils/campaignUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { getCampaignNumber, createAndUploadFile, getSheetData, createExcelSheet,
import { getFormattedStringForDebug, logger } from "./logger";
import createAndSearch from "../config/createAndSearch";
import * as XLSX from 'xlsx';
import { createReadMeSheet, findMapValue, getBoundaryRelationshipData, getLocalizedHeaders, getLocalizedMessagesHandler, modifyBoundaryData, modifyDataBasedOnDifferentTab, replicateRequest, throwError } from "./genericUtils";
import { addDataToSheet, changeFirstRowColumnColour, createReadMeSheet, findMapValue, getBoundaryRelationshipData, getLocalizedHeaders, getLocalizedMessagesHandler, modifyBoundaryData, modifyDataBasedOnDifferentTab, replicateRequest, throwError } from "./genericUtils";
import { enrichProjectDetailsFromCampaignDetails } from "./transforms/projectTypeUtils";
import { executeQuery } from "./db";
import { campaignDetailsTransformer, genericResourceTransformer } from "./transforms/searchResponseConstructor";
Expand All @@ -18,6 +18,8 @@ import { getBoundaryColumnName, getBoundaryTabName } from "./boundaryUtils";
import { searchProjectTypeCampaignService } from "../service/campaignManageService";
import { validateBoundaryOfResouces } from "../validators/campaignValidators";
const _ = require('lodash');
const ExcelJS = require('exceljs');
ashish-egov marked this conversation as resolved.
Show resolved Hide resolved



function updateRange(range: any, desiredSheet: any) {
ashish-egov marked this conversation as resolved.
Show resolved Hide resolved
Expand Down Expand Up @@ -361,7 +363,7 @@ async function generateProcessedFileAndPersist(request: any, localizationMap?: {
produceModifiedMessages(request?.body, config?.kafka?.KAFKA_UPDATE_RESOURCE_DETAILS_TOPIC);
logger.info(`ResourceDetails to persist : ${request.body.ResourceDetails.type}`);
if (request?.body?.Activities && Array.isArray(request?.body?.Activities && request?.body?.Activities.length > 0)) {
logger.info("Activities to persist : " )
logger.info("Activities to persist : ")
logger.debug(getFormattedStringForDebug(request?.body?.Activities));
await new Promise(resolve => setTimeout(resolve, 2000));
produceModifiedMessages(request?.body, config?.kafka?.KAFKA_CREATE_RESOURCE_ACTIVITY_TOPIC);
Expand Down Expand Up @@ -1210,14 +1212,79 @@ async function processBasedOnAction(request: any, actionInUrl: any) {
await enrichAndPersistProjectCampaignRequest(request, actionInUrl, true)
processAfterPersist(request, actionInUrl)
}

function lockTargetFields(newSheet: any, targetColumnNumber: any, boundaryCodeColumnIndex: any) {
// Make every cell locked by default
newSheet.eachRow((row: any) => {
row.eachCell((cell: any) => {
cell.protection = { locked: true };
});
});

// Unlock cells in the target column
if (targetColumnNumber > -1) {
newSheet.eachRow((row: any) => {
const cell = row.getCell(targetColumnNumber + 1); // Excel columns are 1-based
cell.protection = { locked: false };
});
}

// Hide the boundary code column
if (boundaryCodeColumnIndex !== -1) {
newSheet.getColumn(boundaryCodeColumnIndex + 1).hidden = true;
}

// Protect the sheet with a password (optional)
newSheet.protect('passwordhere', {
selectLockedCells: true,
selectUnlockedCells: true
});
}

function createNewSheet(workbook: any, newSheetData: any, uniqueData: any, localizationMap: any, districtLevelRowBoundaryCodeMap: any, localizedHeaders: any) {
const newSheet = workbook.addWorksheet(getLocalizedName(districtLevelRowBoundaryCodeMap.get(uniqueData), localizationMap));
addDataToSheet(newSheet, newSheetData, 'F3842D', 40);

const targetColumnNumber = localizedHeaders.findIndex((header: any) => header == getLocalizedName("HCM_ADMIN_CONSOLE_TARGET", localizationMap));
const boundaryCodeColumnIndex = localizedHeaders.findIndex((header: any) => header === getLocalizedName("HCM_ADMIN_CONSOLE_BOUNDARY_CODE", localizationMap));
if (targetColumnNumber > -1) {
// Change the target column background color
changeFirstRowColumnColour(newSheet, 'B6D7A8', targetColumnNumber + 1);
}
lockTargetFields(newSheet, targetColumnNumber, boundaryCodeColumnIndex);
}



function appendDistricts(workbook: any, uniqueDistrictsForMainSheet: any, differentTabsBasedOnLevel: any, boundaryData: any, localizationMap: any, districtLevelRowBoundaryCodeMap: any) {
for (const uniqueData of uniqueDistrictsForMainSheet) {
const uniqueDataFromLevelForDifferentTabs = uniqueData.slice(uniqueData.lastIndexOf('_') + 1);
const districtDataFiltered = boundaryData.filter((boundary: any) => boundary[differentTabsBasedOnLevel] === uniqueDataFromLevelForDifferentTabs);
const modifiedFilteredData = modifyFilteredData(districtDataFiltered, districtLevelRowBoundaryCodeMap.get(uniqueData), localizationMap);
if (modifiedFilteredData?.[0]) {
const districtIndex = Object.keys(modifiedFilteredData[0]).indexOf(differentTabsBasedOnLevel);
const headers = Object.keys(modifiedFilteredData[0]).slice(districtIndex);
const modifiedHeaders = [...headers, "HCM_ADMIN_CONSOLE_TARGET"];
const localizedHeaders = getLocalizedHeaders(modifiedHeaders, localizationMap);
const newSheetData = [localizedHeaders];

for (const data of modifiedFilteredData) {
const rowData = Object.values(data).slice(districtIndex).map(value => value === null ? '' : String(value)); // Replace null with empty string
newSheetData.push(rowData);
}
createNewSheet(workbook, newSheetData, uniqueData, localizationMap, districtLevelRowBoundaryCodeMap, localizedHeaders);
}
}
}

async function appendSheetsToWorkbook(request: any, boundaryData: any[], differentTabsBasedOnLevel: any, localizationMap?: any) {
try {
logger.info("Received Boundary data for Processing file")
logger.info("Received Boundary data for Processing file");
const uniqueDistrictsForMainSheet: string[] = [];
const workbook = XLSX.utils.book_new();
const type = request?.query?.type
const headingInSheet = headingMapping?.[type]
const localisedHeading = getLocalizedName(headingInSheet, localizationMap)
const workbook = new ExcelJS.Workbook();
const type = request?.query?.type;
const headingInSheet = headingMapping?.[type];
const localisedHeading = getLocalizedName(headingInSheet, localizationMap);
await createReadMeSheet(request, workbook, localisedHeading, localizationMap);
const mainSheetData: any[] = [];
const headersForMainSheet = differentTabsBasedOnLevel ? Object.keys(boundaryData[0]).slice(0, Object.keys(boundaryData[0]).indexOf(differentTabsBasedOnLevel) + 1) : [];
Expand All @@ -1232,8 +1299,7 @@ async function appendSheetsToWorkbook(request: any, boundaryData: any[], differe
const districtIndex = modifiedData[differentTabsBasedOnLevel] !== '' ? rowData.indexOf(data[differentTabsBasedOnLevel]) : -1;
if (districtIndex == -1) {
mainSheetData.push(rowData);
}
else {
} else {
const districtLevelRow = rowData.slice(0, districtIndex + 1);
if (!uniqueDistrictsForMainSheet.includes(districtLevelRow.join('_'))) {
uniqueDistrictsForMainSheet.push(districtLevelRow.join('_'));
Expand All @@ -1242,39 +1308,22 @@ async function appendSheetsToWorkbook(request: any, boundaryData: any[], differe
}
}
}
const mainSheet = XLSX.utils.aoa_to_sheet(mainSheetData);
const localizedBoundaryTab = getLocalizedName(getBoundaryTabName(), localizationMap);
const columnWidths = Array(12).fill({ width: 30 });
mainSheet['!cols'] = columnWidths;
XLSX.utils.book_append_sheet(workbook, mainSheet, localizedBoundaryTab);
for (const uniqueData of uniqueDistrictsForMainSheet) {
const uniqueDataFromLevelForDifferentTabs = uniqueData.slice(uniqueData.lastIndexOf('_') + 1);
const districtDataFiltered = boundaryData.filter(boundary => boundary[differentTabsBasedOnLevel] === uniqueDataFromLevelForDifferentTabs);
const modifiedFilteredData = modifyFilteredData(districtDataFiltered, districtLevelRowBoundaryCodeMap.get(uniqueData), localizationMap);
if (modifiedFilteredData?.[0]) {
const districtIndex = Object.keys(modifiedFilteredData[0]).indexOf(differentTabsBasedOnLevel);
const headers = Object.keys(modifiedFilteredData[0]).slice(districtIndex);
const modifiedHeaders = [...headers, "HCM_ADMIN_CONSOLE_TARGET"];
const localizedHeaders = getLocalizedHeaders(modifiedHeaders, localizationMap);
const newSheetData = [localizedHeaders];

for (const data of modifiedFilteredData) {
const rowData = Object.values(data).slice(districtIndex).map(value => value === null ? '' : String(value)); // Replace null with empty string
newSheetData.push(rowData);
}
const ws = XLSX.utils.aoa_to_sheet(newSheetData);
const localizedDifferentTabsName = getLocalizedName(districtLevelRowBoundaryCodeMap.get(uniqueData), localizationMap);
ws['!cols'] = columnWidths;
XLSX.utils.book_append_sheet(workbook, ws, localizedDifferentTabsName);
}
}
logger.info("File processed successfully")
const mainSheet = workbook.addWorksheet(getLocalizedName(getBoundaryTabName(), localizationMap));
const columnWidths = Array(12).fill(30);
mainSheet.columns = columnWidths.map(width => ({ width }));
// mainSheetData.forEach(row => mainSheet.addRow(row));
addDataToSheet(mainSheet, mainSheetData, 'F3842D', 30);


appendDistricts(workbook, uniqueDistrictsForMainSheet, differentTabsBasedOnLevel, boundaryData, localizationMap, districtLevelRowBoundaryCodeMap);
logger.info("File processed successfully");
return workbook;
} catch (error) {
console.log(error);
throw Error("An error occurred while creating tabs based on district:");
}
}

function modifyFilteredData(districtDataFiltered: any, targetBoundaryCode: any, localizationMap?: any): any {

// Step 2: Slice the boundary code up to the last underscore
Expand Down Expand Up @@ -1437,7 +1486,7 @@ const autoGenerateBoundaryCodes = async (request: any, localizationMap?: any) =>
const headers = [...modifiedHierarchy, config?.boundary?.boundaryCode];
const data = prepareDataForExcel(boundaryDataForSheet, hierarchy, boundaryMap);
const localizedHeaders = getLocalizedHeaders(headers, localizationMap);
const boundarySheetData = await createExcelSheet(data, localizedHeaders, localizedBoundaryTab);
const boundarySheetData: any = await createExcelSheet(data, localizedHeaders);
const boundaryFileDetails: any = await createAndUploadFile(boundarySheetData?.wb, request);
request.body.ResourceDetails.processedFileStoreId = boundaryFileDetails?.[0]?.fileStoreId;
}
Expand Down
Loading
Loading