mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-09-01 21:43:27 +00:00
Two more hardcoded ETB/USD option lists, one on the shared revenue-report filter and one on the contracts export dataset. A report that cannot be filtered to a currency never shows that currency's revenue, which reads as an empty result rather than an error. currencyOf() still defaults to ETB when the caller picks nothing.
160 lines
11 KiB
TypeScript
160 lines
11 KiB
TypeScript
import { FREIGHT_PERMS } from '../../../seed/freight-permissions.registry';
|
|
import { Company } from '../../companies/entities/company.entity';
|
|
import { CompanyProfile } from '../../companies/entities/company-profile.entity';
|
|
import { Contract } from '../../contracts/entities/contract.entity';
|
|
import { ServiceType } from '../../rule-engine/entities/service-type.entity';
|
|
import { applyDirectionScope } from '../../user-trade-access/trade-scope.util';
|
|
import { ExportDataset } from '../export.types';
|
|
import { PAYMENT_CURRENCIES } from '@edr/types';
|
|
|
|
export const contractsDataset: ExportDataset = {
|
|
key: 'contracts',
|
|
title: 'Contracts',
|
|
description: 'Contracts with customer, terms, routes, approval and clearance detail',
|
|
group: 'Commercial',
|
|
permission: FREIGHT_PERMS.contracts.view,
|
|
base: { entity: Contract, alias: 'ct' },
|
|
|
|
joins: [
|
|
{ alias: 'c', entity: Company, on: 'c.id = ct.company_id' },
|
|
{ alias: 'cp', entity: CompanyProfile, on: 'cp.id = ct.company_profile_id' },
|
|
{ alias: 'st', entity: ServiceType, on: 'st.id = ct.service_type_id' },
|
|
{ alias: 'ren', entity: Contract, on: 'ren.id = ct.renewal_of_id' },
|
|
],
|
|
// `search` matches the customer name.
|
|
alwaysJoin: ['c'],
|
|
|
|
groups: [
|
|
{ id: 'contract', label: 'Contract' },
|
|
{ id: 'customer', label: 'Customer' },
|
|
{ id: 'terms', label: 'Terms' },
|
|
{ id: 'routes', label: 'Routes & cargo' },
|
|
{ id: 'approval', label: 'Approval' },
|
|
{ id: 'clearance', label: 'Clearance' },
|
|
],
|
|
|
|
fields: [
|
|
{ key: 'reference', label: 'Reference', type: 'string', group: 'contract', default: true, select: 'ct.reference', sortExpr: 'ct.reference' },
|
|
{ key: 'status', label: 'Status', type: 'string', group: 'contract', default: true, select: 'ct.status', sortExpr: 'ct.status' },
|
|
{ key: 'contractKind', label: 'Kind', type: 'string', group: 'contract', default: true, select: 'ct.contract_kind' },
|
|
{ key: 'contractType', label: 'Type', type: 'string', group: 'contract', select: 'ct.contract_type' },
|
|
{ key: 'createdAt', label: 'Created', type: 'date', group: 'contract', default: true, select: `to_char(ct.created_at, 'YYYY-MM-DD')`, sortExpr: 'ct.created_at' },
|
|
{ key: 'submittedAt', label: 'Submitted', type: 'datetime', group: 'contract', select: `to_char(ct.submitted_at, 'YYYY-MM-DD HH24:MI')` },
|
|
{ key: 'versionNumber', label: 'Version', type: 'number', group: 'contract', select: 'ct.version_number' },
|
|
{ key: 'renewalOf', label: 'Renewal of', type: 'string', group: 'contract', requires: ['ren'], select: 'ren.reference' },
|
|
{ key: 'statusBeforeSuspension', label: 'Status before suspension', type: 'string', group: 'contract', select: 'ct.status_before_suspension' },
|
|
|
|
{ key: 'customer', label: 'Customer', type: 'string', group: 'customer', default: true, requires: ['c'], select: 'c.name', sortExpr: 'c.name' },
|
|
{ key: 'customerTin', label: 'Customer TIN', type: 'string', group: 'customer', requires: ['c'], select: 'c.tin' },
|
|
{ key: 'customerPhone', label: 'Customer phone', type: 'string', group: 'customer', requires: ['c'], select: 'c.phone' },
|
|
{ key: 'customerEmail', label: 'Customer email', type: 'string', group: 'customer', requires: ['c'], select: 'c.email' },
|
|
{ key: 'customerType', label: 'Customer type', type: 'string', group: 'customer', requires: ['c'], select: 'c.type' },
|
|
{ key: 'customerProfileRef', label: 'Profile reference', type: 'string', group: 'customer', requires: ['cp'], select: 'cp.reference' },
|
|
{ key: 'isGovernment', label: 'Government', type: 'boolean', group: 'customer', select: 'ct.is_government' },
|
|
{ key: 'governmentInstitution', label: 'Government institution', type: 'string', group: 'customer', select: 'ct.government_institution' },
|
|
|
|
{ key: 'tradeDirection', label: 'Direction', type: 'string', group: 'terms', default: true, select: 'ct.trade_direction', sortExpr: 'ct.trade_direction' },
|
|
{ key: 'freightType', label: 'Freight type', type: 'string', group: 'terms', default: true, select: 'ct.freight_type' },
|
|
{ key: 'serviceType', label: 'Service type', type: 'string', group: 'terms', requires: ['st'], select: 'st.service_name' },
|
|
{ key: 'paymentCurrency', label: 'Currency', type: 'string', group: 'terms', select: 'ct.payment_currency' },
|
|
{ key: 'validFrom', label: 'Valid from', type: 'date', group: 'terms', default: true, select: `to_char(ct.contract_valid_from, 'YYYY-MM-DD')`, sortExpr: 'ct.contract_valid_from' },
|
|
{ key: 'validUntil', label: 'Valid until', type: 'date', group: 'terms', default: true, select: `to_char(ct.contract_valid_until, 'YYYY-MM-DD')` },
|
|
{ key: 'validityDays', label: 'Validity (days)', type: 'number', group: 'terms', select: 'ct.contract_validity_days' },
|
|
{ key: 'expiresAt', label: 'Expires', type: 'date', group: 'terms', select: `to_char(ct.expires_at, 'YYYY-MM-DD')` },
|
|
{ key: 'estimatedShipmentDate', label: 'Est. shipment date', type: 'date', group: 'terms', select: `to_char(ct.estimated_shipment_date, 'YYYY-MM-DD')` },
|
|
{ key: 'equipmentReturn', label: 'Equipment return', type: 'string', group: 'terms', select: 'ct.equipment_return' },
|
|
{ key: 'pricingDisplayMode', label: 'Pricing display mode', type: 'string', group: 'terms', select: 'ct.pricing_display_mode' },
|
|
|
|
{
|
|
key: 'routes', label: 'Routes', type: 'string', group: 'routes',
|
|
select: `(SELECT string_agg(o.label || ' -> ' || d.label, ' | ' ORDER BY cr.sort_order)
|
|
FROM freight.contract_routes cr
|
|
JOIN freight.yards o ON o.id = cr.origin_yard_id
|
|
JOIN freight.yards d ON d.id = cr.destination_yard_id
|
|
WHERE cr.contract_id = ct.id AND cr.deleted_at IS NULL)`,
|
|
},
|
|
{
|
|
key: 'routeCount', label: 'Route count', type: 'number', group: 'routes',
|
|
select: `(SELECT COUNT(*)::int FROM freight.contract_routes cr
|
|
WHERE cr.contract_id = ct.id AND cr.deleted_at IS NULL)`,
|
|
},
|
|
{
|
|
key: 'bookingCount', label: 'Bookings', type: 'number', group: 'routes',
|
|
select: `(SELECT COUNT(*)::int FROM freight.bookings b
|
|
WHERE b.contract_id = ct.id AND b.deleted_at IS NULL)`,
|
|
},
|
|
{ key: 'isHazardous', label: 'Hazardous', type: 'boolean', group: 'routes', select: 'ct.is_hazardous' },
|
|
{ key: 'hazardClass', label: 'Hazard class', type: 'string', group: 'routes', select: 'ct.hazard_class' },
|
|
{ key: 'unNumber', label: 'UN number', type: 'string', group: 'routes', select: 'ct.un_number' },
|
|
{ key: 'isReefer', label: 'Reefer', type: 'boolean', group: 'routes', select: 'ct.is_reefer' },
|
|
|
|
{ key: 'approvedAt', label: 'Approved at', type: 'datetime', group: 'approval', select: `to_char(ct.approved_by_staff_at, 'YYYY-MM-DD HH24:MI')` },
|
|
{ key: 'signedByDirectorAt', label: 'Director signed', type: 'datetime', group: 'approval', select: `to_char(ct.signed_by_director_at, 'YYYY-MM-DD HH24:MI')` },
|
|
{ key: 'signedByCeoAt', label: 'CEO signed', type: 'datetime', group: 'approval', select: `to_char(ct.signed_by_ceo_at, 'YYYY-MM-DD HH24:MI')` },
|
|
{ key: 'customerSignedAt', label: 'Customer signed', type: 'datetime', group: 'approval', select: `to_char(ct.customer_signed_at, 'YYYY-MM-DD HH24:MI')` },
|
|
{ key: 'fullyExecutedAt', label: 'Fully executed', type: 'datetime', group: 'approval', default: true, select: `to_char(ct.fully_executed_at, 'YYYY-MM-DD HH24:MI')` },
|
|
{ key: 'lockedAt', label: 'Locked at', type: 'datetime', group: 'approval', select: `to_char(ct.locked_at, 'YYYY-MM-DD HH24:MI')` },
|
|
{ key: 'contractGeneratedAt', label: 'Document generated', type: 'datetime', group: 'approval', select: `to_char(ct.contract_generated_at, 'YYYY-MM-DD HH24:MI')` },
|
|
|
|
{ key: 'clearanceStatus', label: 'Clearance status', type: 'string', group: 'clearance', select: 'ct.clearance_status' },
|
|
{ key: 'clearanceCycleNumber', label: 'Clearance cycle', type: 'number', group: 'clearance', select: 'ct.clearance_cycle_number' },
|
|
{ key: 'customsClearingEnabled', label: 'Customs clearing', type: 'boolean', group: 'clearance', select: 'ct.customs_clearing_enabled' },
|
|
{ key: 'customsClearingAgent', label: 'Clearing agent', type: 'string', group: 'clearance', select: 'ct.customs_clearing_agent' },
|
|
{ key: 'firstMileAddress', label: 'Pickup address', type: 'string', group: 'clearance', select: 'ct.first_mile_pickup_address' },
|
|
{ key: 'lastMileAddress', label: 'Delivery address', type: 'string', group: 'clearance', select: 'ct.last_mile_delivery_address' },
|
|
],
|
|
|
|
filters: [
|
|
{ key: 'created', label: 'Created', type: 'daterange' },
|
|
{ key: 'statuses', label: 'Status', type: 'multiselect' },
|
|
{ key: 'contractKind', label: 'Kind', type: 'text' },
|
|
{ key: 'tradeDirection', label: 'Direction', type: 'select', options: ['IMPORT', 'EXPORT', 'DOMESTIC'].map((v) => ({ value: v, label: v })) },
|
|
{ key: 'freightType', label: 'Freight type', type: 'select', options: ['CONTAINER', 'BULK'].map((v) => ({ value: v, label: v })) },
|
|
{ key: 'paymentCurrency', label: 'Currency', type: 'select', options: PAYMENT_CURRENCIES.map((v) => ({ value: v, label: v })) },
|
|
{ key: 'serviceTypeId', label: 'Service type', type: 'text' },
|
|
// Routes are one-to-many on contract_routes, so these filter via EXISTS
|
|
// rather than a column comparison.
|
|
{ key: 'originYardId', label: 'Origin', type: 'text' },
|
|
{ key: 'destinationYardId', label: 'Destination', type: 'text' },
|
|
{ key: 'companyId', label: 'Customer', type: 'text' },
|
|
{ key: 'search', label: 'Search reference or customer', type: 'text' },
|
|
],
|
|
|
|
defaultSort: { key: 'createdAt', dir: 'DESC' },
|
|
|
|
scope(ctx, qb) {
|
|
const { params, directions } = ctx;
|
|
qb.andWhere('ct.deleted_at IS NULL');
|
|
if (params.createdFrom) qb.andWhere('ct.created_at >= :createdFrom', { createdFrom: params.createdFrom });
|
|
if (params.createdTo) qb.andWhere('ct.created_at < :createdTo', { createdTo: params.createdTo });
|
|
const statuses = params.statuses as string[] | null;
|
|
if (statuses?.length) qb.andWhere('ct.status IN (:...statuses)', { statuses });
|
|
if (params.contractKind) qb.andWhere('ct.contract_kind = :contractKind', { contractKind: params.contractKind });
|
|
if (params.tradeDirection) qb.andWhere('ct.trade_direction = :tradeDirection', { tradeDirection: params.tradeDirection });
|
|
if (params.freightType) qb.andWhere('ct.freight_type = :freightType', { freightType: params.freightType });
|
|
if (params.paymentCurrency) qb.andWhere('ct.payment_currency = :paymentCurrency', { paymentCurrency: params.paymentCurrency });
|
|
if (params.serviceTypeId) qb.andWhere('ct.service_type_id = :serviceTypeId', { serviceTypeId: params.serviceTypeId });
|
|
if (params.originYardId) {
|
|
qb.andWhere(
|
|
`EXISTS (SELECT 1 FROM freight.contract_routes cr
|
|
WHERE cr.contract_id = ct.id AND cr.deleted_at IS NULL
|
|
AND cr.origin_yard_id = :originYardId)`,
|
|
{ originYardId: params.originYardId },
|
|
);
|
|
}
|
|
if (params.destinationYardId) {
|
|
qb.andWhere(
|
|
`EXISTS (SELECT 1 FROM freight.contract_routes cr2
|
|
WHERE cr2.contract_id = ct.id AND cr2.deleted_at IS NULL
|
|
AND cr2.destination_yard_id = :destinationYardId)`,
|
|
{ destinationYardId: params.destinationYardId },
|
|
);
|
|
}
|
|
if (params.companyId) qb.andWhere('ct.company_id = :companyId', { companyId: params.companyId });
|
|
if (params.search) {
|
|
qb.andWhere('(ct.reference ILIKE :search OR c.name ILIKE :search)', { search: `%${params.search as string}%` });
|
|
}
|
|
applyDirectionScope(qb, 'ct.trade_direction', directions);
|
|
},
|
|
};
|