feat: колонка has_delivery_problem + delivery_problem_note
- saveShipmentData автоматически заполняет has_delivery_problem (boolean) и delivery_problem_note (текст с перечислением неотгруженных позиций и причин) - OrdersTable: колонка 'Проблема' показывает ⚠ Проблема + детали из delivery_problem_note - orderGroupViews: warning-тон для групп с hasDeliveryProblem - n8n/1C: просто читать has_delivery_problem (0/1) и delivery_problem_note
This commit is contained in:
parent
187ef90c96
commit
b888eba09b
|
|
@ -136,29 +136,17 @@ export const OrdersTable = ({
|
|||
|
||||
<div className="mt-3 text-sm text-[var(--color-text-muted)]">{buildGroupSummary(group)}</div>
|
||||
<div className="mt-2 text-sm text-[var(--color-text-muted)]">{renderMobileOrderNumbers(group)}</div>
|
||||
{(() => {
|
||||
const issues = getShipmentIssues(group);
|
||||
const data = group?.driverShipmentData;
|
||||
if (!Array.isArray(data) || data.length === 0) return null;
|
||||
const shippedCount = data.filter((i) => i.shipped).length;
|
||||
const total = data.length;
|
||||
if (issues && issues.length > 0) {
|
||||
return (
|
||||
{group.hasDeliveryProblem && (
|
||||
<div className="mt-2 rounded-lg border border-[var(--color-warning)] bg-[var(--color-warning-soft)] px-2 py-1 text-xs">
|
||||
<span className="font-medium text-[var(--color-warning)]">⚠ Отгрузка: {shippedCount}/{total}</span>
|
||||
<span className="text-[var(--color-text-muted)]"> — {issues.slice(0, 2).map((i) => i.name).join(", ")}{issues.length > 2 ? ` +${issues.length - 2}` : ""}</span>
|
||||
{issues.some((i) => i.comment) && (
|
||||
<div className="mt-0.5 text-[var(--color-text-muted)]">{issues.filter((i) => i.comment).slice(0, 1).map((i) => i.comment)}</div>
|
||||
<span className="font-medium text-[var(--color-warning)]">⚠ Проблема с доставкой</span>
|
||||
{group.deliveryProblemNote && (
|
||||
<div className="mt-0.5 text-[var(--color-text-muted)]">{group.deliveryProblemNote}</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<div className="mt-2 text-xs text-[var(--color-accent)]">
|
||||
✓ Отгружено: {total}/{total}
|
||||
</div>
|
||||
);
|
||||
})()}
|
||||
)}
|
||||
{!group.hasDeliveryProblem && Array.isArray(group?.driverShipmentData) && group.driverShipmentData.length > 0 && (
|
||||
<div className="mt-2 text-xs text-[var(--color-accent)]">✓ Доставка без проблем</div>
|
||||
)}
|
||||
<div className="mt-3 text-xs text-[var(--color-text-muted)]">
|
||||
{formatDateTime(group.updatedAt)}
|
||||
</div>
|
||||
|
|
@ -179,7 +167,7 @@ export const OrdersTable = ({
|
|||
<div className="px-5 py-4 font-medium">Статус</div>
|
||||
<div className="px-5 py-4 font-medium">Водитель</div>
|
||||
<div className="px-5 py-4 font-medium">Дата доставки</div>
|
||||
<div className="px-5 py-4 font-medium">Отгрузка</div>
|
||||
<div className="px-5 py-4 font-medium">Проблема</div>
|
||||
<div className="px-5 py-4 font-medium">Обновлён</div>
|
||||
</div>
|
||||
{orderGroups.map((group) => (
|
||||
|
|
@ -213,26 +201,20 @@ export const OrdersTable = ({
|
|||
)}
|
||||
</div>
|
||||
<div className="px-5 py-4 text-sm">
|
||||
{(() => {
|
||||
const issues = getShipmentIssues(group);
|
||||
const data = group?.driverShipmentData;
|
||||
if (!Array.isArray(data) || data.length === 0) {
|
||||
return <span className="text-[var(--color-text-muted)]">—</span>;
|
||||
}
|
||||
const shippedCount = data.filter((i) => i.shipped).length;
|
||||
const total = data.length;
|
||||
if (issues && issues.length > 0) {
|
||||
return (
|
||||
{group.hasDeliveryProblem ? (
|
||||
<div>
|
||||
<span className="text-[var(--color-warning)] font-medium">⚠ {shippedCount}/{total}</span>
|
||||
<div className="mt-0.5 text-xs text-[var(--color-text-muted)]">
|
||||
{issues.slice(0, 2).map((i) => i.name).join(", ")}{issues.length > 2 ? ` +${issues.length - 2}` : ""}
|
||||
<span className="text-[var(--color-warning)] font-medium">⚠ Проблема</span>
|
||||
{group.deliveryProblemNote && (
|
||||
<div className="mt-0.5 text-xs text-[var(--color-text-muted)] line-clamp-2">
|
||||
{group.deliveryProblemNote}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
return <span className="text-[var(--color-accent)]">✓ {total}/{total}</span>;
|
||||
})()}
|
||||
) : Array.isArray(group?.driverShipmentData) && group.driverShipmentData.length > 0 ? (
|
||||
<span className="text-[var(--color-accent)]">✓ Ок</span>
|
||||
) : (
|
||||
<span className="text-[var(--color-text-muted)]">—</span>
|
||||
)}
|
||||
</div>
|
||||
<div className="px-5 py-4 text-sm text-[var(--color-text-muted)]">
|
||||
{formatDateTime(group.updatedAt)}
|
||||
|
|
|
|||
|
|
@ -461,12 +461,8 @@ export const buildOrderGroupBuckets = (groups) => {
|
|||
export const getOrderGroupStatusTone = (group) => {
|
||||
const deliveryStatus = group?.deliveryStatus || group?.delivery_status;
|
||||
|
||||
// Highlight groups with shipment issues (partial delivery)
|
||||
const shipmentData = group?.driverShipmentData;
|
||||
if (Array.isArray(shipmentData) && shipmentData.length > 0) {
|
||||
const hasIssues = shipmentData.some((i) => !i.shipped);
|
||||
if (hasIssues) return "warning";
|
||||
}
|
||||
// Highlight groups with delivery problems
|
||||
if (group?.hasDeliveryProblem) return "warning";
|
||||
|
||||
if (deliveryStatus && deliveryStatus !== "pending_confirmation") {
|
||||
return getOrderGroupDeliveryStatusTone(deliveryStatus);
|
||||
|
|
|
|||
|
|
@ -221,6 +221,8 @@ export const mapOrderGroupRowToDeliveryGroup = (row) => {
|
|||
pickupDate: row.pickup_date || null,
|
||||
pickupTimeSlot: row.pickup_time_slot || null,
|
||||
driverShipmentData: row.driver_shipment_data || null,
|
||||
hasDeliveryProblem: row.has_delivery_problem || false,
|
||||
deliveryProblemNote: row.delivery_problem_note || null,
|
||||
syncedTo1cAt: row.synced_to_1c_at || null,
|
||||
deliveryHalfDay: getOrderGroupDeliveryHalfDay({
|
||||
deliveryHalfDay: rawDeliveryHalfDay,
|
||||
|
|
@ -262,7 +264,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, 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, 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, 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, synced_to_1c_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, 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, 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, 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, synced_to_1c_at`;
|
||||
|
||||
export const updateOrderGroupDeliveryChoice = async ({
|
||||
orderGroupId,
|
||||
|
|
@ -391,11 +393,18 @@ export const assignDriverToOrderGroup = async ({
|
|||
export const saveShipmentData = async ({ orderGroupId, shipmentData }) => {
|
||||
return safeSupabaseCall(async () => {
|
||||
const client = requireSupabase();
|
||||
const unshipped = shipmentData.filter((i) => !i.shipped);
|
||||
const hasProblem = unshipped.length > 0;
|
||||
const problemNote = hasProblem
|
||||
? unshipped.map((i) => `${i.name}${i.quantity ? ` (${i.quantity}${i.unit ? ` ${i.unit}` : ""})` : ""}${i.comment ? ` — ${i.comment}` : ""}`).join("; ")
|
||||
: null;
|
||||
|
||||
const { error: updateError } = await client
|
||||
.from("order_groups")
|
||||
.update({
|
||||
driver_shipment_data: shipmentData,
|
||||
has_delivery_problem: hasProblem,
|
||||
delivery_problem_note: problemNote,
|
||||
updated_at: new Date().toISOString(),
|
||||
})
|
||||
.eq("id", orderGroupId);
|
||||
|
|
|
|||
Loading…
Reference in New Issue