mirror of
https://github.com/mauriceboe/TREK.git
synced 2026-10-18 21:16:47 +00:00
api: PUT /assignments/:id/transport gains direction (outgoing|incoming)
This commit is contained in:
@@ -175,7 +175,9 @@ export class AssignmentOpsController {
|
||||
if (!this.assignments.getAssignmentForTrip(id, tripId)) {
|
||||
throw new HttpException({ error: 'Assignment not found' }, 404);
|
||||
}
|
||||
const assignment = this.assignments.setLegTransportMode(id, body.transport_mode ?? null);
|
||||
const assignment = body.direction === 'incoming'
|
||||
? this.assignments.setIncomingLegTransportMode(id, body.transport_mode ?? null)
|
||||
: this.assignments.setLegTransportMode(id, body.transport_mode ?? null);
|
||||
this.assignments.broadcast(tripId, 'assignment:updated', { assignment }, socketId);
|
||||
return { assignment };
|
||||
}
|
||||
|
||||
@@ -272,6 +272,17 @@ export class AssignmentsService {
|
||||
return this.getAssignmentWithPlace(Number(id));
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the travel mode of the leg arriving at this stop (#1281 boundary legs).
|
||||
* Mirrors setLegTransportMode but targets incoming_leg_transport_mode; inert
|
||||
* when the previous timeline element is a place (the column is only read for
|
||||
* non-place origins like a booking arrival or a morning hotel departure).
|
||||
*/
|
||||
setIncomingLegTransportMode(id: string | number, mode: string | null) {
|
||||
this.dbs.run('UPDATE day_assignments SET incoming_leg_transport_mode = ? WHERE id = ?', mode ?? null, id);
|
||||
return this.getAssignmentWithPlace(Number(id));
|
||||
}
|
||||
|
||||
setParticipants(assignmentId: string | number, userIds: number[]) {
|
||||
this.dbs.transaction(() => {
|
||||
this.dbs.run('DELETE FROM assignment_participants WHERE assignment_id = ?', assignmentId);
|
||||
|
||||
@@ -124,4 +124,74 @@ describe('incoming_leg_transport_mode read-path parity', () => {
|
||||
const a = foundDay.assignments.find((x: any) => x.id === assignmentId);
|
||||
expect(a.incoming_leg_transport_mode).toBe('transit');
|
||||
});
|
||||
|
||||
// ───────────────────────────────────────────────────────────────────────────
|
||||
// Write path — PUT .../transport gains `direction` (outgoing|incoming).
|
||||
// ───────────────────────────────────────────────────────────────────────────
|
||||
|
||||
describe('PUT /assignments/:id/transport direction', () => {
|
||||
it('defaults to outgoing (back-compat)', async () => {
|
||||
const { user } = createUser(testDb2);
|
||||
const trip = createTrip(testDb2, user.id);
|
||||
const day = createDay(testDb2, trip.id, { date: '2025-06-01' });
|
||||
const place = createPlace(testDb2, trip.id, { name: 'Test Place' });
|
||||
|
||||
const create = await request(app)
|
||||
.post(`/api/trips/${trip.id}/days/${day.id}/assignments`)
|
||||
.set('Cookie', authCookie(user.id))
|
||||
.send({ place_id: place.id });
|
||||
const assignmentId = create.body.assignment.id;
|
||||
|
||||
const res = await request(app)
|
||||
.put(`/api/trips/${trip.id}/assignments/${assignmentId}/transport`)
|
||||
.set('Cookie', authCookie(user.id))
|
||||
.send({ transport_mode: 'cycling' });
|
||||
expect(res.status).toBe(200);
|
||||
|
||||
const row = testDb2.prepare('SELECT leg_transport_mode, incoming_leg_transport_mode FROM day_assignments WHERE id = ?').get(assignmentId);
|
||||
expect(row.leg_transport_mode).toBe('cycling');
|
||||
expect(row.incoming_leg_transport_mode).toBeNull();
|
||||
});
|
||||
|
||||
it("direction: 'incoming' writes the incoming column", async () => {
|
||||
const { user } = createUser(testDb2);
|
||||
const trip = createTrip(testDb2, user.id);
|
||||
const day = createDay(testDb2, trip.id, { date: '2025-06-01' });
|
||||
const place = createPlace(testDb2, trip.id, { name: 'Test Place' });
|
||||
|
||||
const create = await request(app)
|
||||
.post(`/api/trips/${trip.id}/days/${day.id}/assignments`)
|
||||
.set('Cookie', authCookie(user.id))
|
||||
.send({ place_id: place.id });
|
||||
const assignmentId = create.body.assignment.id;
|
||||
|
||||
const res = await request(app)
|
||||
.put(`/api/trips/${trip.id}/assignments/${assignmentId}/transport`)
|
||||
.set('Cookie', authCookie(user.id))
|
||||
.send({ transport_mode: 'transit', direction: 'incoming' });
|
||||
expect(res.status).toBe(200);
|
||||
|
||||
const row = testDb2.prepare('SELECT incoming_leg_transport_mode FROM day_assignments WHERE id = ?').get(assignmentId);
|
||||
expect(row.incoming_leg_transport_mode).toBe('transit');
|
||||
});
|
||||
|
||||
it('rejects an invalid direction with 400', async () => {
|
||||
const { user } = createUser(testDb2);
|
||||
const trip = createTrip(testDb2, user.id);
|
||||
const day = createDay(testDb2, trip.id, { date: '2025-06-01' });
|
||||
const place = createPlace(testDb2, trip.id, { name: 'Test Place' });
|
||||
|
||||
const create = await request(app)
|
||||
.post(`/api/trips/${trip.id}/days/${day.id}/assignments`)
|
||||
.set('Cookie', authCookie(user.id))
|
||||
.send({ place_id: place.id });
|
||||
const assignmentId = create.body.assignment.id;
|
||||
|
||||
const res = await request(app)
|
||||
.put(`/api/trips/${trip.id}/assignments/${assignmentId}/transport`)
|
||||
.set('Cookie', authCookie(user.id))
|
||||
.send({ transport_mode: 'walking', direction: 'sideways' });
|
||||
expect(res.status).toBe(400);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -83,6 +83,9 @@ export const assignmentTransportRequestSchema = z.object({
|
||||
// The legacy route read `body.transport_mode ?? null`, so an absent key
|
||||
// behaves like an explicit null — keep it optional on the wire.
|
||||
transport_mode: z.string().nullable().optional(),
|
||||
// Which leg this write targets: the one leaving this stop (default, and the
|
||||
// legacy behaviour) or the one arriving at it (#1281 boundary legs).
|
||||
direction: z.enum(['outgoing', 'incoming']).default('outgoing'),
|
||||
});
|
||||
export type AssignmentTransportRequest = z.infer<typeof assignmentTransportRequestSchema>;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user