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.

166 lines
4.7 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.

/**
* CC 烟雾验收
*
* pnpm cc:smoke # 跟随 .env:mock <20>?live
* pnpm cc:smoke -- --mode=mock # 强制 mock(不连网<E8BF9E>?
* pnpm cc:smoke -- --mode=live # 强制 live:需 CC_MOCK=false + 账号
*
* Exit: 0 ok | 1 配置错误 | 2 CC 业务失败 | 3 模式不匹<E4B88D>?
*/
import { getEnv, resetEnvCache } from "../src/lib/env";
import { getCcModeStatus } from "../src/services/cc/mode";
import { saveContainer } from "../src/services/cc/save-container";
import { getShippingLineList } from "../src/services/cc/shipping-line";
import { getContainerListFromCc } from "../src/services/cc/conflict";
type ModeArg = "auto" | "mock" | "live";
function parseMode(argv: string[]): ModeArg {
const raw = argv.find((a) => a.startsWith("--mode="))?.slice("--mode=".length);
if (raw === "mock" || raw === "live" || raw === "auto") return raw;
const idx = argv.indexOf("--mode");
if (idx >= 0) {
const v = argv[idx + 1];
if (v === "mock" || v === "live" || v === "auto") return v;
}
return "auto";
}
async function main() {
resetEnvCache();
const env = getEnv();
const requested = parseMode(process.argv.slice(2));
const status = await getCcModeStatus();
console.log(
JSON.stringify(
{
requested,
runtime: status,
api_base: env.CC_API_BASE,
saas: env.CC_SAAS_HEADER,
},
null,
2,
),
);
if (requested === "live") {
if (status.mode === "mock") {
console.error(
"FAIL: --mode=live <20>?CC_MOCK=true。设 CC_MOCK=false 并配<E5B9B6>?CC_USERNAME + 密码后再跑<E5868D>?,
);
process.exit(3);
}
if (!status.live_ready) {
console.error(
"FAIL: live 未就<EFBFBD>?<EFBFBD>?,
status.reason ?? "缺少 CC_USERNAME / CC_PASSWORD_PLAIN|MD5",
);
process.exit(1);
}
}
if (requested === "mock" && status.mode !== "mock") {
console.error(
"FAIL: --mode=mock 但当<E4BD86>?CC_MOCK=false。请临时<E4B8B4>?CC_MOCK=true,或去掉 --mode<64>?,
);
process.exit(3);
}
if (requested === "auto" && status.mode === "live" && !status.live_ready) {
console.error("FAIL:", status.reason);
process.exit(1);
}
const isLive = status.mode === "live" && status.live_ready;
const containerNo = `SMK${Date.now().toString().slice(-8)}`;
if (isLive) {
const lines = await getShippingLineList();
console.log(`shipping_lines: ${lines.length}`);
if (lines.length === 0) {
console.warn("WARN: GetShippingLineList 空(不阻<EFBFBD>?SaveContainer<EFBFBD>?);
}
const list = await getContainerListFromCc(containerNo);
if (!list.ok) {
console.error("FAIL: GetContainerList", list.error);
process.exit(2);
}
console.log(`conflict_probe items=${list.items.length}`);
} else {
console.log("mode=mock <20>?跳过真网 GetShippingLineList / GetContainerList");
}
const res = await saveContainer({
entity: {
F_TransMode: 0,
F_OperationType: 0,
F_ContainerNo: containerNo,
F_CabinetType: "40HQ",
F_ETA: "2026-07-13",
F_Classis: 0,
F_MemoRemark: `smoke-${status.mode}`,
},
shipments: [
{
row_index: 1,
row_status: "VALID",
F_FBACode: "ABQ2",
F_Transporter: "TRUCK",
F_CTNS: 1,
F_FBAID: "FBA19G5XJLV4",
},
],
});
console.log(JSON.stringify({ containerNo, result: res }, null, 2));
if (!res.ok) {
process.exit(2);
}
// 指令写能力烟雾(默认 mock<63>?
const { executeInstructionWrite } = await import(
"../src/services/cc/instruction-write"
);
const { ensureCcWriteCapabilities, listCcWriteCapabilities } = await import(
"../src/services/cc/write-capability"
);
await ensureCcWriteCapabilities();
const caps = await listCcWriteCapabilities();
console.log(
"cc_write_capabilities",
caps.map((c) => `${c.id}=${c.mode}`).join(", "),
);
for (const kind of ["transfer", "hold_split", "label"] as const) {
const r = await executeInstructionWrite(kind, {
mailId: "0",
containerNo: containerNo,
subject: `smoke ${kind}`,
shipments: [],
remark: "cc-smoke",
});
console.log(`instruction ${kind}:`, r.ok ? "PASS" : "FAIL", r.mode, r.error || "");
if (!r.ok) process.exit(2);
}
if (isLive) {
console.log("PASS: TEST live SaveContainer code=200 + external id");
console.log(
"NOTE: transfer/hold/label live 需 cc_write_capability.mode=live <20>?CC 侧接口可用才算该项完<E9A1B9>?,
);
} else {
console.log(
"PASS: mock SaveContainer + instruction writes <EFBFBD>?非设<EFBFBD>?TEST 烟雾验收。账号到位后:CC_MOCK=false + pnpm cc:smoke -- --mode=live",
);
}
}
main().catch((e) => {
console.error(e);
process.exit(1);
});