208 lines
7.4 KiB
JavaScript
208 lines
7.4 KiB
JavaScript
import { describe, expect, it } from "vitest";
|
||
import { getStatusOwnerRole } from "../constants/deliveryWorkflow";
|
||
import { demoOrders, demoUsers } from "../data/mockAppData";
|
||
import {
|
||
assignDriverToOrder,
|
||
applyStatusUpdate,
|
||
autoAssignOrders,
|
||
buildMetrics,
|
||
cloneOrders,
|
||
createOrderRecord,
|
||
filterOrdersByView,
|
||
getKanbanDropResolution,
|
||
getAvailableTransitions,
|
||
} from "./orderService";
|
||
|
||
describe("orderService", () => {
|
||
it("lets manager see the whole pipeline", () => {
|
||
const result = filterOrdersByView({
|
||
orders: cloneOrders(demoOrders),
|
||
currentUser: demoUsers[0],
|
||
filters: {
|
||
query: "",
|
||
status: "all",
|
||
stage: "all",
|
||
ownerRole: "all",
|
||
agingState: "all",
|
||
managerId: "all",
|
||
logisticianId: "all",
|
||
messenger: "all",
|
||
},
|
||
});
|
||
|
||
expect(result.visibleOrders).toHaveLength(demoOrders.length);
|
||
expect(result.filteredOrders).toHaveLength(demoOrders.length);
|
||
});
|
||
|
||
it("shows employees all orders in their responsibility zone", () => {
|
||
const driver = demoUsers.find((user) => user.role === "driver");
|
||
const result = filterOrdersByView({
|
||
orders: cloneOrders(demoOrders),
|
||
currentUser: driver,
|
||
filters: {
|
||
query: "",
|
||
status: "all",
|
||
stage: "all",
|
||
ownerRole: "all",
|
||
agingState: "all",
|
||
managerId: "all",
|
||
logisticianId: "all",
|
||
messenger: "all",
|
||
},
|
||
});
|
||
|
||
const expectedDriverOrders = demoOrders.filter((order) => getStatusOwnerRole(order.status) === "driver");
|
||
|
||
expect(result.visibleOrders).toHaveLength(expectedDriverOrders.length);
|
||
expect(result.visibleOrders.every((order) => getStatusOwnerRole(order.status) === "driver")).toBe(true);
|
||
});
|
||
|
||
it("finds orders by customer phone, stage, owner role and aging state", () => {
|
||
const result = filterOrdersByView({
|
||
orders: cloneOrders(demoOrders),
|
||
currentUser: demoUsers[0],
|
||
filters: {
|
||
query: "+7 978 000-12-31",
|
||
status: "all",
|
||
stage: "logistics",
|
||
ownerRole: "logistician",
|
||
agingState: "warning",
|
||
managerId: "all",
|
||
logisticianId: "all",
|
||
messenger: "all",
|
||
},
|
||
now: "2026-03-15T12:00:00Z",
|
||
});
|
||
|
||
expect(result.filteredOrders).toHaveLength(1);
|
||
expect(result.filteredOrders[0].orderNumber).toBe("CD-240031");
|
||
});
|
||
|
||
it("updates status and prepends history record", () => {
|
||
const nextOrder = applyStatusUpdate(demoOrders[0], "Доставка согласована", "Ольга Синицына");
|
||
|
||
expect(nextOrder.status).toBe("Доставка согласована");
|
||
expect(nextOrder.history[0].action).toBe("Изменение статуса");
|
||
expect(nextOrder.history[0].newStatus).toBe("Доставка согласована");
|
||
});
|
||
|
||
it("assigns a driver and records the action in history", () => {
|
||
const nextOrder = assignDriverToOrder(demoOrders[0], "u-driver", "Ольга Синицына");
|
||
|
||
expect(nextOrder.assignedDriverId).toBe("u-driver");
|
||
expect(nextOrder.history[0].action).toBe("Назначение водителя");
|
||
expect(nextOrder.history[0].userName).toBe("Ольга Синицына");
|
||
});
|
||
|
||
it("returns role-scoped transitions for logistics stage", () => {
|
||
const transitions = getAvailableTransitions({
|
||
status: "Ожидает согласования доставки",
|
||
role: "logistician",
|
||
});
|
||
|
||
expect(transitions).toEqual(["Доставка согласована", "Проблема доставки", "Отменён"]);
|
||
});
|
||
|
||
it("lets manager move orders across the full workflow from the shared board", () => {
|
||
const transitions = getAvailableTransitions({
|
||
status: "Ожидает согласования доставки",
|
||
role: "manager",
|
||
});
|
||
|
||
expect(transitions).toEqual(["Доставка согласована", "Проблема доставки", "Отменён"]);
|
||
});
|
||
|
||
it("lets logisticians hand orders off into delivery only when a driver is assigned", () => {
|
||
const assignedOrder = {
|
||
...demoOrders.find((order) => order.status === "Доставка согласована"),
|
||
assignedDriverId: "u-driver",
|
||
};
|
||
const blockedOrder = {
|
||
...assignedOrder,
|
||
assignedDriverId: null,
|
||
};
|
||
const deliveryColumn = {
|
||
key: "delivery",
|
||
title: "Доставка",
|
||
statuses: ["Назначен водитель", "Загружен", "В пути"],
|
||
};
|
||
|
||
expect(
|
||
getKanbanDropResolution({
|
||
order: assignedOrder,
|
||
column: deliveryColumn,
|
||
role: "logistician",
|
||
}),
|
||
).toMatchObject({ nextStatus: "Назначен водитель" });
|
||
|
||
expect(
|
||
getKanbanDropResolution({
|
||
order: blockedOrder,
|
||
column: deliveryColumn,
|
||
role: "logistician",
|
||
}),
|
||
).toMatchObject({
|
||
nextStatus: null,
|
||
reason: "Сначала назначьте водителя, потом заказ можно передать в доставку.",
|
||
});
|
||
});
|
||
|
||
it("creates a new order draft with assigned logistician", () => {
|
||
const logisticians = demoUsers.filter((user) => user.role === "logistician");
|
||
const order = createOrderRecord({
|
||
actorName: "Анна Мельник",
|
||
availableLogisticians: logisticians,
|
||
payload: {
|
||
orderNumber: "CD-900000",
|
||
customerName: "Тест Клиент",
|
||
customerPhone: "+7 978 777-00-00",
|
||
customerAddress: "Симферополь",
|
||
messenger: "СМС",
|
||
managerId: "u-manager",
|
||
deliveryDate: "2026-03-15",
|
||
items: "Тестовая позиция",
|
||
comments: "важно",
|
||
tags: "новый",
|
||
},
|
||
});
|
||
|
||
expect(order.status).toBe("Новый");
|
||
expect(order.deliveryAgreementStatus).toBe("Не начато");
|
||
expect(order.logisticianIds).toHaveLength(1);
|
||
expect(order.history[0].action).toBe("Создание заказа");
|
||
});
|
||
|
||
it("auto distributes orders across logisticians", () => {
|
||
const logisticians = demoUsers.filter((user) => user.role === "logistician");
|
||
const assigned = autoAssignOrders(cloneOrders(demoOrders), logisticians);
|
||
|
||
expect(assigned[0].logisticianIds[0]).toBe(logisticians[0].id);
|
||
expect(assigned[1].logisticianIds[0]).toBe(logisticians[1].id);
|
||
});
|
||
|
||
it("builds dashboard metrics", () => {
|
||
const metrics = buildMetrics(demoOrders);
|
||
|
||
expect(metrics.total).toBe(demoOrders.length);
|
||
expect(metrics.readyToShip).toBe(demoOrders.filter((order) => order.status === "Готов к отгрузке").length);
|
||
expect(metrics.awaitingDeliveryCoordination).toBe(
|
||
demoOrders.filter((order) => order.status === "Ожидает согласования доставки").length,
|
||
);
|
||
expect(metrics.exceptions).toBe(demoOrders.filter((order) => order.status === "Проблема доставки").length);
|
||
});
|
||
|
||
it("ships with an expanded demo dataset across the workflow", () => {
|
||
expect(demoOrders.length).toBeGreaterThanOrEqual(32);
|
||
expect(new Set(demoOrders.map((order) => order.status)).size).toBeGreaterThanOrEqual(10);
|
||
expect(
|
||
demoOrders.some((order) => order.status === "Доставка согласована" && order.assignedDriverId),
|
||
).toBe(true);
|
||
expect(
|
||
demoOrders.every((order) => Number.isFinite(new Date(order.createdAt).getTime())),
|
||
).toBe(true);
|
||
expect(
|
||
demoOrders.every((order) => Number.isFinite(new Date(order.scheduledDelivery).getTime())),
|
||
).toBe(true);
|
||
});
|
||
});
|