Merge pull request #912 from Tria-plc/freight_feature/usermanagement

Freight feature/usermanagement
This commit is contained in:
marshal
2026-07-22 15:35:11 +03:00
committed by GitHub
2 changed files with 29 additions and 10 deletions

View File

@@ -276,7 +276,8 @@ export class ContractsController {
if (
!hasFreightPermission(user, FREIGHT_PERMS.bookings.view) &&
!hasFreightPermission(user, FREIGHT_PERMS.bookings.clearanceView) &&
!hasFreightPermission(user, FREIGHT_PERMS.bookings.reviewDocuments)
!hasFreightPermission(user, FREIGHT_PERMS.bookings.reviewDocuments) &&
!hasFreightPermission(user, FREIGHT_PERMS.contracts.view)
) {
await this.contractsService.assertCustomerCanAccessContract(user?.id, contract);
}
@@ -478,7 +479,10 @@ export class ContractsController {
@CurrentUser() user: TCurrentUser,
) {
const contract = await this.contractsService.findById(id);
if (!hasFreightPermission(user, FREIGHT_PERMS.bookings.view)) {
if (
!hasFreightPermission(user, FREIGHT_PERMS.bookings.view) &&
!hasFreightPermission(user, FREIGHT_PERMS.contracts.view)
) {
await this.contractsService.assertCustomerCanAccessContract(user?.id, contract);
}
const { view, html, signatures } =
@@ -513,7 +517,10 @@ export class ContractsController {
@Res() res: Response,
): Promise<void> {
const contract = await this.contractsService.findById(id);
if (!hasFreightPermission(user, FREIGHT_PERMS.bookings.view)) {
if (
!hasFreightPermission(user, FREIGHT_PERMS.bookings.view) &&
!hasFreightPermission(user, FREIGHT_PERMS.contracts.view)
) {
await this.contractsService.assertCustomerCanAccessContract(user?.id, contract);
}
const { stream, record } = await this.transitionService.streamContractPdf(id);
@@ -569,9 +576,12 @@ export class ContractsController {
@CurrentUser() user: TCurrentUser,
) {
// H12(c): a customer may only renew a contract their company owns. Staff
// with bookings.view bypass, mirroring getContractView/downloadContractDocument.
// with bookings.view/contracts.view bypass, mirroring getContractView/downloadContractDocument.
const contract = await this.contractsService.findById(id);
if (!hasFreightPermission(user, FREIGHT_PERMS.bookings.view)) {
if (
!hasFreightPermission(user, FREIGHT_PERMS.bookings.view) &&
!hasFreightPermission(user, FREIGHT_PERMS.contracts.view)
) {
await this.contractsService.assertCustomerCanAccessContract(user?.id, contract);
}
return this.transitionService.renew(id, resolveAuthUserId(user));
@@ -595,9 +605,12 @@ export class ContractsController {
@UploadedFiles() files: Express.Multer.File[],
) {
// H12(c): only the owning company's customer may upload clearance docs.
// Staff with bookings.view bypass, mirroring the other contract handlers.
// Staff with bookings.view/contracts.view bypass, mirroring the other contract handlers.
const contract = await this.contractsService.findById(id);
if (!hasFreightPermission(user, FREIGHT_PERMS.bookings.view)) {
if (
!hasFreightPermission(user, FREIGHT_PERMS.bookings.view) &&
!hasFreightPermission(user, FREIGHT_PERMS.contracts.view)
) {
await this.contractsService.assertCustomerCanAccessContract(user?.id, contract);
}
return this.clearanceService.uploadDocuments(id, files ?? []);

View File

@@ -253,12 +253,18 @@ export function minLocomotiveLimits(
maxTrainLengthMeters: Math.min(
...locomotives.map((l) => num(l.maxTrainLengthMeters, Infinity) || Infinity),
),
// Weakest locomotive's tolerance governs the set, same as its caps.
overageToleranceTons: Math.min(...locomotives.map((l) => num(l.overageToleranceTons))),
overageToleranceMeters: Math.min(...locomotives.map((l) => num(l.overageToleranceMeters))),
// Weakest CONFIGURED tolerance governs the set — a locomotive with no
// tolerance set has no opinion, it does not zero out the others.
overageToleranceTons: minConfigured(locomotives.map((l) => l.overageToleranceTons)),
overageToleranceMeters: minConfigured(locomotives.map((l) => l.overageToleranceMeters)),
};
}
function minConfigured(values: Array<number | string | null | undefined>): number {
const configured = values.filter((v) => v != null).map((v) => num(v));
return configured.length ? Math.min(...configured) : 0;
}
/** Per-booking train length from wagon count and freight-specific wagon type length. */
export function bookingTrainLengthMeters(
freightType: string | null | undefined,