Muster-/Angebot-Endpunkte: WordPress-Feldnamen als Aliase akzeptieren
vorname→first_name, name→last_name, telefon→phone, zipcode→zip, ort→city, produkt_interesse→product. App-Feldnamen behalten Vorrang. So kann ein WordPress-Formular direkt Muster-/Angebotsanfragen anlegen. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -1423,16 +1423,20 @@ const handler = (router, { services, getSchema, logger }) => {
|
|||||||
// ── Angebotsanfrage („Individuelles Angebot") ────────────────────────────
|
// ── Angebotsanfrage („Individuelles Angebot") ────────────────────────────
|
||||||
router.post('/offer-request', async (req, res) => {
|
router.post('/offer-request', async (req, res) => {
|
||||||
const body = req.body || {};
|
const body = req.body || {};
|
||||||
const vorname = String(body.first_name || '').trim();
|
// Feld-Aliase (auch WordPress): vorname→first_name, name→last_name, telefon→phone,
|
||||||
const nachname = String(body.last_name || '').trim();
|
// produkt_interesse→product. App-Feldnamen haben Vorrang.
|
||||||
const name = [vorname, nachname].filter(Boolean).join(' ') || String(body.name || '').trim();
|
const vorname = String(body.first_name ?? body.vorname ?? '').trim();
|
||||||
|
const nachname = String(body.last_name ?? body.name ?? '').trim();
|
||||||
|
const name = [vorname, nachname].filter(Boolean).join(' ');
|
||||||
|
const phone = String(body.phone ?? body.telefon ?? '').trim();
|
||||||
|
const product = String(body.product ?? body.produkt_interesse ?? '').trim();
|
||||||
const email = norm(body.email);
|
const email = norm(body.email);
|
||||||
const message = String(body.message || '').trim();
|
const message = String(body.message || '').trim();
|
||||||
|
|
||||||
const errors = [];
|
const errors = [];
|
||||||
if (!name) errors.push('Name fehlt.');
|
if (!name) errors.push('Name fehlt.');
|
||||||
if (!isEmail(email)) errors.push('Gültige E-Mail-Adresse fehlt.');
|
if (!isEmail(email)) errors.push('Gültige E-Mail-Adresse fehlt.');
|
||||||
if (!message && !body.product) errors.push('Bitte beschreiben Sie Ihr Vorhaben.');
|
if (!message && !product) errors.push('Bitte beschreiben Sie Ihr Vorhaben.');
|
||||||
if (message.length > 5000) errors.push('Beschreibung ist zu lang.');
|
if (message.length > 5000) errors.push('Beschreibung ist zu lang.');
|
||||||
if (errors.length) return res.status(400).json({ errors });
|
if (errors.length) return res.status(400).json({ errors });
|
||||||
|
|
||||||
@@ -1454,9 +1458,9 @@ const handler = (router, { services, getSchema, logger }) => {
|
|||||||
type: 'angebot',
|
type: 'angebot',
|
||||||
name: clean(name),
|
name: clean(name),
|
||||||
email,
|
email,
|
||||||
phone: clean(String(body.phone || '').trim()) || null,
|
phone: clean(phone) || null,
|
||||||
quantity: Number.isFinite(quantity) && quantity > 0 ? quantity : null,
|
quantity: Number.isFinite(quantity) && quantity > 0 ? quantity : null,
|
||||||
product: body.product ? clean(String(body.product)) : null,
|
product: product ? clean(product) : null,
|
||||||
message: clean(message),
|
message: clean(message),
|
||||||
address: (vorname || nachname) ? { first_name: clean(vorname), last_name: clean(nachname) } : null,
|
address: (vorname || nachname) ? { first_name: clean(vorname), last_name: clean(nachname) } : null,
|
||||||
status: 'neu',
|
status: 'neu',
|
||||||
@@ -1464,7 +1468,7 @@ const handler = (router, { services, getSchema, logger }) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Schlanke interne Benachrichtigung.
|
// Schlanke interne Benachrichtigung.
|
||||||
const produkt = body.product ? clean(String(body.product)) : null;
|
const produkt = product ? clean(product) : null;
|
||||||
await teamMail(schema, `Neue Angebotsanfrage: ${name}`,
|
await teamMail(schema, `Neue Angebotsanfrage: ${name}`,
|
||||||
`<p>Neue Angebotsanfrage von <strong>${name}</strong> (${email}${body.phone ? `, ${clean(String(body.phone))}` : ''})`
|
`<p>Neue Angebotsanfrage von <strong>${name}</strong> (${email}${body.phone ? `, ${clean(String(body.phone))}` : ''})`
|
||||||
+ `${produkt ? ` · ${produkt}` : ''} – im Board unter „Neu".</p>`);
|
+ `${produkt ? ` · ${produkt}` : ''} – im Board unter „Neu".</p>`);
|
||||||
@@ -1480,15 +1484,23 @@ const handler = (router, { services, getSchema, logger }) => {
|
|||||||
router.post('/sample-request', async (req, res) => {
|
router.post('/sample-request', async (req, res) => {
|
||||||
const body = req.body || {};
|
const body = req.body || {};
|
||||||
const email = norm(body.email);
|
const email = norm(body.email);
|
||||||
// Vor-/Nachname getrennt; „name" bleibt als Fallback (Altstand/Kompatibilität).
|
// Feld-Aliase, damit auch das WordPress-Formular direkt anlegen kann:
|
||||||
const vollName = [String(body.first_name || '').trim(), String(body.last_name || '').trim()].filter(Boolean).join(' ')
|
// vorname→first_name, name→last_name, telefon→phone, zipcode→zip, ort→city,
|
||||||
|| String(body.name || '').trim();
|
// produkt_interesse→product. Die App-Feldnamen haben Vorrang.
|
||||||
|
const first = String(body.first_name ?? body.vorname ?? '').trim();
|
||||||
|
const last = String(body.last_name ?? body.name ?? '').trim();
|
||||||
|
const product = String(body.product ?? body.produkt_interesse ?? '').trim();
|
||||||
|
const phone = String(body.phone ?? body.telefon ?? '').trim();
|
||||||
|
const street = String(body.street ?? '').trim();
|
||||||
|
const zip = String(body.zip ?? body.zipcode ?? '').trim();
|
||||||
|
const city = String(body.city ?? body.ort ?? '').trim();
|
||||||
|
const country = String(body.country ?? '').trim();
|
||||||
|
const vollName = [first, last].filter(Boolean).join(' ');
|
||||||
const errors = [];
|
const errors = [];
|
||||||
if (!body.product) errors.push('Produkt fehlt.');
|
if (!product) errors.push('Produkt fehlt.');
|
||||||
if (!vollName) errors.push('Name fehlt.');
|
if (!vollName) errors.push('Name fehlt.');
|
||||||
if (!isEmail(email)) errors.push('Gültige E-Mail-Adresse fehlt.');
|
if (!isEmail(email)) errors.push('Gültige E-Mail-Adresse fehlt.');
|
||||||
if (!String(body.street || '').trim() || !String(body.zip || '').trim() || !String(body.city || '').trim())
|
if (!street || !zip || !city) errors.push('Lieferadresse unvollständig.');
|
||||||
errors.push('Lieferadresse unvollständig.');
|
|
||||||
if (errors.length) return res.status(400).json({ errors });
|
if (errors.length) return res.status(400).json({ errors });
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -1505,16 +1517,16 @@ const handler = (router, { services, getSchema, logger }) => {
|
|||||||
type: 'muster',
|
type: 'muster',
|
||||||
name: clean(vollName),
|
name: clean(vollName),
|
||||||
email,
|
email,
|
||||||
phone: clean(String(body.phone || '').trim()) || null,
|
phone: clean(phone) || null,
|
||||||
product: clean(String(body.product)),
|
product: clean(product),
|
||||||
message: clean(String(body.message || '').trim().slice(0, 1000)) || null,
|
message: clean(String(body.message || '').trim().slice(0, 1000)) || null,
|
||||||
address: {
|
address: {
|
||||||
first_name: clean(String(body.first_name || '').trim()),
|
first_name: clean(first),
|
||||||
last_name: clean(String(body.last_name || '').trim()),
|
last_name: clean(last),
|
||||||
street: clean(String(body.street || '')),
|
street: clean(street),
|
||||||
zip: clean(String(body.zip || '')),
|
zip: clean(zip),
|
||||||
city: clean(String(body.city || '')),
|
city: clean(city),
|
||||||
country: clean(String(body.country || '')),
|
country: clean(country),
|
||||||
},
|
},
|
||||||
status: 'neu',
|
status: 'neu',
|
||||||
customer: customer?.id ?? null,
|
customer: customer?.id ?? null,
|
||||||
@@ -1522,8 +1534,8 @@ const handler = (router, { services, getSchema, logger }) => {
|
|||||||
|
|
||||||
const musterNachricht = clean(String(body.message || '').trim().slice(0, 1000));
|
const musterNachricht = clean(String(body.message || '').trim().slice(0, 1000));
|
||||||
await teamMail(schema, `Neue Musteranfrage: ${clean(vollName)}`,
|
await teamMail(schema, `Neue Musteranfrage: ${clean(vollName)}`,
|
||||||
`<p>Neue Musteranfrage von <strong>${clean(vollName)}</strong> (${email}${body.phone ? `, ${clean(String(body.phone))}` : ''})`
|
`<p>Neue Musteranfrage von <strong>${clean(vollName)}</strong> (${email}${phone ? `, ${clean(phone)}` : ''})`
|
||||||
+ ` · Produkt: ${clean(String(body.product))} – im Board unter „Neu".</p>`
|
+ ` · Produkt: ${clean(product)} – im Board unter „Neu".</p>`
|
||||||
+ (musterNachricht ? `<p><strong>Nachricht:</strong><br>${musterNachricht.replace(/\n/g, '<br>')}</p>` : ''));
|
+ (musterNachricht ? `<p><strong>Nachricht:</strong><br>${musterNachricht.replace(/\n/g, '<br>')}</p>` : ''));
|
||||||
|
|
||||||
return res.json({ ok: true });
|
return res.json({ ok: true });
|
||||||
|
|||||||
Reference in New Issue
Block a user