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.

501 lines
14 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.

/**
* One-shot writer for fixtures/emails spec.json + expected.json
*/
import fs from "fs/promises";
import path from "path";
const ROOT = path.join(process.cwd(), "fixtures", "emails");
const PACKING_TWO = [
{
仓库ID: "LAS1",
渠道: "卡派",
件数: 10,
总体积: 2.5,
毛重: 100,
"FBA ID": "FBA16SQQ7PTF",
"Amazon reference ID": "REF-001",
分货标识: "MK-1",
派送地址: "/",
备注: "/",
柜号: "WHSU8127240",
最早送仓日期: "2026-05-20",
最晚送仓日期: "2026-05-25",
},
{
仓库ID: "FTW1",
渠道: "TRUCK",
件数: 4,
总体积: 1.2,
毛重: 40,
"FBA ID": "FBA16AAAAAAA",
"Amazon reference ID": "REF-002",
分货标识: "MK-2",
派送地址: "/",
备注: "/",
柜号: "WHSU8127240",
最早送仓日期: "2026-05-20",
最晚送仓日期: "2026-05-25",
},
];
const fixtures: Array<{ spec: Record<string, unknown>; expected: Record<string, unknown> }> = [
{
spec: {
id: "01-normal-forecast",
category: "normal",
from: "ops@example.com",
subject: "请查收新增预报 智鸿2+WHLC027G597465+WHSU8127240+洛杉矶+40HQ",
text: "请查收新增预报:WHSU8127240 40HQ EDT2026.04-25 ETA2026.05-15 船名航次HMM EMERALD 013E+提拆派",
messageId: "<01-normal-forecast@fixtures.local>",
date: "2026-04-14T00:00:00.000Z",
attachments: [
{ filename: "数据模版-WHSU8127240.xlsx", kind: "packing_xlsx", rows: PACKING_TWO },
],
},
expected: {
mail_type: "NEW_CONTAINER",
status: "PENDING_CONFIRM",
last_error: null,
container_no: "WHSU8127240",
container_no_valid: true,
selected_attachment: "数据模版-WHSU8127240.xlsx",
shipment_count: 2,
valid_shipment_count: 2,
shipments: [
{ F_FBACode: "LAS1", F_Transporter: "TRUCK", F_CTNS: 10, row_status: "VALID" },
{ F_FBACode: "FTW1", F_Transporter: "TRUCK", F_CTNS: 4, row_status: "VALID" },
],
idempotent_with: null,
pull: true,
},
},
{
spec: {
id: "02-normal-transfer",
category: "normal",
from: "ops@example.com",
subject: "MATU2745683 转仓指令",
text: "Dear, 请将 MATU2745683 新增转仓:原仓 ABQ2 转到 FTW1,谢谢。",
messageId: "<02-normal-transfer@fixtures.local>",
date: "2026-04-14T01:00:00.000Z",
attachments: [
{
filename: "柜号:MATU2745683卡派资料.xlsx",
kind: "packing_xlsx",
rows: [
{
仓库ID: "FTW1",
渠道: "卡派",
件数: 8,
总体积: 3,
毛重: 80,
柜号: "MATU2745683",
},
],
},
],
},
expected: {
mail_type: "TRANSFER",
status: "PENDING_CONFIRM",
last_error: null,
container_no: "MATU2745683",
container_no_valid: true,
selected_attachment: "柜号:MATU2745683卡派资料.xlsx",
shipment_count: 1,
valid_shipment_count: 1,
pull: true,
},
},
{
spec: {
id: "03-normal-do-upload",
category: "normal",
from: "ops@example.com",
subject: "WHSU8127240 DO请查收",
text: "DO也同步上传至附件请注意查收!",
messageId: "<03-normal-do-upload@fixtures.local>",
date: "2026-04-14T02:00:00.000Z",
attachments: [
{ filename: "WHSU8127240-DO.pdf", kind: "pdf", text: "DELIVERY ORDER WHSU8127240" },
],
},
expected: {
mail_type: "DO_UPLOAD",
status: "PENDING_CONFIRM",
last_error: null,
container_no: "WHSU8127240",
container_no_valid: true,
selected_attachment: "WHSU8127240-DO.pdf",
shipment_count: 0,
pull: true,
},
},
{
spec: {
id: "04-keyword-subject",
category: "boundary",
from: "ops@example.com",
subject: "新增预报 WHSU8127240",
text: "附件是数据模版,请处理。",
messageId: "<04-keyword-subject@fixtures.local>",
date: "2026-04-14T03:00:00.000Z",
attachments: [
{ filename: "数据模版.xlsx", kind: "packing_xlsx", rows: PACKING_TWO },
],
},
expected: {
mail_type: "NEW_CONTAINER",
status: "PENDING_CONFIRM",
last_error: null,
container_no: "WHSU8127240",
selected_attachment: "数据模版.xlsx",
shipment_count: 2,
valid_shipment_count: 2,
pull: true,
},
},
{
spec: {
id: "05-keyword-body",
category: "boundary",
from: "ops@example.com",
subject: "WHSU8127240 资料",
text: "请查收新增预报,柜号 WHSU8127240,40HQ。",
messageId: "<05-keyword-body@fixtures.local>",
date: "2026-04-14T04:00:00.000Z",
attachments: [
{ filename: "数据模版.xlsx", kind: "packing_xlsx", rows: PACKING_TWO },
],
},
expected: {
mail_type: "NEW_CONTAINER",
status: "PENDING_CONFIRM",
last_error: null,
container_no: "WHSU8127240",
selected_attachment: "数据模版.xlsx",
shipment_count: 2,
pull: true,
},
},
{
spec: {
id: "06-mixed-en-zh",
category: "boundary",
from: "ops@example.com",
subject: "Please check 新增预报 WHSU8127240 / 40HQ ETA 2026-05-15",
text: "Hi team, 请查收新增预报 packing list attached. Vessel HMM EMERALD 013E.",
messageId: "<06-mixed-en-zh@fixtures.local>",
date: "2026-04-14T05:00:00.000Z",
attachments: [
{ filename: "数据模版.xlsx", kind: "packing_xlsx", rows: PACKING_TWO },
],
},
expected: {
mail_type: "NEW_CONTAINER",
status: "PENDING_CONFIRM",
last_error: null,
container_no: "WHSU8127240",
selected_attachment: "数据模版.xlsx",
shipment_count: 2,
pull: true,
},
},
{
spec: {
id: "07-gbk-body",
category: "boundary",
from: "ops@example.com",
subject: "Forecast WHSU8127240",
text: "请查收新增预报 WHSU8127240",
charset: "gbk",
messageId: "<07-gbk-body@fixtures.local>",
date: "2026-04-14T06:00:00.000Z",
attachments: [
{ filename: "数据模版.xlsx", kind: "packing_xlsx", rows: PACKING_TWO },
],
},
expected: {
mail_type: "NEW_CONTAINER",
status: "PENDING_CONFIRM",
last_error: null,
container_no: "WHSU8127240",
selected_attachment: "数据模版.xlsx",
shipment_count: 2,
pull: true,
},
},
{
spec: {
id: "08-oversized-attachment",
category: "boundary",
from: "ops@example.com",
subject: "请查收新增预报 WHSU8127240",
text: "请查收新增预报,附件较大。",
messageId: "<08-oversized-attachment@fixtures.local>",
date: "2026-04-14T07:00:00.000Z",
attachments: [
{ filename: "数据模版.xlsx", kind: "oversized", bytes: 20971521 },
],
},
expected: {
mail_type: "NEW_CONTAINER",
status: "REJECTED_VALIDATION",
last_error: "ATTACHMENT_TOO_LARGE",
container_no: "WHSU8127240",
selected_attachment: null,
pull: true,
},
},
{
spec: {
id: "09-no-attachment",
category: "abnormal",
from: "ops@example.com",
subject: "请查收新增预报 WHSU8127240 40HQ",
text: "请查收新增预报,稍后补附件。",
messageId: "<09-no-attachment@fixtures.local>",
date: "2026-04-14T08:00:00.000Z",
attachments: [],
},
expected: {
mail_type: "NEW_CONTAINER",
status: "REJECTED_VALIDATION",
last_error: "NO_SHIPMENT_ROWS",
container_no: "WHSU8127240",
selected_attachment: null,
shipment_count: 0,
pull: true,
},
},
{
spec: {
id: "10-corrupt-xlsx",
category: "abnormal",
from: "ops@example.com",
subject: "请查收新增预报 WHSU8127240",
text: "请查收新增预报,附件已损坏。",
messageId: "<10-corrupt-xlsx@fixtures.local>",
date: "2026-04-14T09:00:00.000Z",
attachments: [{ filename: "数据模版.xlsx", kind: "corrupt_xlsx" }],
},
expected: {
mail_type: "NEW_CONTAINER",
pipeline_mail_type: "UNKNOWN",
status: "PARSE_FAILED",
last_error: "MIME_PARSE_ERROR",
container_no: "WHSU8127240",
selected_attachment: "数据模版.xlsx",
pull: true,
},
},
{
spec: {
id: "11-wrong-format",
category: "abnormal",
from: "ops@example.com",
subject: "请查收新增预报 WHSU8127240",
text: "请查收新增预报,附件是说明文档。",
messageId: "<11-wrong-format@fixtures.local>",
date: "2026-04-14T10:00:00.000Z",
attachments: [
{
filename: "说明.docx",
kind: "raw",
content: "this is not a spreadsheet",
contentType:
"application/vnd.openxmlformats-officedocument.wordprocessingml.document",
},
],
},
expected: {
mail_type: "NEW_CONTAINER",
status: "PARSE_FAILED",
last_error: "NO_SUPPORTED_SPREADSHEET",
container_no: "WHSU8127240",
selected_attachment: null,
pull: true,
},
},
{
spec: {
id: "12-missing-required",
category: "abnormal",
from: "ops@example.com",
subject: "请查收新增预报 WHSU8127240",
text: "请查收新增预报。",
messageId: "<12-missing-required@fixtures.local>",
date: "2026-04-14T11:00:00.000Z",
attachments: [
{
filename: "数据模版.xlsx",
kind: "packing_xlsx",
headers: ["备注", "柜号"],
rows: [{ 备注: "只有备注没有必填列", 柜号: "WHSU8127240" }],
},
],
},
expected: {
mail_type: "NEW_CONTAINER",
status: "PARSE_FAILED",
last_error: "missing_columns",
container_no: "WHSU8127240",
selected_attachment: "数据模版.xlsx",
missing_columns: true,
shipment_count: 0,
pull: true,
},
},
{
spec: {
id: "13-illegal-date",
category: "abnormal",
from: "ops@example.com",
subject: "请查收新增预报 WHSU8127240",
text: "请查收新增预报。",
messageId: "<13-illegal-date@fixtures.local>",
date: "2026-04-14T12:00:00.000Z",
attachments: [
{
filename: "数据模版.xlsx",
kind: "packing_xlsx",
rows: [
{
仓库ID: "LAS1",
渠道: "卡派",
件数: 2,
总体积: 1,
毛重: 20,
柜号: "WHSU8127240",
最早送仓日期: "not-a-date",
最晚送仓日期: "99/99/99",
},
],
},
],
},
expected: {
mail_type: "NEW_CONTAINER",
status: "PENDING_CONFIRM",
last_error: null,
container_no: "WHSU8127240",
selected_attachment: "数据模版.xlsx",
shipment_count: 1,
valid_shipment_count: 1,
shipments: [
{
F_FBACode: "LAS1",
F_Transporter: "TRUCK",
F_CTNS: 2,
row_status: "VALID",
F_Expected_DeliveryDateB: null,
},
],
pull: true,
},
},
{
spec: {
id: "14-duplicate-pull",
category: "duplicate",
from: "ops@example.com",
subject: "请查收新增预报 智鸿2+WHLC027G597465+WHSU8127240+洛杉矶+40HQ",
text: "请查收新增预报:WHSU8127240 40HQ EDT2026.04-25 ETA2026.05-15 船名航次HMM EMERALD 013E+提拆派",
messageId: "<01-normal-forecast@fixtures.local>",
date: "2026-04-14T00:00:00.000Z",
attachments: [
{ filename: "数据模版-WHSU8127240.xlsx", kind: "packing_xlsx", rows: PACKING_TWO },
],
},
expected: {
mail_type: "NEW_CONTAINER",
status: "PENDING_CONFIRM",
last_error: null,
container_no: "WHSU8127240",
selected_attachment: "数据模版-WHSU8127240.xlsx",
idempotent_with: "01-normal-forecast",
pull: true,
},
},
{
spec: {
id: "15-multi-attachment",
category: "multi_attachment",
from: "ops@example.com",
subject: "请查收新增预报 WHSU8127240,DO请查收",
text: "请查收新增预报。DO也同步上传至附件。",
messageId: "<15-multi-attachment@fixtures.local>",
date: "2026-04-14T13:00:00.000Z",
attachments: [
{
filename: "YT2604021091=76件换标走HIA1卡派出库操作指令.xlsx",
kind: "packing_xlsx",
rows: [
{ 仓库ID: "HIA1", 渠道: "换标", 件数: 76, 柜号: "XXXX0000000" },
],
},
{ filename: "WHSU8127240-DO.pdf", kind: "pdf", text: "DO" },
{ filename: "数据模版-WHSU8127240.xlsx", kind: "packing_xlsx", rows: PACKING_TWO },
{ filename: "4邮箱.pdf", kind: "pdf", text: "screenshot" },
],
},
expected: {
// 附件名含「换标」走硬工单分(45+30=75),压过新增预报(65)与 DO(70);不改生产分类
mail_type: "WORK_ORDER",
status: "PENDING_CONFIRM",
last_error: null,
container_no: "WHSU8127240",
selected_attachment: "数据模版-WHSU8127240.xlsx",
selected_attachments: [
"YT2604021091=76件换标走HIA1卡派出库操作指令.xlsx",
"WHSU8127240-DO.pdf",
"数据模版-WHSU8127240.xlsx",
"4邮箱.pdf",
],
shipment_count: 2,
valid_shipment_count: 2,
pull: true,
},
},
{
spec: {
id: "16-unknown-format",
category: "abnormal",
from: "random@example.com",
subject: "Weekly newsletter",
text: "Hello, this is a marketing newsletter about office snacks.",
messageId: "<16-unknown-format@fixtures.local>",
date: "2026-04-14T14:00:00.000Z",
attachments: [],
},
expected: {
mail_type: "UNKNOWN",
status: "IGNORED",
last_error: "SKIP_FILTER",
selected_attachment: null,
pull: false,
},
},
];
async function main() {
await fs.mkdir(ROOT, { recursive: true });
for (const { spec, expected } of fixtures) {
const id = String(spec.id);
const dir = path.join(ROOT, id);
await fs.mkdir(dir, { recursive: true });
await fs.writeFile(path.join(dir, "spec.json"), JSON.stringify(spec, null, 2) + "\n");
await fs.writeFile(
path.join(dir, "expected.json"),
JSON.stringify(expected, null, 2) + "\n",
);
}
console.log(`wrote ${fixtures.length} fixtures under ${ROOT}`);
}
main().catch((err) => {
console.error(err);
process.exit(1);
});