export interface DiscountCodeLike { isActive: boolean; type: "PERCENT" | "FIXED"; value: number; minOrderCents: number; minQuantity: number | null; maxUses: number | null; usedCount: number; validFrom: Date | null; validUntil: Date | null; } /** * Reine Pruef-/Berechnungsfunktionen ohne Datenbankzugriff — bewusst getrennt * von der Checkout-Route (analog zu shipping-calc.ts), damit die Geldlogik * isoliert testbar ist. totalQuantity ist optional (Default: praktisch immer * erfuellt) — nur Codes mit gesetztem minQuantity (Mengenrabatte) pruefen ihn * ueberhaupt, normale Gutscheine sind davon unberuehrt. */ export function isDiscountCodeValid( code: DiscountCodeLike | null, subtotalCents: number, now: Date, totalQuantity: number = Infinity ): boolean { if (!code) return false; return ( code.isActive && (!code.validFrom || code.validFrom <= now) && (!code.validUntil || code.validUntil >= now) && (code.maxUses === null || code.usedCount < code.maxUses) && subtotalCents >= code.minOrderCents && (code.minQuantity === null || totalQuantity >= code.minQuantity) ); } /** Rabatt gilt nur auf den Warenwert, nie auf den Versand, und kappt bei FIXED an der Zwischensumme (kein negativer Betrag). */ export function calculateDiscountCents(code: Pick, subtotalCents: number): number { return code.type === "PERCENT" ? Math.round((subtotalCents * code.value) / 100) : Math.min(code.value, subtotalCents); }