You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

111 lines
4.1 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

import { describe, expect, it } from "vitest";
import {
extractBlPlusFromMail,
mapBlModulesToHeader,
parseBlPlusTemplate,
} from "@/services/parse/bl-plus-template";
import {
extractContainerHeaderFromText,
shippingLineHintFromBl,
} from "@/services/parse/extract-container-header";
const SAMPLE =
"新辰泽+WHLC027G597465+WHSU8127240+洛杉矶+40HQ+EDT2026.04-25 ETA2026.05-15船名航次HMM EMERALD 013E+提拆派组合柜-不带托架";
describe("parseBlPlusTemplate", () => {
it("parses standard plus template modules", () => {
const m = parseBlPlusTemplate(SAMPLE);
expect(m).not.toBeNull();
expect(m!.customer_name).toBe("新辰泽");
expect(m!.bl_no).toBe("WHLC027G597465");
expect(m!.shipping_line_hint).toBe("WHLC");
expect(m!.container_no).toBe("WHSU8127240");
expect(m!.port).toBe("洛杉矶");
expect(m!.cabinet_type).toBe("40HQ");
expect(m!.etd).toBe("2026-04-25");
expect(m!.eta).toBe("2026-05-15");
expect(m!.vessel_voyage).toContain("HMM EMERALD");
expect(m!.service).toContain("提拆派");
expect(m!.classis).toBe(0);
expect(m!.ops_hints).toEqual(
expect.arrayContaining(["提柜", "拆柜", "派送"]),
);
});
it("maps modules onto SaveContainer-aligned header fields", () => {
const m = parseBlPlusTemplate(SAMPLE)!;
const header = mapBlModulesToHeader(
{ F_ContainerNo: "", container_no_valid: false },
m,
);
expect(header.F_ContainerNo).toBe("WHSU8127240");
expect(header.F_BLCopyCode).toBe("WHLC027G597465");
expect(header.F_Dock).toBe("洛杉矶");
expect(header.F_CabinetType).toBe("40HQ");
expect(header.F_ETD).toBe("2026-04-25");
expect(header.F_ETA).toBe("2026-05-15");
expect(header.F_Classis).toBe(0);
expect(header.F_OperationType).toBe(0);
expect(header.F_TransMode).toBe(0);
expect(header.F_Instruction).toMatch(/船名航次.*HMM EMERALD/);
expect(header.F_MemoRemark).toContain("新辰泽");
});
it("extracts from subject + body like template mail", () => {
const r = extractBlPlusFromMail(
`新增预报136:${SAMPLE}`,
`Dear,\n请查收新增预报:${SAMPLE}DO也同步上传至附件请注意查收!`,
);
expect(r).not.toBeNull();
expect(r!.modules.container_no).toBe("WHSU8127240");
expect(r!.modules.bl_no).toBe("WHLC027G597465");
expect(r!.modules.shipping_line_hint).toBe("WHLC");
expect(r!.modules.customer_name).toBe("新辰泽");
});
it("strips Fw/转发/新增预报N from subject customer segment", () => {
const r = extractBlPlusFromMail(
`Fw: 转发:新增预报136:${SAMPLE}`,
"",
);
expect(r).not.toBeNull();
expect(r!.modules.customer_name).toBe("新辰泽");
expect(r!.modules.bl_no).toBe("WHLC027G597465");
expect(r!.modules.shipping_line_hint).toBe("WHLC");
});
it("parses mail2 transfer subject (4 segments)", () => {
const subject =
"Fw: 转发:LINK EVER INC + MATS4583030000+ 柜号:MATU2745683+ ETA : 7/13";
const r = extractBlPlusFromMail(subject, "新增转仓,请留意");
expect(r).not.toBeNull();
expect(r!.modules.customer_name).toBe("LINK EVER INC");
expect(r!.modules.bl_no).toBe("MATS4583030000");
expect(r!.modules.container_no).toBe("MATU2745683");
expect(r!.modules.vessel_voyage).toBeUndefined();
});
});
describe("shipping line hint priority", () => {
it("BL prefix WHLC beats vessel HMM", () => {
expect(shippingLineHintFromBl("WHLC027G597465")).toBe("WHLC");
const h = extractContainerHeaderFromText(SAMPLE);
expect(h.shipping_line_hint).toBe("WHLC");
expect(h.F_OperationType).toBe(0);
expect(h.F_TransMode).toBe(0);
expect(h.F_Classis).toBe(0);
});
it("提拆派 wins over 直送 when both present", () => {
const h = extractContainerHeaderFromText("提拆派组合柜,说明:另有直送类型");
expect(h.F_OperationType).toBe(0);
});
it("explicit 船司 still preferred over BL prefix", () => {
const h = extractContainerHeaderFromText(
"船司:MSC\n提单:WHLC027G597465\n柜型:40HQ",
);
expect(h.shipping_line_hint).toBe("MSC");
});
});