fix: Leads ohne E-Mails wenn Anymailfinder-Guthaben leer
Anymailfinder-Fehler (z.B. 402) markiert Job nicht mehr als failed. Maps- und SERP-Jobs schließen als complete ab und liefern die gefundenen Unternehmen ohne Kontaktdaten — SERP-Supplement triggert danach normal. - maps-enrich: Anymailfinder in eigenem try-catch, Fehler → complete - serp-enrich: SERP-Rohdaten zuerst speichern, dann Enrichment versuchen Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -110,69 +110,83 @@ async function runMapsEnrich(
|
||||
// 3. Optionally enrich with Anymailfinder
|
||||
if (params.enrichEmails && places.length > 0) {
|
||||
const anymailKey = await getApiKey("anymailfinder");
|
||||
if (!anymailKey) throw new Error("Anymailfinder API-Key fehlt — bitte in den Einstellungen eintragen");
|
||||
const domains = places.filter(p => p.domain).map(p => p.domain!);
|
||||
|
||||
// Map domain → placeId for updating results
|
||||
const domainToResultId = new Map<string, string>();
|
||||
const existingResults = await prisma.leadResult.findMany({
|
||||
where: { jobId },
|
||||
select: { id: true, domain: true },
|
||||
});
|
||||
for (const r of existingResults) {
|
||||
if (r.domain) domainToResultId.set(r.domain, r.id);
|
||||
if (!anymailKey) {
|
||||
// No key configured — complete with Maps-only results (no emails)
|
||||
await prisma.job.update({ where: { id: jobId }, data: { status: "complete", totalLeads: places.length } });
|
||||
return;
|
||||
}
|
||||
|
||||
let emailsFound = 0;
|
||||
const enrichResults = await bulkSearchDomains(
|
||||
domains,
|
||||
params.categories,
|
||||
anymailKey,
|
||||
async (_completed, total) => {
|
||||
await prisma.job.update({ where: { id: jobId }, data: { totalLeads: total } });
|
||||
try {
|
||||
const domains = places.filter(p => p.domain).map(p => p.domain!);
|
||||
|
||||
// Map domain → leadResult id for updating
|
||||
const domainToResultId = new Map<string, string>();
|
||||
const existingResults = await prisma.leadResult.findMany({
|
||||
where: { jobId },
|
||||
select: { id: true, domain: true },
|
||||
});
|
||||
for (const r of existingResults) {
|
||||
if (r.domain) domainToResultId.set(r.domain, r.id);
|
||||
}
|
||||
);
|
||||
|
||||
for (const result of enrichResults) {
|
||||
const hasEmail = !!result.email;
|
||||
if (hasEmail) emailsFound++;
|
||||
let emailsFound = 0;
|
||||
const enrichResults = await bulkSearchDomains(
|
||||
domains,
|
||||
params.categories,
|
||||
anymailKey,
|
||||
async (_completed, total) => {
|
||||
await prisma.job.update({ where: { id: jobId }, data: { totalLeads: total } });
|
||||
}
|
||||
);
|
||||
|
||||
const resultId = domainToResultId.get(result.domain || "");
|
||||
if (!resultId) continue;
|
||||
for (const result of enrichResults) {
|
||||
const hasEmail = !!result.email;
|
||||
if (hasEmail) emailsFound++;
|
||||
|
||||
await prisma.leadResult.update({
|
||||
where: { id: resultId },
|
||||
data: {
|
||||
contactName: result.person_full_name || null,
|
||||
contactTitle: result.person_job_title || null,
|
||||
email: result.email || null,
|
||||
linkedinUrl: result.person_linkedin_url || null,
|
||||
},
|
||||
const resultId = domainToResultId.get(result.domain || "");
|
||||
if (!resultId) continue;
|
||||
|
||||
await prisma.leadResult.update({
|
||||
where: { id: resultId },
|
||||
data: {
|
||||
contactName: result.person_full_name || null,
|
||||
contactTitle: result.person_job_title || null,
|
||||
email: result.email || null,
|
||||
linkedinUrl: result.person_linkedin_url || null,
|
||||
},
|
||||
});
|
||||
|
||||
await prisma.job.update({ where: { id: jobId }, data: { emailsFound } });
|
||||
}
|
||||
|
||||
await prisma.job.update({
|
||||
where: { id: jobId },
|
||||
data: { status: "complete", emailsFound, totalLeads: places.length },
|
||||
});
|
||||
|
||||
await prisma.job.update({ where: { id: jobId }, data: { emailsFound } });
|
||||
// Update vault entries with enrichment results
|
||||
await sinkLeadsToVault(
|
||||
enrichResults
|
||||
.filter(r => r.email)
|
||||
.map(r => ({
|
||||
domain: r.domain,
|
||||
contactName: r.person_full_name || null,
|
||||
contactTitle: r.person_job_title || null,
|
||||
email: r.email || null,
|
||||
linkedinUrl: r.person_linkedin_url || null,
|
||||
})),
|
||||
"maps",
|
||||
params.queries.join(", "),
|
||||
jobId,
|
||||
);
|
||||
} catch (enrichErr) {
|
||||
// Anymailfinder failed (e.g. 402 quota) — complete with Maps-only results
|
||||
console.warn(`[maps-enrich] Anymailfinder failed for job ${jobId}:`, enrichErr);
|
||||
await prisma.job.update({
|
||||
where: { id: jobId },
|
||||
data: { status: "complete", totalLeads: places.length },
|
||||
});
|
||||
}
|
||||
|
||||
await prisma.job.update({
|
||||
where: { id: jobId },
|
||||
data: { status: "complete", emailsFound, totalLeads: places.length },
|
||||
});
|
||||
|
||||
// Update vault entries with enrichment results
|
||||
await sinkLeadsToVault(
|
||||
enrichResults
|
||||
.filter(r => r.email)
|
||||
.map(r => ({
|
||||
domain: r.domain,
|
||||
contactName: r.person_full_name || null,
|
||||
contactTitle: r.person_job_title || null,
|
||||
email: r.email || null,
|
||||
linkedinUrl: r.person_linkedin_url || null,
|
||||
})),
|
||||
"maps",
|
||||
params.queries.join(", "),
|
||||
jobId,
|
||||
);
|
||||
} else {
|
||||
await prisma.job.update({
|
||||
where: { id: jobId },
|
||||
|
||||
Reference in New Issue
Block a user