diff --git a/shop/app/admin/companies/page.tsx b/shop/app/admin/companies/page.tsx index 3a488ae..fb1f79a 100644 --- a/shop/app/admin/companies/page.tsx +++ b/shop/app/admin/companies/page.tsx @@ -14,7 +14,7 @@ import { DialogHeader, DialogTitle, } from '@/components/ui/dialog' -import { getCompanies, createCompany, updateCompany, deleteCompany, syncCompaniesFromLicServer } from '@/lib/actions/companies' +import { getCompanies, createCompany, updateCompany, deleteCompany, syncCompaniesFromLicServer, syncCustomersFromLicServer } from '@/lib/actions/companies' export default function CompaniesPage() { const [companies, setCompanies] = useState([]) @@ -42,8 +42,9 @@ export default function CompaniesPage() { setSyncing(true) setStatusMsg(null) try { - const res = await syncCompaniesFromLicServer() - setStatusMsg(`${res.count} Partner erfolgreich vom LicServer importiert/aktualisiert.`) + const resCompanies = await syncCompaniesFromLicServer() + const resCustomers = await syncCustomersFromLicServer() + setStatusMsg(`${resCompanies.count} Partner und ${resCustomers.count} Kunden erfolgreich vom LicServer importiert.`) setStatusType('success') loadCompanies() } catch (err: any) { diff --git a/shop/app/api/cron/sync-customers/route.ts b/shop/app/api/cron/sync-customers/route.ts new file mode 100644 index 0000000..8c4fc64 --- /dev/null +++ b/shop/app/api/cron/sync-customers/route.ts @@ -0,0 +1,25 @@ +import { NextRequest, NextResponse } from 'next/server' +import { syncCustomersFromLicServer } from '@/lib/actions/companies' + +export const dynamic = 'force-dynamic' + +export async function GET(req: NextRequest) { + // Check authorization header + const authHeader = req.headers.get('authorization') + const cronSecret = process.env.CRON_SECRET + + // Secure the cron endpoint in production + if (process.env.NODE_ENV === 'production' && cronSecret) { + if (authHeader !== `Bearer ${cronSecret}`) { + return NextResponse.json({ error: 'Unauthorized' }, { status: 401 }) + } + } + + try { + const res = await syncCustomersFromLicServer() + return NextResponse.json({ success: true, count: res.count }) + } catch (err: any) { + console.error('[cron] Customer sync failed:', err) + return NextResponse.json({ error: err.message || 'Sync failed' }, { status: 500 }) + } +} diff --git a/shop/lib/actions/companies.ts b/shop/lib/actions/companies.ts index 959183f..7aab64b 100644 --- a/shop/lib/actions/companies.ts +++ b/shop/lib/actions/companies.ts @@ -262,3 +262,78 @@ export async function syncCompaniesFromLicServer() { return { success: true, count: partners.length } } +export async function syncCustomersFromLicServer() { + const admin = createAdminClient() + const cfg = await getLicServerConfigSystem() + + if (!cfg.base_url || !cfg.api_key) { + throw new Error('LicServer ist nicht konfiguriert.') + } + + // 1. Get all local companies + const { data: companies, error: compErr } = await admin + .from('companies') + .select('id') + + if (compErr) throw compErr + if (!companies || companies.length === 0) { + return { success: true, count: 0 } + } + + let totalSynced = 0 + const allUpsertRows: any[] = [] + + // 2. Fetch customers for each company + for (const company of companies) { + try { + const res = await fetch(`${cfg.base_url}/api-v1/partners/${company.id}/customers?pageSize=1000`, { + headers: { 'X-Api-Key': cfg.api_key, 'Accept': 'application/json' }, + signal: AbortSignal.timeout(10_000), + }) + + if (res.ok) { + const result = await res.json() + const customers = result.items || [] + + for (const c of customers) { + const streetCombined = [c.street, c.houseNumber, c.houseNumberAddon] + .filter(Boolean) + .map(s => s.trim()) + .join(' ') + + allUpsertRows.push({ + id: c.id, + partner_id: company.id, + company_name: c.name || 'Unbenannt', + street: streetCombined || null, + zip: c.zipCode || null, + city: c.city || null, + email: c.email || null, + is_anonymized: false, + }) + } + } else { + console.warn(`[sync-customers] Skipping partner ${company.id} due to API status: ${res.status}`) + } + } catch (e: any) { + console.error(`[sync-customers] Error fetching customers for partner ${company.id}:`, e.message || e) + } + } + + if (allUpsertRows.length > 0) { + const { error: upsertErr } = await admin + .from('end_customers') + .upsert(allUpsertRows, { onConflict: 'id' }) + + if (upsertErr) throw upsertErr + totalSynced = allUpsertRows.length + } + + revalidatePath('/my-customers') + revalidatePath('/order') + revalidatePath('/admin/companies') + + return { success: true, count: totalSynced } +} + +