Produktion: Druckdatum je Auftrag, Chargen nach Druck-Durchgang trennen, Empfänger
- Chargen trennen jetzt zusätzlich nach dem Druck-Durchgang (Zeitpunkt „in den Druck gegeben", Minute) – zwei Druckläufe desselben Tages mischen sich nicht mehr. - Charge-Karte: Chip „🖨 gedruckt <Datum/Zeit>". - „Weiteres" je Auftrag: „In den Druck: <Datum/Zeit>" sowie Erster/Letzter Empfänger (nach Briefnummer) zum Auseinandersortieren. - druckIndex (frühester/letzter Job-Zeitpunkt) + empfNamen aus order_entries. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -240,20 +240,31 @@ const Board = defineComponent({
|
||||
// (klein geschrieben). Damit findet die normale Suche oben auch Empfänger,
|
||||
// ohne dass man den Auftrag öffnen muss. Wird bei vollem Laden gebaut.
|
||||
const empfIndex = ref({});
|
||||
// Erster/letzter Empfänger je Auftrag (nach Briefnummer) – zum Auseinandersortieren.
|
||||
const empfNamen = ref({});
|
||||
const entryName = (e) => [e.first_name, e.last_name].filter(Boolean).join(' ')
|
||||
|| (e.free_text ? String(e.free_text).split('\n')[0].trim() : '')
|
||||
|| [e.zip, e.city].filter(Boolean).join(' ') || '—';
|
||||
async function ladeEmpfIndex() {
|
||||
try {
|
||||
const r = await api.get('/items/order_entries', { params: {
|
||||
limit: -1, fields: 'order,salutation,first_name,last_name,street,house_no,zip,city,country,free_text',
|
||||
limit: -1, sort: 'order,letter_number',
|
||||
fields: 'order,letter_number,salutation,first_name,last_name,street,house_no,zip,city,country,free_text',
|
||||
} });
|
||||
const idx = {};
|
||||
const namen = {};
|
||||
for (const e of r.data?.data || []) {
|
||||
const oid = String(e.order?.id ?? e.order ?? '');
|
||||
if (!oid) continue;
|
||||
const txt = [e.salutation, e.first_name, e.last_name, e.street, e.house_no, e.zip, e.city, e.country, e.free_text]
|
||||
.filter(Boolean).join(' ').toLowerCase();
|
||||
idx[oid] = idx[oid] ? idx[oid] + ' · ' + txt : txt;
|
||||
const nm = entryName(e);
|
||||
if (!namen[oid]) namen[oid] = { erste: nm, letzte: nm, anzahl: 1 };
|
||||
else { namen[oid].letzte = nm; namen[oid].anzahl += 1; }
|
||||
}
|
||||
empfIndex.value = idx;
|
||||
empfNamen.value = namen;
|
||||
} catch { /* Suche läuft dann ohne Empfänger weiter */ }
|
||||
}
|
||||
// Sende-Index über ALLE Jobs (auch bereits gedruckte): orderId →
|
||||
@@ -261,12 +272,16 @@ const Board = defineComponent({
|
||||
// Zeigt am Auftrag „auf einen Blick", welche Nummern schon in den Druck
|
||||
// gesendet wurden (leeres numbers = „alle"). Rein informativ, kein Status.
|
||||
const sendIndex = ref({});
|
||||
// Druckzeitpunkt je Auftrag (frühester Job = „in den Druck gegeben"). Basis für
|
||||
// das angezeigte Druckdatum UND die Trennung der Chargen nach Druck-Durchgang.
|
||||
const druckIndex = ref({});
|
||||
async function ladeSendIndex() {
|
||||
try {
|
||||
const r = await api.get('/items/jobs', { params: {
|
||||
limit: -1, sort: 'date_created', fields: 'order,type,numbers',
|
||||
limit: -1, sort: 'date_created', fields: 'order,type,numbers,date_created',
|
||||
} });
|
||||
const idx = {};
|
||||
const dz = {};
|
||||
for (const j of r.data?.data || []) {
|
||||
const oid = String(j.order?.id ?? j.order ?? '');
|
||||
if (!oid) continue;
|
||||
@@ -274,10 +289,16 @@ const Board = defineComponent({
|
||||
const num = (j.numbers && String(j.numbers).trim()) ? String(j.numbers).trim() : 'alle';
|
||||
if (!idx[oid]) idx[oid] = { brief: [], umschlag: [] };
|
||||
if (!idx[oid][typ].includes(num)) idx[oid][typ].push(num);
|
||||
const ts = String(j.date_created || '');
|
||||
if (ts && (!dz[oid] || ts < dz[oid].erste)) dz[oid] = { erste: ts };
|
||||
if (ts && (!dz[oid].letzte || ts > dz[oid].letzte)) dz[oid].letzte = ts;
|
||||
}
|
||||
sendIndex.value = idx;
|
||||
druckIndex.value = dz;
|
||||
} catch { /* Anzeige läuft dann ohne „gesendet" weiter */ }
|
||||
}
|
||||
// Datum/Uhrzeit hübsch (dd.mm.yy HH:MM).
|
||||
const dmYhm = (iso) => { if (!iso) return ''; const d = new Date(iso); return Number.isNaN(d.getTime()) ? '' : `${String(d.getDate()).padStart(2, '0')}.${String(d.getMonth() + 1).padStart(2, '0')}.${String(d.getFullYear()).slice(2)} ${String(d.getHours()).padStart(2, '0')}:${String(d.getMinutes()).padStart(2, '0')}`; };
|
||||
|
||||
// Notizen je Charge (charge_key → Notiz) + Speichern von Auftrags-/Charge-Notizen.
|
||||
const chargeNotizen = ref({});
|
||||
@@ -478,11 +499,16 @@ const Board = defineComponent({
|
||||
const produkt = o.product?.name || '?';
|
||||
const tag = o.shipping_day || '';
|
||||
const eingang = String(o.date_created || '').slice(0, 10);
|
||||
const key = `${kunde}|${produkt}|${tag}|${eingang}`;
|
||||
// Druck-Durchgang: bereits gedruckte Aufträge desselben Tages werden nach
|
||||
// dem Zeitpunkt „in den Druck gegeben" (Minute) getrennt – so mischen sich
|
||||
// zwei Druckläufe desselben Tages nicht mehr. Ungedruckte: kein Batch.
|
||||
const druckTs = druckIndex.value[String(o.id)]?.erste || '';
|
||||
const batch = druckTs ? druckTs.slice(0, 16) : '';
|
||||
const key = `${kunde}|${produkt}|${tag}|${eingang}|${batch}`;
|
||||
let c = map.get(key);
|
||||
if (!c) {
|
||||
c = { key, kundeName: o.api_client?.name || 'API-Kunde', produkt, versandtag: tag, eingang, orders: [],
|
||||
faellig: faelligBis(o.date_created, tag) };
|
||||
druckZeit: druckTs, faellig: faelligBis(o.date_created, tag) };
|
||||
map.set(key, c);
|
||||
}
|
||||
c.orders.push(o);
|
||||
@@ -1018,7 +1044,14 @@ const Board = defineComponent({
|
||||
}
|
||||
// „Weiteres": Verknüpfen · In Kontakte speichern · Neu generieren · In manuellen Druck.
|
||||
function weiteresPanel(o) {
|
||||
const dz = druckIndex.value[String(o.id)];
|
||||
const nm = empfNamen.value[String(o.id)];
|
||||
return h('div', { style: 'margin-top:10px;padding:12px;border:1px solid var(--border-subdued);border-radius:8px;background:var(--background-subdued);display:flex;flex-direction:column;gap:10px;' }, [
|
||||
// Druckdatum + Erster/Letzter Empfänger – zum Wiederfinden/Auseinandersortieren.
|
||||
h('div', { style: 'font-size:12px;color:var(--foreground-normal);line-height:1.6;' }, [
|
||||
h('div', {}, dz ? `🖨 In den Druck: ${dmYhm(dz.erste)}${dz.letzte && dz.letzte.slice(0, 16) !== dz.erste.slice(0, 16) ? ' – ' + dmYhm(dz.letzte) : ''}` : '🖨 Noch nicht gedruckt.'),
|
||||
nm ? h('div', {}, `👥 Erster: ${nm.erste}${nm.anzahl > 1 ? ` · Letzter: ${nm.letzte}` : ''}`) : null,
|
||||
]),
|
||||
h('div', { style: 'display:flex;align-items:center;gap:8px;flex-wrap:wrap;' }, [
|
||||
subdued('🔗 Verknüpfter Auftrag:', ''),
|
||||
h('input', { placeholder: 'Auftragsnr. (leer = keine)', value: o.linked_order?.order_number || '',
|
||||
@@ -1136,6 +1169,7 @@ const Board = defineComponent({
|
||||
h('div', { style: 'font-weight:700;font-size:15px;' }, `📦 ${c.kundeName} · ${c.produkt}`),
|
||||
chip(`${c.orders.length} Aufträge`),
|
||||
c.versandtag ? chip('📅 ' + c.versandtag.charAt(0).toUpperCase() + c.versandtag.slice(1)) : null,
|
||||
c.druckZeit ? chip('🖨 gedruckt ' + dmYhm(c.druckZeit), 'var(--primary-25,rgba(30,80,165,.14))') : null,
|
||||
c.faellig ? chip('⏰ fällig bis ' + dmY(c.faellig), faelligFarbe) : null,
|
||||
]);
|
||||
const body = auf ? h('div', { style: 'margin-top:12px;display:flex;flex-direction:column;gap:2px;' }, c.orders.map((o) => orderCard(o, opts))) : null;
|
||||
|
||||
Reference in New Issue
Block a user