Merge pull request 'fix(delivery): show invoice refs in client flow' (#1) from codex/delivery-rpc-deploy into main
Reviewed-on: https://git.supersamsev.ru/mihail/supersam/pulls/1
This commit is contained in:
commit
2367ff2554
|
|
@ -72,8 +72,8 @@ begin
|
||||||
|
|
||||||
v_order_number := coalesce(
|
v_order_number := coalesce(
|
||||||
nullif(v_invitation.order_number, ''),
|
nullif(v_invitation.order_number, ''),
|
||||||
nullif(v_group.group_key, ''),
|
to_jsonb(v_group.order_numbers) ->> 0,
|
||||||
to_jsonb(v_group.order_numbers) ->> 0
|
nullif(v_group.group_key, '')
|
||||||
);
|
);
|
||||||
v_customer_name := coalesce(
|
v_customer_name := coalesce(
|
||||||
nullif(v_group.customer_name, ''),
|
nullif(v_group.customer_name, ''),
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
import React from "react";
|
import React from "react";
|
||||||
|
import { getInvitationReferenceLabel } from "./invitationReference";
|
||||||
import { Badge } from "../UI/Badge";
|
import { Badge } from "../UI/Badge";
|
||||||
import { Button } from "../UI/Button";
|
import { Button } from "../UI/Button";
|
||||||
import { Panel } from "../UI/Panel";
|
import { Panel } from "../UI/Panel";
|
||||||
|
|
@ -55,8 +56,7 @@ export const DeliveryChoiceFlow = ({
|
||||||
}) => {
|
}) => {
|
||||||
const state = invitation.state || "awaiting_choice";
|
const state = invitation.state || "awaiting_choice";
|
||||||
const isActive = ACTIVE_STATES.has(state);
|
const isActive = ACTIVE_STATES.has(state);
|
||||||
const orderNumber = invitation.orderNumber || "—";
|
const invitationReference = getInvitationReferenceLabel(invitation);
|
||||||
const customerName = invitation.customerName || "Клиент";
|
|
||||||
const orderItems = (invitation.orderItems || invitation.items || [])
|
const orderItems = (invitation.orderItems || invitation.items || [])
|
||||||
.map(splitOrderItem)
|
.map(splitOrderItem)
|
||||||
.filter(Boolean);
|
.filter(Boolean);
|
||||||
|
|
@ -79,7 +79,7 @@ export const DeliveryChoiceFlow = ({
|
||||||
<Badge tone="warning">{STATE_LABELS[state]}</Badge>
|
<Badge tone="warning">{STATE_LABELS[state]}</Badge>
|
||||||
</div>
|
</div>
|
||||||
<p className="text-sm leading-6 text-[var(--color-text-muted)]">
|
<p className="text-sm leading-6 text-[var(--color-text-muted)]">
|
||||||
Заказ {orderNumber} для {customerName}. Проверьте состав заказа и выберите удобную половину дня.
|
{invitationReference}. Проверьте состав заказа и выберите удобную половину дня.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -114,7 +114,7 @@ describe("DeliveryChoiceFlow", () => {
|
||||||
/>,
|
/>,
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(markup).toContain("CD-240032");
|
expect(markup).toContain("Счет CD-240032");
|
||||||
expect(markup).toContain("Александр Савин");
|
expect(markup).not.toContain("Александр Савин");
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,39 @@
|
||||||
|
const getOrderItemNames = (invitation) => {
|
||||||
|
const rawItems = Array.isArray(invitation?.orderItems)
|
||||||
|
? invitation.orderItems
|
||||||
|
: Array.isArray(invitation?.items)
|
||||||
|
? invitation.items
|
||||||
|
: [];
|
||||||
|
|
||||||
|
return rawItems
|
||||||
|
.map((item) => {
|
||||||
|
if (typeof item === "string") {
|
||||||
|
return item.trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (item && typeof item === "object" && typeof item.name === "string") {
|
||||||
|
return item.name.trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
return "";
|
||||||
|
})
|
||||||
|
.filter(Boolean);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getInvitationReferenceLabel = (invitation) => {
|
||||||
|
const invoiceNumbers = [...new Set(getOrderItemNames(invitation))];
|
||||||
|
if (invoiceNumbers.length === 1) {
|
||||||
|
return `Счет ${invoiceNumbers[0]}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (invoiceNumbers.length > 1) {
|
||||||
|
return `Счета: ${invoiceNumbers.join(", ")}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
const orderNumber = typeof invitation?.orderNumber === "string" ? invitation.orderNumber.trim() : "";
|
||||||
|
if (orderNumber) {
|
||||||
|
return `Счет ${orderNumber}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
return "Счет —";
|
||||||
|
};
|
||||||
|
|
@ -2,6 +2,7 @@ import React from "react";
|
||||||
import { useParams } from "react-router-dom";
|
import { useParams } from "react-router-dom";
|
||||||
import { DeliveryChoiceFlow } from "../components/client/DeliveryChoiceFlow";
|
import { DeliveryChoiceFlow } from "../components/client/DeliveryChoiceFlow";
|
||||||
import { DeliverySlotsPicker } from "../components/client/DeliverySlotsPicker";
|
import { DeliverySlotsPicker } from "../components/client/DeliverySlotsPicker";
|
||||||
|
import { getInvitationReferenceLabel } from "../components/client/invitationReference";
|
||||||
import { DeliveryStateNotice } from "../components/client/DeliveryStateNotice";
|
import { DeliveryStateNotice } from "../components/client/DeliveryStateNotice";
|
||||||
import { Panel } from "../components/UI/Panel";
|
import { Panel } from "../components/UI/Panel";
|
||||||
import { formatDeliveryDate } from "../components/client/deliveryDateFormatting";
|
import { formatDeliveryDate } from "../components/client/deliveryDateFormatting";
|
||||||
|
|
@ -312,8 +313,7 @@ export const ClientDeliveryPage = () => {
|
||||||
<p className="text-sm uppercase tracking-[0.24em] text-[var(--color-text-muted)]">Ваш выбор</p>
|
<p className="text-sm uppercase tracking-[0.24em] text-[var(--color-text-muted)]">Ваш выбор</p>
|
||||||
<h2 className="text-xl font-semibold leading-tight">Сохранено: {savedChoiceLabel}</h2>
|
<h2 className="text-xl font-semibold leading-tight">Сохранено: {savedChoiceLabel}</h2>
|
||||||
<p className="text-sm leading-6 text-[var(--color-text-muted)]">
|
<p className="text-sm leading-6 text-[var(--color-text-muted)]">
|
||||||
Заказ {invitation?.orderNumber || "—"}
|
{getInvitationReferenceLabel(invitation)}
|
||||||
{invitation?.customerName ? ` · ${invitation.customerName}` : ""}
|
|
||||||
</p>
|
</p>
|
||||||
<p className="text-sm leading-6 text-[var(--color-text-muted)]">
|
<p className="text-sm leading-6 text-[var(--color-text-muted)]">
|
||||||
Статус: доставка уже согласована. При повторном открытии этой ссылки будет показан тот же выбор.
|
Статус: доставка уже согласована. При повторном открытии этой ссылки будет показан тот же выбор.
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
import { describe, expect, it } from "vitest";
|
import { describe, expect, it } from "vitest";
|
||||||
|
import { getInvitationReferenceLabel } from "../components/client/invitationReference";
|
||||||
import {
|
import {
|
||||||
buildDeliveryConfirmationPayload,
|
buildDeliveryConfirmationPayload,
|
||||||
buildSelectedSlotFromInvitation,
|
buildSelectedSlotFromInvitation,
|
||||||
|
|
@ -162,4 +163,17 @@ describe("ClientDeliveryPage helpers", () => {
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("prefers the invoice number from order items over the customer name", () => {
|
||||||
|
expect(
|
||||||
|
getInvitationReferenceLabel({
|
||||||
|
orderNumber: "9787464846|04.05.26",
|
||||||
|
customerName: "Конаков Сергей Алексеевич (ДАРТС)",
|
||||||
|
orderItems: [
|
||||||
|
{ name: "СФ Т\\ЕА-28687", quantity: "" },
|
||||||
|
{ name: "СФ Т\\ЕА-28700", quantity: "" },
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
).toBe("Счета: СФ Т\\ЕА-28687, СФ Т\\ЕА-28700");
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -226,7 +226,7 @@ export const buildPublicOrderGroupInvitationView = (
|
||||||
orderGroupId: invitation.order_group_id || group.id,
|
orderGroupId: invitation.order_group_id || group.id,
|
||||||
state: invitation.state,
|
state: invitation.state,
|
||||||
token: "",
|
token: "",
|
||||||
orderNumber: invitation.order_number || group.group_key || orderNumbers[0] || null,
|
orderNumber: invitation.order_number || orderNumbers[0] || group.group_key || null,
|
||||||
customerName: maskCustomerName(customerName),
|
customerName: maskCustomerName(customerName),
|
||||||
customerPhone: maskPhoneNumber(customerPhone),
|
customerPhone: maskPhoneNumber(customerPhone),
|
||||||
orderItems: orderNumbers.map((number) => ({ name: number, quantity: "" })),
|
orderItems: orderNumbers.map((number) => ({ name: number, quantity: "" })),
|
||||||
|
|
|
||||||
|
|
@ -612,8 +612,8 @@ begin
|
||||||
|
|
||||||
v_order_number := coalesce(
|
v_order_number := coalesce(
|
||||||
nullif(v_invitation.order_number, ''),
|
nullif(v_invitation.order_number, ''),
|
||||||
nullif(v_group.group_key, ''),
|
to_jsonb(v_group.order_numbers) ->> 0,
|
||||||
to_jsonb(v_group.order_numbers) ->> 0
|
nullif(v_group.group_key, '')
|
||||||
);
|
);
|
||||||
v_customer_name := coalesce(
|
v_customer_name := coalesce(
|
||||||
nullif(v_group.customer_name, ''),
|
nullif(v_group.customer_name, ''),
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue