Files
webshop/shop/lib/actions/end-customers.ts
DanielS 7b22889e23
All checks were successful
Staging Build / build (push) Successful in 2m19s
feat: add partner list and customer list explorer to admin settings
2026-06-24 00:02:27 +02:00

159 lines
5.1 KiB
TypeScript

'use server'
import { createClient } from '@/lib/supabase/server'
import { createAdminClient } from '@/lib/supabase/admin'
import { revalidatePath } from 'next/cache'
import type { EndCustomer } from '@/lib/types'
// ─── Typen ───────────────────────────────────────────────────────────────────
export type EndCustomerFormData = {
company_name: string
vat_id?: string
first_name?: string
last_name?: string
street?: string
zip?: string
city?: string
}
// ─── Lesen ───────────────────────────────────────────────────────────────────
/**
* Holt alle (nicht anonymisierten) Endkunden des eingeloggten Partners.
* RLS stellt sicher, dass nur eigene Kunden zurückgegeben werden.
*/
export async function getEndCustomers(): Promise<EndCustomer[]> {
const supabase = await createClient()
const { data, error } = await supabase
.from('end_customers')
.select('*')
.order('company_name', { ascending: true })
if (error) throw error
return data as EndCustomer[]
}
/**
* Holt einen einzelnen Endkunden (Eigentümerprüfung via RLS).
*/
export async function getEndCustomer(id: string): Promise<EndCustomer | null> {
const supabase = await createClient()
const { data, error } = await supabase
.from('end_customers')
.select('*')
.eq('id', id)
.single()
if (error) return null
return data as EndCustomer
}
// ─── Erstellen ────────────────────────────────────────────────────────────────
/**
* Legt einen neuen Endkunden für den eingeloggten Partner an.
* partner_id wird serverseitig aus der Session gesetzt (kein Client-Trust).
*/
export async function createEndCustomer(formData: EndCustomerFormData): Promise<EndCustomer> {
const supabase = await createClient()
const { data: { user } } = await supabase.auth.getUser()
if (!user) throw new Error('Not authenticated')
const { data, error } = await supabase
.from('end_customers')
.insert([{
partner_id: user.id,
company_name: formData.company_name,
vat_id: formData.vat_id || null,
first_name: formData.first_name || null,
last_name: formData.last_name || null,
street: formData.street || null,
zip: formData.zip || null,
city: formData.city || null,
}])
.select()
.single()
if (error) throw error
revalidatePath('/my-customers')
return data as EndCustomer
}
// ─── Aktualisieren ────────────────────────────────────────────────────────────
/**
* Aktualisiert Adressdaten eines Endkunden.
* RLS verhindert Zugriff auf fremde Kunden.
*/
export async function updateEndCustomer(id: string, formData: EndCustomerFormData): Promise<void> {
const supabase = await createClient()
const { error } = await supabase
.from('end_customers')
.update({
company_name: formData.company_name,
vat_id: formData.vat_id || null,
first_name: formData.first_name || null,
last_name: formData.last_name || null,
street: formData.street || null,
zip: formData.zip || null,
city: formData.city || null,
})
.eq('id', id)
if (error) throw error
revalidatePath('/my-customers')
revalidatePath(`/my-customers/${id}`)
}
// ─── DSGVO: Anonymisieren ─────────────────────────────────────────────────────
/**
* Anonymisiert einen Endkunden gemäß DSGVO „Recht auf Vergessenwerden".
*
* - Überschreibt alle personenbezogenen Felder mit [GELÖSCHT]
* - Setzt is_anonymized = true (verhindert weitere Bearbeitung)
* - LÖSCHT NICHT die Zeile (FK in orders bleibt erhalten)
* - Bestell-Snapshots in orders.customer_data werden NICHT verändert
* (steuerrechtliche Aufbewahrungspflicht)
*/
export async function anonymizeEndCustomer(id: string): Promise<void> {
const supabase = await createClient()
const { error } = await supabase
.from('end_customers')
.update({
company_name: '[GELÖSCHT]',
vat_id: null,
first_name: '[GELÖSCHT]',
last_name: null,
street: null,
zip: null,
city: null,
is_anonymized: true,
})
.eq('id', id)
.eq('is_anonymized', false) // Keine doppelte Anonymisierung
if (error) throw error
revalidatePath('/my-customers')
revalidatePath(`/my-customers/${id}`)
}
export async function getPartnerEndCustomers(partnerId: string): Promise<EndCustomer[]> {
const admin = createAdminClient()
const { data, error } = await admin
.from('end_customers')
.select('*')
.eq('partner_id', partnerId)
.order('company_name', { ascending: true })
if (error) throw error
return data as EndCustomer[]
}