From 9577b9b56c0d4a5b6ef95cd0c9f9b93ef501e82e Mon Sep 17 00:00:00 2001 From: jubnl Date: Tue, 28 Apr 2026 04:45:50 +0200 Subject: [PATCH] fix: delete surplus days when shortening a trip When shrinking a trip's date range, surplus days are now deleted along with their assignments, notes, and accommodations (cascade). Places remain in the trip pool; reservations keep their day reference nulled by the existing ON DELETE SET NULL constraint (issue #909). Updates TRIP-SVC-011 to reflect the new behaviour; adds TRIP-SVC-016 as a regression test for the empty-day case. --- server/src/services/tripService.ts | 7 ++-- .../tests/unit/services/tripService.test.ts | 34 +++++++++++-------- 2 files changed, 23 insertions(+), 18 deletions(-) diff --git a/server/src/services/tripService.ts b/server/src/services/tripService.ts index 1f129d2e..5b37f49f 100644 --- a/server/src/services/tripService.ts +++ b/server/src/services/tripService.ts @@ -117,10 +117,11 @@ export function generateDays(tripId: number | bigint | string, startDate: string } } - // Overflow dated days (trip shrunk): convert to dateless instead of deleting - const nullify = db.prepare('UPDATE days SET date = NULL, day_number = ? WHERE id = ?'); + // Overflow dated days (trip shrunk): delete them (issue #909). + // Cascade removes their assignments, notes, and accommodations. + const del = db.prepare('DELETE FROM days WHERE id = ?'); for (let i = targetDates.length; i < dated.length; i++) { - nullify.run(targetDates.length + (i - targetDates.length) + 1, dated[i].id); + del.run(dated[i].id); } // Any remaining unused dateless days: keep as dateless, just renumber. diff --git a/server/tests/unit/services/tripService.test.ts b/server/tests/unit/services/tripService.test.ts index 12c5a13d..795dbcb2 100644 --- a/server/tests/unit/services/tripService.test.ts +++ b/server/tests/unit/services/tripService.test.ts @@ -96,33 +96,37 @@ describe('generateDays', () => { expect(getNotes(day2.id)[0].id).toBe(note.id); }); - it('TRIP-SVC-011: shrinking range converts overflow days to dateless, preserves their assignments', () => { + it('TRIP-SVC-011: shrinking range deletes overflow days and their assignments (issue #909)', () => { const { user } = createUser(testDb); const trip = createTrip(testDb, user.id, { start_date: '2025-07-01', end_date: '2025-07-05' }); const daysBefore = getDays(trip.id); expect(daysBefore).toHaveLength(5); const place = createPlace(testDb, trip.id); - // Assign places to days 4 and 5 (will become overflow) - const a4 = createDayAssignment(testDb, daysBefore[3].id, place.id); - const a5 = createDayAssignment(testDb, daysBefore[4].id, place.id); + createDayAssignment(testDb, daysBefore[3].id, place.id); + createDayAssignment(testDb, daysBefore[4].id, place.id); - // Shrink from 5 to 3 days + // Shrink from 5 to 3 days — surplus days and their content are removed generateDays(trip.id, '2025-07-01', '2025-07-03'); const daysAfter = getDays(trip.id); - expect(daysAfter).toHaveLength(5); // no rows deleted + expect(daysAfter).toHaveLength(3); + expect(daysAfter.map(d => d.date)).toEqual(['2025-07-01', '2025-07-02', '2025-07-03']); + }); - const dated = daysAfter.filter(d => d.date !== null); - const dateless = daysAfter.filter(d => d.date === null); - expect(dated).toHaveLength(3); - expect(dateless).toHaveLength(2); + it('TRIP-SVC-016: shrinking range deletes empty overflow days (issue #909)', () => { + const { user } = createUser(testDb); + const trip = createTrip(testDb, user.id, { start_date: '2025-07-01', end_date: '2025-07-07' }); + expect(getDays(trip.id)).toHaveLength(7); - // Overflow days still have their assignments - expect(getAssignments(dateless[0].id)).toHaveLength(1); - expect(getAssignments(dateless[0].id)[0].id).toBe(a4.id); - expect(getAssignments(dateless[1].id)).toHaveLength(1); - expect(getAssignments(dateless[1].id)[0].id).toBe(a5.id); + // Shrink 7 → 5; days 6 and 7 have no content + generateDays(trip.id, '2025-07-01', '2025-07-05'); + + const daysAfter = getDays(trip.id); + expect(daysAfter).toHaveLength(5); + expect(daysAfter.map(d => d.date)).toEqual([ + '2025-07-01', '2025-07-02', '2025-07-03', '2025-07-04', '2025-07-05', + ]); }); it('TRIP-SVC-012: growing range keeps existing day content and appends new empty days', () => {