feat: unify manual_required status and driver label

- orderGroupViews: unify notification manual_required + pending delivery_status into single "Требуется ручное управление" status
- LogisticsReadinessBoard: use status:manual_required in funnel instead of delivery:manual_confirmation_required
- DriverDeliveryPlanner: show "Назначено вам" for driver_assigned instead of "Назначен водитель"
- Add sync-manual-status.sql trigger patch for backend
This commit is contained in:
Codex 2026-05-20 12:19:30 +03:00
parent 838c4cb7ae
commit 6244749545
4 changed files with 84 additions and 8 deletions

View File

@ -17,7 +17,7 @@ const DRIVER_DELIVERY_STATUS_OPTIONS = [
{ value: "all", label: "Все статусы" },
...DRIVER_VISIBLE_DELIVERY_STATUSES.map((status) => ({
value: status,
label: getOrderGroupDeliveryStatusLabel(status),
label: status === "driver_assigned" ? "Назначено вам" : getOrderGroupDeliveryStatusLabel(status),
})),
];
@ -211,7 +211,7 @@ export const DriverDeliveryPlanner = ({ orderGroups = [], onOpenOrder, currentUs
</div>
</div>
<Badge tone={getOrderGroupDeliveryStatusTone(item.deliveryStatus || item.delivery_status)}>
{getOrderGroupDeliveryStatusLabel(item.deliveryStatus || item.delivery_status)}
{(() => { const s = item.deliveryStatus || item.delivery_status; return s === "driver_assigned" ? "Назначено вам" : getOrderGroupDeliveryStatusLabel(s); })()}
</Badge>
</div>

View File

@ -55,7 +55,7 @@ export const LogisticsReadinessBoard = ({ orderGroups = [], onSelectSet, statusO
const FUNNEL_ORDER = [
"status:ready_for_notification",
"delivery:pending_confirmation",
"delivery:manual_confirmation_required",
"status:manual_required",
"status:first_sms_sent",
"status:second_sms_sent",
"delivery:agreed",

View File

@ -4,7 +4,7 @@ const getDeliveryDate = (group) => normalizeDate(group.deliveryDate || group.cus
export const DELIVERY_GROUP_STATUS_LABELS = {
pending_confirmation: "Ожидает согласования",
manual_confirmation_required: "Требуется ручное подтверждение",
manual_confirmation_required: "Взят в ручное управление",
agreed: "Согласовано",
driver_assigned: "Назначен водитель",
loaded: "Загружено",
@ -22,7 +22,7 @@ export const NOTIFICATION_STATUS_LABELS = {
second_sms_sent: "2-е приглашение отправлено",
send_failed: "Ошибка отправки",
confirmed: "Согласовано",
manual_required: "Переведено в ручное",
manual_required: "Требуется ручное подтверждение",
};
export const DRIVER_VISIBLE_DELIVERY_STATUSES = [
@ -140,12 +140,19 @@ export const getOrderGroupDeliveryStatusLabel = (status) =>
export const getOrderGroupDisplayStatusLabel = (group) => {
const deliveryStatus = group?.deliveryStatus || group?.delivery_status;
const notificationStatus = group?.notificationStatus || group?.notification_status;
if (deliveryStatus && deliveryStatus !== "pending_confirmation") {
// When auto-SMS failed and logistics hasn't taken action yet → show as a todo item
const isManualRequired = notificationStatus === "manual_required";
const isStillPending = !deliveryStatus || deliveryStatus === "pending_confirmation" || deliveryStatus === "manual_confirmation_required";
if (isManualRequired && isStillPending) {
return "Требуется ручное управление";
}
if (deliveryStatus && deliveryStatus !== "pending_confirmation" && deliveryStatus !== "manual_confirmation_required") {
return getOrderGroupDeliveryStatusLabel(deliveryStatus);
}
const notificationStatus = group?.notificationStatus || group?.notification_status;
const notificationLabel = NOTIFICATION_STATUS_LABELS[notificationStatus];
if (notificationLabel && notificationStatus !== "link_ready" && notificationStatus !== "not_started") {
return notificationLabel;
@ -156,8 +163,16 @@ export const getOrderGroupDisplayStatusLabel = (group) => {
export const getOrderGroupDisplayStatusValue = (group) => {
const deliveryStatus = group?.deliveryStatus || group?.delivery_status;
const notificationStatus = group?.notificationStatus || group?.notification_status;
if (deliveryStatus) {
// Unify manual_required into a single bucket regardless of delivery_status detail
const isManualRequired = notificationStatus === "manual_required";
const isStillPending = !deliveryStatus || deliveryStatus === "pending_confirmation" || deliveryStatus === "manual_confirmation_required";
if (isManualRequired && isStillPending) {
return "status:manual_required";
}
if (deliveryStatus && deliveryStatus !== "pending_confirmation" && deliveryStatus !== "manual_confirmation_required") {
return `delivery:${deliveryStatus}`;
}

View File

@ -0,0 +1,61 @@
-- Sync manual_required notification_status into unified "Требуется ручное управление" workflow
-- and clear it when logistics takes action (changes delivery_status).
-- 1. Backfill: normalize existing rows where notification_status is manual_required
-- and delivery_status is still pending/manual_confirmation_required.
update public.order_groups
set delivery_status = 'pending_confirmation',
updated_at = timezone('utc', now())
where notification_status = 'manual_required'
and delivery_status = 'manual_confirmation_required';
-- 2. When notification_status becomes manual_required, ensure delivery_status stays pending
-- so the group appears in the unified "Требуется ручное управление" bucket.
create or replace function public.sync_manual_required_notification()
returns trigger
language plpgsql
security definer
set search_path = public
as $$
begin
-- Only act when notification_status changed to manual_required
if new.notification_status = 'manual_required'
and (old is null or old.notification_status is distinct from new.notification_status) then
if new.delivery_status is null or new.delivery_status = 'manual_confirmation_required' then
new.delivery_status := 'pending_confirmation';
end if;
end if;
return new;
end;
$$;
drop trigger if exists sync_manual_required_notification_trigger on public.order_groups;
create trigger sync_manual_required_notification_trigger
before insert or update on public.order_groups
for each row
execute function public.sync_manual_required_notification();
-- 3. When delivery_status is changed by logistics (away from pending/manual_confirmation_required),
-- clear notification_status so the group leaves the manual-work bucket.
create or replace function public.clear_manual_required_on_action()
returns trigger
language plpgsql
security definer
set search_path = public
as $$
begin
if old.delivery_status in ('pending_confirmation', 'manual_confirmation_required')
and new.delivery_status not in ('pending_confirmation', 'manual_confirmation_required')
and old.notification_status = 'manual_required' then
new.notification_status := 'confirmed';
end if;
return new;
end;
$$;
drop trigger if exists clear_manual_required_on_action_trigger on public.order_groups;
create trigger clear_manual_required_on_action_trigger
before update on public.order_groups
for each row
when (new.delivery_status is distinct from old.delivery_status)
execute function public.clear_manual_required_on_action();