import assert from "node:assert/strict"; import { readFileSync } from "node:fs"; import { fileURLToPath } from "node:url"; import { specialAdjustmentDirectionLabel, specialAdjustmentMeasureMode, specialAdjustmentOperationKeys } from "../src/utils/specialAdjustmentRules.js"; const viewPath = fileURLToPath(new URL("../src/views/InventoryLedgerView.vue", import.meta.url)); const operationKeys = specialAdjustmentOperationKeys(); assert.equal(specialAdjustmentDirectionLabel("OUT"), "特殊出库"); assert.equal(specialAdjustmentDirectionLabel("out"), "特殊出库"); assert.equal(specialAdjustmentDirectionLabel("IN"), "特殊入库"); assert.equal(specialAdjustmentDirectionLabel(""), "特殊入库"); assert.equal(specialAdjustmentMeasureMode("RAW"), "WEIGHT"); assert.equal(specialAdjustmentMeasureMode("SCRAP"), "WEIGHT"); assert.equal(specialAdjustmentMeasureMode("AUX"), "QTY"); assert.equal(specialAdjustmentMeasureMode("FINISHED"), "QTY_WITH_WEIGHT"); assert.equal(specialAdjustmentMeasureMode("RETURN"), "QTY_WITH_WEIGHT"); assert.equal(specialAdjustmentMeasureMode("SEMI", { remaining_qty: 8, remaining_weight_kg: 0 }), "QTY"); assert.equal(specialAdjustmentMeasureMode("SEMI", { qty_available: 3, weight_available_kg: 0 }), "QTY"); assert.equal(specialAdjustmentMeasureMode("SEMI", { remaining_qty: 0, remaining_weight_kg: 12 }), "WEIGHT"); assert.equal(specialAdjustmentMeasureMode("SEMI", { qty_available: 0, weight_available_kg: 4 }), "WEIGHT"); assert.equal(specialAdjustmentMeasureMode("SEMI", { remaining_qty: 2, remaining_weight_kg: 7 }), "SEMI_SELECT"); assert.equal(specialAdjustmentMeasureMode("SEMI", {}), "SEMI_SELECT"); assert.deepEqual(operationKeys, { raw: { in: "raw-special-in", out: "raw-special-out" }, semi: { in: "semi-special-in", out: "semi-special-out" }, finished: { in: "finished-special-in", out: "finished-special-out" }, auxiliary: { in: "aux-special-in", out: "aux-special-out" }, scrap: { in: "scrap-special-in", out: "scrap-special-out" }, return: { in: "return-special-in", out: "return-special-out" } }); const viewSource = readFileSync(viewPath, "utf8"); const flattenedOperationKeys = Object.values(operationKeys).flatMap((entry) => [entry.in, entry.out]); for (const operationKey of flattenedOperationKeys) { assert.ok(viewSource.includes(operationKey), `InventoryLedgerView.vue should include ${operationKey}`); } assert.ok(viewSource.includes("特殊入库"), "InventoryLedgerView.vue should include the special inbound label"); assert.ok(viewSource.includes("特殊出库"), "InventoryLedgerView.vue should include the special outbound label"); assert.ok(viewSource.includes("入库方式"), "InventoryLedgerView.vue should label the special inbound line mode in Chinese"); assert.ok(viewSource.includes("补增已有明细"), "InventoryLedgerView.vue should allow adding to an existing special inbound stock detail"); assert.ok(viewSource.includes("新增特殊明细"), "InventoryLedgerView.vue should allow creating a new special inbound stock detail"); assert.ok(viewSource.includes("特殊出库必须选择库存明细"), "InventoryLedgerView.vue should keep lot selection required for special outbound"); assert.ok(viewSource.includes("specialAdjustmentLineLotId(line)"), "InventoryLedgerView.vue should route special adjustment lot_id through conditional logic"); assert.ok(viewSource.includes("lot_id: null"), "InventoryLedgerView.vue should submit lot_id null when special inbound creates a new detail"); assert.ok(viewSource.includes("/inventory/special-adjustments"), "InventoryLedgerView.vue should call the special adjustments API"); console.log("special adjustment UI static assertions passed");