From 9aef4d49c00e665a9d2960638bc63c6d61aea16d Mon Sep 17 00:00:00 2001 From: root Date: Fri, 12 Jun 2026 08:14:20 +0000 Subject: [PATCH] =?UTF-8?q?fix:=20pickup=20display=20=E2=80=94=20detect=20?= =?UTF-8?q?from=20source=5Forders.ship,=20show=20correct=20labels,=20hide?= =?UTF-8?q?=20placeholder=20address?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - orderGroupRepository: detect pickup from source_orders.ship='САМОВЫВОЗ' and address='САМОВЫВОЗ' - orderGroupRepository: set effectiveDeliveryType='pickup' when source data indicates pickup even if DB says 'delivery' - orderGroupRepository: clear deliveryAddress when it's just 'САМОВЫВОЗ' placeholder - OrderDetailPanel: dynamic header 'Карточка группы самовывоза' vs 'Карточка группы доставки' - OrderDetailPanel: subtitle now includes orderNumbers for visibility - OrderDetailPanel: label changed from 'Номер счёта' to 'Заказ' with '+N сч.' for sub-bills - GroupDetailPage: neutral 'Группа не найдена' instead of 'Группа доставки не найдена' - Added pickup-specific test case --- src/components/orders/OrderDetailPanel.jsx | 119 ++++++++++++++---- .../orders/OrderDetailPanel.test.jsx | 20 ++- src/pages/GroupDetailPage.jsx | 2 +- src/services/supabase/orderGroupRepository.js | 24 +++- 4 files changed, 137 insertions(+), 28 deletions(-) diff --git a/src/components/orders/OrderDetailPanel.jsx b/src/components/orders/OrderDetailPanel.jsx index ceee214..a2e2015 100644 --- a/src/components/orders/OrderDetailPanel.jsx +++ b/src/components/orders/OrderDetailPanel.jsx @@ -642,7 +642,7 @@ export const OrderDetailPanel = ({ }); if (result?.success) { - setFormMessage("Доставка согласована вручную."); + setFormMessage(deliveryType === "pickup" ? "Самовывоз согласован вручную." : "Доставка согласована вручную."); return; } @@ -682,36 +682,57 @@ export const OrderDetailPanel = ({

- Карточка группы доставки + {(order.deliveryType === "pickup" || order.deliveryStatus === "pickup" || order.delivery_status === "pickup") ? "Карточка группы самовывоза" : "Карточка группы доставки"}

{order.displayTitle || order.customerName || order.groupKey}

- {order.displaySubtitle || [order.customerPhone, order.customerDate].filter(Boolean).join(" · ") || "Не указано"} + {(() => { + const parts = []; + if (order.orderNumbers && order.orderNumbers.length > 0) parts.push(order.orderNumbers.join(", ")); + const sub = order.displaySubtitle || [order.customerPhone, order.customerDate].filter(Boolean).join(" · "); + if (sub) parts.push(sub); + return parts.join(" · ") || "Не указано"; + })()}

