V0.1
This commit is contained in:
86
server/lib/ticket-events-merge.js
Normal file
86
server/lib/ticket-events-merge.js
Normal file
@@ -0,0 +1,86 @@
|
||||
import { mapEvent } from './mappers.js';
|
||||
|
||||
/**
|
||||
* Mehrere ATTACHMENT-DB-Zeilen pro Kalendertag (lokal) zu einem Listeneintrag zusammenführen.
|
||||
* @param {Array<Record<string, unknown>>} rows – SELECT * FROM events (bereits sortiert)
|
||||
* @param {Map<string, Array<Record<string, unknown>>>} byEvent – event_id → ticket_attachments-Zeilen
|
||||
* @param {{ prepare: (sql: string) => { get: (a: unknown) => { d?: string } | undefined } }} db
|
||||
*/
|
||||
export function mergeAttachmentEventsForApi(rows, byEvent, db) {
|
||||
const dayKeyStmt = db.prepare(`SELECT date(?, 'localtime') AS d`);
|
||||
|
||||
const nonAtt = [];
|
||||
/** @type {Map<string, Array<Record<string, unknown>>>} */
|
||||
const attByDay = new Map();
|
||||
|
||||
for (const r of rows) {
|
||||
if (r.type !== 'ATTACHMENT') {
|
||||
nonAtt.push(r);
|
||||
continue;
|
||||
}
|
||||
const dk = dayKeyStmt.get(r.created_at)?.d;
|
||||
const key = dk || String(r.created_at || '').slice(0, 10);
|
||||
if (!attByDay.has(key)) attByDay.set(key, []);
|
||||
attByDay.get(key).push(r);
|
||||
}
|
||||
|
||||
/** @type {Array<{ row: Record<string, unknown>; attachments: Array<Record<string, unknown>> }>} */
|
||||
const mergedChunks = [];
|
||||
|
||||
for (const [, group] of attByDay) {
|
||||
group.sort((a, b) =>
|
||||
String(a.created_at).localeCompare(String(b.created_at)),
|
||||
);
|
||||
const maxCreated = group.reduce((best, x) =>
|
||||
String(x.created_at) > String(best) ? x.created_at : best,
|
||||
group[0].created_at,
|
||||
);
|
||||
const descs = [
|
||||
...new Set(
|
||||
group
|
||||
.map((g) => String(g.description || '').trim())
|
||||
.filter(Boolean),
|
||||
),
|
||||
];
|
||||
const mergedRow = {
|
||||
...group[0],
|
||||
id: group[0].id,
|
||||
created_at: maxCreated,
|
||||
description: descs.join('\n\n'),
|
||||
};
|
||||
|
||||
const allAtt = [];
|
||||
for (const ev of group) {
|
||||
const list = byEvent.get(ev.id);
|
||||
if (list) allAtt.push(...list);
|
||||
}
|
||||
allAtt.sort((a, b) =>
|
||||
String(a.created_at).localeCompare(String(b.created_at)),
|
||||
);
|
||||
|
||||
mergedChunks.push({ row: mergedRow, attachments: allAtt });
|
||||
}
|
||||
|
||||
mergedChunks.sort((a, b) =>
|
||||
String(b.row.created_at).localeCompare(String(a.row.created_at)),
|
||||
);
|
||||
|
||||
nonAtt.sort((a, b) =>
|
||||
String(b.created_at).localeCompare(String(a.created_at)),
|
||||
);
|
||||
|
||||
const out = [
|
||||
...nonAtt,
|
||||
...mergedChunks.map((c) => c.row),
|
||||
];
|
||||
|
||||
const mergedByEventId = new Map(
|
||||
mergedChunks.map((c) => [c.row.id, c.attachments]),
|
||||
);
|
||||
|
||||
return out.map((r) =>
|
||||
r.type === 'ATTACHMENT'
|
||||
? mapEvent(r, mergedByEventId.get(r.id) || [])
|
||||
: mapEvent(r, []),
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user