m3 Security Fixes

This commit is contained in:
Mark Gregory
2026-09-16 17:14:26 +01:00
parent 1602bdd72e
commit d68687f062
78 changed files with 1297 additions and 1228 deletions
@@ -208,7 +208,7 @@
if (isDisabled) {
$('#TOREPORTDATEDIV').hide();
// toMonthPicker.input.style.backgroundColor = '#e9ecef';
// toMonthPicker.input.style.backgroundColor = '#e9ecef';
// toMonthPicker.input.style.cursor = 'not-allowed';
// Set fromMonthPicker to today
@@ -225,7 +225,7 @@
//// Trigger Period change
$('input[name="reportPeriod"]').trigger("change");
//// Update Charts
$("#updateCharts").click(function() {
//// Validate Fields before calling Ajax
@@ -356,7 +356,7 @@
const h = parseFloat(match[1]);
const s = parseFloat(match[2]);
const l = parseFloat(match[3]);
// Create lighter version by increasing lightness and reducing saturation
return `hsl(${h}, ${Math.max(s - 20, 30)}%, ${Math.min(l + 15, 85)}%)`;
}
@@ -367,7 +367,7 @@
let labels = [];
let datasets = [];
const whsSet = new Set();
// Initialize warehouse set from data
data.forEach(entry => whsSet.add(entry.whs));
if (dataLY) dataLY.forEach(entry => whsSet.add(entry.whs));
@@ -378,7 +378,7 @@
// Extract unique year-month combinations
const periodData = new Map();
const monthNames = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
// Process current year data
data.forEach(entry => {
const [year, month] = entry.year.split("-");
@@ -387,21 +387,21 @@
const yearSuffix = year.substring(2); // Last 2 digits
const periodKey = `${monthName}`; // '${yearSuffix}
const periodKey2 = `${monthName} '${yearSuffix}`;
if (!periodData.has(periodKey)) {
periodData.set(periodKey, { current: {}, ly: {} ,label: periodKey2 });
}
const whsData = periodData.get(periodKey).current;
if (!whsData[entry.whs]) {
whsData[entry.whs] = { dollars: 0, weight: 0, lines: 0 };
}
whsData[entry.whs].dollars += entry.dollars;
whsData[entry.whs].weight += entry.weight;
whsData[entry.whs].lines += entry.lines;
});
// Process last year data if available
if (dataLY && dataLY.length > 0) {
dataLY.forEach(entry => {
@@ -411,22 +411,22 @@
const yearSuffix = year.substring(2); // Last 2 digits
const periodKey = `${monthName}`; // '${yearSuffix}
const periodKey2 = `${monthName} '${yearSuffix}`;
if (!periodData.has(periodKey)) {
periodData.set(periodKey, { current: {}, ly: {},label: periodKey2 });
}
const whsData = periodData.get(periodKey).ly;
if (!whsData[entry.whs]) {
whsData[entry.whs] = { dollars: 0, weight: 0, lines: 0 };
}
whsData[entry.whs].dollars += entry.dollars;
whsData[entry.whs].weight += entry.weight;
whsData[entry.whs].lines += entry.lines;
});
}
// Sort labels chronologically
labels = Array.from(periodData.keys()).sort((a, b) => {
// Parse month and year
@@ -434,18 +434,18 @@
const [monthB, yearB] = b.split(" '");
const yearDiff = parseInt(yearA) - parseInt(yearB);
if (yearDiff !== 0) return yearDiff;
// Compare months if same year
const monthOrder = { "Jan": 1, "Feb": 2, "Mar": 3, "Apr": 4, "May": 5, "Jun": 6,"Jul": 7, "Aug": 8, "Sep": 9, "Oct": 10, "Nov": 11, "Dec": 12 };
return monthOrder[monthA] - monthOrder[monthB];
});
// Generate colors for each WHS
const whsColors = {};
whsArray.forEach((whs, index) => {
whsColors[whs] = generateDistinctColors(whsArray.length)[index];
});
// Create datasets for each metric and warehouse
whsArray.forEach(whs => {
if (checkSales === 'on') {
@@ -464,7 +464,7 @@
tension: 0.3,
fill: false
});
// Sales dataset for last year
if (dataLY && dataLY.length > 0) {
datasets.push({
@@ -491,7 +491,7 @@
datasets.push({
type: 'line',
label: `Weight TY (WHS ${whs})`,
data: labels.map(period =>
data: labels.map(period =>
periodData.get(period)?.current[whs]?.weight || 0
),
borderColor: whsColors[whs],
@@ -501,13 +501,13 @@
tension: 0.3,
fill: false
});
// Weight dataset for last year
if (dataLY && dataLY.length > 0) {
datasets.push({
type: 'line',
label: `Weight LY (WHS ${whs})`,
data: labels.map(period =>
data: labels.map(period =>
periodData.get(period)?.ly[whs]?.weight || 0
),
borderColor: createLighterColor(whsColors[whs]),
@@ -526,7 +526,7 @@
datasets.push({
type: 'line',
label: `Lines TY (WHS ${whs})`,
data: labels.map(period =>
data: labels.map(period =>
periodData.get(period)?.current[whs]?.lines || 0
),
borderColor: whsColors[whs],
@@ -536,13 +536,13 @@
tension: 0.3,
fill: false
});
// Lines dataset for last year
if (dataLY && dataLY.length > 0) {
datasets.push({
type: 'line',
label: `Lines LY (WHS ${whs})`,
data: labels.map(period =>
data: labels.map(period =>
periodData.get(period)?.ly[whs]?.lines || 0
),
borderColor: createLighterColor(whsColors[whs]),
@@ -557,28 +557,28 @@
}
});
}
// Quarterly data format handling
else if (dataFormat === "quarterly") {
// Extract unique years and quarters
const yearsSet = new Set();
const periodsSet = new Set();
data.forEach(entry => {
const [quarter, year] = entry.year.split("-");
yearsSet.add(year);
periodsSet.add(quarter);
});
const years = Array.from(yearsSet).sort();
const periods = Array.from(periodsSet).sort((a, b) =>
const periods = Array.from(periodsSet).sort((a, b) =>
parseInt(a.substring(1)) - parseInt(b.substring(1))
);
// Create groupedData structure for quarters
const groupedData = new Map();
const groupedDataLY = new Map();
// Initialize data structures
years.forEach(year => {
groupedData.set(year, new Map());
@@ -586,7 +586,7 @@
groupedData.get(year).set(quarter, new Map());
});
});
// Process current year data
data.forEach(entry => {
const [quarter, year] = entry.year.split("-");
@@ -601,13 +601,13 @@
dollars: 0, weight: 0, lines: 0
});
}
const whsData = groupedData.get(year).get(quarter).get(entry.whs);
whsData.dollars += entry.dollars;
whsData.weight += entry.weight;
whsData.lines += entry.lines;
});
// Process last year data if available
if (dataLY && dataLY.length > 0) {
// Initialize LY structure
@@ -617,7 +617,7 @@
groupedDataLY.get(year).set(quarter, new Map());
});
});
dataLY.forEach(entry => {
const [quarter, year] = entry.year.split("-");
if (!groupedDataLY.has(year)) {
@@ -631,24 +631,24 @@
dollars: 0, weight: 0, lines: 0
});
}
const whsData = groupedDataLY.get(year).get(quarter).get(entry.whs);
whsData.dollars += entry.dollars;
whsData.weight += entry.weight;
whsData.lines += entry.lines;
});
}
// Set labels to quarters
labels = periods;
// Create color map for years
const yearColors = {};
const generatedColors = generateDistinctColors(years.length);
years.forEach((year, index) => {
yearColors[year] = generatedColors[index];
});
// Create datasets
whsArray.forEach(whs => {
years.forEach(year => {
@@ -657,7 +657,7 @@
datasets.push({
type: 'line',
label: `Sales (WHS ${whs} - ${year})`,
data: periods.map(period =>
data: periods.map(period =>
groupedData.get(year)?.get(period)?.get(whs)?.dollars || 0
),
borderColor: yearColors[year],
@@ -666,13 +666,13 @@
tension: 0.3,
fill: false
});
// Last year sales
if (dataLY && dataLY.length > 0) {
datasets.push({
type: 'line',
label: `Sales LY (WHS ${whs} - ${year})`,
data: periods.map(period =>
data: periods.map(period =>
groupedDataLY.get(year)?.get(period)?.get(whs)?.dollars || 0
),
borderColor: yearColors[year],
@@ -685,13 +685,13 @@
});
}
}
if (checkWeight === 'on') {
// Current year weight
datasets.push({
type: 'line',
label: `Weight (WHS ${whs} - ${year})`,
data: periods.map(period =>
data: periods.map(period =>
groupedData.get(year)?.get(period)?.get(whs)?.weight || 0
),
borderColor: yearColors[year],
@@ -701,13 +701,13 @@
tension: 0.3,
fill: false
});
// Last year weight
if (dataLY && dataLY.length > 0) {
datasets.push({
type: 'line',
label: `Weight LY (WHS ${whs} - ${year})`,
data: periods.map(period =>
data: periods.map(period =>
groupedDataLY.get(year)?.get(period)?.get(whs)?.weight || 0
),
borderColor: yearColors[year],
@@ -720,13 +720,13 @@
});
}
}
if (checkLines === 'on') {
// Current year lines
datasets.push({
type: 'line',
label: `Lines (WHS ${whs} - ${year})`,
data: periods.map(period =>
data: periods.map(period =>
groupedData.get(year)?.get(period)?.get(whs)?.lines || 0
),
borderColor: yearColors[year],
@@ -736,13 +736,13 @@
tension: 0.3,
fill: false
});
// Last year lines
if (dataLY && dataLY.length > 0) {
datasets.push({
type: 'line',
label: `Lines LY (WHS ${whs} - ${year})`,
data: periods.map(period =>
data: periods.map(period =>
groupedDataLY.get(year)?.get(period)?.get(whs)?.lines || 0
),
borderColor: yearColors[year],
@@ -763,7 +763,7 @@
// Group data by year/day and warehouse
const groupedData = new Map();
const groupedDataLY = new Map();
// Process current year data
data.forEach(entry => {
if (!groupedData.has(entry.year)) {
@@ -774,13 +774,13 @@
dollars: 0, weight: 0, lines: 0
});
}
const whsData = groupedData.get(entry.year).get(entry.whs);
whsData.dollars += entry.dollars;
whsData.weight += entry.weight;
whsData.lines += entry.lines;
});
// Process last year data if available
if (dataLY && dataLY.length > 0) {
dataLY.forEach(entry => {
@@ -792,17 +792,17 @@
dollars: 0, weight: 0, lines: 0
});
}
const whsData = groupedDataLY.get(entry.year).get(entry.whs);
whsData.dollars += entry.dollars;
whsData.weight += entry.weight;
whsData.lines += entry.lines;
});
}
// Set labels to sorted years or days
labels = Array.from(groupedData.keys()).sort();
// Helper function to get time key
function getTimeKey(yearLabel) {
if (yearLabel.includes("Q")) {
@@ -814,7 +814,7 @@
}
return yearLabel;
}
// Create color map
let uniqueKeys = new Set();
data.forEach(item => {
@@ -832,22 +832,22 @@
});
});
uniqueKeys = [...uniqueKeys];
let colorMap = {};
let generatedColors = generateDistinctColors(uniqueKeys.length);
uniqueKeys.forEach((key, index) => {
colorMap[key] = generatedColors[index];
});
// Function to get color
function getDatasetColor(year, whs, metric, isLastYear = false) {
const timeKey = getTimeKey(year);
const key = /^\d{2}$/.test(year) ?
`${whs}_${metric}${isLastYear ? '_LY' : ''}` :
const key = /^\d{2}$/.test(year) ?
`${whs}_${metric}${isLastYear ? '_LY' : ''}` :
`${timeKey}_${whs}`;
return colorMap[key] || "rgba(200, 200, 200, 0.6)";
}
// Create datasets
whsArray.forEach(whs => {
// Function to create dataset with unique colors
@@ -868,27 +868,27 @@
if (checkSales === 'on') {
// Current year data
datasets.push(createDataset("Sales", "dollars", "Sales", 'yLeft', "Sales", false, groupedData));
// Last year data for daily format
if ((dataFormat === "daily" || dataFormat === "yearly") && dataLY && dataLY.length > 0) {
datasets.push(createDataset("Sales", "dollars", "Sales_LY", 'yLeft', "Sales", true, groupedDataLY));
}
}
if (checkWeight === 'on') {
// Current year data
datasets.push(createDataset("Weight", "weight", "Weight", 'yLeft', "Weight", false, groupedData));
// Last year data for daily/yearly format
if ((dataFormat === "daily" || dataFormat === "yearly") && dataLY && dataLY.length > 0) {
datasets.push(createDataset("Weight", "weight", "Weight_LY", 'yLeft', "Weight", true, groupedDataLY));
}
}
if (checkLines === 'on') {
// Current year data
datasets.push(createDataset("Lines", "lines", "Lines", 'yRight', "Lines", false, groupedData));
// Last year data for daily/yearly format
if ((dataFormat === "daily" || dataFormat === "yearly") && dataLY && dataLY.length > 0) {
datasets.push(createDataset("Lines", "lines", "Lines_LY", 'yRight', "Lines", true, groupedDataLY));
@@ -942,8 +942,8 @@
x: {
title: {
display: true,
text: dataFormat === "quarterly" ? 'Quarter' :
dataFormat === "monthly" ? 'Month' :
text: dataFormat === "quarterly" ? 'Quarter' :
dataFormat === "monthly" ? 'Month' :
dataFormat === "daily" ? 'Day' : 'Year'
}
}
@@ -984,7 +984,7 @@
// End Ajax
});
//// Trigger Click on init
//// Trigger Click on init
$("#updateCharts").trigger("click");
});