237 lines
7.1 KiB
TypeScript
237 lines
7.1 KiB
TypeScript
import { defineEndpoint } from "@directus/extensions-sdk";
|
|
import { AcquisitionService, PdfEngine } from "@mintel/pdf/server";
|
|
import {
|
|
render,
|
|
SiteAuditTemplate,
|
|
ProjectEstimateTemplate,
|
|
} from "@mintel/mail";
|
|
import { createElement } from "react";
|
|
import * as path from "path";
|
|
import * as fs from "fs";
|
|
|
|
export default defineEndpoint((router, { services, env }) => {
|
|
const { ItemsService, MailService } = services;
|
|
|
|
router.get("/ping", (req, res) => res.send("pong"));
|
|
|
|
router.post("/audit/:id", async (req: any, res: any) => {
|
|
const { id } = req.params;
|
|
const leadsService = new ItemsService("leads", {
|
|
schema: req.schema,
|
|
accountability: req.accountability,
|
|
});
|
|
|
|
try {
|
|
const lead = await leadsService.readOne(id);
|
|
if (!lead) return res.status(404).send({ error: "Lead not found" });
|
|
|
|
await leadsService.updateOne(id, { status: "auditing" });
|
|
|
|
const acqService = new AcquisitionService(env.OPENROUTER_API_KEY);
|
|
const result = await acqService.runFullSequence(
|
|
lead.website_url,
|
|
lead.briefing,
|
|
lead.comments,
|
|
);
|
|
|
|
await leadsService.updateOne(id, {
|
|
status: "audit_ready",
|
|
ai_state: result.state,
|
|
audit_context: JSON.stringify(result.usage),
|
|
});
|
|
|
|
res.send({ success: true, result });
|
|
} catch (error: any) {
|
|
console.error("Audit failed:", error);
|
|
await leadsService.updateOne(id, {
|
|
status: "new",
|
|
comments: `Audit failed: ${error.message}`,
|
|
});
|
|
res.status(500).send({ error: error.message });
|
|
}
|
|
});
|
|
|
|
router.post("/audit-email/:id", async (req: any, res: any) => {
|
|
const { id } = req.params;
|
|
const { ItemsService, MailService } = services;
|
|
const leadsService = new ItemsService("leads", {
|
|
schema: req.schema,
|
|
accountability: req.accountability,
|
|
});
|
|
const _peopleService = new ItemsService("people", {
|
|
schema: req.schema,
|
|
accountability: req.accountability,
|
|
});
|
|
const companiesService = new ItemsService("companies", {
|
|
schema: req.schema,
|
|
accountability: req.accountability,
|
|
});
|
|
const mailService = new MailService({
|
|
schema: req.schema,
|
|
accountability: req.accountability,
|
|
});
|
|
|
|
try {
|
|
const lead = await leadsService.readOne(id, {
|
|
fields: ["*", "company.*", "contact_person.*"],
|
|
});
|
|
if (!lead || !lead.ai_state)
|
|
return res.status(400).send({ error: "Lead or Audit not ready" });
|
|
|
|
let recipientEmail = lead.contact_email;
|
|
let companyName = lead.company?.name || lead.company_name;
|
|
|
|
if (lead.contact_person) {
|
|
recipientEmail = lead.contact_person.email || recipientEmail;
|
|
|
|
if (lead.contact_person.company) {
|
|
const personCompany = await companiesService.readOne(
|
|
lead.contact_person.company,
|
|
);
|
|
companyName = personCompany?.name || companyName;
|
|
}
|
|
}
|
|
|
|
if (!recipientEmail)
|
|
return res.status(400).send({ error: "No recipient email found" });
|
|
|
|
const auditHighlights = [
|
|
`Projekt-Typ: ${lead.ai_state.projectType === "website" ? "Website" : "Web App"}`,
|
|
...(lead.ai_state.sitemap || [])
|
|
.slice(0, 3)
|
|
.map((item: any) => `Potenzial in: ${item.category}`),
|
|
];
|
|
|
|
const html = await render(
|
|
createElement(SiteAuditTemplate, {
|
|
companyName: companyName,
|
|
websiteUrl: lead.website_url,
|
|
auditHighlights,
|
|
}),
|
|
);
|
|
|
|
await mailService.send({
|
|
to: recipientEmail,
|
|
subject: `Analyse Ihrer Webpräsenz: ${companyName}`,
|
|
html,
|
|
});
|
|
|
|
await leadsService.updateOne(id, {
|
|
status: "contacted",
|
|
last_contacted_at: new Date().toISOString(),
|
|
});
|
|
|
|
res.send({ success: true });
|
|
} catch (error: any) {
|
|
console.error("Audit Email failed:", error);
|
|
res.status(500).send({ error: error.message });
|
|
}
|
|
});
|
|
|
|
router.post("/estimate/:id", async (req: any, res: any) => {
|
|
const { id } = req.params;
|
|
const leadsService = new ItemsService("leads", {
|
|
schema: req.schema,
|
|
accountability: req.accountability,
|
|
});
|
|
|
|
try {
|
|
const lead = await leadsService.readOne(id);
|
|
if (!lead || !lead.ai_state)
|
|
return res.status(400).send({ error: "Lead or AI state not found" });
|
|
|
|
const pdfEngine = new PdfEngine();
|
|
const filename = `estimate_${id}_${Date.now()}.pdf`;
|
|
const storageRoot = env.STORAGE_LOCAL_ROOT || "./storage";
|
|
const outputPath = path.join(storageRoot, filename);
|
|
|
|
await pdfEngine.generateEstimatePdf(lead.ai_state, outputPath);
|
|
|
|
await leadsService.updateOne(id, {
|
|
audit_pdf_path: filename,
|
|
});
|
|
|
|
res.send({ success: true, filename });
|
|
} catch (error: any) {
|
|
console.error("PDF Generation failed:", error);
|
|
res.status(500).send({ error: error.message });
|
|
}
|
|
});
|
|
|
|
router.post("/estimate-email/:id", async (req: any, res: any) => {
|
|
const { id } = req.params;
|
|
const leadsService = new ItemsService("leads", {
|
|
schema: req.schema,
|
|
accountability: req.accountability,
|
|
});
|
|
const _peopleService = new ItemsService("people", {
|
|
schema: req.schema,
|
|
accountability: req.accountability,
|
|
});
|
|
const companiesService = new ItemsService("companies", {
|
|
schema: req.schema,
|
|
accountability: req.accountability,
|
|
});
|
|
const mailService = new MailService({
|
|
schema: req.schema,
|
|
accountability: req.accountability,
|
|
});
|
|
|
|
try {
|
|
const lead = await leadsService.readOne(id, {
|
|
fields: ["*", "company.*", "contact_person.*"],
|
|
});
|
|
if (!lead || !lead.audit_pdf_path)
|
|
return res.status(400).send({ error: "PDF not generated" });
|
|
|
|
let recipientEmail = lead.contact_email;
|
|
let companyName = lead.company?.name || lead.company_name;
|
|
|
|
if (lead.contact_person) {
|
|
recipientEmail = lead.contact_person.email || recipientEmail;
|
|
|
|
if (lead.contact_person.company) {
|
|
const personCompany = await companiesService.readOne(
|
|
lead.contact_person.company,
|
|
);
|
|
companyName = personCompany?.name || companyName;
|
|
}
|
|
}
|
|
|
|
if (!recipientEmail)
|
|
return res.status(400).send({ error: "No recipient email found" });
|
|
|
|
const html = await render(
|
|
createElement(ProjectEstimateTemplate, {
|
|
companyName: companyName,
|
|
}),
|
|
);
|
|
|
|
const storageRoot = env.STORAGE_LOCAL_ROOT || "./storage";
|
|
const attachmentPath = path.join(storageRoot, lead.audit_pdf_path);
|
|
|
|
await mailService.send({
|
|
to: recipientEmail,
|
|
subject: `Ihre Projekt-Schätzung: ${companyName}`,
|
|
html,
|
|
attachments: [
|
|
{
|
|
filename: `Angebot_${companyName}.pdf`,
|
|
content: fs.readFileSync(attachmentPath),
|
|
},
|
|
],
|
|
});
|
|
|
|
await leadsService.updateOne(id, {
|
|
status: "contacted",
|
|
last_contacted_at: new Date().toISOString(),
|
|
});
|
|
|
|
res.send({ success: true });
|
|
} catch (error: any) {
|
|
console.error("Estimate Email failed:", error);
|
|
res.status(500).send({ error: error.message });
|
|
}
|
|
});
|
|
});
|