+
+
+ Datum der letzten CAS-Lizenz (falls vorhanden)
+
+
setLastLicenseDate(e.target.value)}
+ className="bg-[#0b1329] border-white/10 text-white focus:border-primary"
+ />
+
+ Falls dieser Kunde bereits Lizenzen besitzt, tragen Sie das Datum der letzten Lizenzierung ein. Damit werden die korrekten Update-Gebühren ermittelt.
+
+
+ )}
)}
@@ -819,6 +873,15 @@ export function OrderWizard({
)}
+ {updatePriceModifier.label && (
+ {[selectedEndCustomer.first_name, selectedEndCustomer.last_name].filter(Boolean).join(' ')}
{[selectedEndCustomer.street, selectedEndCustomer.zip, selectedEndCustomer.city].filter(Boolean).join(', ')}
-
Gesamtbetrag:
-
- {new Intl.NumberFormat('de-DE', { style: 'currency', currency: 'EUR' }).format(oneTimeTotal)}
-
+
+
+ Gesamtbetrag:
+
+ {new Intl.NumberFormat('de-DE', { style: 'currency', currency: 'EUR' }).format(oneTimeTotal)}
+
+
+ {updatePriceModifier.label && (
+
+ {updatePriceModifier.label}
+
+ )}
) : (
diff --git a/shop/lib/actions/orders.ts b/shop/lib/actions/orders.ts
index 41668f6..dcb509d 100644
--- a/shop/lib/actions/orders.ts
+++ b/shop/lib/actions/orders.ts
@@ -57,8 +57,9 @@ export async function submitOrder(params: {
endCustomerId?: string | null
endCustomer?: EndCustomer | null
billingInterval?: 'one_time' | 'monthly'
+ lastLicenseDate?: string | null
}): Promise {
- const { selections, moduleQuantities, customerProfile, endCustomerId, endCustomer, billingInterval } = params
+ const { selections, moduleQuantities, customerProfile, endCustomerId, endCustomer, billingInterval, lastLicenseDate } = params
const supabase = await createClient()
const { data: { user } } = await supabase.auth.getUser()
@@ -139,7 +140,7 @@ export async function submitOrder(params: {
// 1. Snapshots aufbauen
// Wenn Endkunde vorhanden: dessen Daten einfrieren; sonst Partner-Profil (Fallback)
const customerSnapshot = buildCustomerSnapshot(customerProfile, endCustomer ?? null)
- const orderSnapshot = buildOrderSnapshot(selections, dbProducts, dbCategories, billingInterval, moduleQuantities)
+ const orderSnapshot = buildOrderSnapshot(selections, dbProducts, dbCategories, billingInterval, moduleQuantities, lastLicenseDate)
// 2. Idempotenz-Guard: Prüfen ob identische Bestellung in den letzten 30s existiert
const orderHash = hashOrderSnapshot(orderSnapshot)
diff --git a/shop/lib/license-transform.ts b/shop/lib/license-transform.ts
index 41f601f..43af559 100644
--- a/shop/lib/license-transform.ts
+++ b/shop/lib/license-transform.ts
@@ -86,7 +86,8 @@ export function buildOrderSnapshot(
products: Product[],
categories: Category[],
billingInterval?: 'one_time' | 'monthly',
- moduleQuantities?: Record
+ moduleQuantities?: Record,
+ lastLicenseDate?: string | null
): OrderSnapshot {
const items: OrderItem[] = []
let subtotal = 0
@@ -131,14 +132,43 @@ export function buildOrderSnapshot(
})
}
- const taxAmount = Math.round(subtotal * (dominantTaxRate / 100) * 100) / 100
- const total = Math.round((subtotal + taxAmount) * 100) / 100
-
// Wenn billingInterval übergeben, dieses nutzen; sonst automatisch ermitteln
const billingCycle = billingInterval || (items.every((i) => i.billing_interval === 'one_time')
? 'one_time'
: 'monthly')
+ let multiplier = 1
+ if (lastLicenseDate && billingCycle === 'one_time') {
+ const lastDate = new Date(lastLicenseDate)
+ const today = new Date()
+ const yearsDiff = today.getFullYear() - lastDate.getFullYear()
+ const monthsDiff = today.getMonth() - lastDate.getMonth()
+ const months = yearsDiff * 12 + monthsDiff
+
+ if (months <= 12) {
+ multiplier = 0
+ } else if (months <= 14) {
+ multiplier = 0.15
+ } else if (months <= 25) {
+ multiplier = 0.30
+ } else if (months <= 37) {
+ multiplier = 0.45
+ } else if (months <= 49) {
+ multiplier = 0.60
+ } else {
+ multiplier = 0.90
+ }
+
+ // Multiply item_total in items by multiplier
+ items.forEach(item => {
+ item.item_total = item.item_total * multiplier
+ })
+ subtotal = subtotal * multiplier
+ }
+
+ const taxAmount = Math.round(subtotal * (dominantTaxRate / 100) * 100) / 100
+ const total = Math.round((subtotal + taxAmount) * 100) / 100
+
return {
schema_version: 1,
billing_cycle: billingCycle,
@@ -147,6 +177,8 @@ export function buildOrderSnapshot(
tax_rate: dominantTaxRate,
tax_amount: taxAmount,
total,
+ last_license_date: lastLicenseDate || null,
+ price_multiplier: lastLicenseDate && billingCycle === 'one_time' ? multiplier : null,
}
}
diff --git a/shop/lib/types.ts b/shop/lib/types.ts
index d51fb05..7ab8c82 100644
--- a/shop/lib/types.ts
+++ b/shop/lib/types.ts
@@ -132,6 +132,8 @@ export type OrderSnapshot = {
tax_rate: number
tax_amount: number
total: number
+ last_license_date?: string | null
+ price_multiplier?: number | null
}
// ─── DB-Zeile (orders-Tabelle) ────────────────────────────────────────────────