liu
11 小时以前 5bf65a4d967c90b4ee51c8405ee9bef766530fd8
feat(mdm): 计量单位新增重量字段

原有 type 字段仅支持「48千克/100千克/吨」三种固定取值,无法录入实际重量,
「新塔棉7号大田用种25公斤」这类单位的重量无处维护,只能塞进名称。

- MdmUnitMeasureDO / MdmUnitMeasureRespDTO / MdmUnitMeasureSaveReqVO 新增 weight 字段
- docs/sql/mdm_schema.sql 同步建表脚本
- sql/mysql/mdm_unit_measure_add_weight.sql 增量脚本,带存在性判断可重复执行
- docs/unit_measure_weight_integration.md 前端联调方案

weight 为可空字段(DECIMAL(24,6),单位 kg),历史数据不回填,
由业务在计量单位维护页面按实际重量补录。

Co-Authored-By: Claude <noreply@anthropic.com>
已添加2个文件
已修改4个文件
142 ■■■■■ 文件已修改
docs/sql/mdm_schema.sql 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
docs/unit_measure_weight_integration.md 109 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
sql/mysql/mdm_unit_measure_add_weight.sql 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
yudao-module-mdm-api/src/main/java/cn/iocoder/yudao/module/mdm/api/unit/dto/MdmUnitMeasureRespDTO.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
yudao-module-mdm/src/main/java/cn/iocoder/yudao/module/mdm/controller/admin/unit/vo/MdmUnitMeasureSaveReqVO.java 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
yudao-module-mdm/src/main/java/cn/iocoder/yudao/module/mdm/dal/dataobject/unit/MdmUnitMeasureDO.java 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
docs/sql/mdm_schema.sql
@@ -34,6 +34,8 @@
    `id` bigint NOT NULL AUTO_INCREMENT COMMENT '单位编号',
    `code` varchar(50) NOT NULL COMMENT '单位编码',
    `name` varchar(50) NOT NULL COMMENT '单位名称',
    `type` varchar(20) DEFAULT NULL COMMENT '类型(48千克/100千克/吨)',
    `weight` decimal(24,6) DEFAULT NULL COMMENT '重量(kg)',
    `primary_flag` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否主单位',
    `primary_id` bigint DEFAULT NULL COMMENT '主单位编号',
    `change_rate` decimal(24,6) DEFAULT 1.000000 COMMENT '与主单位换算比例',
