export const WORKFLOW_STAGES = [ { key: "import", label: "Импорт из 1С" }, { key: "production", label: "Производство" }, { key: "logistics", label: "Логистика" }, { key: "delivery", label: "Доставка" }, { key: "completed", label: "Завершено" }, ]; export const DELIVERY_SET_STATUSES = [ "approaching", "ready_to_launch", "awaiting_client", "manual_work", "agreed", "completed", ]; const getStageLabel = (stageKey) => WORKFLOW_STAGES.find((stage) => stage.key === stageKey)?.label || "Без этапа"; export const ORDER_STATUS_META = { "Новый": { comment: "Заказ импортирован из 1С и ожидает проверки логистом.", ownerRole: "logistician", stageKey: "import", stageLabel: getStageLabel("import"), warningAfterHours: 24, criticalAfterHours: 48, tone: "neutral", }, "Требует уточнения": { comment: "В заказе не хватает данных, логисту нужно уточнить информацию.", ownerRole: "logistician", stageKey: "import", stageLabel: getStageLabel("import"), warningAfterHours: 12, criticalAfterHours: 24, tone: "warning", }, "Подтверждён менеджером": { comment: "Заказ проверен и подтверждён, готов к передаче в работу.", ownerRole: "logistician", stageKey: "import", stageLabel: getStageLabel("import"), warningAfterHours: 12, criticalAfterHours: 24, tone: "accent", }, "В очереди производства": { comment: "Заказ передан на производство и ожидает запуска.", ownerRole: "production_lead", stageKey: "production", stageLabel: getStageLabel("production"), warningAfterHours: 24, criticalAfterHours: 48, tone: "neutral", }, "В производстве": { comment: "Заказ находится в изготовлении на производстве.", ownerRole: "production_lead", stageKey: "production", stageLabel: getStageLabel("production"), warningAfterHours: 48, criticalAfterHours: 96, tone: "accent", }, "Готов к отгрузке": { comment: "Производство завершено, заказ готов к запуску доставки логистом.", ownerRole: "logistician", stageKey: "logistics", stageLabel: getStageLabel("logistics"), warningAfterHours: 8, criticalAfterHours: 24, tone: "accent", }, "Ожидает ответа клиента": { comment: "Клиенту отправлена ссылка, система ждёт подтверждения времени доставки.", ownerRole: "logistician", stageKey: "logistics", stageLabel: getStageLabel("logistics"), warningAfterHours: 1, criticalAfterHours: 3, tone: "warning", }, "Ожидает согласования доставки": { comment: "Клиенту отправлено предложение выбрать дату и половину дня доставки.", ownerRole: "logistician", stageKey: "logistics", stageLabel: getStageLabel("logistics"), warningAfterHours: 24, criticalAfterHours: 96, tone: "warning", }, "Доставка согласована": { comment: "Клиент подтвердил доставку, логист назначает водителя и рейс.", ownerRole: "logistician", stageKey: "logistics", stageLabel: getStageLabel("logistics"), warningAfterHours: 12, criticalAfterHours: 24, tone: "accent", }, "Самовывоз": { comment: "Клиент выбрал самовывоз. Заказ ожидает выдачи на складе.", ownerRole: "logistician", stageKey: "logistics", stageLabel: getStageLabel("logistics"), warningAfterHours: 24, criticalAfterHours: 48, tone: "accent", }, "Требуется адрес": { comment: "Клиент выбрал доставку, но адрес доставки отсутствует. Менеджеру нужно уточнить адрес.", ownerRole: "logistician", stageKey: "logistics", stageLabel: getStageLabel("logistics"), warningAfterHours: 4, criticalAfterHours: 12, tone: "warning", }, "Передан логисту": { comment: "Автоматическое согласование не завершилось, заказ передан логисту на ручную обработку.", ownerRole: "logistician", stageKey: "logistics", stageLabel: getStageLabel("logistics"), warningAfterHours: 4, criticalAfterHours: 12, tone: "warning", }, "Назначен водитель": { comment: "Логист назначил водителя на доставку.", ownerRole: "driver", stageKey: "delivery", stageLabel: getStageLabel("delivery"), warningAfterHours: 12, criticalAfterHours: 24, tone: "accent", }, Загружен: { comment: "Заказ загружен в транспорт, водитель готов к выезду.", ownerRole: "driver", stageKey: "delivery", stageLabel: getStageLabel("delivery"), warningAfterHours: 8, criticalAfterHours: 24, tone: "neutral", }, "В пути": { comment: "Водитель выехал и выполняет доставку.", ownerRole: "driver", stageKey: "delivery", stageLabel: getStageLabel("delivery"), warningAfterHours: 12, criticalAfterHours: 24, tone: "accent", }, Доставлен: { comment: "Заказ успешно передан клиенту.", ownerRole: "driver", stageKey: "completed", stageLabel: getStageLabel("completed"), warningAfterHours: null, criticalAfterHours: null, tone: "accent", }, Закрыт: { comment: "Цикл доставки завершён и больше не требует действий.", ownerRole: "logistician", stageKey: "completed", stageLabel: getStageLabel("completed"), warningAfterHours: null, criticalAfterHours: null, tone: "neutral", }, Отменён: { comment: "Заказ отменён и выведен из процесса доставки.", ownerRole: "logistician", stageKey: "completed", stageLabel: getStageLabel("completed"), warningAfterHours: null, criticalAfterHours: null, tone: "danger", }, "Проблема доставки": { comment: "На этапе доставки возникла проблема, требуется ручной разбор логистом.", ownerRole: "logistician", stageKey: "logistics", stageLabel: getStageLabel("logistics"), warningAfterHours: 12, criticalAfterHours: 48, tone: "danger", }, "Платное хранение": { comment: "Согласование доставки не достигнуто, заказ переведен на платное хранение.", ownerRole: "logistician", stageKey: "logistics", stageLabel: getStageLabel("logistics"), warningAfterHours: 24, criticalAfterHours: 72, tone: "danger", }, }; export const ORDER_STATUSES = Object.keys(ORDER_STATUS_META); export const DELIVERY_AGREEMENT_STATUS_META = { "Не начато": { comment: "Процесс согласования доставки ещё не запускался.", }, "Отправлено клиенту": { comment: "Клиенту отправлено предложение согласовать доставку.", }, "Ожидание ответа": { comment: "Система ждёт ответ клиента по предложенному слоту.", }, "Подтверждено клиентом": { comment: "Клиент подтвердил дату и половину дня доставки.", }, "Перенос запрошен": { comment: "Клиент просит изменить дату или временной интервал.", }, "Нет ответа": { comment: "Клиент не ответил в пределах SLA.", }, "Ошибка отправки": { comment: "Сообщение не удалось отправить, требуется повторная попытка.", }, }; export const DELIVERY_AGREEMENT_STATUSES = Object.keys(DELIVERY_AGREEMENT_STATUS_META); export const ORDER_STATUS_TRANSITIONS = { "Новый": ["Требует уточнения", "Подтверждён менеджером", "Отменён"], "Требует уточнения": ["Новый", "Подтверждён менеджером", "Отменён"], "Подтверждён менеджером": ["В очереди производства", "Требует уточнения", "Отменён"], "В очереди производства": ["В производстве", "Требует уточнения", "Отменён"], "В производстве": ["Готов к отгрузке", "Требует уточнения", "Отменён"], "Готов к отгрузке": ["Ожидает согласования доставки", "Ожидает ответа клиента", "Проблема доставки", "Отменён"], "Ожидает ответа клиента": ["Доставка согласована", "Передан логисту", "Платное хранение", "Проблема доставки", "Отменён"], "Ожидает согласования доставки": ["Доставка согласована", "Самовывоз", "Требуется адрес", "Проблема доставки", "Отменён"], "Доставка согласована": ["Назначен водитель", "Ожидает согласования доставки", "Проблема доставки", "Самовывоз", "Требуется адрес"], "Передан логисту": ["Доставка согласована", "Платное хранение", "Проблема доставки", "Отменён"], "Назначен водитель": ["Загружен", "Проблема доставки"], Загружен: ["Доставлен", "Проблема доставки"], "В пути": ["Доставлен", "Проблема доставки"], Доставлен: ["Закрыт"], "Проблема доставки": ["Ожидает согласования доставки", "Назначен водитель", "Отменён", "Закрыт"], "Платное хранение": ["Доставка согласована", "Отменён", "Закрыт"], "Самовывоз": ["Доставка согласована", "Закрыт", "Отменён", "Платное хранение"], "Требуется адрес": ["Доставка согласована", "Самовывоз", "Отменён", "Проблема доставки"], Закрыт: [], Отменён: [], }; export const ROLE_TRANSITION_TARGETS = { manager: [...ORDER_STATUSES], production_lead: ["В очереди производства", "В производстве", "Готов к отгрузке", "Требует уточнения", "Отменён"], logistician: [ "Новый", "Требует уточнения", "Ожидает ответа клиента", "Ожидает согласования доставки", "Доставка согласована", "Передан логисту", "Назначен водитель", "Самовывоз", "Требуется адрес", "Проблема доставки", "Платное хранение", "Закрыт", "Отменён", ], driver: ["Загружен", "Доставлен", "Проблема доставки"], admin: ORDER_STATUSES, }; export const PRODUCTION_STATUSES = [ "В очереди производства", "В производстве", "Готов к отгрузке", ]; export const LOGISTICS_STATUSES = [ "Готов к отгрузке", "Ожидает ответа клиента", "Ожидает согласования доставки", "Доставка согласована", "Назначен водитель", "Самовывоз", "Требуется адрес", "Проблема доставки", ]; export const DRIVER_STATUSES = ["Назначен водитель", "Загружен", "Доставлен"]; export const getOrderStatusComment = (status) => ORDER_STATUS_META[status]?.comment || "Комментарий не задан."; export const getDeliveryAgreementComment = (status) => DELIVERY_AGREEMENT_STATUS_META[status]?.comment || "Комментарий не задан."; export const getStatusTone = (status) => ORDER_STATUS_META[status]?.tone || "neutral"; export const getStatusOwnerRole = (status) => ORDER_STATUS_META[status]?.ownerRole || null; export const getStatusStageKey = (status) => ORDER_STATUS_META[status]?.stageKey || null; export const getStatusStageLabel = (status) => ORDER_STATUS_META[status]?.stageLabel || "Без этапа"; export const getStatusSla = (status) => ({ warningAfterHours: ORDER_STATUS_META[status]?.warningAfterHours ?? null, criticalAfterHours: ORDER_STATUS_META[status]?.criticalAfterHours ?? null, }); export const getAvailableTransitionsByRole = ({ status, role }) => { const nextStatuses = ORDER_STATUS_TRANSITIONS[status] || []; const allowedTargets = ROLE_TRANSITION_TARGETS[role] || []; return nextStatuses.filter((nextStatus) => allowedTargets.includes(nextStatus)); };