first commit
This commit is contained in:
@@ -0,0 +1,91 @@
|
||||
/**
|
||||
* Copyright (c) 2026 Niolla
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is proprietary and confidential.
|
||||
* Unauthorized copying, modification, distribution, or use
|
||||
* of this file, via any medium, is strictly prohibited.
|
||||
*/
|
||||
|
||||
// app/utills/excel/confirmOrder.excel.js
|
||||
|
||||
const ExcelJS = require("exceljs");
|
||||
|
||||
/**
|
||||
* Generate Excel template buffer
|
||||
*/
|
||||
exports.generateTemplate = async (items) => {
|
||||
const workbook = new ExcelJS.Workbook();
|
||||
const sheet = workbook.addWorksheet("Confirm Order");
|
||||
|
||||
sheet.columns = [
|
||||
{ header: "Item ID", key: "id", width: 25 },
|
||||
{ header: "Item Name", key: "item_name", width: 30 },
|
||||
{ header: "Original Quantity", key: "quantity", width: 20 },
|
||||
{ header: "Confirmed Quantity", key: "confirmed_quantity", width: 20 },
|
||||
];
|
||||
|
||||
const headerRow = sheet.getRow(1);
|
||||
|
||||
headerRow.eachCell((cell) => {
|
||||
cell.fill = {
|
||||
type: "pattern",
|
||||
pattern: "solid",
|
||||
fgColor: { argb: "1F4E78" },
|
||||
};
|
||||
|
||||
cell.font = {
|
||||
bold: true,
|
||||
color: { argb: "FFFFFF" },
|
||||
};
|
||||
|
||||
cell.alignment = {
|
||||
vertical: "middle",
|
||||
horizontal: "center",
|
||||
};
|
||||
|
||||
cell.border = {
|
||||
top: { style: "thin" },
|
||||
left: { style: "thin" },
|
||||
bottom: { style: "thin" },
|
||||
right: { style: "thin" },
|
||||
};
|
||||
});
|
||||
|
||||
items.forEach((item) => {
|
||||
sheet.addRow({
|
||||
id: item.data_id,
|
||||
item_name: item.item_name,
|
||||
quantity: item.quantity,
|
||||
confirmed_quantity: item.quantity,
|
||||
});
|
||||
});
|
||||
|
||||
return workbook.xlsx.writeBuffer();
|
||||
};
|
||||
|
||||
/**
|
||||
* Parse uploaded Excel buffer
|
||||
*/
|
||||
exports.parseExcel = async (buffer) => {
|
||||
const workbook = new ExcelJS.Workbook();
|
||||
await workbook.xlsx.load(buffer);
|
||||
|
||||
const sheet = workbook.getWorksheet("Confirm Order");
|
||||
if (!sheet) throw new Error("Invalid sheet name");
|
||||
|
||||
const confirmedMap = new Map();
|
||||
|
||||
sheet.eachRow((row, rowNumber) => {
|
||||
if (rowNumber === 1) return;
|
||||
|
||||
const itemId = row.getCell(1).value;
|
||||
const confirmedQty = Number(row.getCell(4).value);
|
||||
|
||||
if (itemId) {
|
||||
confirmedMap.set(itemId, confirmedQty);
|
||||
}
|
||||
});
|
||||
|
||||
return confirmedMap;
|
||||
};
|
||||
@@ -0,0 +1,116 @@
|
||||
/**
|
||||
* Copyright (c) 2026 Niolla
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is proprietary and confidential.
|
||||
* Unauthorized copying, modification, distribution, or use
|
||||
* of this file, via any medium, is strictly prohibited.
|
||||
*/
|
||||
|
||||
// app/utills/generateExcelTemplate.utill.js
|
||||
|
||||
const ExcelJS = require("exceljs");
|
||||
|
||||
exports.generateExcelTemplate = async (columns, vendors) => {
|
||||
const workbook = new ExcelJS.Workbook();
|
||||
|
||||
// =========================
|
||||
// Template Sheet
|
||||
// =========================
|
||||
|
||||
const worksheet = workbook.addWorksheet("Template");
|
||||
|
||||
const headers = columns.map((col) =>
|
||||
col.is_required ? `${col.column_name} *` : col.column_name,
|
||||
);
|
||||
|
||||
const headerRow = worksheet.addRow(headers);
|
||||
|
||||
headerRow.eachCell((cell) => {
|
||||
cell.font = { bold: true };
|
||||
cell.alignment = { vertical: "middle", horizontal: "center" };
|
||||
});
|
||||
|
||||
headers.forEach((header, i) => {
|
||||
worksheet.getColumn(i + 1).width = Math.max(header.length + 5, 20);
|
||||
});
|
||||
|
||||
columns.forEach((col, index) => {
|
||||
const headerCell = worksheet.getCell(1, index + 1);
|
||||
|
||||
if (col.is_required) {
|
||||
headerCell.fill = {
|
||||
type: "pattern",
|
||||
pattern: "solid",
|
||||
fgColor: { argb: "FFF4CCCC" },
|
||||
};
|
||||
|
||||
headerCell.font = {
|
||||
bold: true,
|
||||
color: { argb: "FF000000" },
|
||||
};
|
||||
} else {
|
||||
headerCell.fill = {
|
||||
type: "pattern",
|
||||
pattern: "solid",
|
||||
fgColor: { argb: "FFFFF2CC" },
|
||||
};
|
||||
|
||||
headerCell.font = {
|
||||
bold: true,
|
||||
color: { argb: "FF000000" },
|
||||
};
|
||||
}
|
||||
|
||||
if (col.validation_type === "number") {
|
||||
for (let i = 2; i <= 100; i++) {
|
||||
worksheet.getCell(i, index + 1).dataValidation = {
|
||||
type: "whole",
|
||||
operator: "greaterThanOrEqual",
|
||||
formulae: [0],
|
||||
showErrorMessage: true,
|
||||
error: "Please enter a valid number",
|
||||
};
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
worksheet.views = [{ state: "frozen", ySplit: 1 }];
|
||||
|
||||
// =========================
|
||||
// Vendors Sheet
|
||||
// =========================
|
||||
const vendorSheet = workbook.addWorksheet("Vendors");
|
||||
|
||||
const vendorHeader = vendorSheet.addRow(["Supplier ID", "Supplier Name"]);
|
||||
|
||||
vendorHeader.eachCell((cell) => {
|
||||
cell.font = {
|
||||
bold: true,
|
||||
color: { argb: "FFFFFFFF" },
|
||||
};
|
||||
|
||||
cell.alignment = {
|
||||
vertical: "middle",
|
||||
horizontal: "center",
|
||||
};
|
||||
|
||||
cell.fill = {
|
||||
type: "pattern",
|
||||
pattern: "solid",
|
||||
fgColor: { argb: "4472C4" },
|
||||
};
|
||||
});
|
||||
|
||||
// Add vendor rows
|
||||
vendors.forEach((vendor) => {
|
||||
vendorSheet.addRow([vendor.vendor_id, vendor.name]);
|
||||
});
|
||||
|
||||
// Optional styling
|
||||
vendorSheet.columns = [{ width: 25 }, { width: 35 }];
|
||||
|
||||
vendorSheet.views = [{ state: "frozen", ySplit: 1 }];
|
||||
|
||||
return workbook;
|
||||
};
|
||||
@@ -0,0 +1,101 @@
|
||||
/**
|
||||
* Copyright (c) 2026 Niolla
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is proprietary and confidential.
|
||||
* Unauthorized copying, modification, distribution, or use
|
||||
* of this file, via any medium, is strictly prohibited.
|
||||
*/
|
||||
|
||||
// app/utills/validateExcel.utill.js
|
||||
|
||||
const ExcelJS = require("exceljs");
|
||||
|
||||
exports.validateExcel = async (buffer, columns) => {
|
||||
const workbook = new ExcelJS.Workbook();
|
||||
await workbook.xlsx.load(buffer);
|
||||
const worksheet = workbook.worksheets[0];
|
||||
|
||||
if (!worksheet) {
|
||||
throw { status: 400, message: "Excel sheet is empty" };
|
||||
}
|
||||
|
||||
const expectedHeaders = columns.map((col) =>
|
||||
col.is_required ? `${col.column_name} *` : col.column_name
|
||||
);
|
||||
|
||||
const headerRow = worksheet.getRow(1);
|
||||
|
||||
for (let i = 1; i <= expectedHeaders.length; i++) {
|
||||
const cellValue = (headerRow.getCell(i).value || "").toString().trim();
|
||||
|
||||
if (cellValue !== expectedHeaders[i - 1]) {
|
||||
throw {
|
||||
status: 400,
|
||||
message: `Invalid header in column ${i}`,
|
||||
expected: expectedHeaders[i - 1],
|
||||
received: cellValue,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
const errors = [];
|
||||
const validData = [];
|
||||
|
||||
worksheet.eachRow((row, rowNumber) => {
|
||||
if (rowNumber === 1) return;
|
||||
|
||||
let rowData = {};
|
||||
let rowHasError = false;
|
||||
|
||||
columns.forEach((col, index) => {
|
||||
let value = row.getCell(index + 1).value;
|
||||
|
||||
if (value && typeof value === "object") {
|
||||
value = value.text || value.result || "";
|
||||
}
|
||||
|
||||
value = value?.toString().trim() || "";
|
||||
|
||||
if (col.is_required && !value) {
|
||||
errors.push({
|
||||
row: rowNumber,
|
||||
column: col.column_name,
|
||||
message: "Required field is missing",
|
||||
});
|
||||
rowHasError = true;
|
||||
}
|
||||
|
||||
if (value) {
|
||||
if (col.validation_type === "number" && isNaN(value)) {
|
||||
errors.push({
|
||||
row: rowNumber,
|
||||
column: col.column_name,
|
||||
message: "Must be a number",
|
||||
});
|
||||
rowHasError = true;
|
||||
}
|
||||
|
||||
if (
|
||||
col.validation_type === "boolean" &&
|
||||
!["true", "false"].includes(value.toLowerCase())
|
||||
) {
|
||||
errors.push({
|
||||
row: rowNumber,
|
||||
column: col.column_name,
|
||||
message: "Must be true or false",
|
||||
});
|
||||
rowHasError = true;
|
||||
}
|
||||
}
|
||||
|
||||
rowData[col.column_name] = value;
|
||||
});
|
||||
|
||||
if (!rowHasError) {
|
||||
validData.push(rowData);
|
||||
}
|
||||
});
|
||||
|
||||
return { errors, validData };
|
||||
};
|
||||
Reference in New Issue
Block a user