diff --git a/extensions/directus-extension-skrift-orders/dist/index.js b/extensions/directus-extension-skrift-orders/dist/index.js index f9f691f..4bf2015 100644 --- a/extensions/directus-extension-skrift-orders/dist/index.js +++ b/extensions/directus-extension-skrift-orders/dist/index.js @@ -1592,16 +1592,9 @@ const handler = (router, { services, getSchema, logger }) => { const jt = new Date(); const praefix = `${String(jt.getDate()).padStart(2, '0')}-${String(jt.getMonth() + 1).padStart(2, '0')}-${String(jt.getFullYear()).slice(2)}`; - // Freie Basis-Nummer; prüft auch die Split-Varianten -DE / -INT auf Kollision. - const freieBasis = async () => { + const naechsteNummer = async () => { const heutige = await svc('orders').readByQuery({ filter: { order_number: { _starts_with: `${praefix}-` } }, limit: -1, fields: ['id'] }); - let n = (heutige?.length ?? 0) + 1; - for (let v = 0; v < 30; v += 1, n += 1) { - const basis = `${praefix}-${String(n).padStart(3, '0')}`; - const koll = await svc('orders').readByQuery({ filter: { order_number: { _in: [basis, `${basis}-DE`, `${basis}-INT`] } }, limit: 1, fields: ['id'] }); - if (!koll?.length) return basis; - } - throw new Error('Keine freie Auftragsnummer gefunden.'); + return `${praefix}-${String((heutige?.length ?? 0) + 1).padStart(3, '0')}`; }; const orderData = { @@ -1634,54 +1627,38 @@ const handler = (router, { services, getSchema, logger }) => { net_total: quote?.net_total ?? null, vat_amount: quote?.vat_amount ?? null, gross_total: quote?.gross_total ?? null, }; - const entryFelder = (e, nr) => ({ - letter_number: nr, - salutation: clean(e.salutation) ?? null, first_name: clean(e.first_name) ?? null, last_name: clean(e.last_name) ?? null, - street: clean(e.street) ?? null, house_no: clean(e.house_no) ?? null, zip: clean(e.zip) ?? null, - city: clean(e.city) ?? null, country: clean(e.country) ?? null, free_text: clean(e.free_text) ?? null, - placeholders: e.placeholders && typeof e.placeholders === 'object' - ? Object.fromEntries(Object.entries(e.placeholders).map(([k, v]) => [k, clean(String(v))])) : null, - }); - const entriesSvc = svc('order_entries'); - - // Länder-Split: sobald DE- UND Welt-Empfänger vorkommen → zwei getrennte - // Aufträge (-DE / -INT), sonst ein Auftrag ohne Suffix. Gilt für Schriftstücke UND Kuverts. - const deEntries = entries.filter((e) => istInland(e)); - const intEntries = entries.filter((e) => !istInland(e)); - const gemischt = deEntries.length > 0 && intEntries.length > 0; - - const anlegen = async (subEntries, nummer, gebiet) => { - const auslandN = subEntries.filter((e) => !istInland(e)).length; - let q = null; - try { q = await calculatePrice(schema, { ...body, quantity: subEntries.length }); } catch { /* nur Aufzeichnung */ } - const id = await svc('orders').createOne({ - order_number: nummer, - ...orderData, - entries_count: subEntries.length, - count_inland: subEntries.length - auslandN, - count_ausland: auslandN, - net_total: q?.net_total ?? null, vat_amount: q?.vat_amount ?? null, gross_total: q?.gross_total ?? null, - }); - let k = 0; - for (const e of subEntries) { k += 1; await entriesSvc.createOne({ order: id, ...entryFelder(e, k) }); } - await svc('status_history').createOne({ order: id, status: 'eingegangen', note: gebiet ? `Manuell angelegt (Länder-Split: ${gebiet}).` : 'Manuell im Admin angelegt.' }); - // Generierung IMMER anstoßen – das Backend entscheidet, was zu erzeugen ist. - fetch(`${BACKEND_URL}/api/order/from-directus`, { - method: 'POST', headers: { 'Content-Type': 'application/json', 'X-API-Token': BACKEND_TOKEN }, - body: JSON.stringify({ orderId: id }), - }).catch((err) => logger.warn(`[skrift-orders] Manuell-Generierung nicht gestartet: ${err.message}`)); - return { order_number: nummer, id }; - }; - - if (gemischt) { - const basis = await freieBasis(); - const de = await anlegen(deEntries, `${basis}-DE`, 'Deutschland'); - const int = await anlegen(intEntries, `${basis}-INT`, 'weltweit'); - return res.json({ ok: true, split: true, orders: [de, int], order_number: de.order_number, id: de.id }); + let orderId, orderNumber; + for (let v = 0; v < 6; v += 1) { + orderNumber = await naechsteNummer(); + try { orderId = await svc('orders').createOne({ order_number: orderNumber, ...orderData }); break; } + catch (e) { if (v === 5 || !/unique|duplicate|bereits|exists/i.test(String(e?.message || ''))) throw e; } } - const basis = await freieBasis(); - const einzel = await anlegen(entries, basis, null); - return res.json({ ok: true, order_number: einzel.order_number, id: einzel.id }); + + const entriesSvc = svc('order_entries'); + let n = 0; + for (const e of entries) { + n += 1; + await entriesSvc.createOne({ + order: orderId, letter_number: n, + salutation: clean(e.salutation) ?? null, first_name: clean(e.first_name) ?? null, last_name: clean(e.last_name) ?? null, + street: clean(e.street) ?? null, house_no: clean(e.house_no) ?? null, zip: clean(e.zip) ?? null, + city: clean(e.city) ?? null, country: clean(e.country) ?? null, free_text: clean(e.free_text) ?? null, + placeholders: e.placeholders && typeof e.placeholders === 'object' + ? Object.fromEntries(Object.entries(e.placeholders).map(([k, v]) => [k, clean(String(v))])) : null, + }); + } + + await svc('status_history').createOne({ order: orderId, status: 'eingegangen', note: 'Manuell im Admin angelegt.' }); + + // Generierung IMMER anstoßen – für jedes Produkt. Das Backend entscheidet, + // was zu erzeugen ist (Schriftstücke bei Handschrift-Produkten, Kuverts immer + // wenn gewünscht; bei Datei-Produkten NUR die Kuverts). Nichts = No-Op. + 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] Manuell-Generierung nicht gestartet: ${e.message}`)); + + return res.json({ ok: true, order_number: orderNumber, id: orderId }); } catch (err) { logger.error(`[skrift-orders] manual-order: ${err.stack || err.message}`); return res.status(400).json({ error: err.message });