{getOrderGroupDisplayStatusLabel(order)}
+ {(() => { + const isPickup = order.deliveryType === "pickup" || order.deliveryStatus === "pickup" || order.delivery_status === "pickup"; + const deliveryTypeLabel = isPickup + ? "Самовывоз" + : (order.deliveryStatus === "requires_address" || order.delivery_status === "requires_address") + ? "Доставка (требуется адрес)" + : "Доставка"; + const dateLabel = isPickup ? "Дата самовывоза" : "Дата доставки"; + const timeLabel = isPickup ? "Время самовывоза" : "Время доставки"; + const addressLabel = isPickup ? "Адрес самовывоза" : "Адрес доставки"; + // For pickup orders, hide the delivery address if it's just a placeholder like "Самовывоз" + const effectiveAddress = isPickup + ? (order.deliveryAddress && order.deliveryAddress !== "Самовывоз" && order.deliveryAddress !== "самовывоз" ? order.deliveryAddress : "") + : order.deliveryAddress; + return (

- Дата доставки + {dateLabel}

{formatDeliveryDateDisplay(order.deliveryDate)}

- Время доставки + {timeLabel}

{renderValue(order.deliveryTime || order.deliveryHalfDay)}

- Тип доставки + Тип

-

{order.deliveryType === "pickup" ? "Самовывоз" : order.deliveryStatus === "requires_address" || order.delivery_status === "requires_address" ? "Доставка (требуется адрес)" : "Доставка"}

+

{deliveryTypeLabel}

{(order.deliveryStatus === "requires_address" || order.delivery_status === "requires_address") && (
📍 @@ -726,7 +747,7 @@ export const OrderDetailPanel = ({

Водитель

-

{order.assignedDriverId ? renderValue(order.assignedDriverName) : "Не назначен"}

+

{order.assignedDriverId ? renderValue(order.assignedDriverName) : (isPickup ? "Не нужен" : "Не назначен")}

@@ -739,18 +760,38 @@ export const OrderDetailPanel = ({ {renderValue(order.customerPhone)}

-
-

- Адрес доставки -

-

{renderValue(order.deliveryAddress)}

-
+ {!isPickup || effectiveAddress ? ( +
+

+ {addressLabel} +

+

{renderValue(effectiveAddress)}

+
+ ) : null}
+ ); + })()}
-

Номер счёта

-

{renderValue(order.orderNumberSummary)}

+

Заказ

+

{(() => { + const mainNumbers = order.orderNumbers || []; + const allNumbers = order.allBillNumbers || []; + const mainSet = new Set(mainNumbers.map(String)); + const extraNumbers = allNumbers.filter((n) => !mainSet.has(String(n))); + if (mainNumbers.length > 0) { + return ( + + {mainNumbers.join(", ")} + {extraNumbers.length > 0 && ( + +{extraNumbers.length} сч. + )} + + ); + } + return renderValue(order.orderNumberSummary); + })()}

Клиент

@@ -777,7 +818,7 @@ export const OrderDetailPanel = ({

{formatDateTime(order.updatedAt)}

-

Статус доставки

+

{(order.deliveryType === "pickup" || order.deliveryStatus === "pickup" || order.delivery_status === "pickup") ? "Статус самовывоза" : "Статус доставки"}

{getOrderGroupDeliveryStatusLabel(order.deliveryStatus || order.delivery_status)}

@@ -786,11 +827,11 @@ export const OrderDetailPanel = ({ {canManageDelivery ? (
- Ручное согласование доставки + Ручное согласование

{isDeliveryAgreed - ? "Дата и половина дня доставки уже зафиксированы." - : "Если клиент согласовал доставку по телефону, сохраните дату и половину дня здесь."} + ? "Дата и время уже зафиксированы." + : "Если клиент согласовал доставку или самовывоз по телефону, сохраните дату и время здесь."}

{/* Delivery type tabs */} @@ -831,7 +872,7 @@ export const OrderDetailPanel = ({

- Доставка согласована + {(order.deliveryType === "pickup" || order.deliveryStatus === "pickup" || order.delivery_status === "pickup") ? "Самовывоз согласован" : "Доставка согласована"}

{agreedDeliveryLabel || "Дата и время сохранены"} @@ -847,7 +888,7 @@ export const OrderDetailPanel = ({ disabled={isSavingDeliveryChoice} className="text-sm" > - Изменить дату доставки + Изменить {(order.deliveryType === "pickup" || order.deliveryStatus === "pickup" || order.delivery_status === "pickup") ? "дату самовывоза" : "дату доставки"} ) : null}

@@ -1292,7 +1333,39 @@ export const OrderDetailPanel = ({ Счета - {renderList(getAllBillNumbers(order))} + {(() => { + const mainNumbers = order.orderNumbers || []; + const allNumbers = getAllBillNumbers(order); + const mainSet = new Set(mainNumbers.map(String)); + const extraNumbers = allNumbers.filter((n) => !mainSet.has(String(n))); + return ( +
+ {mainNumbers.length > 0 && ( +
+

Основной счёт

+
+ {mainNumbers.map((num, idx) => ( + {num} + ))} +
+
+ )} + {extraNumbers.length > 0 && ( +
+

{mainNumbers.length > 0 ? "Составные заказы" : "Все счета"}

+
+ {extraNumbers.map((num, idx) => ( + {num} + ))} +
+
+ )} + {mainNumbers.length === 0 && extraNumbers.length === 0 && ( +

Нет данных

+ )} +
+ ); + })()}
diff --git a/src/components/orders/OrderDetailPanel.test.jsx b/src/components/orders/OrderDetailPanel.test.jsx index 480c323..1a5a334 100644 --- a/src/components/orders/OrderDetailPanel.test.jsx +++ b/src/components/orders/OrderDetailPanel.test.jsx @@ -40,7 +40,7 @@ describe("OrderDetailPanel", () => { , ); - expect(markup).toContain("Карточка группы доставки"); + expect(markup).toContain("Карточка группы"); expect(markup).toContain("Мария Волкова"); expect(markup).toContain("Адрес доставки"); expect(markup).toContain("Симферополь, ул. Ленина, 10"); @@ -109,4 +109,22 @@ describe("OrderDetailPanel", () => { it("skips weekends when selecting the default manual delivery date", () => { expect(getNextSelectableDateKey(new Date("2026-05-15T12:00:00Z"))).toBe("2026-05-18"); }); + + it("shows pickup labels for pickup orders", () => { + const markup = renderToStaticMarkup( + , + ); + expect(markup).toContain("Карточка группы самовывоза"); + expect(markup).toContain("Самовывоз"); + expect(markup).toContain("Дата самовывоза"); + expect(markup).toContain("Статус самовывоза"); + expect(markup).not.toContain("Адрес доставки"); + }); }); diff --git a/src/pages/GroupDetailPage.jsx b/src/pages/GroupDetailPage.jsx index e3ab5f7..b033e55 100644 --- a/src/pages/GroupDetailPage.jsx +++ b/src/pages/GroupDetailPage.jsx @@ -109,7 +109,7 @@ export const GroupDetailPage = () => { /> ) : ( - Группа доставки не найдена. + Группа не найдена. )}
diff --git a/src/services/supabase/orderGroupRepository.js b/src/services/supabase/orderGroupRepository.js index a4eb953..9784419 100644 --- a/src/services/supabase/orderGroupRepository.js +++ b/src/services/supabase/orderGroupRepository.js @@ -110,6 +110,24 @@ export const mapOrderGroupRowToDeliveryGroup = (row) => { }; const deliveryAddress = normalizeText(row.delivery_address) || extractAddressFromSourceOrders(row.source_orders); + + // Detect pickup from source_orders ship field (1C sends "САМОВЫВОЗ") + const isPickupFromSource = Array.isArray(row.source_orders) && row.source_orders.length > 0 + && normalizeText(row.source_orders[0].ship || "").toUpperCase() === "САМОВЫВОЗ"; + // Also treat address equal to "САМОВЫВОЗ" as pickup indicator + const isPickupAddress = deliveryAddress.toUpperCase() === "САМОВЫВОЗ"; + + // Resolve effective delivery type: DB field takes precedence, but if it says "delivery" + // while source data clearly indicates pickup, treat as pickup + const effectiveDeliveryType = (row.delivery_type === "pickup" || deliveryStatus === "pickup" || isPickupFromSource || isPickupAddress) + ? "pickup" + : (row.delivery_type || "delivery"); + + // Clear placeholder pickup address + const resolvedDeliveryAddress = (effectiveDeliveryType === "pickup" && (deliveryAddress.toUpperCase() === "САМОВЫВОЗ" || !deliveryAddress)) + ? "" + : deliveryAddress; + const customerAddress = normalizeText(row.customer_address) || ""; const extractCity = (addr) => { @@ -151,7 +169,7 @@ export const mapOrderGroupRowToDeliveryGroup = (row) => { customerPhone, customerPhoneNormalized: parsedKey.phone || normalizePhone(customerPhone), customerDate, - deliveryAddress, + deliveryAddress: resolvedDeliveryAddress, customerAddress, city, assignedDriverId: row.assigned_driver_id || null, @@ -189,7 +207,7 @@ export const mapOrderGroupRowToDeliveryGroup = (row) => { deliveryDate, deliveryTime, deliveryDateSource: row.delivery_date_source || null, - deliveryType: row.delivery_type || "delivery", + deliveryType: effectiveDeliveryType, pickupDate: row.pickup_date || null, pickupTimeSlot: row.pickup_time_slot || null, driverShipmentData: row.driver_shipment_data || null, @@ -205,7 +223,7 @@ export const mapOrderGroupRowToDeliveryGroup = (row) => { customerName, customerPhone, customerDate, - deliveryAddress, + resolvedDeliveryAddress, customerAddress, city, rawDeliveryHalfDay,