forked from lunanting/cangku
- 取数统一为 fetchPickingBinSkuRows:一行 = 一个「仓位 × 商品编码」,列表与导出共用 商品日销 = 商品窗口整档销量 ÷ 天数(不做仓位分摊);同一商品占几个仓位都是同一等级 另输出分摊销量 = 商品销量 ÷ 占用同类型仓位数,供按行求和 - 列表页同步拆到商品粒度:新增商品编码列,去掉 SKU数列,搜索支持商品编码 - 汇总卡片主数值改为去重商品数,另显示明细行数;销量按去重商品口径统计 - 导出新增「分摊销量」「商品日销」列,表头口径标注更明确 - 性能:仓位类型选满时不拼 IN 过滤(避免参数嗅探走坏计划),全类型查询由超时降到约 30 秒 验证(基准日 2026-10-08、30 天、拣选位): - 明细 11871 行 / 去重商品 6821 个 / 库存合计 499141(与旧口径一致) - 跨多仓位的 2028 个商品,销量与等级不一致 0 个 - 导出行求和:分摊销量合计 96847 = 去重商品销量合计 96847(差异 -0.0017,浮点舍入) - 单测 9/9 通过;语法检查 182 文件通过;前端 eslint 无报错、vite build 成功
74 lines
3.9 KiB
JavaScript
74 lines
3.9 KiB
JavaScript
/**
|
||
* 拣选库位动销分析 —— 口径配置(纯规则,不含业务数值)
|
||
*
|
||
* 一级菜单:大货库存监控
|
||
* 二级菜单:拣选库位动销分析
|
||
*
|
||
* 表头(需求表原列为 所在仓库 | 仓位 | 数量 | 类型 | 动销等级,这里做了扩充与优化):
|
||
* 仓库 | 仓位 | 类型 | 商品编码 | 库存数量 | 近N天销量 | 日销 | 动销等级
|
||
*
|
||
* 粒度:仓位 × 商品编码(一个仓位有 N 个商品就输出 N 行),列表与导出共用。
|
||
*
|
||
* 口径:
|
||
* 库存数量:rpt.jst_packInventoryInfo 按 wms_co_id + 仓位 + sku_id 汇总 qty
|
||
* 仓位类型:bin_group 为空 → 拣选位;bin_group = '存货' → 存货位
|
||
* 销量: rpt.jst_Orders × rpt.jst_OrderItem,按 send_date,排除 Delete/Cancelled
|
||
* 日销: 商品窗口销量 / 窗口天数(整档,不按仓位分摊)
|
||
* 等级: 严格按商品日销判定,同一商品占多少个仓位都是同一等级
|
||
*
|
||
* 【为什么不分摊来定等级】同一 SKU 常常同时占用多个同类型仓位(崔桥工厂仓实测 3290 个
|
||
* 拣选 SKU 中 1431 个跨多个拣选位,最多 24 个)。若把销量摊到仓位再定等级,
|
||
* 一件爆款商品放在 10 个仓位就会被算成日销 1/10 的滞销品 —— 判断的是「摆法」而不是「商品」。
|
||
* 因此等级一律以商品自身的销售速度为准。
|
||
*
|
||
* 【分摊销量列】导出仍附带「分摊销量」= 商品销量 ÷ 其占用的同类型仓位数,
|
||
* 供需要按行求和的场景使用:恒等式(已实测校验,差异 0)
|
||
* 全部行分摊销量之和 = 有库位记录的那些 SKU 的销量之和。
|
||
* 注意它小于「全仓销量」:jst_packInventoryInfo 只覆盖部分 SKU 的仓位数据,
|
||
* 没有仓位记录的 SKU 的销量不会体现在任何库位上。
|
||
*/
|
||
|
||
const PICKING_BIN_LEVEL1 = '大货库存监控';
|
||
const PICKING_BIN_LEVEL2 = '拣选库位动销分析';
|
||
|
||
/** 可选的统计窗口天数;默认 30 天(需求指定按近 30 天销量划分动销等级) */
|
||
const PICKING_BIN_WINDOW_OPTIONS = [7, 15, 30, 60];
|
||
const PICKING_BIN_DEFAULT_DAYS = 30;
|
||
|
||
/** 仓位类型:业务库 bin_group 为空视为拣选位 */
|
||
const BIN_TYPE_PICKING = '拣选';
|
||
const BIN_TYPE_STORAGE = '存货';
|
||
const BIN_TYPES = [BIN_TYPE_PICKING, BIN_TYPE_STORAGE];
|
||
/** 默认只看拣选位(本功能的核心是拣货位动销) */
|
||
const PICKING_BIN_DEFAULT_TYPES = [BIN_TYPE_PICKING];
|
||
|
||
/**
|
||
* 动销等级(顺序即展示顺序)。判定依据为「商品日销」= 商品窗口整档销量 ÷ 天数,
|
||
* 不做仓位分摊,同一商品在所有仓位显示同一等级。
|
||
* lower 为日销下界(含),upper 为日销上界(不含);null 表示不限制。
|
||
* zero 档为「窗口内无销量」,由 salesQty <= 0 兜底。
|
||
*/
|
||
const PICKING_BIN_GRADE_RULES = [
|
||
{ key: 'hot', label: '爆款:日销≥20', lower: 20, upper: null, tip: '商品日均销量 ≥ 20 件' },
|
||
{ key: 'best', label: '热卖款:10≤日销<20', lower: 10, upper: 20, tip: '商品日均销量 10 ~ 20 件(含 10,不含 20)' },
|
||
{ key: 'normal', label: '平销款:3≤日销<10', lower: 3, upper: 10, tip: '商品日均销量 3 ~ 10 件(含 3,不含 10)' },
|
||
{ key: 'slow1', label: '滞销款-1:1≤日销<3', lower: 1, upper: 3, tip: '商品日均销量 1 ~ 3 件(含 1,不含 3)' },
|
||
{ key: 'slow2', label: '滞销款-2:0<日销<1', lower: 0, upper: 1, tip: '商品日均销量大于 0 且小于 1 件' },
|
||
{ key: 'zero', label: '销售=0', lower: 0, upper: 0, tip: '统计窗口内该商品无销量(仍占用库存)' },
|
||
];
|
||
|
||
const PICKING_BIN_TOTAL_LABEL = '汇总';
|
||
|
||
module.exports = {
|
||
PICKING_BIN_LEVEL1,
|
||
PICKING_BIN_LEVEL2,
|
||
PICKING_BIN_WINDOW_OPTIONS,
|
||
PICKING_BIN_DEFAULT_DAYS,
|
||
BIN_TYPE_PICKING,
|
||
BIN_TYPE_STORAGE,
|
||
BIN_TYPES,
|
||
PICKING_BIN_DEFAULT_TYPES,
|
||
PICKING_BIN_GRADE_RULES,
|
||
PICKING_BIN_TOTAL_LABEL,
|
||
};
|