import { Document, Page, Text, View, StyleSheet } from '@react-pdf/renderer'; const styles = StyleSheet.create({ page: { padding: 50, fontSize: 10, color: '#333', fontFamily: 'Helvetica', }, header: { flexDirection: 'row', justifyContent: 'space-between', marginBottom: 40, }, companyInfo: { textAlign: 'right', }, title: { fontSize: 24, color: '#000', marginBottom: 20, }, section: { marginBottom: 20, }, label: { fontSize: 8, color: '#999', textTransform: 'uppercase', marginBottom: 2, }, table: { width: 'auto', borderStyle: 'solid', borderWidth: 1, borderColor: '#eee', borderRightWidth: 0, borderBottomWidth: 0, marginBottom: 20, }, tableRow: { margin: 'auto', flexDirection: 'row', }, tableCol: { width: '60%', borderStyle: 'solid', borderWidth: 1, borderColor: '#eee', borderLeftWidth: 0, borderTopWidth: 0, padding: 8, }, tableColPrice: { width: '40%', borderStyle: 'solid', borderWidth: 1, borderColor: '#eee', borderLeftWidth: 0, borderTopWidth: 0, padding: 8, textAlign: 'right', }, total: { flexDirection: 'row', justifyContent: 'flex-end', marginTop: 20, borderTopWidth: 1, borderColor: '#000', paddingTop: 10, }, totalLabel: { fontSize: 11, fontWeight: 'bold', }, footer: { position: 'absolute', bottom: 30, left: 50, right: 50, textAlign: 'center', color: '#999', fontSize: 8, borderTopWidth: 1, borderColor: '#eee', paddingTop: 10, }, sepaBox: { marginTop: 15, padding: 10, backgroundColor: '#f9f9f9', borderWidth: 1, borderColor: '#ddd', } }); export const InvoicePDF = ({ order, orderSnapshot, customer }: any) => { const items = orderSnapshot?.items ?? []; const taxRate = orderSnapshot?.tax_rate ?? 19; const isSubscription = order?.type === 'subscription' || orderSnapshot?.billing_cycle === 'monthly'; let oneTimeNet = 0; let monthlyNet = 0; items.forEach((item: any) => { if (item.billing_interval === 'monthly') { monthlyNet += item.base_price || 0; } else { oneTimeNet += item.base_price || 0; } item.selected_modules?.forEach((mod: any) => { const qty = mod.quantity || 1; const price = mod.total_price ?? (mod.price * qty); // Module sind monatliche wiederkehrende Beträge (Abo/Miete) monthlyNet += price; }); }); const oneTimeTax = Math.round(oneTimeNet * (taxRate / 100) * 100) / 100; const oneTimeGross = Math.round((oneTimeNet + oneTimeTax) * 100) / 100; const monthlyTax = Math.round(monthlyNet * (taxRate / 100) * 100) / 100; const monthlyGross = Math.round((monthlyNet + monthlyTax) * 100) / 100; const formattedPrice = (val: number) => new Intl.NumberFormat('de-DE', { style: 'currency', currency: 'EUR' }).format(val); const groupedItems: { [key: string]: any[] } = {}; items.forEach((item: any) => { const devName = item.device_name || 'Kasse 1'; if (!groupedItems[devName]) { groupedItems[devName] = []; } groupedItems[devName].push(item); }); return ( CASPOS Die Kasse CASPOS Computerabrechnungssysteme GmbH Alte Bundesstraße 16 76846 Hauenstein Deutschland {isSubscription ? 'Anfragebestätigung: Software-Abonnement' : 'Anfragebestätigung: Einmalige Lizenzen'} Kunde {customer.company_name} {customer.first_name} {customer.last_name} {customer.address} {customer.zip_code} {customer.city} USt-IdNr: {customer.vat_id} Bestelldetails Bestellnummer: {order.order_number || order.id} Zahlungsart: {isSubscription ? 'SEPA-Lastschrift' : 'Rechnung'} Datum: {new Date(order.created_at || Date.now()).toLocaleDateString('de-DE')} Beschreibung Preis (netto) {Object.entries(groupedItems).map(([deviceName, devItems], groupIdx) => ( Gerät: {deviceName} {devItems.map((item: any, idx: number) => ( {item.product_name} ({item.category_name}) {formattedPrice(item.base_price)} {item.billing_interval === 'one_time' ? 'einmalig' : 'mtl.'} {item.selected_modules?.map((mod: any, mIdx: number) => { const qty = mod.quantity || 1; const price = mod.total_price ?? (mod.price * qty); return ( + {mod.module_name} {qty > 1 ? `(x${qty})` : ''} +{formattedPrice(price)} mtl. ); })} ))} ))} {oneTimeNet > 0 && ( Einmalige Beträge: Netto-Zwischensumme: {formattedPrice(oneTimeNet)} zzgl. {taxRate}% USt: {formattedPrice(oneTimeTax)} Gesamt einmalig (brutto): {formattedPrice(oneTimeGross)} )} {monthlyNet > 0 && ( 0 ? 1 : 0, borderTopColor: '#e2e8f0' }}> Monatlich wiederkehrende Beträge: Netto-Zwischensumme: {formattedPrice(monthlyNet)} / mtl. zzgl. {taxRate}% USt: {formattedPrice(monthlyTax)} / mtl. Gesamt monatlich (brutto): {formattedPrice(monthlyGross)} / mtl. )} {isSubscription ? ( SEPA-Lastschriftmandat Ich ermächtige die CASPOS GmbH, Zahlungen von meinem Konto mittels Lastschrift einzuziehen. Zugleich weise ich mein Kreditinstitut an, die von der CASPOS GmbH auf mein Konto gezogenen Lastschriften einzulösen. Das Mandat wird erst mit der finalen Aktivierung der Lizenzen durch den CASPOS-Support wirksam. {customer.bank_iban && ( IBAN: {customer.bank_iban.replace(/(.{4})/g, '$1 ')} · Inhaber: {customer.bank_owner || 'Kunde'} )} ) : ( Dies ist eine unverbindliche Bestätigung Ihrer Anfrage. Ein verbindliches Angebot wird Ihnen in Kürze von unserem Vertriebsteam zugesendet. )} CASPOS Computerabrechnungssysteme GmbH · Amtsgericht Zweibrücken HRB 12345 Dies ist ein automatisch erzeugtes Dokument. ); };