docs/unit_measure_weight_integration.md
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,109 @@
# è®¡é‡å•位新增「重量」字段 - å‰ç«¯è”调方案
## éœ€æ±‚背景
计量单位原先只有 `type`(类型)字段,取值被限制为 `48千克 / 100千克 / å¨` ä¸‰ç§ï¼Œæ— æ³•录入实际重量。
实际业务中大量单位名称携带重量,例如「新塔棉7号大田用种**25公斤**」「新塔7号大田用种**10公斤**」,
这些单位的重量目前只能写进名称,无法单独维护。
本次在计量单位上新增可输入的「重量(kg)」字段,重量与名称解耦,可独立录入、修改、展示。
## æ¶‰åŠé¡µé¢
- åŸºç¡€æ•°æ® > è®¡é‡å•位(列表页、新增/修改弹窗)
- è®¡é‡å•位选择器(物料/品种等表单中选用计量单位时的悬浮详情)
## æ•°æ®åº“变更
表 `mdm_unit_measure` æ–°å¢žå­—段:
| å­—段 | ç±»åž‹ | å¯ç©º | è¯´æ˜Ž |
|------|------|------|------|
| `weight` | decimal(24,6) | æ˜¯ | é‡é‡(kg) |
- ä½äºŽ `type` å­—段之后。
- **不做历史数据回填**:历史记录 `weight` å‡ä¸ºç©ºï¼Œéœ€ä¸šåŠ¡åœ¨é¡µé¢ä¸ŠæŒ‰å®žé™…é‡é‡è¡¥å½•ã€‚
- è„šæœ¬ï¼š`sql/mysql/mdm_unit_measure_add_weight.sql`
## API
本轮无新增接口、无接口路径调整,仅在既有接口的请求/响应中增加 `weight` å­—段。
| æ–¹æ³• | è·¯å¾„ | è¯´æ˜Ž |
|------|------|------|
| POST | /mdm/unit/create | æ–°å¢žè®¡é‡å•位 |
| PUT | /mdm/unit/update | ä¿®æ”¹è®¡é‡å•位 |
| GET | /mdm/unit/get | æŸ¥è¯¢è®¡é‡å•位详情 |
| GET | /mdm/unit/page | æŸ¥è¯¢è®¡é‡å•位分页 |
| GET | /mdm/unit/list | æŸ¥è¯¢è®¡é‡å•位列表 |
| GET | /mdm/unit/list-by-ids | æ ¹æ®ç¼–号列表查询计量单位 |
**请求参数新增:**
| å‚æ•° | ç±»åž‹ | å¿…å¡« | è¯´æ˜Ž |
|------|------|------|------|
| weight | Number | å¦ | é‡é‡(kg),单位千克,可传小数 |
**响应字段新增:**
| å­—段 | ç±»åž‹ | è¯´æ˜Ž |
|------|------|------|
| weight | Number | é‡é‡(kg),未录入时返回 null |
**响应示例(/mdm/unit/get):**
```json
{
  "code": 0,
  "data": {
    "id": 1,
    "code": "3",
    "name": "新塔棉7号大田用种25公斤",
    "type": "48千克",
    "weight": 25,
    "primaryFlag": false,
    "primaryId": null,
    "changeRate": 1.0,
    "status": 0,
    "remark": null
  },
  "msg": ""
}
```
## å­—段展示规则
| å­—段 | å±•示位置 | è¯´æ˜Ž |
|------|----------|------|
| weight | è®¡é‡å•位列表 | åˆ—标题「重量(kg)」,为空时展示 `-`,不参与排序 |
| weight | è®¡é‡å•位新增/修改弹窗 | æ•°å­—输入框,标签「重量(kg)」,非必填,最小值 0,建议精度 2 |
| weight | è®¡é‡å•位选择器悬浮详情 | åœ¨ã€Œåç§°ã€ä¸‹æ–¹è¿½åŠ ä¸€è¡Œã€Œé‡é‡ï¼š{weight} kg」,weight ä¸ºç©ºæ—¶ä¸å±•示该行 |
## ä¸šåŠ¡è§„åˆ™è¯´æ˜Ž
| åœºæ™¯ | è§„则 |
|------|------|
| æ–°å¢ž/修改 | é‡é‡éžå¿…填;允许留空表示尚未维护 |
| é‡é‡å–值 | å•位固定为千克(kg),只存数值,不存单位文本 |
| ç±»åž‹æ ¡éªŒ | `type` å·²**由必填改为非必填**,只填名称+重量即可保存成功 |
| ä¸Ž type çš„关系 | `type` ä¿ç•™ä¸åˆ ï¼›è¢‹ç ç”Ÿæˆé€»è¾‘仍读取 `type`,本次不受影响 |
| ä¸Žåç§°çš„关系 | é‡é‡ç‹¬ç«‹äºŽåç§°ï¼Œåç§°ä¸­çš„「25公斤」等字样不再作为重量来源 |
## æ³¨æ„äº‹é¡¹
1. **`type` å­—段已放开必填限制。**
   æ­¤å‰åŽç«¯ `MdmUnitMeasureSaveReqVO` å¯¹ `type` æœ‰ `@NotBlank` æ ¡éªŒï¼Œè€Œå‰ç«¯æ–°å¢ž/修改弹窗并未提交该字段,
   å¯¼è‡´ä»Žé¡µé¢æ–°å¢žè®¡é‡å•位固定返回「类型不能为空」。本次已去掉该校验,该问题一并修复。
2. **`type` ä¸ºç©ºä¼šå¯¼è‡´æ— æ³•生成袋码。**
   MES è¢‹ç ç”Ÿæˆä»ä¾èµ– `type` è§£æžæ¯æ‰˜è¢‹æ•°ï¼ˆ`48千克` â†’ æ¯æ‰˜ 48 è¢‹ï¼‰ï¼Œ`type` ä¸ºç©ºæˆ–不在
   `48千克 / 100千克 / å¨` èŒƒå›´å†…时会报「品种主计量单位未配置类型」。
   å› æ­¤ï¼šä»…维护重量、不维护类型的计量单位,不可用于需要生成袋码的品种。
