diff --git a/README.md b/README.md index b826181..59ddb4e 100644 --- a/README.md +++ b/README.md @@ -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 diff --git a/app/api/account/orders/[orderNumber]/switch-to-stripe/route.ts b/app/api/account/orders/[orderNumber]/switch-to-stripe/route.ts index 65af0ec..cafc006 100644 --- a/app/api/account/orders/[orderNumber]/switch-to-stripe/route.ts +++ b/app/api/account/orders/[orderNumber]/switch-to-stripe/route.ts @@ -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 }); } diff --git a/app/impressum/components/AnbieterAngaben.tsx b/app/impressum/components/AnbieterAngaben.tsx index 8910f08..246eeae 100644 --- a/app/impressum/components/AnbieterAngaben.tsx +++ b/app/impressum/components/AnbieterAngaben.tsx @@ -76,7 +76,9 @@ export function AnbieterAngaben({ seller }: { seller: CompanySettings }) { {seller.sellerZip} {seller.sellerCity}

{seller.sellerCountry}

-

E-Mail: {seller.sellerEmail}

+

+ E-Mail: {seller.sellerEmail} +

{seller.vatId && ( diff --git a/app/konto/bestellungen/[orderNumber]/page.tsx b/app/konto/bestellungen/[orderNumber]/page.tsx index ca1eadf..961a915 100644 --- a/app/konto/bestellungen/[orderNumber]/page.tsx +++ b/app/konto/bestellungen/[orderNumber]/page.tsx @@ -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 ( diff --git a/app/lib/customerAuth.ts b/app/lib/customerAuth.ts index 846ec6e..fa8295d 100644 --- a/app/lib/customerAuth.ts +++ b/app/lib/customerAuth.ts @@ -455,7 +455,14 @@ export const ORDER_STATUS_LABEL: Record = { // 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; }