|
|
@ -939,6 +939,25 @@ exports.getCurrentSupplier = async (req, reply) => {
|
|
|
|
// }
|
|
|
|
// }
|
|
|
|
// };
|
|
|
|
// };
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// "10-09-2025" or "10/09/2025" -> "10-Sep-2025"; if already "10-Sep-2025", returns as-is
|
|
|
|
|
|
|
|
const toDDMonYYYY = (s) => {
|
|
|
|
|
|
|
|
if (!s) return null;
|
|
|
|
|
|
|
|
const onlyDate = String(s).trim().split(/\s+/)[0];
|
|
|
|
|
|
|
|
if (/^\d{2}-[A-Za-z]{3}-\d{4}$/.test(onlyDate)) return onlyDate; // already DD-Mon-YYYY
|
|
|
|
|
|
|
|
const parts = onlyDate.includes("/") ? onlyDate.split("/") : onlyDate.split("-");
|
|
|
|
|
|
|
|
if (parts.length !== 3) return onlyDate;
|
|
|
|
|
|
|
|
const [dd, mm, yyyy] = parts;
|
|
|
|
|
|
|
|
const MON = ["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"];
|
|
|
|
|
|
|
|
const mon = MON[Math.max(0, Math.min(11, parseInt(mm,10)-1))];
|
|
|
|
|
|
|
|
return `${dd.padStart(2,"0")}-${mon}-${String(yyyy).padStart(4,"0")}`;
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Normalise capacity strings like "10,000 L" / "10000" / 100 -> 100 (number)
|
|
|
|
|
|
|
|
const numify = (v) => {
|
|
|
|
|
|
|
|
if (v == null) return 0;
|
|
|
|
|
|
|
|
const n = parseFloat(String(v).replace(/[^\d.]/g, ""));
|
|
|
|
|
|
|
|
return Number.isFinite(n) ? n : 0;
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
exports.getSuppliers = async (req, reply) => {
|
|
|
|
exports.getSuppliers = async (req, reply) => {
|
|
|
@ -1039,21 +1058,63 @@ if (isValidPrice(price_from) && isValidPrice(price_to)) {
|
|
|
|
|
|
|
|
|
|
|
|
const isConnected = friendRequest && friendRequest.status === "accepted";
|
|
|
|
const isConnected = friendRequest && friendRequest.status === "accepted";
|
|
|
|
const isFavorite = favorateSuppliers.includes(supplierObj.supplierId);
|
|
|
|
const isFavorite = favorateSuppliers.includes(supplierObj.supplierId);
|
|
|
|
|
|
|
|
// Normalize inputs for matching RequestedBooking
|
|
|
|
|
|
|
|
// --- compute these once per request (you can move them above the loop too) ---
|
|
|
|
|
|
|
|
// --- normalize once per request (you can move these above the loop if you like) ---
|
|
|
|
|
|
|
|
// --- helpers (put once near your other helpers) ---
|
|
|
|
|
|
|
|
const escapeRegExp = (s) => String(s || "").replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// normalise inputs once
|
|
|
|
|
|
|
|
const targetDate = toDDMonYYYY((date || "").trim()); // e.g. "10-Sep-2025"
|
|
|
|
|
|
|
|
const reqCapNum = numify(requestedCapacityStr); // "100" -> 100
|
|
|
|
|
|
|
|
const reqQtyNum = parseInt((requestedQuantityStr || "0"), 10);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let requestedBooking = { status: false };
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// be defensive about supplierId
|
|
|
|
|
|
|
|
const supId = String(supplierObj.supplierId || "").trim();
|
|
|
|
|
|
|
|
// case-insensitive exact match for supplierId
|
|
|
|
|
|
|
|
const supIdRegex = new RegExp(`^${escapeRegExp(supId)}$`, "i");
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 1) fetch *all* candidates with same customer + date + supplierId
|
|
|
|
|
|
|
|
const rbDocs = await RequestedBooking.find(
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
customerId,
|
|
|
|
|
|
|
|
date: targetDate,
|
|
|
|
|
|
|
|
"requested_suppliers.supplierId": { $regex: supIdRegex }
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
capacity: 1,
|
|
|
|
|
|
|
|
quantity: 1,
|
|
|
|
|
|
|
|
time: 1,
|
|
|
|
|
|
|
|
requested_suppliers: 1
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
).lean();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 2) scan docs and confirm cap/qty numerically
|
|
|
|
|
|
|
|
for (const rb of (rbDocs || [])) {
|
|
|
|
|
|
|
|
const dbCapNum = numify(rb.capacity);
|
|
|
|
|
|
|
|
const dbQtyNum = numify(rb.quantity); // quantity may be string
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (dbCapNum === reqCapNum && dbQtyNum === reqQtyNum) {
|
|
|
|
|
|
|
|
// pick the exact supplier subdoc (there can be several)
|
|
|
|
|
|
|
|
const supSub = (rb.requested_suppliers || []).find(
|
|
|
|
|
|
|
|
s => String(s.supplierId || "").trim().toLowerCase() === supId.toLowerCase()
|
|
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
// 🔥 Now check RequestedBooking collection
|
|
|
|
|
|
|
|
const requestedBookingRecord = await RequestedBooking.findOne({
|
|
|
|
|
|
|
|
customerId: customerId,
|
|
|
|
|
|
|
|
"requested_suppliers.supplierId": supplierObj.supplierId
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let requestedBooking = { status: false };
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (requestedBookingRecord) {
|
|
|
|
|
|
|
|
requestedBooking = {
|
|
|
|
requestedBooking = {
|
|
|
|
status: true,
|
|
|
|
status: true,
|
|
|
|
time: requestedBookingRecord.time
|
|
|
|
time: supSub?.time || rb.time || null
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
break; // we found a match, no need to continue
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Optional: quick debug if still false
|
|
|
|
|
|
|
|
// if (!requestedBooking.status) {
|
|
|
|
|
|
|
|
// console.log('[DBG requestedBooking miss]', { customerId, targetDate, supId, reqCapNum, reqQtyNum, rbDocs });
|
|
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
suppliers.push({
|
|
|
|
suppliers.push({
|
|
|
|
supplier: supplierData,
|
|
|
|
supplier: supplierData,
|
|
|
|