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.

266 lines
9.5 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 {
cleanCustomerInstructionDisplayBody,
extractWorkOrderFormFields,
parseWorkOrderReferCode,
parseWorkOrderRefNo,
splitWorkOrderContentAndRemark,
stripWorkOrderBodyNoise,
} from "@/services/parse/work-order-fields";
import { buildCcWorkOrderFormValue } from "@/components/CcWorkOrderForm";
describe("splitWorkOrderContentAndRemark(对齐 AI 助手)", () => {
const cases: Array<[string, string, string]> = [
[
"安排卡转海,麻烦安排贴标操作。\n注意:ups默认一件贴2张面单",
"安排卡转海",
"ups默认",
],
["特别说明:拍照要清晰", "", "拍照要清晰"],
[
"WL1 2件\n注意:加急处理,必须今天下午前交付",
"WL1",
"加急处理",
],
[
"WL103262-6件\n派送要求:分别按票打板 千万不要混打\n注意:柜子里的亚马逊卡派货物,是我们在国内换过标签",
"派送要求",
"换过标签",
],
[
"1.WL104834-2 SCK8 2件\n这票2件每箱都需要开箱拍下里面的产品并回传照片\n2.\n以上货物需要卡转海 麻烦贴标交付\n注意:FBA箱号需要对应快递子单号",
"开箱拍下",
"FBA箱号需要对应",
],
[
"拆柜清单更新 以此为准\n注意:\n1.WL103516\n以上几票需要拦截\n2.\n这2票改自提",
"改自提",
"",
],
[
"TCNU4412465+拆柜清单\n注意:\nWL103262-6件\nWL104381-24件\n派送要求:分别按票打板 千万不要混打\n注意:\n柜子里的亚马逊卡派货物,是我们在国内换过标签,WL唛头上的仓点和FBA标签可能不一样,需要注意下区分。需要根据wl唛头、拆柜清单还有FBA来分货,不能只根据WL唛头来打托。",
"派送要求",
"换过标签",
],
[
"TCNU4412465\nWL103262 6件\n这两票客户需要美时7/10 下午2点前送达 尽量早些哈",
"WL103262",
"尽量早些",
],
[
"TCNU4412465\nWL103262 6件\nWL104381 25件\n这两票总共31件记得叫仓库拍一下照片过来哈。今晚辛苦操作一下",
"WL104381",
"拍一下照片",
],
["请安排贴标", "请安排贴标", ""],
];
for (const [text, needContent, needRemark] of cases) {
it(`splits: ${text.slice(0, 28).replace(/\n/g, " ")}…`, () => {
const { content, remark } = splitWorkOrderContentAndRemark(text);
if (needContent) expect(content).toContain(needContent);
if (needRemark) expect(remark).toContain(needRemark);
else expect(remark.trim()).toBe("");
if (needContent.includes("开箱拍下")) {
expect(remark).not.toContain("开箱拍下");
}
if (needRemark.includes("换过标签") && text.includes("派送要求")) {
expect(content).toContain("派送要求");
expect(content).not.toContain("柜子里的亚马逊");
expect(remark).not.toContain("派送要求");
}
if (needRemark.includes("尽量早些")) {
expect(content).not.toContain("尽量早些");
expect(content).toContain("WL103262");
}
if (needRemark.includes("拍一下照片")) {
expect(content).not.toContain("拍一下照片");
expect(content).toContain("WL103262");
}
});
}
});
describe("work-order refer / ref no", () => {
it("parses ISO container as refer code", () => {
expect(parseWorkOrderReferCode("参考号:TCNU4412465\n请安排换标")).toBe(
"TCNU4412465",
);
expect(parseWorkOrderReferCode("请处理 TCNU4412465 贴标")).toBe(
"TCNU4412465",
);
});
it("parses Ref No / FBA as ref no, not container", () => {
expect(parseWorkOrderRefNo("Ref No:WL003\n请安排贴标")).toBe("WL003");
expect(
parseWorkOrderRefNo(
"FBA19DYHCDLS-XPB2-37件\n安排卡转海",
"",
),
).toMatch(/FBA19DYHCDLS/);
});
});
describe("stripWorkOrderBodyNoise 邮箱/附件栏", () => {
it("drops standalone email and QQ attachment chrome from content", () => {
const raw = [
"2.",
"WL101167",
"WL92334",
"这2票改自提",
"clx@cnwally.com.cn",
].join("\n");
const { content, remark } = splitWorkOrderContentAndRemark(raw);
expect(content).toContain("改自提");
expect(content).toContain("WL101167");
expect(content).not.toMatch(/clx@cnwally\.com\.cn/i);
expect(remark).not.toMatch(/@/);
});
it("drops attachment footer after intercept instruction", () => {
const raw = [
"以上单号需要拦截 清单中已备注",
"1个附件",
"普通附件 (1MB)",
"WHSU5574991 卡转海.zip (1M)",
"clx@cnwally.com.cn",
].join("\n");
const cleaned = stripWorkOrderBodyNoise(raw);
expect(cleaned).toContain("需要拦截");
expect(cleaned).not.toMatch(/个附件|普通附件|\.zip|clx@/i);
});
it("drops 网易灵犀签名与落款短名", () => {
const raw = [
"FCIU7089474 MR03002964 改地址派送到 7400 E. Slauson Ave commerce. CA 90040",
"km16",
"km16@kmfba.com",
"签名由 网易灵犀办公 定制",
].join("\n");
const cleaned = stripWorkOrderBodyNoise(raw);
expect(cleaned).toContain("改地址派送到");
expect(cleaned).toContain("FCIU7089474");
expect(cleaned).not.toMatch(/km16|网易灵犀|签名由/i);
});
it("cleanCustomerInstructionDisplayBody drops quote header and emails", () => {
const raw = [
'在 2026-05-09 18:00:16, "luo" <luo@usasinogroup.com> 写道:',
"好的",
"luo",
"luo@usasinogroup.com",
].join("\n");
const cleaned = cleanCustomerInstructionDisplayBody(raw);
expect(cleaned).toBe("好的");
expect(cleaned).not.toMatch(/写道|@usasinogroup|luo@/i);
});
it("cleanCustomerInstructionDisplayBody keeps reject reason without shell", () => {
const raw = [
'在 2026-05-09 10:52:25, "luo" <luo@usasinogroup.com> 写道:',
"抱歉 仓库产能有限 该柜子我们目前无法接收 请您谅解",
"luo",
"luo@usasinogroup.com",
].join("\n");
const cleaned = cleanCustomerInstructionDisplayBody(raw);
expect(cleaned).toContain("产能有限");
expect(cleaned).toContain("无法接收");
expect(cleaned).not.toMatch(/写道|@usasinogroup/i);
});
it("keeps 注意 remark but strips trailing signature email", () => {
const { content, remark } = splitWorkOrderContentAndRemark(
[
"WL99583 LAX9 2",
"以上货物需要卡转海 麻烦贴标交付",
"注意:FBA箱号需要对应快递子单号,例如:FBA0001对应第一张快递面单",
"clx@cnwally.com.cn",
].join("\n"),
);
expect(content).toContain("卡转海");
expect(remark).toContain("FBA箱号需要对应");
expect(remark).not.toMatch(/clx@cnwally\.com\.cn/i);
expect(content).not.toMatch(/clx@cnwally\.com\.cn/i);
});
it("strips company/signature lines from remark after 注意", () => {
const { content, remark } = splitWorkOrderContentAndRemark(
[
"派送要求:分别按票打板",
"注意:",
"柜子里的亚马逊卡派货物,是我们在国内换过标签",
"沃利供应链",
"朱甜甜 港后客服",
].join("\n"),
);
expect(content).toContain("派送要求");
expect(remark).toContain("换过标签");
expect(remark).not.toMatch(/沃利供应链|港后客服/);
});
});
describe("buildCcWorkOrderFormValue 备注分界", () => {
it("does not put 邮件动作 into F_Remark; only 注意: block", () => {
const v = buildCcWorkOrderFormValue({
subject: "贴标操作",
body: [
"Dear,",
"FBA19DYHCDLS-XPB2-37件",
"安排卡转海,麻烦安排贴标操作。",
"注意:ups默认一件贴2张面单",
].join("\n"),
filenames: [],
});
expect(v.F_MessageContent).toContain("安排卡转海");
expect(v.F_MessageContent).toContain("FBA19DYHCDLS");
expect(v.F_MessageContent).not.toMatch(/注意:/);
expect(v.F_Remark).toContain("ups默认");
expect(v.F_Remark).not.toMatch(/邮件动作/);
expect(v.F_RefNo).toMatch(/FBA19DYHCDLS/);
});
it("keeps numbered ops after 注意: in content", () => {
const v = buildCcWorkOrderFormValue({
subject: "拆柜清单更新",
body: [
"Dear,",
"拆柜清单更新 以此为准",
"注意:",
"1.WL103516",
"以上几票需要拦截",
"2.",
"这2票改自提",
].join("\n"),
});
expect(v.F_MessageContent).toContain("改自提");
expect(v.F_MessageContent).toContain("WL103516");
expect(v.F_Remark.trim()).toBe("");
});
it("mail98 unit1 keeps FBA line in content and ups in remark", () => {
const v = buildCcWorkOrderFormValue({
subject: "贴标操作",
body: [
"TCNU4412465 WL003 FBA19DYHCDLS-XPB2-37件",
"安排卡转海,麻烦安排贴标操作。",
"注意:ups默认一件贴2张面单",
].join("\n"),
filenames: [],
containerNo: "TCNU4412465",
});
expect(v.F_MessageContent).toContain("FBA19DYHCDLS");
expect(v.F_MessageContent).toContain("安排卡转海");
expect(v.F_Remark).toContain("ups默认");
expect(v.F_RefNo).toMatch(/WL003|FBA19DYHCDLS/);
});
it("extractWorkOrderFormFields preserves remark boundary", () => {
const f = extractWorkOrderFormFields({
body: "请安排贴标\n注意:照片要清晰",
});
expect(f.F_MessageContent).toBe("请安排贴标");
expect(f.F_Remark).toContain("照片要清晰");
});
});