Compare commits

..

2 Commits

Author SHA1 Message Date
97a93766e8 Merge pull request 'fix: MKH-BOM 配件仓位仓名改用 wms_co_id 关联,修正误显示「常州简尚家居有限公司」' (#22) from codex/mkh-pack-warehouse-join-0919 into main 2026-09-22 23:58:40 +08:00
da08b03dcb fix: MKH-BOM 配件仓位仓名改用 wms_co_id 关联,修正误显示「常州简尚家居有限公司」
根因
- rpt.jst_packInventoryInfo.wh_id **不是** rpt.jst_warehouseInfo.Id:
  全表只有 6 个取值(1/2/3/4/6/7),90% 的行都是 wh_id=1,
  按 `w.Id = p.wh_id` 关联后,727 个配件的仓位仓名被统一显示成「常州简尚家居有限公司」。
- 该表的仓 id 列是自带的 `wms_co_id`:
  09-19 实测 30,236 行 **0 NULL**、14 个仓取值,按 `w.wms_co_id = p.wms_co_id`
  关联即得到正确仓名「简尚-崔桥工厂半成品包装项目仓」。
- 旧结论「该表 wms_co_id 全表 NULL,必须用 wh_id」只对 09-17 的表状态成立
  (当时 85,152 行、只有 3 个箱、bin 全空、与 MKH 配件零交集);
  该表由上游**小时级增量刷新**(业务确认 09-19),09-18 重建后 wms_co_id 已全部有值。

改动
- backend/src/services/mkhBomService.js
  · loadComponentLocations() 的 JOIN 与 GROUP BY:p.wh_id → p.wms_co_id
  · 文件头 ⑤ 与 formatPackLocation() 注释更新为正确关联列,并记录该表的小时级
    增量刷新特性(行级 updateTime 只反映「有变化的行」,不能当表的更新频率;
    行数/箱数/命中数会随上游变化,不要写死)。
- backend/src/services/modularStockMonitorService.js
  · 补注:该页只取 bin、不 join 仓名,不受此关联列问题影响;命中数会随上游变化。
- backend/test/mkhBomService.test.js
  · 仓位格式化用例的 fixture 改回真实仓名,避免继续固化错误仓名。

影响与验证
- 仅影响 MKH-BOM 页「配件仓位」列与导出配件明细的仓名文本;
  A4 打印预览本就会去掉仓名前缀(stripWarehousePrefix),不受影响。
- 配件监控页不 join 仓名,无影响。
- 实测:修正后 15 个真实配件编码输出「简尚-崔桥工厂半成品包装项目仓 · BCP01-01-1」。
- 后端:check-syntax 151 文件通过;node --test 337/338 通过
  (唯一失败为既有环境问题 resilientSecretStore 权限断言,与本改动无关)。
2026-09-19 17:08:00 +08:00
3 changed files with 13 additions and 10 deletions

View File

@ -2020,7 +2020,8 @@ function matchesPackSku(componentCode, packSkuCode) {
function formatPackLocation(row) {
const warehouseName = toText(row.warehouseName);
const warehouseId = toText(row.warehouseId);
// 仓库优先显示名称(wh_id → jst_warehouseInfo.Id → name),取不到时退回 id
// 仓库优先显示名称(wms_co_id → jst_warehouseInfo.wms_co_id → name),取不到时退回 id。
// ⚠️ 关联列是 wms_co_id 不是 wh_id,见文件头 ⑤(09-19 修正)
const warehouse = warehouseName || (warehouseId ? `仓库 ${warehouseId}` : '');
const binGroup = toText(row.binGroup);
const bin = toText(row.bin);
@ -2099,15 +2100,15 @@ async function loadComponentLocations(codes = []) {
const rows = await cloudDatabase.query(
`SELECT p.sku_id AS skuId,
p.pack_id AS packId,
p.wh_id AS warehouseId,
p.wms_co_id AS warehouseId,
p.bin AS bin,
p.bin_group AS binGroup,
w.name AS warehouseName,
SUM(p.qty) AS qty
FROM rpt.jst_packInventoryInfo p WITH (NOLOCK)
LEFT JOIN rpt.jst_warehouseInfo w WITH (NOLOCK) ON w.Id = p.wh_id
LEFT JOIN rpt.jst_warehouseInfo w WITH (NOLOCK) ON w.wms_co_id = p.wms_co_id
WHERE ${conditions.join(' OR ')}
GROUP BY p.sku_id, p.pack_id, p.wh_id, p.bin, p.bin_group, w.name
GROUP BY p.sku_id, p.pack_id, p.wms_co_id, p.bin, p.bin_group, w.name
HAVING SUM(p.qty) > 0`,
params,
{ requestTimeout: 120000 }

View File

@ -117,7 +117,9 @@ const buildWarningOrderSql = () => (
* 统一的「仓位」表达式(2026-09-18 改源)。
* 旧源 `jst_sku.bin / other_bin` 在目标仓 794 行**恒为空**(页面因此长期显示「未维护」);
* 真货位在 `rpt.jst_packInventoryInfo.bin` —— 该表 2026-09-18 10:48 被上游刷新后,
* 目标仓 794 个 SKU **命中 727 个**(实测),如 ZT-8 / BCP01-01-1。
* 目标仓 794 个 SKU **命中 727 个**(09-19 实测;该表小时级增量刷新,命中数会变)。
* ⚠️ 只取 bin,**不 join 仓名**,所以不受该表 wh_id / wms_co_id 关联列问题影响(见
* mkhBomService 文件头 ⑤;那个坑只影响 MKH-BOM 页配件仓位列的仓名文本)。
* · 只取 `qty > 0` 的箱,同 SKU 多箱时取库存最大的那个(列表页只展示主货位)
* · 取不到才回退商品档案的 bin / other_bin(目前仍全空,保留兜底不影响结果)
* 与 MKH-BOM 页 `mkhBomService.loadComponentLocations()` 同源,区别只在本页取单个主货位。

View File

@ -1017,8 +1017,8 @@ test('pack inventory location prefers the warehouse name and keeps the box fallb
const locations = _private.buildPackLocationMap([
{
skuId: 'PART-1-1',
warehouseId: 1,
warehouseName: '常州简尚家居有限公司',
warehouseId: 15718196,
warehouseName: '简尚-崔桥工厂半成品包装项目仓',
binGroup: null,
bin: '',
packId: 'BOX-1',
@ -1026,8 +1026,8 @@ test('pack inventory location prefers the warehouse name and keeps the box fallb
},
{
skuId: 'PART-1-2',
warehouseId: 1,
warehouseName: '常州简尚家居有限公司',
warehouseId: 15718196,
warehouseName: '简尚-崔桥工厂半成品包装项目仓',
binGroup: '成品区',
bin: 'A-01',
packId: 'BOX-2',
@ -1037,7 +1037,7 @@ test('pack inventory location prefers the warehouse name and keeps the box fallb
assert.equal(
locations.get('PART-1'),
'常州简尚家居有限公司 · 箱号 BOX-1、常州简尚家居有限公司 · 成品区 / A-01'
'简尚-崔桥工厂半成品包装项目仓 · 箱号 BOX-1、简尚-崔桥工厂半成品包装项目仓 · 成品区 / A-01'
);
});