feat: implement shipping line bookings management

- Add ShippingLineBookingsPage for listing and managing shipping line bookings.
- Create ShippingLineDocumentsModal for document uploads related to bookings.
- Introduce ShippingLineInitiateModal for initiating new shipping line bookings.
- Implement booking document state management with booking-doc-state utility.
- Add shipping line bookings service for API interactions.
- Update index to export new components and services.
- Enhance types for freight to include shipping line credits.
This commit is contained in:
marshalyordanos
2026-08-13 15:54:40 +03:00
parent 9aae132dd4
commit 9fff469ffa
50 changed files with 4485 additions and 77 deletions

View File

@@ -69,6 +69,7 @@ export class RatesRepository implements IRatesRepository {
findByPattern(pattern: {
rateType: string;
rateUnit?: string;
shippingLineCompanyId?: string | null;
containerTypeId?: string | null;
cargoTypeId?: string | null;
tradeDirection?: string | null;
@@ -85,6 +86,16 @@ export class RatesRepository implements IRatesRepository {
qb.andWhere('rate.rate_unit = :rateUnit', { rateUnit: pattern.rateUnit });
}
// The owner is part of the identity: a line's rate for a lane is a
// different rate from the standard one, not a duplicate of it.
if (pattern.shippingLineCompanyId) {
qb.andWhere('rate.shipping_line_company_id = :shippingLineCompanyId', {
shippingLineCompanyId: pattern.shippingLineCompanyId,
});
} else {
qb.andWhere('rate.shipping_line_company_id IS NULL');
}
if (pattern.containerTypeId) {
qb.andWhere('rate.container_type_id = :containerTypeId', { containerTypeId: pattern.containerTypeId });
} else {
@@ -139,8 +150,22 @@ export class RatesRepository implements IRatesRepository {
// yards joined the route columns have only ids to render.
.leftJoinAndSelect('rate.originYard', 'originYard')
.leftJoinAndSelect('rate.destinationYard', 'destinationYard')
// The shipping-line tab renders the owning line's name, not its id.
.leftJoinAndSelect('rate.shippingLineCompany', 'shippingLineCompany')
.orderBy('rate.createdAt', query.sortOrder ?? 'DESC');
if (query.shippingLineCompanyId) {
qb.andWhere('rate.shippingLineCompanyId = :shippingLineCompanyId', {
shippingLineCompanyId: query.shippingLineCompanyId,
});
} else if (query.isShippingLineRate !== undefined) {
// Tab filter: shipping-line rates (any line) vs standard customer rates.
qb.andWhere(
query.isShippingLineRate
? 'rate.shippingLineCompanyId IS NOT NULL'
: 'rate.shippingLineCompanyId IS NULL',
);
}
if (query.status) {
qb.andWhere('rate.status = :status', { status: query.status });
}
@@ -164,7 +189,7 @@ export class RatesRepository implements IRatesRepository {
}
if (query.search) {
qb.andWhere(
'(rate.rateType ILIKE :search OR rate.status ILIKE :search OR rate.rateUnit ILIKE :search OR rate.currency ILIKE :search)',
'(rate.rateType ILIKE :search OR rate.status ILIKE :search OR rate.rateUnit ILIKE :search OR rate.currency ILIKE :search OR shippingLineCompany.name ILIKE :search)',
{ search: `%${query.search}%` },
);
}