supersam/src/services/driverDeliveries.js

159 lines
4.4 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

const ACTIVE_DRIVER_STATUSES = new Set(["Назначен водитель", "Загружен", "В пути"]);
const COMPLETED_DRIVER_STATUSES = new Set(["Доставлен", "Закрыт"]);
const PROBLEM_DRIVER_STATUSES = new Set(["Проблема доставки"]);
const DRIVER_KANBAN_COLUMNS = [
{
key: "assigned",
title: "Назначен",
statuses: ["Назначен водитель"],
dropStatus: "Назначен водитель",
},
{
key: "loaded",
title: "Загружен",
statuses: ["Загружен"],
dropStatus: "Загружен",
},
{
key: "on_route",
title: "В пути",
statuses: ["В пути"],
dropStatus: "В пути",
},
{
key: "delivered",
title: "Доставлен",
statuses: ["Доставлен", "Закрыт"],
dropStatus: "Доставлен",
},
{
key: "problem",
title: "Проблема",
statuses: ["Проблема доставки"],
dropStatus: "Проблема доставки",
},
];
export const getDeliveryDay = (order) =>
order.deliverySlots?.[0]?.date || order.scheduledDelivery?.slice(0, 10) || "";
export const getDeliveryCity = (order) =>
order.customer.address?.split(",")[0]?.trim() || "Без города";
export const getDeliveryHalfDay = (order) => {
if (order.deliverySlots?.[0]?.time) {
return order.deliverySlots[0].time;
}
const deliveryHour = Number(order.scheduledDelivery?.slice(11, 13) || 0);
return deliveryHour >= 12 ? "Вторая половина дня" : "Первая половина дня";
};
const isWithinDateRange = (order, dateFrom, dateTo) => {
const deliveryDay = getDeliveryDay(order);
if (dateFrom && deliveryDay < dateFrom) {
return false;
}
if (dateTo && deliveryDay > dateTo) {
return false;
}
return true;
};
const isIncludedByView = (order, viewMode, showCompleted) => {
if (viewMode === "all") {
return showCompleted || !COMPLETED_DRIVER_STATUSES.has(order.status);
}
if (viewMode === "active") {
return ACTIVE_DRIVER_STATUSES.has(order.status) || (showCompleted && COMPLETED_DRIVER_STATUSES.has(order.status));
}
if (viewMode === "problems") {
return PROBLEM_DRIVER_STATUSES.has(order.status);
}
return true;
};
export const filterDriverDeliveries = (orders, filters) => {
const {
dateFrom = "",
dateTo = "",
city = "all",
timeSlot = "all",
viewMode = "active",
showCompleted = false,
} = filters;
return orders.filter((order) => {
if (!isWithinDateRange(order, dateFrom, dateTo)) {
return false;
}
if (city !== "all" && getDeliveryCity(order) !== city) {
return false;
}
if (timeSlot !== "all" && getDeliveryHalfDay(order) !== timeSlot) {
return false;
}
return isIncludedByView(order, viewMode, showCompleted);
});
};
const compareByRouteOrder = (left, right) => {
const leftOrder = left.driverRouteOrder ?? Number.MAX_SAFE_INTEGER;
const rightOrder = right.driverRouteOrder ?? Number.MAX_SAFE_INTEGER;
if (leftOrder !== rightOrder) {
return leftOrder - rightOrder;
}
return new Date(left.scheduledDelivery) - new Date(right.scheduledDelivery);
};
export const groupDriverDeliveriesByDate = (orders) => {
const grouped = orders.reduce((accumulator, order) => {
const date = getDeliveryDay(order);
accumulator[date] = accumulator[date] || [];
accumulator[date].push(order);
return accumulator;
}, {});
return Object.entries(grouped)
.sort(([leftDate], [rightDate]) => leftDate.localeCompare(rightDate))
.map(([date, items]) => ({
date,
items: [...items].sort(compareByRouteOrder),
}));
};
export const reorderDriverDeliveries = (orders, orderedIds) => {
const routeIndexMap = new Map(orderedIds.map((id, index) => [id, index + 1]));
return orders.map((order) =>
routeIndexMap.has(order.id)
? {
...order,
driverRouteOrder: routeIndexMap.get(order.id),
}
: order,
);
};
export const getDriverCities = (orders) =>
[...new Set(orders.map((order) => getDeliveryCity(order)).filter(Boolean))].sort((left, right) =>
left.localeCompare(right),
);
export const buildDriverKanbanColumns = (orders) =>
DRIVER_KANBAN_COLUMNS.map((column) => ({
...column,
items: orders.filter((order) => column.statuses.includes(order.status)).sort(compareByRouteOrder),
}));