|
|
import { createHash } from "crypto";
|
|
|
import type { NormalizedCargo } from "@/modules/quote/types";
|
|
|
|
|
|
export type CargoHashInput = {
|
|
|
pickupSerialized: string;
|
|
|
deliverySerialized: string;
|
|
|
weightLb: number;
|
|
|
dimLIn: number;
|
|
|
dimWIn: number;
|
|
|
dimHIn: number;
|
|
|
palletCount: number;
|
|
|
cargoType: string;
|
|
|
};
|
|
|
|
|
|
/** 地址序列化为含 place_id 的标准 JSON(BR-4.4) */
|
|
|
export function serializeAddress(addr: {
|
|
|
street: string;
|
|
|
city: string;
|
|
|
state: string;
|
|
|
zip: string;
|
|
|
place_id: string;
|
|
|
mothership_option_id?: string;
|
|
|
}): string {
|
|
|
return JSON.stringify({
|
|
|
street: addr.street.trim(),
|
|
|
city: addr.city.trim(),
|
|
|
state: addr.state.trim().toUpperCase(),
|
|
|
zip: addr.zip.trim(),
|
|
|
place_id: addr.mothership_option_id?.trim() || addr.place_id,
|
|
|
});
|
|
|
}
|
|
|
|
|
|
/** cargo_hash = MD5(pickup+delivery+weight_lb+dims+pallet_count+cargo_type) */
|
|
|
export function buildCargoHash(input: CargoHashInput): string {
|
|
|
const raw = [
|
|
|
input.pickupSerialized,
|
|
|
input.deliverySerialized,
|
|
|
input.weightLb.toFixed(2),
|
|
|
input.dimLIn.toFixed(2),
|
|
|
input.dimWIn.toFixed(2),
|
|
|
input.dimHIn.toFixed(2),
|
|
|
String(input.palletCount),
|
|
|
input.cargoType,
|
|
|
].join("|");
|
|
|
return createHash("md5").update(raw).digest("hex");
|
|
|
}
|
|
|
|
|
|
export function buildCargoHashFromNormalized(cargo: NormalizedCargo): string {
|
|
|
return buildCargoHash({
|
|
|
pickupSerialized: cargo.pickupSerialized,
|
|
|
deliverySerialized: cargo.deliverySerialized,
|
|
|
weightLb: cargo.weightLb,
|
|
|
dimLIn: cargo.dimLIn,
|
|
|
dimWIn: cargo.dimWIn,
|
|
|
dimHIn: cargo.dimHIn,
|
|
|
palletCount: cargo.palletCount,
|
|
|
cargoType: cargo.cargoType,
|
|
|
});
|
|
|
}
|