feat(autocall): локация без звонков помечена «Не звоним (город)»
Заказ из города, выключенного для звонков (Настройки → Коммуникации → Автодозвон → 📍 Локации), больше не выглядит как «звонка не было»: - autocall_status(og) отдаёт новый статус city_disabled (порядок: ручной запрет → локация выключена → исключение по номеру → журнал звонков); - бейдж в реестре: 🚫 не звоним, виден и в завершённом заказе; - фильтр «Статус автодозвона»: «Не звоним (город)»; - карточка «Автодозвон»: пояснение «Не звоним — <город>», кнопка «Позвонить сейчас» заблокирована (планировщик такие заявки пропускает); - сводка заказа и шаг «Звонок» в цепочке: «не звоним (локация выключена)»; - в детальную выборку группы добавлены autocall_status/exclusion_reason; - SW-кэш static-v129. На SMS выключение локации не влияет — уведомления продолжают уходить.
This commit is contained in:
parent
20e942235a
commit
4cf5c0ffab
|
|
@ -1,7 +1,7 @@
|
||||||
const isLocalhost = self.location.hostname === "localhost" || self.location.hostname === "127.0.0.1";
|
const isLocalhost = self.location.hostname === "localhost" || self.location.hostname === "127.0.0.1";
|
||||||
|
|
||||||
if (!isLocalhost) {
|
if (!isLocalhost) {
|
||||||
const STATIC_CACHE = "construction-delivery-static-v128";
|
const STATIC_CACHE = "construction-delivery-static-v129";
|
||||||
const RUNTIME_CACHE = "construction-delivery-runtime-v119";
|
const RUNTIME_CACHE = "construction-delivery-runtime-v119";
|
||||||
const APP_SHELL_URLS = ["/", "/client", "/index.html", "/manifest.webmanifest", "/icons/icon-192.png", "/icons/icon-512.png"];
|
const APP_SHELL_URLS = ["/", "/client", "/index.html", "/manifest.webmanifest", "/icons/icon-192.png", "/icons/icon-512.png"];
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,57 @@
|
||||||
|
-- Заказ из локации, где звонки выключены (Настройки -> Коммуникации -> Автодозвон -> Локации),
|
||||||
|
-- помечается статусом city_disabled = «Не звоним (город)». На SMS это не влияет.
|
||||||
|
-- Порядок: ручной запрет -> локация выключена -> исключение по номеру -> журнал звонков.
|
||||||
|
|
||||||
|
CREATE OR REPLACE FUNCTION public.autocall_status(og public.order_groups)
|
||||||
|
RETURNS text
|
||||||
|
LANGUAGE sql
|
||||||
|
STABLE SECURITY DEFINER
|
||||||
|
SET search_path TO 'public'
|
||||||
|
AS $function$
|
||||||
|
select case
|
||||||
|
when og.autocall_opt_out then 'opt_out'
|
||||||
|
when exists (
|
||||||
|
select 1 from public.autocall_city_rules c
|
||||||
|
where btrim(c.city) = btrim(coalesce(og.town, ''))
|
||||||
|
and c.calls_enabled = false
|
||||||
|
) then 'city_disabled'
|
||||||
|
when exists (
|
||||||
|
select 1 from public.autocall_exclusions e
|
||||||
|
where e.active
|
||||||
|
and (
|
||||||
|
(e.rule_type = 'phone' and coalesce(og.customer_phone_normalized, regexp_replace(coalesce(og.customer_phone,''),'\D','','g')) = e.value)
|
||||||
|
or
|
||||||
|
(e.rule_type = 'prefix' and coalesce(og.customer_phone_normalized, regexp_replace(coalesce(og.customer_phone,''),'\D','','g')) like e.value || '%')
|
||||||
|
)
|
||||||
|
) then 'excluded'
|
||||||
|
when not exists (select 1 from public.autocall_log l where l.order_group_id = og.id) then 'not_called'
|
||||||
|
when exists (
|
||||||
|
select 1 from public.autocall_log l
|
||||||
|
where l.order_group_id = og.id
|
||||||
|
and l.outcome in ('confirmed','confirmed_silent','confirmed_kept_previous')
|
||||||
|
) then 'confirmed'
|
||||||
|
else (
|
||||||
|
select case
|
||||||
|
when l.outcome = 'no_answer' then 'no_answer'
|
||||||
|
when l.outcome in ('no_input_day','no_input_half') then
|
||||||
|
case
|
||||||
|
when exists (select 1 from public.autocall_log l2
|
||||||
|
where l2.order_group_id = og.id and l2.outcome = 'no_input_day')
|
||||||
|
and exists (select 1 from public.autocall_log l3
|
||||||
|
where l3.order_group_id = og.id and l3.outcome = 'no_input_half')
|
||||||
|
then 'no_input_both'
|
||||||
|
when l.outcome = 'no_input_half' then 'no_input_half'
|
||||||
|
else 'no_input_day'
|
||||||
|
end
|
||||||
|
when l.outcome in ('operator','error','invalid_number') then 'manual'
|
||||||
|
else 'not_called'
|
||||||
|
end
|
||||||
|
from public.autocall_log l
|
||||||
|
where l.order_group_id = og.id
|
||||||
|
order by l.created_at desc
|
||||||
|
limit 1
|
||||||
|
)
|
||||||
|
end;
|
||||||
|
$function$;
|
||||||
|
|
||||||
|
NOTIFY pgrst, 'reload schema';
|
||||||
|
|
@ -27,6 +27,7 @@ const STYLES = {
|
||||||
manual: "bg-[rgba(245,158,11,0.14)] text-[var(--color-warning)]",
|
manual: "bg-[rgba(245,158,11,0.14)] text-[var(--color-warning)]",
|
||||||
opt_out: "bg-[rgba(239,68,68,0.14)] text-[var(--color-danger)]",
|
opt_out: "bg-[rgba(239,68,68,0.14)] text-[var(--color-danger)]",
|
||||||
excluded: "bg-[var(--color-surface-strong)] text-[var(--color-text-muted)]",
|
excluded: "bg-[var(--color-surface-strong)] text-[var(--color-text-muted)]",
|
||||||
|
city_disabled: "bg-[var(--color-surface-strong)] text-[var(--color-text-muted)]",
|
||||||
not_called: "bg-[var(--color-surface-strong)] text-[var(--color-text-muted)]",
|
not_called: "bg-[var(--color-surface-strong)] text-[var(--color-text-muted)]",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -39,6 +40,7 @@ const TITLES = {
|
||||||
manual: "Нужен менеджер: неверный номер или ошибка звонка",
|
manual: "Нужен менеджер: неверный номер или ошибка звонка",
|
||||||
opt_out: "Звонки по этому клиенту запрещены вручную",
|
opt_out: "Звонки по этому клиенту запрещены вручную",
|
||||||
excluded: "Исключение: по этому номеру или городу не звоним",
|
excluded: "Исключение: по этому номеру или городу не звоним",
|
||||||
|
city_disabled: "Локация выключена для звонков: робот по этому городу не набирает (SMS продолжают уходить)",
|
||||||
not_called: "Автодозвона по заказу ещё не было",
|
not_called: "Автодозвона по заказу ещё не было",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -57,6 +57,14 @@ describe("resolveCallBadge — что видно в строке", () => {
|
||||||
expect(excluded.title).toContain("МТС-диапазон");
|
expect(excluded.title).toContain("МТС-диапазон");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("выключенная локация помечена «не звоним» и видна в завершённом заказе", () => {
|
||||||
|
const badge = resolveCallBadge(group({ autocallStatus: "city_disabled", town: "Ялта", deliveryStatus: "delivered" }));
|
||||||
|
expect(badge.label).toContain("не звоним");
|
||||||
|
expect(badge.title).toContain("Локация выключена для звонков");
|
||||||
|
expect(AUTOCALL_STATUS_META.city_disabled.label).toBe("Не звоним (город)");
|
||||||
|
expect(AUTOCALL_STATUS_OPTIONS.map((o) => o.value)).toContain("city_disabled");
|
||||||
|
});
|
||||||
|
|
||||||
it("неизвестный статус не рисуем", () => {
|
it("неизвестный статус не рисуем", () => {
|
||||||
expect(resolveCallBadge(group({ autocallStatus: "какой-то-старый" }))).toBeNull();
|
expect(resolveCallBadge(group({ autocallStatus: "какой-то-старый" }))).toBeNull();
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@
|
||||||
import React, { useState, useEffect, useCallback, useMemo } from "react";
|
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, isCityCallsDisabled } from "../../services/orderGroupViews";
|
||||||
import { describeCallProcess, isOrderAgreed } from "../../services/autocallProcess";
|
import { describeCallProcess, isOrderAgreed } from "../../services/autocallProcess";
|
||||||
import { isAutocallPossible } from "../../services/autocallAvailability";
|
import { isAutocallPossible } from "../../services/autocallAvailability";
|
||||||
import { autocallSlotText } from "./autocallSlot";
|
import { autocallSlotText } from "./autocallSlot";
|
||||||
|
|
@ -43,6 +43,10 @@ export const AutocallStatusCard = ({ order, userRole }) => {
|
||||||
const optOut = order.autocall_opt_out ?? order.autocallOptOut ?? false;
|
const optOut = order.autocall_opt_out ?? order.autocallOptOut ?? false;
|
||||||
const isAutocall = order.delivery_date_source === "autocall" || order.deliveryDateSource === "autocall";
|
const isAutocall = order.delivery_date_source === "autocall" || order.deliveryDateSource === "autocall";
|
||||||
const exclusionReason = order.autocall_exclusion_reason || order.autocallExclusionReason || null;
|
const exclusionReason = order.autocall_exclusion_reason || order.autocallExclusionReason || null;
|
||||||
|
// Локация выключена для звонков (админка автодозвона) — робот по ней не набирает,
|
||||||
|
// ни массово, ни по заявке «Позвонить сейчас». Клиент получает SMS со ссылкой.
|
||||||
|
const cityDisabled = isCityCallsDisabled(order);
|
||||||
|
const town = order.town || order.city || "";
|
||||||
|
|
||||||
const loadCalls = useCallback(async () => {
|
const loadCalls = useCallback(async () => {
|
||||||
if (!order?.id) return;
|
if (!order?.id) return;
|
||||||
|
|
@ -230,7 +234,7 @@ export const AutocallStatusCard = ({ order, userRole }) => {
|
||||||
const lastSlot = lastCall ? autocallSlotText(lastCall, order) : null;
|
const lastSlot = lastCall ? autocallSlotText(lastCall, order) : null;
|
||||||
|
|
||||||
// Единый человеческий статус (по аналогии со статусом SMS)
|
// Единый человеческий статус (по аналогии со статусом SMS)
|
||||||
const statusKey = resolveAutocallStatus(calls, { optOut, exclusionReason });
|
const statusKey = resolveAutocallStatus(calls, { optOut, exclusionReason, cityDisabled });
|
||||||
const statusMeta = AUTOCALL_STATUS_META[statusKey] || AUTOCALL_STATUS_META.not_called;
|
const statusMeta = AUTOCALL_STATUS_META[statusKey] || AUTOCALL_STATUS_META.not_called;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
@ -252,6 +256,14 @@ export const AutocallStatusCard = ({ order, userRole }) => {
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
{/* Локация выключена для звонков — почему звонка не было и не будет */}
|
||||||
|
{cityDisabled && (
|
||||||
|
<div className="mb-3 rounded-lg bg-[var(--color-surface-strong)] px-2.5 py-1.5 text-[11px] text-[var(--color-text-muted)]">
|
||||||
|
🚫 Не звоним{town ? ` — ${town}` : ""}: локация выключена для звонков. Уведомления по ней уходят
|
||||||
|
SMS со ссылкой. Включается в Настройки → Коммуникации → Автодозвон → 📍 Локации.
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
{/* Счётчик попыток — как у SMS «Попыток отправки: N» */}
|
{/* Счётчик попыток — как у SMS «Попыток отправки: N» */}
|
||||||
{calls.length > 0 && (
|
{calls.length > 0 && (
|
||||||
<div className="mb-2 text-[11px] text-[var(--color-text-muted)]">
|
<div className="mb-2 text-[11px] text-[var(--color-text-muted)]">
|
||||||
|
|
@ -356,13 +368,15 @@ export const AutocallStatusCard = ({ order, userRole }) => {
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={handleCallNow}
|
onClick={handleCallNow}
|
||||||
disabled={sending || processing || optOut || autocallBlocked || orderAgreed}
|
disabled={sending || processing || optOut || autocallBlocked || orderAgreed || cityDisabled}
|
||||||
title={
|
title={
|
||||||
orderAgreed
|
cityDisabled
|
||||||
? "Заказ уже согласован — звонок робота не нужен"
|
? `Звонки по локации «${town || "город"}» выключены — включите их в Настройки → Коммуникации → Автодозвон → 📍 Локации`
|
||||||
: autocallBlocked
|
: orderAgreed
|
||||||
? (availability?.reason || "Автодозвон недоступен")
|
? "Заказ уже согласован — звонок робота не нужен"
|
||||||
: undefined
|
: autocallBlocked
|
||||||
|
? (availability?.reason || "Автодозвон недоступен")
|
||||||
|
: undefined
|
||||||
}
|
}
|
||||||
className="rounded-xl border border-[var(--color-accent)] px-3 py-1.5 text-xs font-medium text-[var(--color-accent)] hover:bg-[var(--color-accent-soft)] disabled:opacity-50"
|
className="rounded-xl border border-[var(--color-accent)] px-3 py-1.5 text-xs font-medium text-[var(--color-accent)] hover:bg-[var(--color-accent-soft)] disabled:opacity-50"
|
||||||
>
|
>
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
import React, { useEffect, useState, useMemo } from "react";
|
import React, { useEffect, useState, useMemo } from "react";
|
||||||
import { supabase } from "../../supabaseClient";
|
import { supabase } from "../../supabaseClient";
|
||||||
import { autocallSlotText } from "./autocallSlot";
|
import { autocallSlotText } from "./autocallSlot";
|
||||||
|
import { isCityCallsDisabled } from "../../services/orderGroupViews";
|
||||||
|
|
||||||
// ─── Status labels ──────────────────────────────────────────────────
|
// ─── Status labels ──────────────────────────────────────────────────
|
||||||
const STATUS_LABELS = {
|
const STATUS_LABELS = {
|
||||||
|
|
@ -203,8 +204,12 @@ export const getAutocallStepState = (autocallLogs = []) => {
|
||||||
};
|
};
|
||||||
|
|
||||||
// Подсказка к шагу (title на десктопе): сколько было звонков и чем кончился последний.
|
// Подсказка к шагу (title на десктопе): сколько было звонков и чем кончился последний.
|
||||||
export const autocallStepHint = (autocallLogs = [], order = null) => {
|
// Если звонков не было, а локация выключена для звонков — так и говорим, а не «Звонков не было».
|
||||||
if (!Array.isArray(autocallLogs) || autocallLogs.length === 0) return "Звонков не было";
|
export const autocallStepHint = (autocallLogs = [], order = null, cityDisabled = false) => {
|
||||||
|
if (!Array.isArray(autocallLogs) || autocallLogs.length === 0) {
|
||||||
|
const off = cityDisabled || isCityCallsDisabled(order);
|
||||||
|
return off ? "Локация выключена для звонков — робот сюда не звонит" : "Звонков не было";
|
||||||
|
}
|
||||||
const last = autocallLogs[0];
|
const last = autocallLogs[0];
|
||||||
const meta = AUTOCALL_OUTCOME_LABELS[last?.outcome];
|
const meta = AUTOCALL_OUTCOME_LABELS[last?.outcome];
|
||||||
const what = meta ? meta.label.replace(/^Автодозвон:\s*/, "") : (last?.outcome || "—");
|
const what = meta ? meta.label.replace(/^Автодозвон:\s*/, "") : (last?.outcome || "—");
|
||||||
|
|
@ -431,7 +436,12 @@ const StatusSummary = ({ order, smsLogs = [], autocallLogs = [] }) => {
|
||||||
tone: acMeta.tone,
|
tone: acMeta.tone,
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
items.push({ icon: "🤖", label: "Автодозвон", value: "не звонили", tone: "muted" });
|
items.push({
|
||||||
|
icon: "🤖",
|
||||||
|
label: "Автодозвон",
|
||||||
|
value: isCityCallsDisabled(order) ? "не звоним (локация выключена)" : "не звонили",
|
||||||
|
tone: "muted",
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Driver (delivery only)
|
// Driver (delivery only)
|
||||||
|
|
|
||||||
|
|
@ -389,6 +389,9 @@ export const AUTOCALL_STATUS_META = {
|
||||||
manual: { label: "Нужен менеджер", short: "нужен менеджер", tone: "warning", icon: "🆘" },
|
manual: { label: "Нужен менеджер", short: "нужен менеджер", tone: "warning", icon: "🆘" },
|
||||||
opt_out: { label: "Не звонить", short: "не звонить", tone: "danger", icon: "🚫" },
|
opt_out: { label: "Не звонить", short: "не звонить", tone: "danger", icon: "🚫" },
|
||||||
excluded: { label: "Не звоним (исключение)", short: "исключение", tone: "neutral", icon: "🚫" },
|
excluded: { label: "Не звоним (исключение)", short: "исключение", tone: "neutral", icon: "🚫" },
|
||||||
|
// Локация выключена для звонков в админке (Настройки → Коммуникации → Автодозвон → Локации).
|
||||||
|
// Считается в БД (autocall_status), на SMS не влияет.
|
||||||
|
city_disabled: { label: "Не звоним (город)", short: "не звоним", tone: "neutral", icon: "🚫" },
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Порядок для выпадающих списков — один список на всё приложение. */
|
/** Порядок для выпадающих списков — один список на всё приложение. */
|
||||||
|
|
@ -402,6 +405,7 @@ export const AUTOCALL_STATUS_OPTIONS = [
|
||||||
{ value: "manual", label: "Нужен менеджер" },
|
{ value: "manual", label: "Нужен менеджер" },
|
||||||
{ value: "opt_out", label: "Не звонить (запрет вручную)" },
|
{ value: "opt_out", label: "Не звонить (запрет вручную)" },
|
||||||
{ value: "excluded", label: "Не звоним (исключение)" },
|
{ value: "excluded", label: "Не звоним (исключение)" },
|
||||||
|
{ value: "city_disabled", label: "Не звоним (город)" },
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -421,8 +425,20 @@ export const resolveNoInputKind = (calls = []) => {
|
||||||
return null;
|
return null;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const resolveAutocallStatus = (calls = [], { optOut = false, exclusionReason = null } = {}) => {
|
/**
|
||||||
|
* Локация выключена для звонков (Настройки → Коммуникации → Автодозвон → 📍 Локации).
|
||||||
|
* Источник — то же значение, что считает БД (`autocall_status` = 'city_disabled'),
|
||||||
|
* плюс явный флаг, если объект пришёл не из реестра.
|
||||||
|
*/
|
||||||
|
export const isCityCallsDisabled = (group) =>
|
||||||
|
(group?.autocall_status || group?.autocallStatus) === "city_disabled" ||
|
||||||
|
Boolean(group?.cityCallsDisabled ?? group?.city_calls_disabled);
|
||||||
|
|
||||||
|
export const resolveAutocallStatus = (calls = [], { optOut = false, exclusionReason = null, cityDisabled = false } = {}) => {
|
||||||
if (optOut) return "opt_out";
|
if (optOut) return "opt_out";
|
||||||
|
// Локация выключена для звонков: робот по ней не набирает вообще — это важнее
|
||||||
|
// частного исключения по номеру.
|
||||||
|
if (cityDisabled) return "city_disabled";
|
||||||
if (exclusionReason) return "excluded";
|
if (exclusionReason) return "excluded";
|
||||||
if (!Array.isArray(calls) || calls.length === 0) return "not_called";
|
if (!Array.isArray(calls) || calls.length === 0) return "not_called";
|
||||||
const last = calls[0];
|
const last = calls[0];
|
||||||
|
|
@ -609,6 +625,7 @@ export const filterOrderGroups = (groups, filters = {}) => {
|
||||||
const acStatus = group.autocall_status || group.autocallStatus || resolveAutocallStatus([], {
|
const acStatus = group.autocall_status || group.autocallStatus || resolveAutocallStatus([], {
|
||||||
optOut: group.autocall_opt_out,
|
optOut: group.autocall_opt_out,
|
||||||
exclusionReason: group.autocall_exclusion_reason,
|
exclusionReason: group.autocall_exclusion_reason,
|
||||||
|
cityDisabled: isCityCallsDisabled(group),
|
||||||
});
|
});
|
||||||
if (acStatus !== autocallStatus) return false;
|
if (acStatus !== autocallStatus) return false;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,8 @@ import {
|
||||||
groupOrderGroupsByDate,
|
groupOrderGroupsByDate,
|
||||||
isOrderGroupAgreedForDelivery,
|
isOrderGroupAgreedForDelivery,
|
||||||
isOrderGroupVisibleToDriver,
|
isOrderGroupVisibleToDriver,
|
||||||
|
isCityCallsDisabled,
|
||||||
|
resolveAutocallStatus,
|
||||||
} from "./orderGroupViews";
|
} from "./orderGroupViews";
|
||||||
|
|
||||||
describe("orderGroupViews", () => {
|
describe("orderGroupViews", () => {
|
||||||
|
|
@ -208,3 +210,27 @@ describe("resolveConfirmChannel — как согласовали дату", ()
|
||||||
expect(confirmChannelMeta({})).toBeNull();
|
expect(confirmChannelMeta({})).toBeNull();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("«Не звоним» по локации (city_disabled)", () => {
|
||||||
|
it("флаг берётся из статуса, который считает БД", () => {
|
||||||
|
expect(isCityCallsDisabled({ autocall_status: "city_disabled" })).toBe(true);
|
||||||
|
expect(isCityCallsDisabled({ autocallStatus: "city_disabled", town: "Ялта" })).toBe(true);
|
||||||
|
expect(isCityCallsDisabled({ autocall_status: "not_called" })).toBe(false);
|
||||||
|
expect(isCityCallsDisabled(null)).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("ручной запрет важнее локации, локация важнее исключения по номеру", () => {
|
||||||
|
expect(resolveAutocallStatus([], { cityDisabled: true })).toBe("city_disabled");
|
||||||
|
expect(resolveAutocallStatus([], { cityDisabled: true, exclusionReason: "МТС-диапазон" })).toBe("city_disabled");
|
||||||
|
expect(resolveAutocallStatus([], { cityDisabled: true, optOut: true })).toBe("opt_out");
|
||||||
|
expect(resolveAutocallStatus([], { exclusionReason: "МТС-диапазон" })).toBe("excluded");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("фильтр реестра находит заказы выключенной локации", () => {
|
||||||
|
const groups = [
|
||||||
|
{ id: "a", town: "Ялта", cityCallsDisabled: true, deliveryStatus: "pending_confirmation" },
|
||||||
|
{ id: "b", town: "Севастополь", deliveryStatus: "pending_confirmation" },
|
||||||
|
];
|
||||||
|
expect(filterOrderGroups(groups, { autocallStatus: "city_disabled" }).map((g) => g.id)).toEqual(["a"]);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
|
||||||
|
|
@ -300,7 +300,7 @@ export const mapOrderGroupRowToDeliveryGroup = (row) => {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
const ORDER_GROUP_SELECT_FIELDS = `id, group_key, order_numbers, status, delivery_status, sms_sent_at, created_at, updated_at, created_from_exchange_at, source_key, town, customer_name, customer_phone, customer_phone_normalized, customer_date, orders_total, orders_ready, orders_not_ready, source_orders, order_list, order_list_structured, delivery_invitation_id, delivery_link, delivery_link_code, notification_status, sms_attempts, first_sms_sent_at, second_sms_sent_at, last_sms_error, next_notification_check_at, delivery_date, delivery_time, delivery_address, customer_address, delivery_date_source, autocall_opt_out, manual_confirmation_at, paid_storage_at, assigned_driver_id, assigned_driver:users!order_groups_assigned_driver_id_fkey(id, name), driver_shipment_data, delivery_type, pickup_date, pickup_time_slot, has_delivery_problem, delivery_problem_note, pickup_code, synced_to_1c_at, manager_name, manager_email, manager_tel, payed_ship, is_payed_ship, delivery_invitation:delivery_invitations!order_groups_delivery_invitation_id_fkey(confirmed_at, opened_at, access_count, last_accessed_at), called, called_at, called_comment, order_history(id, action, old_status, new_status, user_id, metadata, created_at)`;
|
const ORDER_GROUP_SELECT_FIELDS = `id, group_key, order_numbers, status, delivery_status, sms_sent_at, created_at, updated_at, created_from_exchange_at, source_key, town, customer_name, customer_phone, customer_phone_normalized, customer_date, orders_total, orders_ready, orders_not_ready, source_orders, order_list, order_list_structured, delivery_invitation_id, delivery_link, delivery_link_code, notification_status, sms_attempts, first_sms_sent_at, second_sms_sent_at, last_sms_error, next_notification_check_at, delivery_date, delivery_time, delivery_address, customer_address, delivery_date_source, autocall_opt_out, manual_confirmation_at, paid_storage_at, assigned_driver_id, assigned_driver:users!order_groups_assigned_driver_id_fkey(id, name), driver_shipment_data, delivery_type, pickup_date, pickup_time_slot, has_delivery_problem, delivery_problem_note, pickup_code, synced_to_1c_at, manager_name, manager_email, manager_tel, payed_ship, is_payed_ship, delivery_invitation:delivery_invitations!order_groups_delivery_invitation_id_fkey(confirmed_at, opened_at, access_count, last_accessed_at), called, called_at, called_comment, autocall_status, autocall_exclusion_reason, order_history(id, action, old_status, new_status, user_id, metadata, created_at)`;
|
||||||
export const ORDER_GROUP_LIST_SELECT_FIELDS = `id, group_key, order_numbers, status, delivery_status, sms_sent_at, created_at, updated_at, created_from_exchange_at, source_key, town, customer_name, customer_phone, customer_phone_normalized, customer_date, orders_total, orders_ready, orders_not_ready, notification_status, sms_attempts, last_sms_error, first_sms_sent_at, second_sms_sent_at, delivery_date, delivery_time, delivery_address, customer_address, delivery_date_source, autocall_opt_out, manual_confirmation_at, paid_storage_at, assigned_driver_id, assigned_driver:users!order_groups_assigned_driver_id_fkey(id, name), driver_shipment_data, delivery_type, pickup_date, pickup_time_slot, has_delivery_problem, delivery_problem_note, pickup_code, synced_to_1c_at, manager_name, manager_email, manager_tel, payed_ship, is_payed_ship, called, called_at, called_comment, autocall_exclusion_reason, autocall_status, delivery_invitation:delivery_invitations!order_groups_delivery_invitation_id_fkey(confirmed_at)`;
|
export const ORDER_GROUP_LIST_SELECT_FIELDS = `id, group_key, order_numbers, status, delivery_status, sms_sent_at, created_at, updated_at, created_from_exchange_at, source_key, town, customer_name, customer_phone, customer_phone_normalized, customer_date, orders_total, orders_ready, orders_not_ready, notification_status, sms_attempts, last_sms_error, first_sms_sent_at, second_sms_sent_at, delivery_date, delivery_time, delivery_address, customer_address, delivery_date_source, autocall_opt_out, manual_confirmation_at, paid_storage_at, assigned_driver_id, assigned_driver:users!order_groups_assigned_driver_id_fkey(id, name), driver_shipment_data, delivery_type, pickup_date, pickup_time_slot, has_delivery_problem, delivery_problem_note, pickup_code, synced_to_1c_at, manager_name, manager_email, manager_tel, payed_ship, is_payed_ship, called, called_at, called_comment, autocall_exclusion_reason, autocall_status, delivery_invitation:delivery_invitations!order_groups_delivery_invitation_id_fkey(confirmed_at)`;
|
||||||
|
|
||||||
// Delivery statuses treated as "finished" — hidden by default in the board.
|
// Delivery statuses treated as "finished" — hidden by default in the board.
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue