import assert from "node:assert/strict";
import { readFileSync } from "node:fs";
import { fileURLToPath } from "node:url";

import { buildGenericItemOptions, buildProductOperationOptions } from "../src/utils/inventoryOperationOptions.js";

const stockedBalances = [
  {
    item_id: 101,
    item_code: "原材料00001",
    item_name: "304不锈钢",
    warehouse_id: 1,
    warehouse_type: "RAW",
    weight_available_kg: 100,
    qty_available: 0,
    avg_unit_cost: 4
  },
  {
    item_id: 101,
    item_code: "原材料00001",
    item_name: "304不锈钢",
    warehouse_id: 1,
    warehouse_type: "RAW",
    weight_available_kg: 40,
    qty_available: 0,
    avg_unit_cost: 5
  },
  {
    item_id: 102,
    item_code: "原材料00002",
    item_name: "冷轧板",
    warehouse_id: 1,
    warehouse_type: "RAW",
    weight_available_kg: 0,
    qty_available: 0
  },
  {
    item_id: 103,
    item_code: "原材料00003",
    item_name: "铝合金",
    warehouse_id: 2,
    warehouse_type: "RAW",
    weight_available_kg: 80,
    qty_available: 0
  }
];

const rawOutboundOptions = buildGenericItemOptions({
  direction: "out",
  activeInventoryTab: "raw",
  activeWarehouseType: "RAW",
  warehouseId: 1,
  balances: stockedBalances,
  materials: [],
  products: []
});

assert.deepEqual(
  rawOutboundOptions.map((item) => ({
    item_id: item.item_id,
    item_code: item.item_code,
    item_name: item.item_name,
    weight_available_kg: item.weight_available_kg
  })),
  [
    {
      item_id: 101,
      item_code: "原材料00001",
      item_name: "304不锈钢",
      weight_available_kg: 140
    }
  ]
);

const rawInboundOptions = buildGenericItemOptions({
  direction: "in",
  activeInventoryTab: "raw",
  activeWarehouseType: "RAW",
  warehouseId: 1,
  balances: stockedBalances,
  materials: [{ item_id: 201, item_code: "原材料00004", item_name: "铜板" }],
  products: [{ item_id: 301, item_code: "产品00001", item_name: "支架" }]
});

assert.deepEqual(rawInboundOptions.map((item) => item.item_id), [201]);

const finishedOutboundOptions = buildGenericItemOptions({
  direction: "out",
  activeInventoryTab: "finished",
  activeWarehouseType: "FINISHED",
  warehouseId: 8,
  balances: [
    {
      item_id: 401,
      item_code: "产品需规00001",
      item_name: "电脑支架",
      warehouse_id: 8,
      warehouse_type: "FINISHED",
      qty_available: 12,
      weight_available_kg: 30
    }
  ],
  materials: [],
  products: []
});

assert.equal(finishedOutboundOptions.length, 1);
assert.equal(finishedOutboundOptions[0].qty_available, 12);

const semiOutboundOptions = buildGenericItemOptions({
  direction: "out",
  activeInventoryTab: "semi",
  activeWarehouseType: "SEMI",
  warehouseId: 9,
  balances: [
    {
      item_id: 501,
      item_code: "产品需规00002",
      item_name: "半成品支架",
      source_line_id: 9101,
      option_key: "501::9101",
      operation_label: "产品：半成品支架；已完成工序：第1道 冲压",
      warehouse_id: 9,
      warehouse_type: "SEMI",
      qty_available: 6,
      weight_available_kg: 12
    },
    {
      item_id: 501,
      item_code: "产品需规00002",
      item_name: "半成品支架",
      source_line_id: 9102,
      option_key: "501::9102",
      operation_label: "产品：半成品支架；已完成工序：第2道 折弯",
      warehouse_id: 9,
      warehouse_type: "SEMI",
      qty_available: 8,
      weight_available_kg: 20
    }
  ],
  materials: [],
  products: []
});

assert.equal(semiOutboundOptions.length, 2);
assert.deepEqual(semiOutboundOptions.map((item) => item.option_key), ["501::9101", "501::9102"]);

const productMasterRows = [{ item_id: 601, item_code: "产品需规00003", item_name: "委外成品" }];
const productOperationRows = [
  {
    option_key: "601::7001",
    item_id: 601,
    item_code: "产品需规00003",
    item_name: "委外成品",
    route_id: 8001,
    route_operation_id: 7001,
    seq_no: 1,
    operation_name: "冲压"
  },
  {
    option_key: "601::7002",
    item_id: 601,
    item_code: "产品需规00003",
    item_name: "委外成品",
    route_id: 8001,
    route_operation_id: 7002,
    seq_no: 2,
    operation_name: "折弯"
  }
];
const routeOperationOptions = buildProductOperationOptions([
  {
    route_id: 8001,
    product_item_id: 601,
    product_code: "产品需规00003",
    product_name: "委外成品",
    version_no: "V1.0",
    status: "ACTIVE",
    operations: [
      {
        route_operation_id: 7001,
        seq_no: 1,
        operation_name: "1",
        process_name: "1",
        stamping_method: "切边冲孔",
        status: "ACTIVE"
      }
    ]
  }
]);

assert.equal(routeOperationOptions[0].operation_label, "第1道 切边冲孔");
assert.equal(routeOperationOptions[0].source_material_summary, "产品：委外成品；已完成工序：第1道 切边冲孔");

const operationWithoutStampingMethod = buildProductOperationOptions([
  {
    route_id: 8002,
    product_item_id: 602,
    product_code: "产品需规00004",
    product_name: "无冲压方式产品",
    version_no: "V1.0",
    status: "ACTIVE",
    operations: [
      {
        route_operation_id: 7003,
        seq_no: 1,
        operation_name: "1",
        process_name: "开平",
        stamping_method: "",
        status: "ACTIVE"
      }
    ]
  }
]);

assert.equal(operationWithoutStampingMethod[0].operation_label, "第1道");
const semiInboundOptions = buildGenericItemOptions({
  direction: "in",
  activeInventoryTab: "semi",
  activeWarehouseType: "SEMI",
  warehouseId: 9,
  balances: [],
  materials: [],
  products: productMasterRows,
  productOperations: productOperationRows
});
const finishedInboundOptions = buildGenericItemOptions({
  direction: "in",
  activeInventoryTab: "finished",
  activeWarehouseType: "FINISHED",
  warehouseId: 8,
  balances: [],
  materials: [],
  products: productMasterRows
});

assert.deepEqual(semiInboundOptions.map((item) => item.option_key), ["601::7001", "601::7002"]);
assert.deepEqual(semiInboundOptions.map((item) => item.route_operation_id), [7001, 7002]);
assert.deepEqual(finishedInboundOptions.map((item) => item.item_id), [601]);

const auxiliaryOutboundOptions = buildGenericItemOptions({
  direction: "out",
  activeInventoryTab: "auxiliary",
  activeWarehouseType: "AUX",
  warehouseId: 10,
  balances: [
    {
      item_id: 701,
      item_code: "辅料00001",
      item_name: "包装膜",
      warehouse_id: 10,
      warehouse_type: "AUX",
      qty_available: 0,
      weight_available_kg: 25
    }
  ],
  materials: [],
  products: []
});
const auxiliaryInboundOptions = buildGenericItemOptions({
  direction: "in",
  activeInventoryTab: "auxiliary",
  activeWarehouseType: "AUX",
  warehouseId: 10,
  balances: [],
  materials: [{ item_id: 702, item_code: "辅料00002", item_name: "手套" }],
  products: []
});

assert.equal(auxiliaryOutboundOptions.length, 1);
assert.equal(auxiliaryOutboundOptions[0].item_id, 701);
assert.deepEqual(auxiliaryInboundOptions.map((item) => item.item_id), [702]);

const scrapInboundOptions = buildGenericItemOptions({
  direction: "in",
  activeInventoryTab: "scrap",
  activeWarehouseType: "SCRAP",
  warehouseId: 11,
  balances: [],
  materials: [{ item_id: 801, item_code: "原材料00005", item_name: "冲压边角料" }],
  products: [{ item_id: 901, item_code: "产品需规00004", item_name: "报废支架" }]
});
const scrapOutboundOptions = buildGenericItemOptions({
  direction: "out",
  activeInventoryTab: "scrap",
  activeWarehouseType: "SCRAP",
  warehouseId: 11,
  balances: [
    {
      item_id: 801,
      item_code: "原材料00005",
      item_name: "冲压边角料",
      warehouse_id: 11,
      warehouse_type: "SCRAP",
      qty_available: 10,
      weight_available_kg: 0
    },
    {
      item_id: 901,
      item_code: "产品需规00004",
      item_name: "报废支架",
      warehouse_id: 11,
      warehouse_type: "SCRAP",
      qty_available: 0,
      weight_available_kg: 42
    },
    {
      item_id: 902,
      item_code: "产品需规00005",
      item_name: "异仓废料",
      warehouse_id: 12,
      warehouse_type: "SCRAP",
      qty_available: 0,
      weight_available_kg: 18
    }
  ],
  materials: [],
  products: []
});
const scrapWarehouseTypeInboundOptions = buildGenericItemOptions({
  direction: "in",
  activeInventoryTab: "raw",
  activeWarehouseType: "SCRAP",
  warehouseId: 11,
  balances: [],
  materials: [{ item_id: 803, item_code: "原材料00006", item_name: "废铜" }],
  products: [{ item_id: 903, item_code: "产品需规00006", item_name: "报废夹具" }]
});

assert.deepEqual(scrapInboundOptions.map((item) => item.item_id), [801, 901]);
assert.deepEqual(scrapWarehouseTypeInboundOptions.map((item) => item.item_id), [803, 903]);
assert.deepEqual(
  scrapOutboundOptions.map((item) => ({
    item_id: item.item_id,
    qty_available: item.qty_available,
    weight_available_kg: item.weight_available_kg
  })),
  [
    {
      item_id: 901,
      qty_available: 0,
      weight_available_kg: 42
    }
  ]
);

const inventoryLedgerSource = readFileSync(
  fileURLToPath(new URL("../src/views/InventoryLedgerView.vue", import.meta.url)),
  "utf8"
);
const deliveryManagementSource = readFileSync(
  fileURLToPath(new URL("../src/views/DeliveryManagementView.vue", import.meta.url)),
  "utf8"
);
const tableControlsSource = readFileSync(
  fileURLToPath(new URL("../src/components/TableControls.vue", import.meta.url)),
  "utf8"
);
const stockLotTagSelectSource = readFileSync(
  fileURLToPath(new URL("../src/components/StockLotTagSelect.vue", import.meta.url)),
  "utf8"
);

assert.match(inventoryLedgerSource, /key: "scrap"/);
assert.match(inventoryLedgerSource, /label: "废料库"/);
assert.match(inventoryLedgerSource, /PRODUCTION_SCRAP_IN/);
assert.match(
  inventoryLedgerSource,
  /const genericUnitCostLabel = computed\(\(\) =>[\s\S]*isProductionScrapInbound\.value[\s\S]*原材料成本单价\(元\/kg\)/,
  "production scrap inbound should label unit cost as raw material cost unit price"
);
assert.match(
  inventoryLedgerSource,
  /const productionScrapToleranceRemainingWeight = computed\(\(\) => \{[\s\S]*productionScrapExpectedWeight\.value[\s\S]*1\.15[\s\S]*productionScrapInboundBeforeWeight/,
  "production scrap inbound should calculate the non-settle upper limit from cumulative scrap inbound weight"
);
assert.match(
  inventoryLedgerSource,
  /genericForm\.settle_work_order && productionScrapSettleNeedsRemark\.value/,
  "production scrap inbound should require a settle explanation when final scrap weight is outside tolerance"
);
assert.match(
  inventoryLedgerSource,
  /const scrapToleranceMax = Number\(productionScrapToleranceRemainingWeight\.value \|\| 0\);[\s\S]*inboundWeight > scrapToleranceMax/,
  "production scrap inbound validation should compare inbound weight against cumulative upper-limit remaining amount"
);
assert.match(
  inventoryLedgerSource,
  /activeOperation\?\.direction !== 'out' && !isCustomerSuppliedInbound && !isSourceLotReturnInbound && !isSemiSourceLotTraceInbound && !isFinishedOutsourcingInbound && !isProductionScrapInbound && !isReworkScrapInbound && !isOutsourcingScrapInbound/,
  "production scrap inbound should hide the manual batch number field"
);
assert.match(
  inventoryLedgerSource,
  /lot_no: isCustomerSuppliedInbound\.value \? null : isProductionScrapInbound\.value \? null[\s\S]*isOutsourcingScrapInbound\.value \? null/,
  "production scrap inbound should never submit a manually-entered batch number"
);
assert.match(inventoryLedgerSource, /OUTSOURCING_SCRAP_IN/);
assert.match(inventoryLedgerSource, /SCRAP_SALE_OUT/);
assert.match(inventoryLedgerSource, /LOGISTICS_REQUIRED_BIZ_TYPES/);
assert.match(inventoryLedgerSource, /"CUSTOMER_SUPPLIED"/);
assert.match(inventoryLedgerSource, /const isCustomerSuppliedInbound = computed/);
assert.match(inventoryLedgerSource, /customerSuppliedLotNoPreview/);
assert.match(inventoryLedgerSource, /提交后自动生成/);
assert.match(inventoryLedgerSource, /activeOperation\?\.direction !== 'out' && !isCustomerSuppliedInbound/);
assert.match(inventoryLedgerSource, /lot_no: isCustomerSuppliedInbound\.value \? null/);
assert.match(inventoryLedgerSource, /source_material_sub_batch_no: isCustomerSuppliedInbound\.value\s+\?\s+null/);
assert.match(inventoryLedgerSource, /const workOrderLedgerRows = ref\(\[\]\);/);
assert.match(inventoryLedgerSource, /fetchResource\("\/production\/work-order-ledger\?limit=500", \[\]\)/);
assert.match(inventoryLedgerSource, /workOrderLedgerRows\.value = workOrderLedgerRowData;/);
assert.match(
  stockLotTagSelectSource,
  /issued_weight_kg:\s*normalizeSelectedIssuedWeight\(lot\)/,
  "StockLotTagSelect should preserve an option's issued_weight_kg instead of overwriting it with remaining weight"
);
assert.match(
  stockLotTagSelectSource,
  /function displayWeight\(lot\)/,
  "StockLotTagSelect should support scenario-specific selected-tag weight display"
);
assert.match(
  inventoryLedgerSource,
  /:display-weight-field="isProductionSurplusInbound \? 'issued_weight_kg' : 'remaining_weight_kg'"/,
  "production surplus inbound should display selected source lots by work-order issued weight"
);
assert.doesNotMatch(
  inventoryLedgerSource,
  /<div v-if="usesGenericSourceLotSelector && !isProductTraceOnlySourceLotInbound" class="feedback-banner">/,
  "source-lot return/outbound live total should not use feedback-banner because it triggers toast notifications while typing"
);
assert.doesNotMatch(
  inventoryLedgerSource,
  /<div v-else-if="isProductTraceOnlySourceLotInbound && selectedGenericSourceLots\.length" class="feedback-banner">/,
  "source-lot trace-only live summary should not use feedback-banner because it is not an operation result"
);
assert.match(
  inventoryLedgerSource,
  /function computeWorkOrderSourceLotReturnLimit\(workOrder,\s*material\)/,
  "production surplus inbound should calculate source-lot return limit from the work-order surplus limit"
);
assert.match(
  inventoryLedgerSource,
  /max_return_weight_kg:\s*returnLimit\.normal/,
  "source-lot normal return weight should be capped by the work-order normal surplus amount"
);
assert.match(
  inventoryLedgerSource,
  /tolerance_return_weight_kg:\s*returnLimit\.tolerance/,
  "source-lot tolerance return weight should be capped by the work-order 15 percent tolerance amount"
);
assert.match(
  inventoryLedgerSource,
  /const productionSurplusToleranceRemainingWeight = computed\(\(\) => \{[\s\S]*productionSurplusExpectedReturnWeight\.value[\s\S]*1\.15[\s\S]*productionSurplusReturnedBeforeWeight/,
  "production surplus inbound should calculate the non-settle upper limit from cumulative returned weight"
);
assert.match(
  inventoryLedgerSource,
  /:max="productionSurplusReturnInputMax\(lot\)"/,
  "production surplus inbound input should use a dynamic return max so settle mode can allow explained deviations"
);
assert.match(
  inventoryLedgerSource,
  /function productionSurplusReturnInputMax\(lot\)[\s\S]*genericForm\.settle_work_order[\s\S]*source_remaining_weight_kg/,
  "production surplus inbound should relax the input max to source-lot remaining return weight when settling"
);
assert.match(
  inventoryLedgerSource,
  /const toleranceMax = Number\(productionSurplusToleranceRemainingWeight\.value \|\| 0\);[\s\S]*genericSourceLotReturnWeight\.value > toleranceMax/,
  "production surplus inbound validation should compare the selected return total against the cumulative upper-limit remaining amount"
);
assert.match(
  inventoryLedgerSource,
  /const receivableWorkOrders = computed\(\(\) =>\s*workOrderLedgerRows\.value\.filter\([\s\S]*!isWorkOrderSettled\(item\)[\s\S]*tolerance_finished_inbound_qty[\s\S]*\)\s*\);/
);
assert.match(
  inventoryLedgerSource,
  /completionForm\.tolerance_receivable_qty = Number\(workOrder\.limits\?\.tolerance_finished_inbound_qty \|\| completionForm\.max_receivable_qty \|\| 0\);/
);
assert.match(
  inventoryLedgerSource,
  /const genericWorkOrderOptions = computed\(\(\) => \{[\s\S]*!isWorkOrderSettled\(item,\s*"PRODUCTION_SCRAP_IN"\)[\s\S]*tolerance_scrap_inbound_weight_kg[\s\S]*!isWorkOrderSettled\(item,\s*"PRODUCTION_SURPLUS"\)[\s\S]*tolerance_surplus_inbound_weight_kg[\s\S]*return workOrderLedgerRows\.value\.filter\(\(item\) => !isWorkOrderSettled\(item\)\);[\s\S]*\}\);/
);
assert.match(
  inventoryLedgerSource,
  /source_doc_type: isProductionSurplusInbound\.value \? "WORK_ORDER" : null[\s\S]*source_doc_id: isProductionSurplusInbound\.value \? Number\(selectedGenericWorkOrder\.value\.work_order_id\) : null/
);
assert.match(
  inventoryLedgerSource,
  /source_doc_type: isProductionScrapInbound\.value \|\| isReworkScrapInbound\.value \? "WORK_ORDER" : activeWarehouseType\.value === "SEMI" \? "PRODUCT_ROUTE_OPERATION" : null[\s\S]*source_doc_id: isProductionScrapInbound\.value \|\| isReworkScrapInbound\.value \? Number\(selectedGenericWorkOrder\.value\.work_order_id\) : activeWarehouseType\.value === "SEMI" \? Number\(selectedSourceDocId \|\| 0\) : null/
);
assert.match(inventoryLedgerSource, /:key="`inventory-main-table-\$\{activeInventoryTab\}`"/);
assert.match(inventoryLedgerSource, /:key="`inventory-controls-\$\{activeInventoryTab\}`"/);
assert.match(inventoryLedgerSource, /balanceControls\.sortKey\.value === "operation_label"/);
assert.match(tableControlsSource, /hasEnhancedButton/);
assert.match(tableControlsSource, /currentHeaderLabel/);
assert.match(inventoryLedgerSource, /const isSelectedFinishedWarehouse = computed/);
assert.match(inventoryLedgerSource, /const selectedPrimaryAvailableLabel = computed/);
assert.match(inventoryLedgerSource, /const selectedPrimaryOnHandLabel = computed/);
assert.match(inventoryLedgerSource, /const selectedAuxiliaryMetricLabel = computed/);
assert.match(inventoryLedgerSource, /function formatSelectedUnitCost/);
assert.match(inventoryLedgerSource, /selectedWarehouseType\.value === "FINISHED"[\s\S]*return "\/件"/);
assert.match(inventoryLedgerSource, /import DrawerDataTable from "\.\.\/components\/DrawerDataTable\.vue"/);
assert.match(inventoryLedgerSource, /const overviewLotDrawerColumns = computed/);
assert.match(inventoryLedgerSource, /const lotDrawerColumns = computed/);
assert.match(inventoryLedgerSource, /const txnDrawerColumns = computed/);
assert.match(inventoryLedgerSource, /key: "inbound_qty"[\s\S]*label: "入库数量"/);
assert.match(inventoryLedgerSource, /key: "auxiliary_weight"[\s\S]*label: "辅助重量\(kg\)"/);
assert.match(inventoryLedgerSource, /v-model:expanded-rows="expandedLotRows"/);
assert.match(inventoryLedgerSource, /v-model:expanded-rows="expandedTxnRows"/);
assert.match(inventoryLedgerSource, /"OUTSOURCING_SURPLUS"/);
assert.match(inventoryLedgerSource, /"OUTSOURCING_IN"/);
assert.match(inventoryLedgerSource, /"OUTSOURCING_SCRAP_IN"/);
assert.match(inventoryLedgerSource, /"OUTSOURCING_OUT"/);
assert.match(inventoryLedgerSource, /"SCRAP_SALE_OUT"/);
assert.match(inventoryLedgerSource, /v-model\.trim="genericForm\.waybill_no"/);
assert.match(inventoryLedgerSource, /v-model\.number="genericForm\.freight_amount"/);
assert.match(inventoryLedgerSource, /handleLogisticsPhotoUpload\(genericForm/);
assert.match(inventoryLedgerSource, /order_photo_url: genericRequiresLogistics\.value \? genericForm\.order_photo_url/);
assert.match(inventoryLedgerSource, /v-model\.trim="deliveryForm\.waybill_no"/);
assert.match(inventoryLedgerSource, /v-model\.number="deliveryForm\.freight_amount"/);
assert.match(inventoryLedgerSource, /handleLogisticsPhotoUpload\(deliveryForm/);
assert.match(inventoryLedgerSource, /order_photo_url: deliveryForm\.order_photo_url/);
assert.match(deliveryManagementSource, /发货台账/);
assert.match(deliveryManagementSource, /交付查询/);
assert.doesNotMatch(deliveryManagementSource, /v-model\.trim="form\.waybill_no"/);
assert.doesNotMatch(deliveryManagementSource, /v-model\.number="form\.freight_amount"/);
assert.doesNotMatch(deliveryManagementSource, /handleLogisticsPhotoUpload/);
assert.doesNotMatch(deliveryManagementSource, /waybill_no: form\.waybill_no/);
assert.doesNotMatch(deliveryManagementSource, /order_photo_url: form\.order_photo_url/);
assert.doesNotMatch(deliveryManagementSource, /freight_amount: Number\(form\.freight_amount\)/);
assert.match(inventoryLedgerSource, /fetchResource\("\/master-data\/materials\?limit=200", \[\]\)/);
assert.match(inventoryLedgerSource, /fetchResource\("\/master-data\/products\?limit=200", \[\]\)/);
assert.match(inventoryLedgerSource, /fetchResource\("\/sales\/customers\?limit=200", \[\]\)/);
assert.doesNotMatch(inventoryLedgerSource, /fetchResource\("\/master-data\/materials\?limit=500", \[\]\)/);
assert.doesNotMatch(inventoryLedgerSource, /fetchResource\("\/master-data\/products\?limit=500", \[\]\)/);
assert.doesNotMatch(inventoryLedgerSource, /fetchResource\("\/sales\/customers\?limit=500", \[\]\)/);
assert.match(inventoryLedgerSource, /const isSemiSourceLotTraceInbound = computed/);
assert.match(inventoryLedgerSource, /\["WIP_IN", "OUTSOURCING_IN"\]\.includes/);
assert.match(inventoryLedgerSource, /const isSemiAutoSourceOutbound = computed/);
assert.match(inventoryLedgerSource, /\["WIP_OUT", "OUTSOURCING_OUT"\]\.includes/);
assert.match(inventoryLedgerSource, /const semiAutoSourceOutboundSourceLots = computed/);
assert.match(inventoryLedgerSource, /入库数量/);
assert.match(inventoryLedgerSource, /出库数量/);
assert.match(inventoryLedgerSource, /入库类型/);
assert.match(inventoryLedgerSource, /按件入库/);
assert.match(inventoryLedgerSource, /按重入库/);
assert.match(inventoryLedgerSource, /const selectedSemiMeasureBasis = computed/);
assert.match(inventoryLedgerSource, /function formatSemiAvailability/);
assert.match(inventoryLedgerSource, /function formatSemiMeasureValue/);
assert.match(inventoryLedgerSource, /委外方/);
assert.match(inventoryLedgerSource, /outsourcing_party_name/);
assert.match(inventoryLedgerSource, /getProductBomMaterialItemIds\(genericForm\.item_id\)/);
assert.match(inventoryLedgerSource, /:allow-unavailable="isSourceLotReturnInbound \|\| isSemiSourceLotTraceInbound \|\| isOutsourcingScrapInbound"/);
assert.match(inventoryLedgerSource, /const inboundQty = activeWarehouseType\.value === "AUX" \|\| isFinishedOutsourcingInbound\.value[\s\S]*\? Number\(genericForm\.qty \|\| 0\)[\s\S]*: isSemiSourceLotTraceInbound\.value && selectedSemiMeasureBasis\.value === "PIECE"/);
assert.match(inventoryLedgerSource, /outbound_qty: activeWarehouseType\.value === "AUX"[\s\S]*\? Number\(genericForm\.qty \|\| 0\)[\s\S]*: isSemiAutoSourceOutbound\.value && selectedSemiMeasureBasis\.value === "PIECE"/);
assert.match(inventoryLedgerSource, /const selectedTraceSourceLotIds = isProductTraceOnlySourceLotInbound\.value[\s\S]*selectedGenericSourceLots\.value\.map/);
assert.match(inventoryLedgerSource, /source_lot_ids: selectedTraceSourceLotIds/);
assert.match(inventoryLedgerSource, /semiAutoSourceOutboundSourceLotSummary/);
assert.match(inventoryLedgerSource, /仅用于来源追溯，不扣减原材料库存/);

console.log("inventory ledger option tests passed");
