feat: add update price modifier for existing customers based on last license date
Some checks failed
Staging Build / build (push) Has been cancelled

This commit is contained in:
DanielS
2026-06-25 23:04:48 +02:00
parent 16fb713665
commit 1a2ace937c
6 changed files with 182 additions and 13 deletions

View File

@@ -57,8 +57,9 @@ export async function submitOrder(params: {
endCustomerId?: string | null
endCustomer?: EndCustomer | null
billingInterval?: 'one_time' | 'monthly'
lastLicenseDate?: string | null
}): Promise<Order> {
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)

View File

@@ -86,7 +86,8 @@ export function buildOrderSnapshot(
products: Product[],
categories: Category[],
billingInterval?: 'one_time' | 'monthly',
moduleQuantities?: Record<string, number>
moduleQuantities?: Record<string, number>,
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,
}
}

View File

@@ -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) ────────────────────────────────────────────────