mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-26 18:42:49 +00:00
fix padding on portal
This commit is contained in:
@@ -0,0 +1,44 @@
|
||||
import { ConflictException } from '@nestjs/common';
|
||||
|
||||
import { VehiclesService } from './vehicles.service';
|
||||
|
||||
// One driver ⇒ one truck: create/update must refuse a driver already assigned
|
||||
// to another (non-deleted) vehicle until they are detached.
|
||||
describe('VehiclesService driver assignment guard', () => {
|
||||
const otherTruck = { id: 'v2', plateNumber: '3-11111', assignedDriverId: 'd1' };
|
||||
|
||||
const makeService = (findOne: jest.Mock) =>
|
||||
new VehiclesService(
|
||||
{ findOne, create: jest.fn((x) => x), save: jest.fn(async (x) => x) } as any,
|
||||
{ record: jest.fn() } as any,
|
||||
);
|
||||
|
||||
it('rejects create when the driver is on another truck', async () => {
|
||||
// First findOne = plate uniqueness (null), second = driver holder.
|
||||
const findOne = jest.fn().mockResolvedValueOnce(null).mockResolvedValueOnce(otherTruck);
|
||||
const svc = makeService(findOne);
|
||||
await expect(
|
||||
svc.create({ plateNumber: '3-22222', vehicleType: 'TRUCK', assignedDriverId: 'd1' } as any),
|
||||
).rejects.toThrow(ConflictException);
|
||||
});
|
||||
|
||||
it('rejects update when reassigning a driver still attached elsewhere', async () => {
|
||||
const findOne = jest
|
||||
.fn()
|
||||
.mockResolvedValueOnce({ id: 'v1', plateNumber: '3-22222', assignedDriverId: null }) // findById
|
||||
.mockResolvedValueOnce(otherTruck); // driver holder
|
||||
const svc = makeService(findOne);
|
||||
await expect(svc.update('v1', { assignedDriverId: 'd1' } as any)).rejects.toThrow(
|
||||
ConflictException,
|
||||
);
|
||||
});
|
||||
|
||||
it('allows update that keeps the same driver on the same truck', async () => {
|
||||
const findOne = jest
|
||||
.fn()
|
||||
.mockResolvedValueOnce({ id: 'v1', plateNumber: '3-22222', assignedDriverId: 'd1' });
|
||||
const svc = makeService(findOne);
|
||||
await expect(svc.update('v1', { assignedDriverId: 'd1' } as any)).resolves.toBeDefined();
|
||||
expect(findOne).toHaveBeenCalledTimes(1); // guard skipped — no holder lookup
|
||||
});
|
||||
});
|
||||
@@ -20,6 +20,25 @@ export class VehiclesService {
|
||||
private readonly history: FleetHistoryService,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* A driver holds one truck at a time — reassignment requires detaching them
|
||||
* from their current truck first.
|
||||
* ponytail: app-level guard only (race window); add a partial unique index on
|
||||
* assigned_driver_id if concurrent fleet edits ever become real.
|
||||
*/
|
||||
private async assertDriverUnassigned(driverId: string, exceptVehicleId?: string): Promise<void> {
|
||||
const holder = await this.vehicleRepo.findOne({
|
||||
where: exceptVehicleId
|
||||
? { assignedDriverId: driverId, id: Not(exceptVehicleId) }
|
||||
: { assignedDriverId: driverId },
|
||||
});
|
||||
if (holder) {
|
||||
throw new ConflictException(
|
||||
`This driver is already assigned to truck ${holder.plateNumber ?? holder.code ?? holder.id} — detach the driver from that truck first`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
async create(dto: CreateVehicleDto): Promise<Vehicle> {
|
||||
const existing = await this.vehicleRepo.findOne({
|
||||
where: { plateNumber: dto.plateNumber },
|
||||
@@ -31,6 +50,10 @@ export class VehiclesService {
|
||||
);
|
||||
}
|
||||
|
||||
if (dto.assignedDriverId) {
|
||||
await this.assertDriverUnassigned(dto.assignedDriverId);
|
||||
}
|
||||
|
||||
const registrationNumber = `REG-${dto.vehicleType}-${Date.now()}`;
|
||||
const vehicle = this.vehicleRepo.create({
|
||||
...dto,
|
||||
@@ -121,6 +144,10 @@ export class VehiclesService {
|
||||
}
|
||||
}
|
||||
|
||||
if (dto.assignedDriverId && dto.assignedDriverId !== vehicle.assignedDriverId) {
|
||||
await this.assertDriverUnassigned(dto.assignedDriverId, id);
|
||||
}
|
||||
|
||||
const prev = {
|
||||
assignedDriverId: vehicle.assignedDriverId,
|
||||
assignedDriverName: vehicle.assignedDriverName,
|
||||
|
||||
@@ -31,7 +31,7 @@ export function WarehouseLocationCard({ bookingId }: WarehouseLocationCardProps)
|
||||
const latest = items[0];
|
||||
|
||||
return (
|
||||
<Paper withBorder radius="md" padding="lg">
|
||||
<Paper withBorder radius="md" p="lg">
|
||||
<Stack gap="md">
|
||||
<Group gap="xs">
|
||||
<WarehouseIcon size={18} />
|
||||
|
||||
Reference in New Issue
Block a user