From 0105891355ff62058e7ce114175507ba617db1ab Mon Sep 17 00:00:00 2001 From: Maurice Date: Sat, 17 Oct 2026 02:31:01 +0000 Subject: [PATCH] fix(tours): a checklist cut short at its caps says so, also when an earlier decision tips it over --- .../nest/tours/tour-paddle-check.service.ts | 5 ++- .../unit/nest/tours.paddle-check.test.ts | 39 +++++++++++++++++++ 2 files changed, 43 insertions(+), 1 deletion(-) diff --git a/server/src/nest/tours/tour-paddle-check.service.ts b/server/src/nest/tours/tour-paddle-check.service.ts index 6939e957c..5003cfb35 100644 --- a/server/src/nest/tours/tour-paddle-check.service.ts +++ b/server/src/nest/tours/tour-paddle-check.service.ts @@ -162,9 +162,12 @@ export class TourPaddleCheckService { own = []; data = UNAVAILABLE; } - // The checklist carries as many entries and own portages and locks as its contract holds. + // The checklist carries as many entries and own portages and locks as its contract holds; a list cut + // short says so, since what it left out (a ban, a vanished object) no longer counts on the bench. + const cut = entries.length > PADDLE_CHECK_MAX_ENTRIES || own.length > PADDLE_CHECK_MAX_OWN; entries = entries.slice(0, PADDLE_CHECK_MAX_ENTRIES); own = own.slice(0, PADDLE_CHECK_MAX_OWN); + if (cut && (data.data === 'covered' || data.data === 'partial')) data = { ...data, data: 'limited' }; const summary = paddleCheckSummaryOf(entries, own, data); return { entries, own, check: { ...summary, revision: shortHash(JSON.stringify({ entries, own, data })) } }; } diff --git a/server/tests/unit/nest/tours.paddle-check.test.ts b/server/tests/unit/nest/tours.paddle-check.test.ts index 89c23674d..ee2660524 100644 --- a/server/tests/unit/nest/tours.paddle-check.test.ts +++ b/server/tests/unit/nest/tours.paddle-check.test.ts @@ -312,6 +312,45 @@ describe('TourPaddleCheckService: the checklist and the bench', () => { expect(read.tour.paddle_check).toMatchObject({ data: 'limited', entries: PADDLE_CHECK_MAX_ENTRIES }); expect(read.obstacle_check?.entries).toHaveLength(PADDLE_CHECK_MAX_ENTRIES); }); + + it('TPC-011: a checklist cut short by an earlier decision past its cap says so too', async () => { + const { user, trip, paddle } = await fixture(); + await region(); + await insertRows( + orm(), + PaddleFeatures, + Array.from({ length: PADDLE_CHECK_MAX_ENTRIES }, (_, i) => weir(`node/${i + 1}`, 49.2, 12.0001 + i * 0.00003)), + ); + const snapshot = { + v: 1, + kind: 'weir', + name: null, + refs: ['node/999'], + at: [49.2, 12.009], + bounds: [ + [49.2, 12.009], + [49.2, 12.009], + ], + relation: 'on_route', + along_m: 650, + region_id: 'oberpfalz', + data_as_of: null, + }; + await insertRow(orm(), TourObstacleReviews, { + place: paddle.id, + obstacle_key: 'node/999', + decision: 'pass', + note: null, + route_fingerprint: 'p1:o:_', + source_fingerprint: 's1:0123456789abcdef:4920000,1200900', + obstacle_snapshot: JSON.stringify(snapshot), + decided_at: '2026-10-03 10:00:00', + decided_by: user.id, + }); + const read = await detail(trip.id, paddle.id); + expect(read.tour.paddle_check).toMatchObject({ data: 'limited' }); + expect(read.obstacle_check?.entries).toHaveLength(PADDLE_CHECK_MAX_ENTRIES); + }); }); describe('TourObstacleReviewsService.save', () => {