Statistik-Tab, Unterschriftenservice-Kuverts, Auftragsverknüpfung & Notizen
- Produktion: Statistik-Tab (versendete Briefe je Kunde/Monat), verknüpfter Auftrag je Karte anzeigen/ändern/entfernen, Datei-Aufträge werden beim Übernehmen wieder in den Signatur-Tab überführt. - Unterschriftenservice (neuauftrag): optionale Kuverts (je Empfänger ein Umschlag, Absender möglich) und Verknüpfung mit vorhandenem Auftrag. - orders: signature-order erzeugt Kuverts über die Standard-Pipeline (Datei-Produkt -> nur Umschläge, Seiten bleiben erhalten) und speichert linked_order; nachträgliches Verknüpfen im Board. - bootstrap: orders.linked_order (Self-Relation). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -310,6 +310,20 @@ const handler = (router, { services, getSchema, logger }) => {
|
||||
const pages = (await r.json())?.pages || [];
|
||||
if (!pages.length) return res.status(422).json({ error: 'Keine Seiten erzeugt.' });
|
||||
|
||||
// Optionale Kuverts (wie manueller Druck): je Empfänger ein Umschlag. Empfänger
|
||||
// als Blöcke (durch Leerzeile getrennt) im Freitext. Absender optional.
|
||||
const kuvertsAn = !!body.kuverts;
|
||||
const empf = kuvertsAn
|
||||
? String(body.recipients_text || '')
|
||||
.split(/\n\s*\n/).map((s) => s.trim()).filter(Boolean)
|
||||
.map((free_text) => ({ free_text }))
|
||||
: [];
|
||||
if (kuvertsAn && !empf.length) return res.status(400).json({ error: 'Kuverts gewählt, aber keine Empfänger angegeben.' });
|
||||
const envFormat = ['c6', 'dinlang'].includes(body.envelope_format) ? body.envelope_format : 'dinlang';
|
||||
const absender = String(body.envelope_sender || '').trim();
|
||||
const absenderScale = Math.max(0.5, Math.min(2, Number(body.envelope_sender_scale) || 1));
|
||||
const countAusland = empf.filter((e) => !zielInland(e)).length;
|
||||
|
||||
const jt = new Date();
|
||||
const praefix = `${String(jt.getDate()).padStart(2, '0')}-${String(jt.getMonth() + 1).padStart(2, '0')}-${String(jt.getFullYear()).slice(2)}`;
|
||||
const naechsteNummer = async () => {
|
||||
@@ -320,9 +334,14 @@ const handler = (router, { services, getSchema, logger }) => {
|
||||
customer: customerId, customer_email: customerEmail, product: product.id,
|
||||
person_type: 'privat', source: 'operator', status: 'in_queue', production_status: 'eingegangen',
|
||||
payment_status: 'bezahlt', payment_method: 'rechnung', shipping_type: 'sammel',
|
||||
needs_envelope: false, envelope_labeling: 'keine',
|
||||
needs_envelope: kuvertsAn, envelope_labeling: kuvertsAn ? 'empfaenger' : 'keine',
|
||||
envelope_format: kuvertsAn ? envFormat : null,
|
||||
envelope_sender: kuvertsAn && absender ? absender : null,
|
||||
envelope_sender_scale: absenderScale,
|
||||
source_file: pdfId, source_files: [pdfId],
|
||||
entries_count: pages.length, count_inland: pages.length, count_ausland: 0,
|
||||
entries_count: kuvertsAn ? empf.length : pages.length,
|
||||
count_inland: kuvertsAn ? (empf.length - countAusland) : pages.length,
|
||||
count_ausland: kuvertsAn ? countAusland : 0,
|
||||
};
|
||||
let orderId, orderNumber;
|
||||
for (let v = 0; v < 6; v += 1) {
|
||||
@@ -332,11 +351,28 @@ const handler = (router, { services, getSchema, logger }) => {
|
||||
}
|
||||
|
||||
const entriesSvc = svc('order_entries');
|
||||
for (let i = 0; i < pages.length; i += 1) {
|
||||
await entriesSvc.createOne({ order: orderId, letter_number: i + 1, free_text: `Seite ${i + 1}` });
|
||||
if (kuvertsAn) {
|
||||
// Empfänger als Zeilen – daraus erzeugt die Pipeline je einen Umschlag.
|
||||
for (let i = 0; i < empf.length; i += 1) {
|
||||
await entriesSvc.createOne({ order: orderId, letter_number: i + 1, free_text: empf[i].free_text });
|
||||
}
|
||||
} else {
|
||||
for (let i = 0; i < pages.length; i += 1) {
|
||||
await entriesSvc.createOne({ order: orderId, letter_number: i + 1, free_text: `Seite ${i + 1}` });
|
||||
}
|
||||
}
|
||||
await svc('status_history').createOne({ order: orderId, status: 'eingegangen', note: 'Unterschriftenservice – manuell angelegt.' }).catch(() => {});
|
||||
|
||||
// Verknüpfung mit vorhandenem Auftrag (dessen Kuverts genutzt werden) – optional.
|
||||
if (body.link_order_number) {
|
||||
try {
|
||||
const linked = (await svc('orders').readByQuery({
|
||||
filter: { order_number: { _eq: String(body.link_order_number).trim() } }, limit: 1, fields: ['id'],
|
||||
}))?.[0];
|
||||
if (linked) await svc('orders').updateOne(orderId, { linked_order: linked.id });
|
||||
} catch (e) { logger.warn(`[skrift-orders] signature-order Verknüpfung: ${e.message}`); }
|
||||
}
|
||||
|
||||
// Seiten-SVGs als Schriftstück in den Auftragsordner schreiben.
|
||||
const ordner = path.join(OUTPUT_DIR, orderNumber);
|
||||
fs.mkdirSync(ordner, { recursive: true });
|
||||
@@ -344,7 +380,16 @@ const handler = (router, { services, getSchema, logger }) => {
|
||||
fs.writeFileSync(path.join(ordner, `letter_${String(i + 1).padStart(3, '0')}.svg`), p.svg, 'utf8');
|
||||
});
|
||||
|
||||
return res.json({ ok: true, order_number: orderNumber, id: orderId, pages: pages.length });
|
||||
// Kuverts über die Standard-Pipeline erzeugen (Datei-Produkt → NUR Umschläge;
|
||||
// die Seiten-SVGs bleiben erhalten, da runGeneration den Ordner nicht leert).
|
||||
if (kuvertsAn) {
|
||||
fetch(`${BACKEND_URL}/api/order/from-directus`, {
|
||||
method: 'POST', headers: { 'Content-Type': 'application/json', 'X-API-Token': BACKEND_TOKEN },
|
||||
body: JSON.stringify({ orderId }),
|
||||
}).catch((e) => logger.warn(`[skrift-orders] signature-order Kuverts nicht gestartet: ${e.message}`));
|
||||
}
|
||||
|
||||
return res.json({ ok: true, order_number: orderNumber, id: orderId, pages: pages.length, kuverts: empf.length });
|
||||
} catch (err) {
|
||||
logger.error(`[skrift-orders] signature-order: ${err.stack || err.message}`);
|
||||
return res.status(500).json({ error: 'Auftrag konnte nicht angelegt werden.', detail: String(err.message || err).slice(0, 400) });
|
||||
|
||||
Reference in New Issue
Block a user