This commit is contained in:
@@ -123,7 +123,46 @@ const findOutboundStatusByCustomerId = (outboundCustomerStatuses, customerId) =>
|
|||||||
return outboundCustomerStatuses.find((item) => toObjectIdText(item?.customer_id) === targetId) || {};
|
return outboundCustomerStatuses.find((item) => toObjectIdText(item?.customer_id) === targetId) || {};
|
||||||
};
|
};
|
||||||
|
|
||||||
const buildRoutePdfBuffer = async (templateBytes, route, seqNum, driversMap, vehiclesMap, outboundCustomerStatuses, unicodeFontBytes) => {
|
const normalizeRouteName = (name) => (name || "").toString().toLowerCase().replace(/\s+/g, "");
|
||||||
|
|
||||||
|
const findRelatedCustomersForReport = (route, customer, allRoutes) => {
|
||||||
|
const customerId = toObjectIdText(customer?.customer_id);
|
||||||
|
const oppositeType = route?.type === "inbound" ? "outbound" : "inbound";
|
||||||
|
const sameDateOppositeRoutes = (allRoutes || []).filter(
|
||||||
|
(item) => item?.type === oppositeType && item?.schedule_date === route?.schedule_date
|
||||||
|
);
|
||||||
|
const relativeRoute = sameDateOppositeRoutes.find(
|
||||||
|
(item) => normalizeRouteName(item?.name) === normalizeRouteName(route?.name)
|
||||||
|
);
|
||||||
|
const relativeRouteCustomer = (relativeRoute?.route_customer_list || []).find(
|
||||||
|
(item) => toObjectIdText(item?.customer_id) === customerId
|
||||||
|
);
|
||||||
|
const otherRoute = sameDateOppositeRoutes.find(
|
||||||
|
(item) =>
|
||||||
|
normalizeRouteName(item?.name) !== normalizeRouteName(route?.name) &&
|
||||||
|
(item?.route_customer_list || []).some((itemCustomer) => toObjectIdText(itemCustomer?.customer_id) === customerId)
|
||||||
|
);
|
||||||
|
const customerInOtherRoute = (otherRoute?.route_customer_list || []).find(
|
||||||
|
(item) => toObjectIdText(item?.customer_id) === customerId
|
||||||
|
);
|
||||||
|
return { relativeRouteCustomer, customerInOtherRoute };
|
||||||
|
};
|
||||||
|
|
||||||
|
const resolveNoteFromCandidates = (...candidates) => {
|
||||||
|
for (const candidate of candidates) {
|
||||||
|
const note = (candidate?.customer_note || candidate?.customer_special_needs || "").toString().trim();
|
||||||
|
if (note) return note;
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
};
|
||||||
|
|
||||||
|
const hasEnterCenterTimeByCandidate = (...candidates) =>
|
||||||
|
candidates.some((item) => item?.customer_enter_center_time !== undefined && item?.customer_enter_center_time !== null && item?.customer_enter_center_time !== "");
|
||||||
|
|
||||||
|
const hasInCenterStatusByCandidate = (...candidates) =>
|
||||||
|
candidates.some((item) => (item?.customer_route_status || "").toString() === "inCenter");
|
||||||
|
|
||||||
|
const buildRoutePdfBuffer = async (templateBytes, route, seqNum, driversMap, vehiclesMap, outboundCustomerStatuses, unicodeFontBytes, allRoutes) => {
|
||||||
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 });
|
||||||
@@ -147,24 +186,33 @@ const buildRoutePdfBuffer = async (templateBytes, route, seqNum, driversMap, veh
|
|||||||
const customers = Array.isArray(route?.route_customer_list) ? route.route_customer_list : [];
|
const customers = Array.isArray(route?.route_customer_list) ? route.route_customer_list : [];
|
||||||
customers.forEach((customer, index) => {
|
customers.forEach((customer, index) => {
|
||||||
const row = index + 1;
|
const row = index + 1;
|
||||||
|
const { relativeRouteCustomer, customerInOtherRoute } = findRelatedCustomersForReport(route, customer, allRoutes);
|
||||||
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 = customer?.customer_note || customer?.customer_special_needs || "";
|
const customerNoteText = resolveNoteFromCandidates(customer, relativeRouteCustomer, customerInOtherRoute);
|
||||||
safeSetField(form, `note_${row}`, customerNoteText);
|
safeSetField(form, `note_${row}`, customerNoteText);
|
||||||
|
|
||||||
const pickupTime = formatUtcToLocalHm(customer?.customer_pickup_time);
|
const pickupTime = formatUtcToLocalHm(
|
||||||
|
customer?.customer_pickup_time ||
|
||||||
|
relativeRouteCustomer?.customer_pickup_time ||
|
||||||
|
customerInOtherRoute?.customer_pickup_time
|
||||||
|
);
|
||||||
if (pickupTime) safeSetField(form, `pick_${row}`, pickupTime);
|
if (pickupTime) safeSetField(form, `pick_${row}`, pickupTime);
|
||||||
|
|
||||||
const hasEnterCenterTime = customer?.customer_enter_center_time !== undefined && customer?.customer_enter_center_time !== null;
|
const hasEnterCenterTime = hasEnterCenterTimeByCandidate(customer, relativeRouteCustomer, customerInOtherRoute);
|
||||||
if (hasEnterCenterTime) {
|
if (hasEnterCenterTime) {
|
||||||
const enterCenterTime = formatUtcToLocalHm(customer?.customer_enter_center_time);
|
const enterCenterTime = formatUtcToLocalHm(
|
||||||
|
customer?.customer_enter_center_time ||
|
||||||
|
relativeRouteCustomer?.customer_enter_center_time ||
|
||||||
|
customerInOtherRoute?.customer_enter_center_time
|
||||||
|
);
|
||||||
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: 11 });
|
||||||
safeSetField(form, `n_${row}`, "", { fontSize: 11 });
|
safeSetField(form, `n_${row}`, "", { fontSize: 11 });
|
||||||
} else if (customer?.customer_route_status === "inCenter") {
|
} else if (hasInCenterStatusByCandidate(customer, relativeRouteCustomer, customerInOtherRoute)) {
|
||||||
safeSetField(form, `y_${row}`, "✓", { fontSize: 11 });
|
safeSetField(form, `y_${row}`, "✓", { fontSize: 11 });
|
||||||
safeSetField(form, `n_${row}`, "", { fontSize: 11 });
|
safeSetField(form, `n_${row}`, "", { fontSize: 11 });
|
||||||
} else {
|
} else {
|
||||||
@@ -368,7 +416,8 @@ exports.exportRouteReportZip = async (req, res) => {
|
|||||||
driversMap,
|
driversMap,
|
||||||
vehiclesMap,
|
vehiclesMap,
|
||||||
outboundCustomerStatuses,
|
outboundCustomerStatuses,
|
||||||
unicodeFontBytes
|
unicodeFontBytes,
|
||||||
|
routes
|
||||||
);
|
);
|
||||||
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;
|
||||||
|
|||||||
Reference in New Issue
Block a user