/** * 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; expected: Record }> = [ { 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); });