feat(customer): add bank account details support
This commit is contained in:
@@ -22,6 +22,7 @@ export default function CustomerDetailPage({ params }: { params: Promise<{ id: s
|
||||
const [showGdprConfirm, setShowGdprConfirm] = useState(false)
|
||||
const [form, setForm] = useState({
|
||||
company_name: '', vat_id: '', first_name: '', last_name: '', street: '', zip: '', city: '', email: '',
|
||||
bank_iban: '', bank_bic: '', bank_name: '', bank_owner: '',
|
||||
})
|
||||
|
||||
useEffect(() => {
|
||||
@@ -38,6 +39,10 @@ export default function CustomerDetailPage({ params }: { params: Promise<{ id: s
|
||||
zip: c.zip ?? '',
|
||||
city: c.city ?? '',
|
||||
email: c.email ?? '',
|
||||
bank_iban: c.bank_iban ?? '',
|
||||
bank_bic: c.bank_bic ?? '',
|
||||
bank_name: c.bank_name ?? '',
|
||||
bank_owner: c.bank_owner ?? '',
|
||||
})
|
||||
setLoading(false)
|
||||
})
|
||||
@@ -126,6 +131,10 @@ export default function CustomerDetailPage({ params }: { params: Promise<{ id: s
|
||||
{ label: 'Straße & Hausnummer', key: 'street', span: true },
|
||||
{ label: 'PLZ', key: 'zip', span: false },
|
||||
{ label: 'Ort', key: 'city', span: false },
|
||||
{ label: 'Kontoinhaber', key: 'bank_owner', span: false },
|
||||
{ label: 'IBAN', key: 'bank_iban', span: false },
|
||||
{ label: 'BIC', key: 'bank_bic', span: false },
|
||||
{ label: 'Bankname', key: 'bank_name', span: false },
|
||||
] as const).map(({ label, key, span }) => (
|
||||
<div key={key} className={`space-y-1.5 ${span ? 'md:col-span-2' : ''}`}>
|
||||
<Label className="text-slate-300 text-sm">{label}</Label>
|
||||
|
||||
@@ -15,6 +15,7 @@ export default function NewCustomerPage() {
|
||||
const [saving, setSaving] = useState(false)
|
||||
const [form, setForm] = useState({
|
||||
company_name: '', vat_id: '', first_name: '', last_name: '', street: '', zip: '', city: '', email: '',
|
||||
bank_iban: '', bank_bic: '', bank_name: '', bank_owner: '',
|
||||
})
|
||||
|
||||
const handleSave = async () => {
|
||||
@@ -62,6 +63,10 @@ export default function NewCustomerPage() {
|
||||
{ label: 'Straße & Hausnummer', key: 'street', span: true, placeholder: 'Musterstraße 1' },
|
||||
{ label: 'PLZ', key: 'zip', span: false, placeholder: '12345' },
|
||||
{ label: 'Ort', key: 'city', span: false, placeholder: 'Musterstadt' },
|
||||
{ label: 'Kontoinhaber', key: 'bank_owner', span: false, placeholder: 'Max Mustermann' },
|
||||
{ label: 'IBAN', key: 'bank_iban', span: false, placeholder: 'DE89370400440532013000' },
|
||||
{ label: 'BIC', key: 'bank_bic', span: false, placeholder: 'SOLADE21XXX' },
|
||||
{ label: 'Bankname', key: 'bank_name', span: false, placeholder: 'Musterbank' },
|
||||
] as const).map(({ label, key, span, placeholder }) => (
|
||||
<div key={key} className={`space-y-1.5 ${span ? 'md:col-span-2' : ''}`}>
|
||||
<Label className="text-slate-300 text-sm">{label}</Label>
|
||||
|
||||
@@ -194,6 +194,14 @@ export default async function OrderSuccessPage({
|
||||
<p className="font-semibold text-white">{o.customer_data?.company_name}</p>
|
||||
<p>{o.customer_data?.first_name} {o.customer_data?.last_name}</p>
|
||||
<p>{o.customer_data?.address}, {o.customer_data?.zip_code} {o.customer_data?.city}</p>
|
||||
{o.customer_data?.bank_iban && (
|
||||
<div className="text-xs text-slate-500 pt-2 border-t border-white/5 mt-2 space-y-0.5">
|
||||
<p><span className="font-semibold text-slate-400">Kontoinhaber:</span> {o.customer_data.bank_owner}</p>
|
||||
<p><span className="font-semibold text-slate-400">IBAN:</span> {o.customer_data.bank_iban}</p>
|
||||
{o.customer_data.bank_bic && <p><span className="font-semibold text-slate-400">BIC:</span> {o.customer_data.bank_bic}</p>}
|
||||
{o.customer_data.bank_name && <p><span className="font-semibold text-slate-400">Bank:</span> {o.customer_data.bank_name}</p>}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* PDF-Download */}
|
||||
|
||||
@@ -134,6 +134,11 @@ export const InvoicePDF = ({ order, orderSnapshot, customer }: any) => {
|
||||
<Text>{customer.address}</Text>
|
||||
<Text>{customer.zip_code} {customer.city}</Text>
|
||||
<Text>USt-IdNr: {customer.vat_id}</Text>
|
||||
{customer.bank_iban && (
|
||||
<Text style={{ marginTop: 4, color: '#666' }}>
|
||||
Bank: {customer.bank_name || '-'} · IBAN: {customer.bank_iban} · BIC: {customer.bank_bic || '-'} · Inhaber: {customer.bank_owner || '-'}
|
||||
</Text>
|
||||
)}
|
||||
</View>
|
||||
|
||||
<View style={styles.section}>
|
||||
|
||||
@@ -135,6 +135,7 @@ export function OrderWizard({
|
||||
const [isCreatingCustomer, setIsCreatingCustomer] = useState(false)
|
||||
const [newCustomerForm, setNewCustomerForm] = useState({
|
||||
company_name: '', vat_id: '', first_name: '', last_name: '', street: '', zip: '', city: '',
|
||||
bank_iban: '', bank_bic: '', bank_name: '', bank_owner: '',
|
||||
})
|
||||
|
||||
// Abrechnungsmodell-Auswahl ('one_time' = Kauf, 'monthly' = Abo)
|
||||
@@ -388,7 +389,10 @@ export function OrderWizard({
|
||||
setEndCustomers(prev => [...prev, created])
|
||||
setSelectedEndCustomerId(created.id)
|
||||
setCustomerMode('select')
|
||||
setNewCustomerForm({ company_name: '', vat_id: '', first_name: '', last_name: '', street: '', zip: '', city: '' })
|
||||
setNewCustomerForm({
|
||||
company_name: '', vat_id: '', first_name: '', last_name: '', street: '', zip: '', city: '',
|
||||
bank_iban: '', bank_bic: '', bank_name: '', bank_owner: '',
|
||||
})
|
||||
} catch (e) {
|
||||
alert('Fehler beim Anlegen des Kunden.')
|
||||
} finally {
|
||||
@@ -573,6 +577,10 @@ export function OrderWizard({
|
||||
{ label: 'Straße & Hausnummer', key: 'street', span: true, placeholder: '' },
|
||||
{ label: 'PLZ', key: 'zip', span: false, placeholder: '' },
|
||||
{ label: 'Ort', key: 'city', span: false, placeholder: '' },
|
||||
{ label: 'Kontoinhaber', key: 'bank_owner', span: false, placeholder: 'Max Mustermann' },
|
||||
{ label: 'IBAN', key: 'bank_iban', span: false, placeholder: 'DE89370400440532013000' },
|
||||
{ label: 'BIC', key: 'bank_bic', span: false, placeholder: 'SOLADE21XXX' },
|
||||
{ label: 'Bankname', key: 'bank_name', span: false, placeholder: 'Musterbank' },
|
||||
] as const).map(({ label, key, span, placeholder }) => (
|
||||
<div key={key} className={`space-y-1.5 ${span ? 'md:col-span-2' : ''}`}>
|
||||
<Label className="text-slate-300 text-sm">{label}</Label>
|
||||
|
||||
@@ -174,6 +174,10 @@ export async function adminCreateEndCustomer(data: {
|
||||
zip?: string
|
||||
city?: string
|
||||
email?: string
|
||||
bank_iban?: string
|
||||
bank_bic?: string
|
||||
bank_name?: string
|
||||
bank_owner?: string
|
||||
}) {
|
||||
const admin = createAdminClient()
|
||||
const { data: dbData, error } = await admin
|
||||
@@ -188,6 +192,10 @@ export async function adminCreateEndCustomer(data: {
|
||||
zip: data.zip || null,
|
||||
city: data.city || null,
|
||||
email: data.email || null,
|
||||
bank_iban: data.bank_iban || null,
|
||||
bank_bic: data.bank_bic || null,
|
||||
bank_name: data.bank_name || null,
|
||||
bank_owner: data.bank_owner || null,
|
||||
}])
|
||||
.select()
|
||||
.single()
|
||||
@@ -205,6 +213,10 @@ export async function adminUpdateEndCustomer(id: string, data: {
|
||||
zip?: string
|
||||
city?: string
|
||||
email?: string
|
||||
bank_iban?: string
|
||||
bank_bic?: string
|
||||
bank_name?: string
|
||||
bank_owner?: string
|
||||
}) {
|
||||
const admin = createAdminClient()
|
||||
const { data: dbData, error } = await admin
|
||||
@@ -219,6 +231,10 @@ export async function adminUpdateEndCustomer(id: string, data: {
|
||||
zip: data.zip || null,
|
||||
city: data.city || null,
|
||||
email: data.email || null,
|
||||
bank_iban: data.bank_iban || null,
|
||||
bank_bic: data.bank_bic || null,
|
||||
bank_name: data.bank_name || null,
|
||||
bank_owner: data.bank_owner || null,
|
||||
})
|
||||
.eq('id', id)
|
||||
.select()
|
||||
|
||||
@@ -16,6 +16,10 @@ export type EndCustomerFormData = {
|
||||
zip?: string
|
||||
city?: string
|
||||
email?: string
|
||||
bank_iban?: string
|
||||
bank_bic?: string
|
||||
bank_name?: string
|
||||
bank_owner?: string
|
||||
}
|
||||
|
||||
// ─── Lesen ───────────────────────────────────────────────────────────────────
|
||||
@@ -74,6 +78,10 @@ export async function createEndCustomer(formData: EndCustomerFormData): Promise<
|
||||
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()
|
||||
@@ -104,6 +112,10 @@ export async function updateEndCustomer(id: string, formData: EndCustomerFormDat
|
||||
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)
|
||||
|
||||
@@ -138,6 +150,10 @@ export async function anonymizeEndCustomer(id: string): Promise<void> {
|
||||
zip: null,
|
||||
city: null,
|
||||
email: null,
|
||||
bank_iban: null,
|
||||
bank_bic: null,
|
||||
bank_name: null,
|
||||
bank_owner: null,
|
||||
is_anonymized: true,
|
||||
})
|
||||
.eq('id', id)
|
||||
|
||||
@@ -58,6 +58,10 @@ export function buildCustomerSnapshot(
|
||||
address: endCustomer.street ?? '',
|
||||
zip_code: endCustomer.zip ?? '',
|
||||
city: endCustomer.city ?? '',
|
||||
bank_iban: endCustomer.bank_iban ?? undefined,
|
||||
bank_bic: endCustomer.bank_bic ?? undefined,
|
||||
bank_name: endCustomer.bank_name ?? undefined,
|
||||
bank_owner: endCustomer.bank_owner ?? undefined,
|
||||
}
|
||||
}
|
||||
return {
|
||||
|
||||
@@ -68,6 +68,10 @@ export type EndCustomer = {
|
||||
zip: string | null
|
||||
city: string | null
|
||||
email?: string | null
|
||||
bank_iban: string | null
|
||||
bank_bic: string | null
|
||||
bank_name: string | null
|
||||
bank_owner: string | null
|
||||
is_anonymized: boolean
|
||||
created_at: string
|
||||
}
|
||||
@@ -100,6 +104,10 @@ export type CustomerSnapshot = {
|
||||
zip_code: string
|
||||
city: string
|
||||
email?: string
|
||||
bank_iban?: string
|
||||
bank_bic?: string
|
||||
bank_name?: string
|
||||
bank_owner?: string
|
||||
}
|
||||
|
||||
export type OrderModuleSnapshot = {
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
-- Migration: Add bank details to end_customers table
|
||||
ALTER TABLE end_customers
|
||||
ADD COLUMN IF NOT EXISTS bank_iban TEXT,
|
||||
ADD COLUMN IF NOT EXISTS bank_bic TEXT,
|
||||
ADD COLUMN IF NOT EXISTS bank_name TEXT,
|
||||
ADD COLUMN IF NOT EXISTS bank_owner TEXT;
|
||||
Reference in New Issue
Block a user