fix: import exell for tabs
CI / build-and-test (push) Canceled after 0s

This commit is contained in:
2026-10-26 21:58:23 +01:00
parent 4e43521da7
commit db3500032e
2 changed files with 21 additions and 4 deletions
@@ -1,9 +1,9 @@
import { PlannedTabsService } from './planned-tabs.service';
type Row = { id: string; venueId: string; customerName: string; email: string | null; position: number };
type Row = { id: string; venueId: string; customerName: string; email: string | null; position: number; deliveredAt?: Date | null };
function createService(initial: Omit<Row, 'venueId'>[]) {
let rows: Row[] = initial.map((r) => ({ ...r, venueId: 'v1' }));
let rows: Row[] = initial.map((r) => ({ deliveredAt: null, ...r, venueId: 'v1' }));
const tx = {
plannedTab: {
findMany: jest.fn(async () => [...rows].sort((a, b) => a.position - b.position)),
@@ -60,6 +60,17 @@ describe('PlannedTabsService.import', () => {
expect(rows()[0].email).toBe('piet@example.com');
});
it('queues delivered customers again so a deleted tab is reopened', async () => {
const { service, rows } = createService([
{ id: 'a', customerName: 'Jan', email: 'jan@example.com', position: 0, deliveredAt: new Date() },
]);
const result = await service.import('v1', [{ customerName: 'jan' }], 'merge');
expect(result).toEqual({ created: 0, updated: 1, unchanged: 0, removed: 0 });
expect(rows()[0]).toMatchObject({ deliveredAt: null, email: 'jan@example.com' });
});
it('removes names missing from the import only in replace mode', async () => {
const initial = [
{ id: 'a', customerName: 'Jan', email: null, position: 0 },
@@ -84,6 +84,7 @@ export class PlannedTabsService {
* Names match case-insensitively and existing spelling is kept, because the terminal matches
* planned names to tabs exactly and a respelled name would open a second tab.
* A missing email in the import never clears an existing one.
* Customers already delivered are queued again, so a tab deleted since is reopened on the next sync.
*/
async import(venueId: string, entries: { customerName: string; email?: string }[], mode: 'merge' | 'replace') {
const incoming = new Map<string, { customerName: string; email?: string }>();
@@ -112,8 +113,13 @@ export class PlannedTabsService {
data: { id: uuidv4(), venueId, customerName: entry.customerName, customerNameKey: key, email: entry.email ?? null, position: nextPosition++ },
});
created++;
} else if (entry.email && entry.email !== current.email) {
await tx.plannedTab.update({ where: { id: current.id }, data: { email: entry.email } });
} else if (current.deliveredAt || (entry.email && entry.email !== current.email)) {
// Re-importing a delivered customer queues them again: their tab may have been deleted since, and the
// next sync skips anyone who still has an open tab
await tx.plannedTab.update({
where: { id: current.id },
data: { deliveredAt: null, ...(entry.email && entry.email !== current.email ? { email: entry.email } : {}) },
});
updated++;
} else {
unchanged++;