fix: Leads ohne Domain werden gefiltert und nicht gespeichert

Maps-Ergebnisse ohne Domain werden vor Speicherung herausgefiltert.
sinkLeadsToVault überspringt Leads ohne Domain komplett.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
TimoUttenweiler
2026-04-01 10:54:30 +02:00
parent 929d5ab3a1
commit 25234b70ee
2 changed files with 13 additions and 7 deletions

View File

@@ -75,7 +75,11 @@ async function runMapsEnrich(
}); });
// 2. Store raw Google Maps results + immediately sink to LeadVault // 2. Store raw Google Maps results + immediately sink to LeadVault
for (const place of places) { // Skip places without a domain — not actionable as leads
const placesWithDomain = places.filter(p => !!p.domain);
await prisma.job.update({ where: { id: jobId }, data: { totalLeads: placesWithDomain.length } });
for (const place of placesWithDomain) {
await prisma.leadResult.create({ await prisma.leadResult.create({
data: { data: {
jobId, jobId,
@@ -94,7 +98,7 @@ async function runMapsEnrich(
// Sink Google Maps results to vault immediately (before enrichment) // Sink Google Maps results to vault immediately (before enrichment)
// so they're available even if Anymailfinder fails // so they're available even if Anymailfinder fails
await sinkLeadsToVault( await sinkLeadsToVault(
places.map(p => ({ placesWithDomain.map(p => ({
domain: p.domain, domain: p.domain,
companyName: p.name || null, companyName: p.name || null,
phone: p.phone, phone: p.phone,
@@ -108,16 +112,16 @@ async function runMapsEnrich(
); );
// 3. Optionally enrich with Anymailfinder // 3. Optionally enrich with Anymailfinder
if (params.enrichEmails && places.length > 0) { if (params.enrichEmails && placesWithDomain.length > 0) {
const anymailKey = await getApiKey("anymailfinder"); const anymailKey = await getApiKey("anymailfinder");
if (!anymailKey) { if (!anymailKey) {
// No key configured — complete with Maps-only results (no emails) // No key configured — complete with Maps-only results (no emails)
await prisma.job.update({ where: { id: jobId }, data: { status: "complete", totalLeads: places.length } }); await prisma.job.update({ where: { id: jobId }, data: { status: "complete", totalLeads: placesWithDomain.length } });
return; return;
} }
try { try {
const domains = places.filter(p => p.domain).map(p => p.domain!); const domains = placesWithDomain.map(p => p.domain!);
// Map domain → leadResult id for updating // Map domain → leadResult id for updating
const domainToResultId = new Map<string, string>(); const domainToResultId = new Map<string, string>();
@@ -161,7 +165,7 @@ async function runMapsEnrich(
await prisma.job.update({ await prisma.job.update({
where: { id: jobId }, where: { id: jobId },
data: { status: "complete", emailsFound, totalLeads: places.length }, data: { status: "complete", emailsFound, totalLeads: placesWithDomain.length },
}); });
// Update vault entries with enrichment results // Update vault entries with enrichment results
@@ -184,7 +188,7 @@ async function runMapsEnrich(
console.warn(`[maps-enrich] Anymailfinder failed for job ${jobId}:`, enrichErr); console.warn(`[maps-enrich] Anymailfinder failed for job ${jobId}:`, enrichErr);
await prisma.job.update({ await prisma.job.update({
where: { id: jobId }, where: { id: jobId },
data: { status: "complete", totalLeads: places.length }, data: { status: "complete", totalLeads: placesWithDomain.length },
}); });
} }
} else { } else {

View File

@@ -98,6 +98,8 @@ export async function sinkLeadsToVault(
const domain = lead.domain || null; const domain = lead.domain || null;
const email = lead.email || null; const email = lead.email || null;
if (!domain) { skipped++; continue; } // no domain → skip entirely
if (domain) { if (domain) {
// Strict domain dedup: one lead per domain // Strict domain dedup: one lead per domain
const existing = await prisma.lead.findFirst({ where: { domain } }); const existing = await prisma.lead.findFirst({ where: { domain } });