商品成本价与调价单开发计划.md
11.6 KB
商品成本价体系与调价单开发计划
现有基础:前端
wtPriceAdjust/index.vue+Form.vue(骨架页面),后端和数据库均不存在
一、背景与目标
现状问题
- 没有统一的成本价存储:当前成本价只能从最近一次采购入库单的单价推算,不准确
- 同一商品不同仓库成本不同:如"卡带 开心镇"在莱迪仓平均成本 42.92,景枫仓 111.00
- 出库时不记录成本价:
wt_xsckd_mx表只有售价(dj),无法计算毛利 - 拆装单成本价精度丢失:
wt_czdmx.cbdj字段是decimal(50,0),没有小数位 - 缺少调价单功能:无法对在库商品进行成本调整
目标
建立完整的加权平均成本价体系,支持:采购入库自动算成本 → 调价单手动调整 → 出库时记录快照 → 拆装单/调拨单联动
二、数据库变更
2.1 新建表:wt_sp_cost(商品仓库成本表)
核心表,按「商品+仓库」维度存储当前加权平均成本价
CREATE TABLE wt_sp_cost (
F_Id VARCHAR(50) NOT NULL COMMENT '主键',
spbh VARCHAR(50) NOT NULL COMMENT '商品编号',
ck VARCHAR(50) NOT NULL COMMENT '仓库ID',
cbj DECIMAL(18,2) DEFAULT 0.00 COMMENT '当前加权平均成本价',
sl INT DEFAULT 0 COMMENT '当前在库数量',
update_time DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后更新时间',
PRIMARY KEY (F_Id),
UNIQUE KEY uk_sp_ck (spbh, ck)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='商品仓库成本表';
2.2 新建表:wt_tjd(调价单主表)
CREATE TABLE wt_tjd (
F_Id VARCHAR(50) NOT NULL COMMENT '单据编号(TJD+日期+序号)',
djrq DATETIME COMMENT '单据日期',
ck VARCHAR(50) COMMENT '仓库(选仓库加载全部商品)',
jsr VARCHAR(50) COMMENT '经手人',
zdr VARCHAR(50) COMMENT '制单人',
djzt VARCHAR(50) DEFAULT '草稿' COMMENT '单据状态(草稿/已审核)',
bz TEXT COMMENT '备注',
PRIMARY KEY (F_Id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='商品调价单';
2.3 新建表:wt_tjd_mx(调价单明细)
CREATE TABLE wt_tjd_mx (
F_Id VARCHAR(50) NOT NULL COMMENT '主键',
djbh VARCHAR(50) NOT NULL COMMENT '单据编号(FK→wt_tjd)',
ck VARCHAR(50) COMMENT '仓库',
spbh VARCHAR(50) COMMENT '商品编号',
spmc VARCHAR(200) COMMENT '商品名称',
dw VARCHAR(50) COMMENT '单位',
sl INT DEFAULT 0 COMMENT '数量(在库数量,自动带出)',
tqdj DECIMAL(18,2) DEFAULT 0.00 COMMENT '调前单价(自动带出)',
tjbl DECIMAL(8,4) DEFAULT 0.00 COMMENT '调价比率%',
thdj DECIMAL(18,2) DEFAULT 0.00 COMMENT '调后单价',
tqje DECIMAL(18,2) DEFAULT 0.00 COMMENT '调前金额(sl×tqdj)',
thje DECIMAL(18,2) DEFAULT 0.00 COMMENT '调后金额(sl×thdj)',
bz VARCHAR(500) COMMENT '备注',
PRIMARY KEY (F_Id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='商品调价单明细';
2.4 修改表:wt_xsckd_mx(出库单明细加成本价字段)
出库时保存成本价快照,用于后续毛利计算
ALTER TABLE wt_xsckd_mx
ADD COLUMN cbdj DECIMAL(18,2) DEFAULT 0.00 COMMENT '成本单价(出库时快照)',
ADD COLUMN cbje DECIMAL(18,2) DEFAULT 0.00 COMMENT '成本金额(出库时快照)';
2.5 修改表:wt_czdmx + wt_czdmx_2(修复精度)
当前 cbdj/cbje 是 decimal(50,0) 没有小数位,需要修复
ALTER TABLE wt_czdmx MODIFY COLUMN cbdj DECIMAL(18,2) DEFAULT 0.00 COMMENT '成本单价';
ALTER TABLE wt_czdmx MODIFY COLUMN cbje DECIMAL(18,2) DEFAULT 0.00 COMMENT '成本金额';
ALTER TABLE wt_czdmx_2 MODIFY COLUMN cbdj DECIMAL(18,2) DEFAULT 0.00 COMMENT '成本单价';
ALTER TABLE wt_czdmx_2 MODIFY COLUMN cbje DECIMAL(18,2) DEFAULT 0.00 COMMENT '成本金额';
2.6 初始化 wt_sp_cost 数据
根据当前在库序列号的批次入库价计算加权平均成本
INSERT INTO wt_sp_cost (F_Id, spbh, ck, cbj, sl, update_time)
SELECT
CONCAT(sub.spbh, '_', sub.in_warehouse) AS F_Id,
sub.spbh,
sub.in_warehouse AS ck,
ROUND(SUM(IFNULL(mx.dj, 0) * sub.qty) / NULLIF(SUM(sub.qty), 0), 2) AS cbj,
SUM(sub.qty) AS sl,
NOW() AS update_time
FROM (
SELECT sn.spbh, sn.in_warehouse, sn.in_djbh, COUNT(*) AS qty
FROM wt_serial_number sn
WHERE sn.status = 0
GROUP BY sn.spbh, sn.in_warehouse, sn.in_djbh
) sub
LEFT JOIN wt_xsckd_mx mx ON sub.in_djbh = mx.djbh AND sub.spbh = mx.spbh
GROUP BY sub.spbh, sub.in_warehouse;
三、业务逻辑变更
3.1 成本价读取(统一入口)
所有需要取成本价的地方,统一从 wt_sp_cost 读取:
GetProductCost(商品ID, 仓库ID)
→ SELECT cbj FROM wt_sp_cost WHERE spbh = 商品ID AND ck = 仓库ID
→ 如果没记录,兜底取最近采购入库单价 → 取零售价 → 返回 0
影响范围:拆装单(WtCzdService)、出库单(WtXsckdService)、调价单(新)
3.2 采购入库时更新成本(WtXsckdService.Create)
当 djlx = "采购入库单" 时,保存后自动更新 wt_sp_cost
对每个明细行:
旧记录 = SELECT cbj, sl FROM wt_sp_cost WHERE spbh AND ck
如果存在:
新成本 = (旧sl × 旧cbj + 入库数 × 入库单价) ÷ (旧sl + 入库数)
UPDATE wt_sp_cost SET cbj = 新成本, sl = 旧sl + 入库数
如果不存在:
INSERT wt_sp_cost (spbh, ck, cbj, sl) VALUES (商品, 仓库, 入库单价, 入库数)
3.3 销售出库时记录成本快照(WtXsckdService.Create)
当 djlx = "销售出库单" 时
对每个明细行:
cbdj = SELECT cbj FROM wt_sp_cost WHERE spbh AND ck
cbje = cbdj × 数量
保存到 wt_xsckd_mx.cbdj, wt_xsckd_mx.cbje
UPDATE wt_sp_cost SET sl = sl - 出库数 WHERE spbh AND ck
3.4 调价单审核时更新成本(WtTjdService,新建)
对每个明细行:
UPDATE wt_sp_cost SET cbj = 调后单价 WHERE spbh AND ck
3.5 拆装单保存时联动(WtCzdService.Create)
出货明细:
cbdj 从 wt_sp_cost 取出货仓库的成本价
UPDATE wt_sp_cost SET sl = sl - 出库数 WHERE 出货仓库
入货明细:
cbdj = 出货总成本金额 ÷ 入货总数量(分摊成本)
UPSERT wt_sp_cost SET cbj = 加权后新成本, sl = sl + 入库数 WHERE 入货仓库
3.6 调拨单联动
出仓成本不变(从 wt_sp_cost 取)
入仓按出仓成本入库(加权平均计入)
3.7 采购退货 / 销售退货
退货入库:按原出库成本价回入(不改变成本单价,只增加数量和总成本)
退货出库:减少数量,成本单价不变
四、后端开发任务
4.1 数据库与 Entity
| 任务 | 说明 |
|---|---|
| 执行 SQL 建表/改表 | 2.1~2.6 的 SQL 语句 |
| WtSpCostEntity | 映射 wt_sp_cost |
| WtTjdEntity | 映射 wt_tjd |
| WtTjdMxEntity | 映射 wt_tjd_mx |
| WtXsckdMxEntity 加字段 | 加 Cbdj、Cbje 属性 |
| WtCzdmxEntity 修复精度 | cbdj/cbje 改为 decimal |
4.2 调价单 Service(WtTjdService,新建)
| 接口 | 方法 | 说明 |
|---|---|---|
| GET /api/Extend/WtTjd/{id} | GetInfo | 获取调价单详情 |
| GET /api/Extend/WtTjd | GetList | 列表查询(分页) |
| POST /api/Extend/WtTjd | Create | 新建调价单 |
| PUT /api/Extend/WtTjd/{id} | Update | 修改调价单 |
| DELETE /api/Extend/WtTjd/{id} | Delete | 删除调价单 |
| POST /api/Extend/WtTjd/Actions/Audit/{id} | Audit | 审核(更新 wt_sp_cost) |
| GET /api/Extend/WtTjd/Actions/LoadProducts | LoadProducts | 按仓库加载商品+成本价+库存 |
4.3 成本价 Service(WtSpCostService,新建或合并)
| 接口 | 说明 |
|---|---|
| GET /api/Extend/WtSpCost/GetCost?spbh=&ck= | 查询单个商品在指定仓库的成本价 |
| POST /api/Extend/WtSpCost/RecalcAll | 重算所有成本(基于当前库存数据) |
4.4 改造现有 Service
| Service | 改造内容 |
|---|---|
| WtXsckdService.Create | 采购入库:更新 wt_sp_cost 加权平均 销售出库:快照 cbdj/cbje 到明细 |
| WtCzdService.Create | 出货:快照 cbdj 从 wt_sp_cost 取 入货:按出货总成本分摊 |
| WtCzdService.GetProductCost | 改为从 wt_sp_cost 读取 |
五、前端开发任务
5.1 调价单页面(新建)
列表页 views/wtTjd/index.vue:
- 搜索条件:单据编号、仓库、日期范围、状态
- 列表字段:单据编号、单据日期、仓库、经手人、状态、操作(编辑/审核/删除)
表单页 views/wtTjd/Form.vue:
- 主表:单据编号(自动生成 TJD+日期+序号)、单据日期、仓库(下拉选择)、经手人、备注
- 明细表(el-table 内嵌编辑):
| 列 | 说明 | 交互 |
|---|---|---|
| 仓库 | 自动带出(跟主表仓库) | 只读 |
| 商品编码 | 选择或仓库加载 | 可选/只读 |
| 商品名称 | 自动带出 | 只读 |
| 单位 | 自动带出 | 只读 |
| 数量 | 在库数量 | 只读 |
| 调前单价 | 自动从 wt_sp_cost 带出 | 只读 |
| 调价比率% | 用户输入 | 可编辑,变化 → 自动算调后单价 |
| 调后单价 | 用户输入或自动算 | 可编辑,变化 → 自动算比率 |
| 调前金额 | 数量×调前单价 | 自动算,只读 |
| 调后金额 | 数量×调后单价 | 自动算,只读 |
| 备注 | 可编辑 |
交互逻辑:
- 选择仓库 → 调用 LoadProducts → 加载该仓库所有有库存商品到明细表
- 也可手动添加行选择商品
- 输入调价比率 → 调后单价 = 调前单价 × (1 + 比率/100)
- 输入调后单价 → 调价比率 = (调后 - 调前) / 调前 × 100
- 审核按钮 → 确认后批量更新成本价
5.2 改造拆装单
GetProductCost接口改为从wt_sp_cost取成本价(后端改,前端无需变)
5.3 改造出库单
- 保存时后端自动写入 cbdj/cbje(后端改,前端可选显示)
六、开发顺序(建议)
| 阶段 | 任务 | 依赖 |
|---|---|---|
| P1 | 执行 SQL:建 wt_sp_cost 表 + 初始化数据 | 无 |
| P1 | 执行 SQL:修复 wt_czdmx 精度 | 无 |
| P1 | 执行 SQL:wt_xsckd_mx 加 cbdj/cbje | 无 |
| P2 | 后端:WtSpCostEntity + GetCost 接口 | P1 |
| P2 | 后端:改造 GetProductCost 从 wt_sp_cost 读 | P2 |
| P3 | 执行 SQL:建 wt_tjd + wt_tjd_mx 表 | 无 |
| P3 | 后端:WtTjdEntity/DTO/Service 全套 CRUD | P3 |
| P3 | 后端:LoadProducts + Audit 接口 | P2+P3 |
| P3 | 前端:调价单列表页 + 表单页 | P3 后端 |
| P4 | 后端:改造 WtXsckdService 采购入库更新成本 | P2 |
| P4 | 后端:改造 WtXsckdService 出库快照成本 | P2 |
| P4 | 后端:改造 WtCzdService 拆装单成本联动 | P2 |
| P5 | 测试:全流程验证 | 全部 |
七、验收标准
- ✅
wt_sp_cost初始化后,每个商品+仓库组合有正确的加权平均成本价 - ✅ 拆装单选商品后自动带出成本单价(从 wt_sp_cost)
- ✅ 调价单:选仓库加载所有商品,调价比率和调后单价双向联动
- ✅ 调价单审核后,wt_sp_cost.cbj 更新为调后单价
- ✅ 采购入库后,wt_sp_cost 自动重算加权平均成本
- ✅ 销售出库时,wt_xsckd_mx.cbdj/cbje 记录出库时刻的成本价
- ✅ 成本金额精度为 2 位小数