3. é‡é‡ä¸º**每单位(袋)的重量**,不是整批重量,请勿与库存数量相乘后回填。
4. åŽ†å²æ•°æ® `weight` ä¸ºç©ºï¼Œå‰ç«¯å±•示需做空值兜底,避免出现 `null kg` æˆ– `NaN`。
5. `decimal(24,6)` ç²¾åº¦è¾ƒé«˜ï¼Œå‰ç«¯å»ºè®®æŒ‰ 2 ä½å°æ•°å±•示,避免出现 `25.000000` è¿™ç±»å¤šä½™å°¾æ•°ã€‚
6. è®¡é‡å•位存在删除保护:被物料引用的单位不允许删除,重量字段的增改不影响该规则。
sql/mysql/mdm_unit_measure_add_weight.sql
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,14 @@
-- MDM è®¡é‡å•位新增「重量」字段
-- èƒŒæ™¯ï¼šåŽŸæœ‰ type å­—段只支持 48千克/100千克/吨 ä¸‰ç§å›ºå®šå–值,无法录入实际重量,
--       å¯¼è‡´ã€Œæ–°å¡”棉7号大田用种25公斤」这类单位的重量无处填写。
-- è¯´æ˜Žï¼šweight ä¸ºå¯ç©ºå­—段,历史数据不做回填,由业务在计量单位维护页面按实际重量补录。
-- MySQL çš„ ALTER TABLE ADD COLUMN ä¸æ”¯æŒ IF NOT EXISTS,使用兼容写法保证脚本可重复执行
SET @exists = (SELECT COUNT(*) FROM information_schema.columns
               WHERE table_schema = DATABASE() AND table_name = 'mdm_unit_measure' AND column_name = 'weight');
SET @sql = IF(@exists = 0,
              'ALTER TABLE mdm_unit_measure ADD COLUMN weight DECIMAL(24,6) NULL COMMENT ''重量(kg)'' AFTER type',
              'SELECT 1');
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
yudao-module-mdm-api/src/main/java/cn/iocoder/yudao/module/mdm/api/unit/dto/MdmUnitMeasureRespDTO.java
@@ -21,6 +21,9 @@
    @Schema(description = "类型(48千克/100千克/吨)", example = "48千克")
    private String type;
    @Schema(description = "重量(kg)", example = "25")
    private BigDecimal weight;
    @Schema(description = "是否主单位", example = "true")
    private Boolean primaryFlag;
yudao-module-mdm/src/main/java/cn/iocoder/yudao/module/mdm/controller/admin/unit/vo/MdmUnitMeasureSaveReqVO.java
@@ -1,7 +1,6 @@
package cn.iocoder.yudao.module.mdm.controller.admin.unit.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import lombok.Data;
import java.math.BigDecimal;
@@ -19,10 +18,12 @@
    @Schema(description = "单位名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "个")
    private String name;
    @Schema(description = "类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "48千克")
    @NotBlank(message = "类型不能为空")
    @Schema(description = "类型(48千克/100千克/吨),非必填;袋码生成依赖该字段,为空时无法生成袋码", example = "48千克")
    private String type;
    @Schema(description = "重量(kg)", example = "25")
    private BigDecimal weight;
    @Schema(description = "是否主单位", example = "true")
    private Boolean primaryFlag;
yudao-module-mdm/src/main/java/cn/iocoder/yudao/module/mdm/dal/dataobject/unit/MdmUnitMeasureDO.java
@@ -43,10 +43,17 @@
     * ç±»åž‹
     *
     * å¯é€‰å€¼ï¼š48千克、100千克、吨
     *
     * éžå¿…å¡«ï¼›MES è¢‹ç ç”Ÿæˆä¾èµ–该字段换算每托袋数,为空时无法生成袋码
     */
    private String type;
    /**
     * é‡é‡(kg)
     */
    private BigDecimal weight;
    /**
     * æ˜¯å¦ä¸»å•位
     */
    private Boolean primaryFlag;