feat: Patenschafts-Honig automatisch waehlen (nie cremig, neueste Ernte)
Docker Image bauen und veroeffentlichen / typecheck (push) Successful in 2m18s
Docker Image bauen und veroeffentlichen / test (push) Successful in 5m32s
Docker Image bauen und veroeffentlichen / lint (push) Successful in 3m41s
Docker Image bauen und veroeffentlichen / build-and-push (push) Canceled after 20m38s
Docker Image bauen und veroeffentlichen / typecheck (push) Successful in 2m18s
Docker Image bauen und veroeffentlichen / test (push) Successful in 5m32s
Docker Image bauen und veroeffentlichen / lint (push) Successful in 3m41s
Docker Image bauen und veroeffentlichen / build-and-push (push) Canceled after 20m38s
Pakete, Abo-Reservierung und Abo-Lieferungen nehmen immer den aktiven, nicht cremigen Honig der neuesten Ernte mit genug freiem Bestand, bei gleichem Jahrgang den mit dem meisten Bestand. Feste Honig-Zuordnung im Admin entfaellt (Spalte bleibt, wird nicht mehr genutzt). Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
This commit is contained in:
1 parent
3ddf0bfa73
commit
1d88bac52e
30 files changed
+1152
-394
No files matched your search
@@ -24,6 +24,8 @@ import { vatRateForProduct } from "@/lib/vat";
|
||||
import { getLocale } from "@/i18n/locale";
|
||||
import { expandCheckoutItems, type CheckoutProduct } from "@/lib/sponsorship/checkout-expand";
|
||||
import { getOffersByProductIds } from "@/lib/sponsorship/offers";
|
||||
import { loadHoneyCandidates } from "@/lib/sponsorship/honey-candidates";
|
||||
import { isCreamy } from "@/lib/sponsorship/honey-selection";
|
||||
import { reservedJarsByProduct } from "@/lib/sponsorship-subscription/reservation";
|
||||
|
||||
class OutOfStockError extends Error {}
|
||||
@@ -231,9 +233,16 @@ export async function POST(request: Request) {
|
||||
const productIds = [...new Set(input.items.map((item) => item.productId))];
|
||||
const locale = await getLocale();
|
||||
const offersByProduct = await getOffersByProductIds(productIds, locale);
|
||||
const honeyIds = [...offersByProduct.values()]
|
||||
.map((offer) => offer.honeyProduct?.id)
|
||||
.filter((id): id is string => Boolean(id) && !productIds.includes(id as string));
|
||||
// Honig fuer Pakete waehlt der Checkout selbst, im Moment der Bestellung
|
||||
// (lib/sponsorship/honey-selection.ts) — dafuer braucht er alle Kandidaten
|
||||
// mit freiem Bestand und deren Produktdaten (Charge, Gewicht, Steuersatz).
|
||||
// Cremiger Honig kommt nie in ein Paket, seine Produktdaten braucht es
|
||||
// deshalb nicht.
|
||||
const needsHoney = [...offersByProduct.values()].some((offer) => offer.honeyJars > 0);
|
||||
const honeyCandidates = needsHoney ? await loadHoneyCandidates() : [];
|
||||
const honeyIds = honeyCandidates
|
||||
.filter((candidate) => !isCreamy(candidate.consistency) && !productIds.includes(candidate.id))
|
||||
.map((candidate) => candidate.id);
|
||||
const products = await getProductsByIds(productIds);
|
||||
const honeyProducts = honeyIds.length > 0 ? await getProductsByIds(honeyIds) : [];
|
||||
|
||||
@@ -290,6 +299,7 @@ export async function POST(request: Request) {
|
||||
cartItems: input.items,
|
||||
products: productMap,
|
||||
offers: offersByProduct,
|
||||
honeyCandidates,
|
||||
vatRateFor: (product) => vatRateForProduct(product, process.env),
|
||||
locale,
|
||||
now: new Date(),
|
||||
@@ -329,9 +339,16 @@ export async function POST(request: Request) {
|
||||
|
||||
// Fuer Abos reservierte Glaeser duerfen weder einzeln noch im Paket
|
||||
// verkauft werden (lib/sponsorship-subscription/reservation.ts). Vor der
|
||||
// Transaktion gelesen: die Reservierung aendert sich nur mit Abos, nicht
|
||||
// durch gleichzeitige Bestellungen — die verbindliche Bestandspruefung
|
||||
// bleibt das bedingte Update in der Transaktion.
|
||||
// Transaktion gelesen, wie bisher: die verbindliche Bestandspruefung bleibt
|
||||
// das bedingte Update in der Transaktion. Seit die Abo-Glaeser automatisch
|
||||
// auf dem gerade gewaehlten Honig liegen, kann eine gleichzeitige Bestellung
|
||||
// die Reservierung zwar auf einen anderen Honig verschieben; das bedingte
|
||||
// Update haelt aber den Honig, auf dem sie laut dieser Momentaufnahme
|
||||
// liegt, ueber ihrem Anteil. Die Reservierung in die Serializable-
|
||||
// Transaktion zu ziehen, wuerde jede Bestellung mit jeder anderen
|
||||
// Honigbuchung kollidieren lassen — bei Andrang deutlich mehr Abbrueche
|
||||
// fuer einen Randfall, den im schlimmsten Fall eine zurueckgestellte
|
||||
// Abo-Lieferung in der Aufmerksamkeitsliste auffaengt.
|
||||
const reservedByProduct = await reservedJarsByProduct(expanded.reserve.map((line) => line.productId));
|
||||
|
||||
// Gutscheincode nur auf den Warenwert anwenden, nicht auf den Versand —
|
||||
|
||||
Reference in new issue
Block a user