'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 email?: string bank_iban?: string bank_bic?: string bank_name?: string bank_owner?: 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 { const supabase = await createClient() const { data: { user } } = await supabase.auth.getUser() if (!user) throw new Error('Not authenticated') const { data: dbUser, error: dbUserError } = await supabase .from('users') .select('company_id') .eq('id', user.id) .single() if (dbUserError || !dbUser || !dbUser.company_id) { return [] } const { data, error } = await supabase .from('end_customers') .select('*') .eq('partner_id', dbUser.company_id) .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 { 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 { const supabase = await createClient() const { data: { user } } = await supabase.auth.getUser() if (!user) throw new Error('Not authenticated') const { data: dbUser, error: dbUserError } = await supabase .from('users') .select('company_id') .eq('id', user.id) .single() if (dbUserError || !dbUser || !dbUser.company_id) { throw new Error('Kein Unternehmen zugewiesen.') } const { data, error } = await supabase .from('end_customers') .insert([{ partner_id: dbUser.company_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, email: formData.email || null, bank_iban: formData.bank_iban || null, bank_bic: formData.bank_bic || null, bank_name: formData.bank_name || null, bank_owner: formData.bank_owner || 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 { 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, email: formData.email || null, bank_iban: formData.bank_iban || null, bank_bic: formData.bank_bic || null, bank_name: formData.bank_name || null, bank_owner: formData.bank_owner || 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 { const supabase = await createClient() const { error } = await supabase .from('end_customers') .update({ company_name: '[GELÖSCHT]', vat_id: '[GELÖSCHT]', first_name: '[GELÖSCHT]', last_name: '[GELÖSCHT]', street: '[GELÖSCHT]', zip: '[GELÖSCHT]', city: '[GELÖSCHT]', email: '[GELÖSCHT]', bank_iban: '[GELÖSCHT]', bank_bic: '[GELÖSCHT]', bank_name: '[GELÖSCHT]', bank_owner: '[GELÖSCHT]', 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 { const admin = createAdminClient() const { data: dbUser } = await admin .from('users') .select('company_id') .eq('id', partnerId) .single() const targetId = dbUser?.company_id || partnerId const { data, error } = await admin .from('end_customers') .select('*') .eq('partner_id', targetId) .order('company_name', { ascending: true }) if (error) throw error return data as EndCustomer[] }