fix(autocall): «ручное управление» — это НЕ согласованный заказ; кнопку автодозвона по нему больше не блокирует (ошибка из прошлой правки)
This commit is contained in:
parent
512aab9ff2
commit
775a72ea29
|
|
@ -593,8 +593,11 @@ def process_queue(conn, settings):
|
||||||
# Заказ уже согласован (клиент выбрал дату или менеджер поставил её сам) —
|
# Заказ уже согласован (клиент выбрал дату или менеджер поставил её сам) —
|
||||||
# роботу звонить не о чем, иначе он предложит дни по заказу, где всё решено.
|
# роботу звонить не о чем, иначе он предложит дни по заказу, где всё решено.
|
||||||
# Заявку НЕ закрываем (правило владельца) — просто не обрабатываем.
|
# Заявку НЕ закрываем (правило владельца) — просто не обрабатываем.
|
||||||
agreed = (str(q.get("notification_status") or "") in ("confirmed", "manual_required", "opt_out")
|
# ВАЖНО: 'manual_required' («нужен менеджер») сюда не относится — это как раз
|
||||||
or q.get("delivery_date") is not None)
|
# заказ, где клиент дату НЕ выбрал, звонок робота по нему допустим.
|
||||||
|
agreed = (str(q.get("notification_status") or "") == "confirmed"
|
||||||
|
or q.get("delivery_date") is not None
|
||||||
|
or q.get("autocall_opt_out") is True)
|
||||||
if agreed and not is_test:
|
if agreed and not is_test:
|
||||||
log.info(
|
log.info(
|
||||||
f"Queue item {q['queue_id']} (group {group_id}): заказ уже согласован "
|
f"Queue item {q['queue_id']} (group {group_id}): заказ уже согласован "
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ import React, { useState, useEffect, useCallback, useMemo } from "react";
|
||||||
import { Badge } from "../UI/Badge";
|
import { Badge } from "../UI/Badge";
|
||||||
import { supabase } from "../../supabaseClient";
|
import { supabase } from "../../supabaseClient";
|
||||||
import { resolveAutocallStatus, AUTOCALL_STATUS_META } from "../../services/orderGroupViews";
|
import { resolveAutocallStatus, AUTOCALL_STATUS_META } from "../../services/orderGroupViews";
|
||||||
import { describeCallProcess } from "../../services/autocallProcess";
|
import { describeCallProcess, isOrderAgreed } from "../../services/autocallProcess";
|
||||||
import { isAutocallPossible } from "../../services/autocallAvailability";
|
import { isAutocallPossible } from "../../services/autocallAvailability";
|
||||||
|
|
||||||
const OUTCOME_META = {
|
const OUTCOME_META = {
|
||||||
|
|
@ -161,11 +161,10 @@ export const AutocallStatusCard = ({ order, userRole }) => {
|
||||||
}, [order?.id, order?.delivery_type, order?.created_at]);
|
}, [order?.id, order?.delivery_type, order?.created_at]);
|
||||||
const autocallBlocked = availability ? !availability.possible : false;
|
const autocallBlocked = availability ? !availability.possible : false;
|
||||||
|
|
||||||
// Заказ уже согласован — дату выбрал клиент (в том числе в звонке) или поставил менеджер
|
// Заказ уже согласован — дату выбрал клиент (в том числе в звонке) или поставил менеджер.
|
||||||
const orderAgreed = Boolean(order?.delivery_date || order?.deliveryDate)
|
// 'manual_required' («нужен менеджер») сюда НЕ входит: там дату как раз не выбрали,
|
||||||
|| ["confirmed", "manual_required", "opt_out"].includes(
|
// и звонок робота допустим (см. isOrderAgreed и её тесты).
|
||||||
String(order?.notification_status || order?.notificationStatus || ""),
|
const orderAgreed = isOrderAgreed(order);
|
||||||
);
|
|
||||||
|
|
||||||
const process = useMemo(
|
const process = useMemo(
|
||||||
() => describeCallProcess({
|
() => describeCallProcess({
|
||||||
|
|
|
||||||
|
|
@ -185,3 +185,19 @@ export const describeCallProcess = ({ queueItem, callAfter, settings = {}, now =
|
||||||
hint: `Робот звонит только в рабочее время: ${padHour(startHour)}–${padHour(endHour)}, дни — ${workDays.join(", ")} — ${requested}`,
|
hint: `Робот звонит только в рабочее время: ${padHour(startHour)}–${padHour(endHour)}, дни — ${workDays.join(", ")} — ${requested}`,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Согласован ли уже заказ (дату выбрал клиент или поставил менеджер).
|
||||||
|
*
|
||||||
|
* Нужно карточке, чтобы не предлагать автодозвон по заказу, где всё решено.
|
||||||
|
* ВАЖНО: `manual_required` («нужен менеджер») — это НЕ согласованный заказ:
|
||||||
|
* дату клиент как раз не выбрал, и звонок робота по нему допустим.
|
||||||
|
* Отдельно стоит флаг «не звонить» (`autocall_opt_out`) — он про запрет звонков,
|
||||||
|
* а не про согласование, и обрабатывается своим состоянием.
|
||||||
|
*/
|
||||||
|
export const isOrderAgreed = (order) => {
|
||||||
|
if (!order) return false;
|
||||||
|
const date = order.delivery_date ?? order.deliveryDate;
|
||||||
|
const status = String(order.notification_status ?? order.notificationStatus ?? "");
|
||||||
|
return Boolean(date) || status === "confirmed";
|
||||||
|
};
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@
|
||||||
import { describe, it, expect } from "vitest";
|
import { describe, it, expect } from "vitest";
|
||||||
import {
|
import {
|
||||||
describeCallProcess,
|
describeCallProcess,
|
||||||
|
isOrderAgreed,
|
||||||
isCallTimeNow,
|
isCallTimeNow,
|
||||||
moscowNow,
|
moscowNow,
|
||||||
nextCallDayLabel,
|
nextCallDayLabel,
|
||||||
|
|
@ -160,3 +161,32 @@ describe("describeCallProcess — что видит логист", () => {
|
||||||
expect(res.title).not.toContain("уже согласован");
|
expect(res.title).not.toContain("уже согласован");
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("isOrderAgreed — когда автодозвон предлагать нельзя", () => {
|
||||||
|
it("дата выбрана — согласован", () => {
|
||||||
|
expect(isOrderAgreed({ delivery_date: "2026-09-18", notification_status: "pickup" })).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("статус «согласовано» — согласован", () => {
|
||||||
|
expect(isOrderAgreed({ notification_status: "confirmed" })).toBe(true);
|
||||||
|
expect(isOrderAgreed({ notificationStatus: "confirmed" })).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("«ручное управление» — НЕ согласован: клиент дату не выбрал", () => {
|
||||||
|
expect(isOrderAgreed({ notification_status: "manual_required", delivery_date: null })).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("«первое приглашение отправлено» — НЕ согласован", () => {
|
||||||
|
expect(isOrderAgreed({ notification_status: "first_sms_sent" })).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("«не звонить» само по себе не делает заказ согласованным", () => {
|
||||||
|
expect(isOrderAgreed({ notification_status: "first_sms_sent", autocall_opt_out: true })).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("пустой заказ — не согласован", () => {
|
||||||
|
expect(isOrderAgreed(null)).toBe(false);
|
||||||
|
expect(isOrderAgreed(undefined)).toBe(false);
|
||||||
|
expect(isOrderAgreed({})).toBe(false);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue