Manueller Auftrag: Neukundenzwang + Mails-Checkbox
- Neue E-Mail im Neuauftrag -> Pruefung; unbekannt => Stammdaten (Vor-/Nachname oder Firma + Adresse) werden erzwungen und beim Anlegen am Kundenkonto gespeichert (statt leerem Auto-Konto). - Checkbox "Mails an Kunden senden" je manuellem Auftrag; orders.mails_senden (Default true). Mailer unterdrueckt Kunden-Mails bei mails_senden=false. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -170,7 +170,7 @@ export default (register, { services, getSchema, logger }) => {
|
||||
|
||||
const order = await new ItemsService('orders', { schema, accountability: null }).readOne(orderId, {
|
||||
fields: [
|
||||
'order_number', 'customer_email', 'entries_count', 'shipping_type',
|
||||
'order_number', 'customer_email', 'entries_count', 'shipping_type', 'mails_senden',
|
||||
'needs_envelope', 'envelope_labeling', 'envelope_format',
|
||||
'net_total', 'vat_amount', 'gross_total', 'billing', 'shipping_address',
|
||||
'customer.first_name', 'customer.last_name', 'customer.company',
|
||||
@@ -178,6 +178,8 @@ export default (register, { services, getSchema, logger }) => {
|
||||
],
|
||||
});
|
||||
if (!order?.customer_email) return;
|
||||
// Manuell deaktivierbar: „Mails senden = nein" unterdrückt Kunden-Mails.
|
||||
if (order.mails_senden === false) return;
|
||||
// Datei-Produkte (Unterschriftenservice) erhalten KEINE Standard-Bestell-
|
||||
// bestätigung – dafür geht eine eigene Vorlage aus dem Bestell-Endpunkt raus.
|
||||
if (key === 'order_created' && order.product?.input_mode === 'datei') return;
|
||||
|
||||
@@ -73,6 +73,10 @@ const NeuAuftrag = defineComponent({
|
||||
const leereZeile = () => ({ free_text: '', placeholders: {} });
|
||||
const neu = reactive({
|
||||
product: '', format: '', font: 'tilda', orderName: '',
|
||||
// Mails an den Kunden senden (Bestätigung/Status). Pro manuellem Auftrag abschaltbar.
|
||||
mailsSenden: true,
|
||||
// Kunden-Check: '', 'pruefe', 'vorhanden', 'neu'. Bei 'neu' werden Stammdaten erzwungen.
|
||||
kundeStatus: '', kundeVorname: '', kundeNachname: '', kundeFirma: '', kundeStr: '', kundePlz: '', kundeOrt: '',
|
||||
// Relative Schriftgröße in % (getrennt Brief/Kuvert); 100 = Standard.
|
||||
fontSizeLetter: 100, fontSizeEnvelope: 100,
|
||||
// Unterschrift auf dem Brief ([[signatur1]]): SVG-Inhalt + Feinjustierung.
|
||||
@@ -89,6 +93,20 @@ const NeuAuftrag = defineComponent({
|
||||
docs: [], previewSession: null, pLaedt: false, msg: '', err: '', hinweis: '', lb: '', lbDoc: null,
|
||||
});
|
||||
// Ist das gewählte Format eine Postkarte (Text links, Adresse rechts, ein SVG)?
|
||||
// Kunden-Check: existiert die E-Mail? Bei „neu" werden Stammdaten erzwungen.
|
||||
let kundeTimer = null;
|
||||
function pruefeKunde() {
|
||||
const mail = String(neu.customer_email || '').trim();
|
||||
clearTimeout(kundeTimer);
|
||||
if (!mail || !/^[^@\s]+@[^@\s]+\.[^@\s]+$/.test(mail)) { neu.kundeStatus = ''; return; }
|
||||
neu.kundeStatus = 'pruefe';
|
||||
kundeTimer = setTimeout(async () => {
|
||||
try {
|
||||
const r = await api.get('/users', { params: { filter: { email: { _eq: mail } }, limit: 1, fields: 'id' } });
|
||||
neu.kundeStatus = (r.data?.data?.[0]) ? 'vorhanden' : 'neu';
|
||||
} catch { neu.kundeStatus = ''; }
|
||||
}, 350);
|
||||
}
|
||||
const istPostkarte = () => pkFormate.value.has(neu.format);
|
||||
// Kuverts nur generieren, wenn angehakt (Beschriftung aus der Empfängeradresse).
|
||||
// Postkarte: KEIN separater Umschlag – der Absender kommt über envelope_sender
|
||||
@@ -398,6 +416,10 @@ const NeuAuftrag = defineComponent({
|
||||
neu.msg = `✓ Auftrag ${nr} angelegt – Dokumente werden noch generiert. Status im Produktions-Board prüfen.`;
|
||||
}
|
||||
async function absenden() {
|
||||
// Neukunde: Stammdaten erzwingen, bevor der Auftrag angelegt wird.
|
||||
if (neu.kundeStatus === 'neu' && !((neu.kundeVorname.trim() && neu.kundeNachname.trim()) || neu.kundeFirma.trim())) {
|
||||
neu.err = 'Neuer Kunde: bitte Vor- und Nachnamen oder eine Firma angeben.'; return;
|
||||
}
|
||||
// Ohne Kuvert & ohne eigene Platzhalter: N identische Schriftstücke (Blankozeilen).
|
||||
// Sonst: die erfassten Empfänger – ohne Empfänger genau ein Schriftstück.
|
||||
let payloadEntries;
|
||||
@@ -420,6 +442,11 @@ const NeuAuftrag = defineComponent({
|
||||
envelope_format: kv.envelope_format,
|
||||
shipping_type: 'sammel',
|
||||
customer_email: neu.customer_email.trim() || undefined,
|
||||
mails_senden: neu.mailsSenden,
|
||||
customer_vorname: neu.kundeVorname.trim() || undefined,
|
||||
customer_nachname: neu.kundeNachname.trim() || undefined,
|
||||
customer_company: neu.kundeFirma.trim() || undefined,
|
||||
customer_address: (neu.kundeStr || neu.kundePlz || neu.kundeOrt) ? { street: neu.kundeStr.trim(), zip: neu.kundePlz.trim(), city: neu.kundeOrt.trim(), country: 'Deutschland' } : undefined,
|
||||
text_template: neu.text, preview_session: neu.previewSession || undefined,
|
||||
entries: payloadEntries,
|
||||
});
|
||||
@@ -435,6 +462,7 @@ const NeuAuftrag = defineComponent({
|
||||
function zuruecksetzen() {
|
||||
Object.assign(neu, {
|
||||
product: produkte.value[0]?.key || 'briefe', format: neuFormate()[0]?.key || '', font: 'tilda', orderName: '',
|
||||
mailsSenden: true, kundeStatus: '', kundeVorname: '', kundeNachname: '', kundeFirma: '', kundeStr: '', kundePlz: '', kundeOrt: '',
|
||||
fontSizeLetter: 100, fontSizeEnvelope: 100,
|
||||
sigSvg: '', sigLabel: '', sigX: 0, sigY: 0, sigScale: 100, sigSpacing: '', mehrseitig: false, seitenInfo: '',
|
||||
adressModus: '5zeilen', kuverts: true, absenderAufKuvert: false, envelopeSender: '', envelopeSenderScale: 100, envFormat: '', realistic: true, customer_email: '', text: '', rows: [leereZeile()],
|
||||
@@ -697,9 +725,28 @@ const NeuAuftrag = defineComponent({
|
||||
]),
|
||||
h('div', { style: 'flex:1 1 280px;max-width:420px;' }, [
|
||||
label('Kunde verknüpfen (E-Mail, optional)'),
|
||||
h('input', { type: 'email', value: neu.customer_email, placeholder: 'kunde@example.de', style: WFELD + 'width:100%;', onInput: (e) => { neu.customer_email = e.target.value; } }),
|
||||
h('input', { type: 'email', value: neu.customer_email, placeholder: 'kunde@example.de', style: WFELD + 'width:100%;', onInput: (e) => { neu.customer_email = e.target.value; pruefeKunde(); } }),
|
||||
neu.kundeStatus === 'vorhanden' ? h('div', { style: 'font-size:12px;color:var(--success,#2e7d32);margin-top:5px;font-weight:600;' }, '✓ Bestehender Kunde wird verknüpft') : null,
|
||||
neu.kundeStatus === 'neu' ? h('div', { style: 'font-size:12px;color:var(--primary,#1e50a5);margin-top:5px;font-weight:600;' }, 'Neuer Kunde – bitte unten Stammdaten erfassen.') : null,
|
||||
]),
|
||||
]),
|
||||
// Neukundenanlage erzwingen, sobald eine unbekannte E-Mail eingetragen ist.
|
||||
neu.kundeStatus === 'neu' ? h('div', { style: 'margin-top:14px;border:1px solid var(--border-normal);border-radius:10px;padding:16px;background:var(--background-subdued,#f1f4f9);' }, [
|
||||
h('div', { style: 'font-weight:600;margin-bottom:10px;' }, 'Neuen Kunden anlegen'),
|
||||
h('div', { style: 'display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:12px;' }, [
|
||||
h('div', {}, [label('Vorname'), h('input', { value: neu.kundeVorname, style: WFELD + 'width:100%;', onInput: (e) => { neu.kundeVorname = e.target.value; } })]),
|
||||
h('div', {}, [label('Nachname'), h('input', { value: neu.kundeNachname, style: WFELD + 'width:100%;', onInput: (e) => { neu.kundeNachname = e.target.value; } })]),
|
||||
h('div', {}, [label('Firma (optional)'), h('input', { value: neu.kundeFirma, style: WFELD + 'width:100%;', onInput: (e) => { neu.kundeFirma = e.target.value; } })]),
|
||||
h('div', {}, [label('Straße + Nr.'), h('input', { value: neu.kundeStr, style: WFELD + 'width:100%;', onInput: (e) => { neu.kundeStr = e.target.value; } })]),
|
||||
h('div', {}, [label('PLZ'), h('input', { value: neu.kundePlz, style: WFELD + 'width:100%;', onInput: (e) => { neu.kundePlz = e.target.value; } })]),
|
||||
h('div', {}, [label('Ort'), h('input', { value: neu.kundeOrt, style: WFELD + 'width:100%;', onInput: (e) => { neu.kundeOrt = e.target.value; } })]),
|
||||
]),
|
||||
]) : null,
|
||||
// Mails an Kunden senden (Bestätigung/Status) – pro Auftrag abschaltbar.
|
||||
h('label', { style: 'display:flex;align-items:center;gap:8px;margin-top:14px;font-size:14px;cursor:pointer;' }, [
|
||||
h('input', { type: 'checkbox', checked: neu.mailsSenden, onChange: (e) => { neu.mailsSenden = e.target.checked; }, style: 'width:16px;height:16px;' }),
|
||||
'Mails an Kunden senden (Bestätigung/Status)',
|
||||
]),
|
||||
]);
|
||||
|
||||
const aktionen = h('div', { class: 'sk-btnrow', style: 'display:flex;gap:8px;flex-wrap:wrap;' }, [
|
||||
|
||||
@@ -2053,7 +2053,16 @@ const handler = (router, { services, getSchema, logger }) => {
|
||||
const role = (await new RolesService({ schema, accountability: null }).readByQuery({
|
||||
filter: { name: { _eq: 'Kunde' } }, limit: 1, fields: ['id'],
|
||||
}))?.[0];
|
||||
customerId = await users.createOne({ email: kundeMail, password: zufallsPasswort(), role: role?.id ?? null, status: 'active' });
|
||||
// Neukunde mit den im Formular erfassten Stammdaten anlegen.
|
||||
const neuKunde = { email: kundeMail, password: zufallsPasswort(), role: role?.id ?? null, status: 'active',
|
||||
first_name: clean(body.customer_vorname) || null,
|
||||
last_name: clean(body.customer_nachname) || null,
|
||||
company: clean(body.customer_company) || null,
|
||||
person_type: body.customer_company ? 'unternehmen' : 'privat',
|
||||
};
|
||||
const adr = body.customer_address && typeof body.customer_address === 'object' ? body.customer_address : null;
|
||||
if (adr && (adr.street || adr.zip || adr.city)) neuKunde.billing_address = adr;
|
||||
customerId = await users.createOne(neuKunde);
|
||||
customerEmail = kundeMail;
|
||||
} catch (e) { logger.warn(`[skrift-orders] manual-order Kunde anlegen: ${e.message}`); customerEmail = kundeMail; }
|
||||
}
|
||||
@@ -2084,6 +2093,7 @@ const handler = (router, { services, getSchema, logger }) => {
|
||||
const orderData = {
|
||||
customer: customerId, customer_email: customerEmail,
|
||||
order_name: clean(body.order_name) || null,
|
||||
mails_senden: body.mails_senden !== false,
|
||||
product: product.id, format: formatId,
|
||||
person_type: body.person_type === 'unternehmen' ? 'unternehmen' : 'privat',
|
||||
font: ['tilda', 'alva', 'ellie'].includes(body.font) ? body.font : 'tilda',
|
||||
|
||||
Reference in New Issue
Block a user