mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-28 05:30:55 +00:00
add dispute functionality for contract duty and implement collection dates
This commit is contained in:
@@ -25,7 +25,18 @@ export type ContractDocumentChange =
|
||||
toOrder: number;
|
||||
}
|
||||
| { kind: 'DOCUMENT_TITLE_CHANGED'; title: string; fromTitle: string | null }
|
||||
| { kind: 'WHEREAS_CHANGED'; added: number; removed: number };
|
||||
| { kind: 'WHEREAS_CHANGED'; added: number; removed: number }
|
||||
/**
|
||||
* A contract field (not a document article) changed — the customer editing a
|
||||
* DRAFT/CHANGES_REQUESTED contract, e.g. its route, cargo or service type.
|
||||
*/
|
||||
| {
|
||||
kind: 'FIELD_CHANGED';
|
||||
field: string;
|
||||
label: string;
|
||||
from: string | null;
|
||||
to: string | null;
|
||||
};
|
||||
|
||||
type SnapshotLike = Pick<
|
||||
ContractDocumentSnapshot,
|
||||
@@ -134,6 +145,60 @@ export function diffSnapshots(
|
||||
return changes;
|
||||
}
|
||||
|
||||
/** Human label per audited contract field, in the order they read on the form. */
|
||||
export const CONTRACT_FIELD_LABELS: Record<string, string> = {
|
||||
contractKind: 'Contract kind',
|
||||
tradeDirection: 'Trade direction',
|
||||
freightType: 'Freight type',
|
||||
serviceType: 'Service type',
|
||||
paymentCurrency: 'Payment currency',
|
||||
contractType: 'Contract type',
|
||||
isHazardous: 'Hazardous',
|
||||
hazardClass: 'Hazard class',
|
||||
unNumber: 'UN number',
|
||||
isReefer: 'Reefer',
|
||||
equipmentReturn: 'Equipment return',
|
||||
customsClearingAgent: 'Customs clearing agent',
|
||||
firstMilePickupAddress: 'First-mile pickup address',
|
||||
lastMileDeliveryAddress: 'Last-mile delivery address',
|
||||
routes: 'Routes',
|
||||
cargoScope: 'Cargo scope',
|
||||
};
|
||||
|
||||
/** Render a field value for the audit trail — never "[object Object]". */
|
||||
function displayValue(value: unknown): string | null {
|
||||
if (value === null || value === undefined || value === '') return null;
|
||||
if (typeof value === 'boolean') return value ? 'Yes' : 'No';
|
||||
return String(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compare two flat maps of contract fields and report what changed. Only keys
|
||||
* present in `after` are considered, so a partial update never reports the
|
||||
* fields it did not touch.
|
||||
*/
|
||||
export function diffContractFields(
|
||||
before: Record<string, unknown>,
|
||||
after: Record<string, unknown>,
|
||||
): ContractDocumentChange[] {
|
||||
const changes: ContractDocumentChange[] = [];
|
||||
|
||||
for (const [field, nextRaw] of Object.entries(after)) {
|
||||
const next = displayValue(nextRaw);
|
||||
const previous = displayValue(before[field]);
|
||||
if (next === previous) continue;
|
||||
changes.push({
|
||||
kind: 'FIELD_CHANGED',
|
||||
field,
|
||||
label: CONTRACT_FIELD_LABELS[field] ?? field,
|
||||
from: previous,
|
||||
to: next,
|
||||
});
|
||||
}
|
||||
|
||||
return changes;
|
||||
}
|
||||
|
||||
/** Short human summary of a change set, e.g. "2 articles edited, 1 article added". */
|
||||
export function summarizeChanges(changes: ContractDocumentChange[]): string {
|
||||
if (changes.length === 0) return 'No changes';
|
||||
@@ -148,6 +213,7 @@ export function summarizeChanges(changes: ContractDocumentChange[]): string {
|
||||
|
||||
const counts = new Map<string, number>();
|
||||
const parts: string[] = [];
|
||||
const fields: string[] = [];
|
||||
|
||||
for (const change of changes) {
|
||||
const verb = articleVerbs[change.kind];
|
||||
@@ -157,9 +223,19 @@ export function summarizeChanges(changes: ContractDocumentChange[]): string {
|
||||
parts.push('document title changed');
|
||||
} else if (change.kind === 'WHEREAS_CHANGED') {
|
||||
parts.push('recitals changed');
|
||||
} else if (change.kind === 'FIELD_CHANGED') {
|
||||
fields.push(change.label.toLowerCase());
|
||||
}
|
||||
}
|
||||
|
||||
if (fields.length > 0) {
|
||||
parts.push(
|
||||
fields.length <= 3
|
||||
? `${fields.join(', ')} changed`
|
||||
: `${fields.length} contract fields changed`,
|
||||
);
|
||||
}
|
||||
|
||||
const articleParts = [...counts.entries()].map(
|
||||
([verb, count]) => `${count} article${count === 1 ? '' : 's'} ${verb}`,
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user