mirror of
https://github.com/mauriceboe/TREK.git
synced 2026-10-23 07:26:30 +00:00
fix(calendar): a fully timed stay is its two hand-overs, not a week-long bar
Closes #2136 A stay was always exported as an all-day block across its whole range, and the check-in and check-out markers came on top of it. When the stay records both ends of its clock the markers already say everything the block does, and the block is the half nobody can act on: it takes a week of calendar to repeat what two one-hour events state precisely. Same shape as the parking and rental windows in #2068. Only where the markers actually stand in for the booking, though. They are emitted once per stay and titled from its lowest-id reservation, so a second room on the same stay would otherwise be left with nothing at all. A stay that knows only one end keeps its block too, since nothing else carries the other end's date. CAL-025b covers the drop, -025c the one-sided stay, -025d the second room.
This commit is contained in:
@@ -829,6 +829,57 @@ describe('accommodations', () => {
|
||||
expect(ics).toContain('SUMMARY:Hotel Bellevue');
|
||||
});
|
||||
|
||||
it('CAL-025b: a stay that records both ends of its clock drops the all-day block (#2136)', () => {
|
||||
// The two markers already say when to arrive and when to leave, which is the
|
||||
// part a subscriber can act on. Keeping the block as well buries the week
|
||||
// under a bar that repeats what the markers say.
|
||||
const { user } = createUser(testDb);
|
||||
const trip = createTrip(testDb, user.id, { title: 'Paris' });
|
||||
createStay(trip.id, {
|
||||
start: '2026-07-07', end: '2026-07-12',
|
||||
check_in: '15:00', check_out: '11:00',
|
||||
});
|
||||
|
||||
const { ics } = svc.exportICS(trip.id);
|
||||
|
||||
expect(ics).not.toContain('DTSTART;VALUE=DATE:20260707\r\nDTEND;VALUE=DATE:20260713');
|
||||
expect(ics).toContain('SUMMARY:Check-in: Hotel Bellevue');
|
||||
expect(ics).toContain('SUMMARY:Check-out: Hotel Bellevue');
|
||||
});
|
||||
|
||||
it('CAL-025d: a second room on the same stay keeps its block, since no marker names it', () => {
|
||||
// The markers are emitted once per stay and titled from its lowest-id
|
||||
// booking, so dropping every block would leave the second one with nothing.
|
||||
const { user } = createUser(testDb);
|
||||
const trip = createTrip(testDb, user.id, { title: 'Paris' });
|
||||
const { stayId } = createStay(trip.id, {
|
||||
start: '2026-07-07', end: '2026-07-12',
|
||||
check_in: '15:00', check_out: '11:00',
|
||||
});
|
||||
const day = testDb.prepare('SELECT id FROM days WHERE trip_id = ? ORDER BY id ASC LIMIT 1').get(trip.id) as { id: number };
|
||||
testDb.prepare(`
|
||||
INSERT INTO reservations (trip_id, day_id, title, reservation_time, status, type, accommodation_id)
|
||||
VALUES (?, ?, 'Bellevue second room', NULL, 'confirmed', 'hotel', ?)
|
||||
`).run(trip.id, day.id, String(stayId));
|
||||
|
||||
const { ics } = svc.exportICS(trip.id);
|
||||
|
||||
expect(ics).toContain('SUMMARY:Bellevue second room');
|
||||
expect(ics).toContain('SUMMARY:Check-in: Hotel Bellevue');
|
||||
});
|
||||
|
||||
it('CAL-025c: knowing only one end keeps the block, since nothing else carries the other', () => {
|
||||
const { user } = createUser(testDb);
|
||||
const trip = createTrip(testDb, user.id, { title: 'Paris' });
|
||||
createStay(trip.id, { start: '2026-07-07', end: '2026-07-12', check_in: '15:00' });
|
||||
|
||||
const { ics } = svc.exportICS(trip.id);
|
||||
|
||||
expect(ics).toContain('DTSTART;VALUE=DATE:20260707\r\nDTEND;VALUE=DATE:20260713');
|
||||
expect(ics).toContain('SUMMARY:Check-in: Hotel Bellevue');
|
||||
expect(ics).not.toContain('SUMMARY:Check-out');
|
||||
});
|
||||
|
||||
it('CAL-026: check-in and check-out become their own timed events in the stay zone', () => {
|
||||
const { user } = createUser(testDb);
|
||||
const trip = createTrip(testDb, user.id, { title: 'Paris' });
|
||||
|
||||
Reference in New Issue
Block a user