Restrict Rücksendung anfragen to delivered orders, fix Impressum email link
- customerOrderAction() only offers "Rücksendung anfragen" once an order is delivered, not already at shipped — a return before the package arrived doesn't make sense yet. UI-only change (a stricter subset of what the backend's CUSTOMER_ALLOWED_TRANSITIONS already permits). - AnbieterAngaben.tsx's seller email is now a real mailto: link — it was plain text, the only non-clickable email on the site.
This commit is contained in:
@@ -2072,6 +2072,31 @@ had `isManualPayment: false` — the Vorkasse/Überweisung branch (and its
|
||||
new switch-option mention) was never previewable in the admin at all
|
||||
before this.
|
||||
|
||||
**Follow-up same day: switch-to-stripe eligibility narrowed.**
|
||||
`canSwitchPayment` (page.tsx) and the `switch-to-stripe` route's own
|
||||
re-check both changed from `paymentStatus !== "paid"` to an explicit
|
||||
allowlist (`"pending"` or `"not_applicable"`) — see the Payload backend's
|
||||
own README for why the blocklist form was too permissive. No visible
|
||||
behavior change for the normal case, just closes an edge case
|
||||
(`"failed"`/`"refunded"`/`"partially_refunded"` on a manual order — not
|
||||
realistic today, but not meaningful states to switch *from* either).
|
||||
|
||||
**Two more same-day fixes:**
|
||||
- `customerOrderAction()` now only offers "Rücksendung anfragen" once an
|
||||
order is actually `delivered`, not already at `shipped` — a (partial)
|
||||
return before the package has even arrived doesn't make sense yet. The
|
||||
backend's own `CUSTOMER_ALLOWED_TRANSITIONS` still technically permits
|
||||
`shipped` → `return_requested` too (an extensive existing test suite is
|
||||
built around that as its base fixture, see the Payload backend's
|
||||
README) — this only narrows what the UI itself offers, a stricter
|
||||
subset of what the backend already allows, not a security boundary
|
||||
being loosened.
|
||||
- `/impressum`'s "Angaben zum Anbieter" email (`AnbieterAngaben.tsx`) was
|
||||
plain text, not a `mailto:` link — the only email address on the whole
|
||||
site that wasn't clickable, since this one section is rendered
|
||||
straight from `company-settings` fields rather than through the CMS
|
||||
richText renderer (which already links emails/URLs correctly).
|
||||
|
||||
## Deployment
|
||||
|
||||
- **Dockerfile**: 3-stage build (`deps` → `builder` → `runner`) with
|
||||
|
||||
@@ -21,10 +21,13 @@ export async function POST(request: Request, { params }: { params: Promise<{ ord
|
||||
if (!order) return NextResponse.json({ ok: false, reason: "Bestellung nicht gefunden." }, { status: 404 });
|
||||
|
||||
// Same eligibility the backend endpoint re-checks authoritatively —
|
||||
// checked here too for a friendly error instead of a bare 409. An admin
|
||||
// can mark an Überweisung order paid by hand (Orders.ts's paymentStatus
|
||||
// field) — that order must never also be switched to Stripe.
|
||||
if (order.paymentProvider !== "manual" || order.status !== "received" || order.paymentStatus === "paid") {
|
||||
// checked here too for a friendly error instead of a bare 409. An
|
||||
// explicit allowlist ('pending'/'not_applicable'), not a
|
||||
// paymentStatus !== "paid" blocklist — see switchPaymentToStripe.ts's
|
||||
// own comment on why 'failed'/'refunded'/'partially_refunded' aren't
|
||||
// meaningful states to switch from either.
|
||||
const eligiblePaymentStatus = order.paymentStatus === "pending" || order.paymentStatus === "not_applicable";
|
||||
if (order.paymentProvider !== "manual" || order.status !== "received" || !eligiblePaymentStatus) {
|
||||
return NextResponse.json({ ok: false, reason: "Die Zahlungsart kann für diese Bestellung gerade nicht geändert werden." }, { status: 400 });
|
||||
}
|
||||
|
||||
|
||||
@@ -76,7 +76,9 @@ export function AnbieterAngaben({ seller }: { seller: CompanySettings }) {
|
||||
{seller.sellerZip} {seller.sellerCity}
|
||||
</P>
|
||||
<P>{seller.sellerCountry}</P>
|
||||
<P>E-Mail: {seller.sellerEmail}</P>
|
||||
<P>
|
||||
E-Mail: <a href={`mailto:${seller.sellerEmail}`} className="text-brand hover:underline">{seller.sellerEmail}</a>
|
||||
</P>
|
||||
</div>
|
||||
|
||||
{seller.vatId && (
|
||||
|
||||
@@ -55,7 +55,7 @@ export default async function KontoBestellungDetailPage({ params }: { params: Pr
|
||||
const canSwitchPayment =
|
||||
order.paymentProvider === "manual" &&
|
||||
order.status === "received" &&
|
||||
order.paymentStatus !== "paid" &&
|
||||
(order.paymentStatus === "pending" || order.paymentStatus === "not_applicable") &&
|
||||
groupPaymentMethodsForCheckout(await getPaymentMethods()).some((m) => m.provider === "stripe");
|
||||
|
||||
return (
|
||||
|
||||
@@ -455,7 +455,14 @@ export const ORDER_STATUS_LABEL: Record<string, string> = {
|
||||
// decide which button, if any, to show).
|
||||
export function customerOrderAction(status: string): "cancel" | "request-return" | null {
|
||||
if (status === "received") return "cancel";
|
||||
if (status === "shipped" || status === "delivered") return "request-return";
|
||||
// Only once actually delivered — a (partial) return before the package
|
||||
// even arrived doesn't make sense yet. The backend's own
|
||||
// CUSTOMER_ALLOWED_TRANSITIONS still technically permits 'shipped' →
|
||||
// 'return_requested' too (an extensive existing test suite is built
|
||||
// around that as its base fixture) — this only narrows what the UI
|
||||
// itself offers, a stricter subset of what the backend already allows,
|
||||
// not a security boundary being loosened.
|
||||
if (status === "delivered") return "request-return";
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user