This commit is contained in:
@@ -5,12 +5,13 @@ const path = require("path");
|
|||||||
const crypto = require("crypto");
|
const crypto = require("crypto");
|
||||||
const moment = require("moment-timezone");
|
const moment = require("moment-timezone");
|
||||||
const archiver = require("archiver");
|
const archiver = require("archiver");
|
||||||
const { PDFDocument } = require("pdf-lib");
|
const { PDFDocument, rgb } = require("pdf-lib");
|
||||||
const fontkit = require("@pdf-lib/fontkit");
|
const fontkit = require("@pdf-lib/fontkit");
|
||||||
const Report = db.report;
|
const Report = db.report;
|
||||||
const RoutePath = db.route_path;
|
const RoutePath = db.route_path;
|
||||||
const Employee = db.employee;
|
const Employee = db.employee;
|
||||||
const Vehicle = db.vehicle;
|
const Vehicle = db.vehicle;
|
||||||
|
const Customer = db.customer;
|
||||||
|
|
||||||
const ROOT_DIR = path.resolve(__dirname, "../..");
|
const ROOT_DIR = path.resolve(__dirname, "../..");
|
||||||
const TARGET_TIMEZONE = "America/New_York";
|
const TARGET_TIMEZONE = "America/New_York";
|
||||||
@@ -105,6 +106,12 @@ const safeSetField = (form, fieldName, value, options = {}) => {
|
|||||||
if (typeof options.fontSize === "number") {
|
if (typeof options.fontSize === "number") {
|
||||||
field.setFontSize(options.fontSize);
|
field.setFontSize(options.fontSize);
|
||||||
}
|
}
|
||||||
|
if (options.center === true) {
|
||||||
|
field.setAlignment(1);
|
||||||
|
}
|
||||||
|
if (options.blackText === true) {
|
||||||
|
field.setTextColor(rgb(0, 0, 0));
|
||||||
|
}
|
||||||
field.setText(text);
|
field.setText(text);
|
||||||
return;
|
return;
|
||||||
} catch (_textErr) {}
|
} catch (_textErr) {}
|
||||||
@@ -181,7 +188,7 @@ const appendNoticeLine = (parts, text) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const buildRoutePdfBuffer = async (templateBytes, route, seqNum, driversMap, vehiclesMap, outboundCustomerStatuses, unicodeFontBytes, allRoutes) => {
|
const buildRoutePdfBuffer = async (templateBytes, route, seqNum, driversMap, vehiclesMap, outboundCustomerStatuses, unicodeFontBytes, allRoutes, customerNotesById) => {
|
||||||
const pdfDoc = await PDFDocument.load(templateBytes);
|
const pdfDoc = await PDFDocument.load(templateBytes);
|
||||||
pdfDoc.registerFontkit(fontkit);
|
pdfDoc.registerFontkit(fontkit);
|
||||||
const unicodeFont = await pdfDoc.embedFont(unicodeFontBytes, { subset: true });
|
const unicodeFont = await pdfDoc.embedFont(unicodeFontBytes, { subset: true });
|
||||||
@@ -209,7 +216,9 @@ const buildRoutePdfBuffer = async (templateBytes, route, seqNum, driversMap, veh
|
|||||||
safeSetField(form, `name_${row}`, customer?.customer_name || "");
|
safeSetField(form, `name_${row}`, customer?.customer_name || "");
|
||||||
safeSetField(form, `addr_${row}`, customer?.customer_address || "");
|
safeSetField(form, `addr_${row}`, customer?.customer_address || "");
|
||||||
safeSetField(form, `phone_${row}`, customer?.customer_phone || "");
|
safeSetField(form, `phone_${row}`, customer?.customer_phone || "");
|
||||||
const customerNoteText = resolveNoteFromCandidates(customer, relativeRouteCustomer, customerInOtherRoute);
|
const customerId = toObjectIdText(customer?.customer_id);
|
||||||
|
const profileNoteToDriver = (customerNotesById?.get(customerId) || "").toString().trim();
|
||||||
|
const customerNoteText = profileNoteToDriver || resolveNoteFromCandidates(customer, relativeRouteCustomer, customerInOtherRoute);
|
||||||
safeSetField(form, `note_${row}`, customerNoteText);
|
safeSetField(form, `note_${row}`, customerNoteText);
|
||||||
|
|
||||||
const pickupTime = formatUtcToLocalHm(
|
const pickupTime = formatUtcToLocalHm(
|
||||||
@@ -229,14 +238,14 @@ const buildRoutePdfBuffer = async (templateBytes, route, seqNum, driversMap, veh
|
|||||||
if (enterCenterTime) {
|
if (enterCenterTime) {
|
||||||
safeSetField(form, `arrive_${row}`, enterCenterTime);
|
safeSetField(form, `arrive_${row}`, enterCenterTime);
|
||||||
}
|
}
|
||||||
safeSetField(form, `y_${row}`, "✓", { fontSize: 11 });
|
safeSetField(form, `y_${row}`, "✓", { fontSize: 12, center: true, blackText: true });
|
||||||
safeSetField(form, `n_${row}`, "", { fontSize: 11 });
|
safeSetField(form, `n_${row}`, "", { fontSize: 12, center: true, blackText: true });
|
||||||
} else if (hasInCenterStatusByCandidate(customer, relativeRouteCustomer, customerInOtherRoute)) {
|
} else if (hasInCenterStatusByCandidate(customer, relativeRouteCustomer, customerInOtherRoute)) {
|
||||||
safeSetField(form, `y_${row}`, "✓", { fontSize: 11 });
|
safeSetField(form, `y_${row}`, "✓", { fontSize: 12, center: true, blackText: true });
|
||||||
safeSetField(form, `n_${row}`, "", { fontSize: 11 });
|
safeSetField(form, `n_${row}`, "", { fontSize: 12, center: true, blackText: true });
|
||||||
} else {
|
} else {
|
||||||
safeSetField(form, `y_${row}`, "", { fontSize: 11 });
|
safeSetField(form, `y_${row}`, "", { fontSize: 12, center: true, blackText: true });
|
||||||
safeSetField(form, `n_${row}`, "✕", { fontSize: 11 });
|
safeSetField(form, `n_${row}`, "✕", { fontSize: 12, center: true, blackText: true });
|
||||||
}
|
}
|
||||||
|
|
||||||
const outboundStatus = findOutboundStatusByCustomerId(outboundCustomerStatuses, customer?.customer_id);
|
const outboundStatus = findOutboundStatusByCustomerId(outboundCustomerStatuses, customer?.customer_id);
|
||||||
@@ -440,10 +449,11 @@ exports.exportRouteReportZip = async (req, res) => {
|
|||||||
return res.status(500).send({ message: "Missing Unicode font file: NotoSansSC-Regular.ttf" });
|
return res.status(500).send({ message: "Missing Unicode font file: NotoSansSC-Regular.ttf" });
|
||||||
}
|
}
|
||||||
|
|
||||||
const [routes, drivers, vehicles] = await Promise.all([
|
const [routes, drivers, vehicles, customers] = await Promise.all([
|
||||||
RoutePath.find(splitSite.splitSiteGet(req, { schedule_date: date, status: { $ne: "disabled" } })),
|
RoutePath.find(splitSite.splitSiteGet(req, { schedule_date: date, status: { $ne: "disabled" } })),
|
||||||
Employee.find(splitSite.splitSiteGet(req, {})),
|
Employee.find(splitSite.splitSiteGet(req, {})),
|
||||||
Vehicle.find(splitSite.splitSiteGet(req, { status: "active" }))
|
Vehicle.find(splitSite.splitSiteGet(req, { status: "active" })),
|
||||||
|
Customer.find(splitSite.splitSiteGet(req, {}))
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const outboundRoutes = (routes || []).filter((route) => route?.type === "outbound");
|
const outboundRoutes = (routes || []).filter((route) => route?.type === "outbound");
|
||||||
@@ -464,6 +474,12 @@ exports.exportRouteReportZip = async (req, res) => {
|
|||||||
vehicle
|
vehicle
|
||||||
])
|
])
|
||||||
);
|
);
|
||||||
|
const customerNotesById = new Map(
|
||||||
|
(customers || []).map((customer) => [
|
||||||
|
toObjectIdText(customer?._id || customer?.id),
|
||||||
|
(customer?.notes_for_driver || "").toString().trim()
|
||||||
|
])
|
||||||
|
);
|
||||||
const getRouteVehicleNumber = (route) => {
|
const getRouteVehicleNumber = (route) => {
|
||||||
const vehicleId = toObjectIdText(route?.vehicle);
|
const vehicleId = toObjectIdText(route?.vehicle);
|
||||||
const vehicleNumberRaw = vehiclesMap.get(vehicleId)?.vehicle_number;
|
const vehicleNumberRaw = vehiclesMap.get(vehicleId)?.vehicle_number;
|
||||||
@@ -511,7 +527,8 @@ exports.exportRouteReportZip = async (req, res) => {
|
|||||||
vehiclesMap,
|
vehiclesMap,
|
||||||
outboundCustomerStatuses,
|
outboundCustomerStatuses,
|
||||||
unicodeFontBytes,
|
unicodeFontBytes,
|
||||||
routes
|
routes,
|
||||||
|
customerNotesById
|
||||||
);
|
);
|
||||||
const base = sanitizeFileName(route?.name || `route_${i + 1}`) || `route_${i + 1}`;
|
const base = sanitizeFileName(route?.name || `route_${i + 1}`) || `route_${i + 1}`;
|
||||||
const existingCount = filenameCounter.get(base) || 0;
|
const existingCount = filenameCounter.get(base) || 0;
|
||||||
|
|||||||
@@ -85,7 +85,8 @@ const RouteReportWithSignature = () => {
|
|||||||
(res?.data || []).forEach((customer) => {
|
(res?.data || []).forEach((customer) => {
|
||||||
nextMap.set(customer?.id, {
|
nextMap.set(customer?.id, {
|
||||||
program_type: customer?.program_type || '',
|
program_type: customer?.program_type || '',
|
||||||
pay_source: customer?.pay_source || ''
|
pay_source: customer?.pay_source || '',
|
||||||
|
notes_for_driver: customer?.notes_for_driver || ''
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
setCustomerMetaById(nextMap);
|
setCustomerMetaById(nextMap);
|
||||||
@@ -183,7 +184,9 @@ const RouteReportWithSignature = () => {
|
|||||||
return { y: '', n: '✗' };
|
return { y: '', n: '✗' };
|
||||||
};
|
};
|
||||||
|
|
||||||
const getRouteNoteToDriverText = (...customerCandidates) => {
|
const getRouteNoteToDriverText = (customerId, ...customerCandidates) => {
|
||||||
|
const profileNote = (customerMetaById.get(customerId)?.notes_for_driver || '').toString().trim();
|
||||||
|
if (profileNote) return profileNote;
|
||||||
for (const item of customerCandidates) {
|
for (const item of customerCandidates) {
|
||||||
const noteText = (item?.customer_note || '').toString().trim();
|
const noteText = (item?.customer_note || '').toString().trim();
|
||||||
if (noteText) return noteText;
|
if (noteText) return noteText;
|
||||||
@@ -317,7 +320,7 @@ const RouteReportWithSignature = () => {
|
|||||||
const customerInOtherRoute = otherRouteWithThisCustomer?.route_customer_list?.find(cust => cust?.customer_id === customer?.customer_id);
|
const customerInOtherRoute = otherRouteWithThisCustomer?.route_customer_list?.find(cust => cust?.customer_id === customer?.customer_id);
|
||||||
const otherOutboundRoute = getOtherOutboundRouteWithThisCustomer(customer?.customer_id);
|
const otherOutboundRoute = getOtherOutboundRouteWithThisCustomer(customer?.customer_id);
|
||||||
const attendanceDisplay = getAttendanceDisplayByReportLogic(customer, relativeRouteCustomer, customerInOtherRoute);
|
const attendanceDisplay = getAttendanceDisplayByReportLogic(customer, relativeRouteCustomer, customerInOtherRoute);
|
||||||
const routeNoteText = getRouteNoteToDriverText(customer, relativeRouteCustomer, customerInOtherRoute);
|
const routeNoteText = getRouteNoteToDriverText(customer?.customer_id, customer, relativeRouteCustomer, customerInOtherRoute);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<tr key={index}>
|
<tr key={index}>
|
||||||
|
|||||||
Reference in New Issue
Block a user