diff --git a/klp-wms/src/main/java/com/klp/domain/WmsMaterialCoil.java b/klp-wms/src/main/java/com/klp/domain/WmsMaterialCoil.java
index 83d166aa..6eec2879 100644
--- a/klp-wms/src/main/java/com/klp/domain/WmsMaterialCoil.java
+++ b/klp-wms/src/main/java/com/klp/domain/WmsMaterialCoil.java
@@ -213,5 +213,15 @@ public class WmsMaterialCoil extends BaseEntity {
private Long specId;
private Long versionId;
+
+ /**
+ * 理论厚度(单位:毫米)
+ */
+ private BigDecimal theoreticalThickness;
+
+ /**
+ * 镀铬卷号
+ */
+ private String chromePlateCoilNo;
}
diff --git a/klp-wms/src/main/java/com/klp/domain/bo/WmsMaterialCoilBo.java b/klp-wms/src/main/java/com/klp/domain/bo/WmsMaterialCoilBo.java
index 6e0832b1..867a2213 100644
--- a/klp-wms/src/main/java/com/klp/domain/bo/WmsMaterialCoilBo.java
+++ b/klp-wms/src/main/java/com/klp/domain/bo/WmsMaterialCoilBo.java
@@ -381,5 +381,15 @@ public class WmsMaterialCoilBo extends BaseEntity {
private Long specId;
private Long versionId;
+
+ /**
+ * 理论厚度(单位:毫米)
+ */
+ private BigDecimal theoreticalThickness;
+
+ /**
+ * 镀铬卷号
+ */
+ private String chromePlateCoilNo;
}
diff --git a/klp-wms/src/main/java/com/klp/domain/vo/WmsMaterialCoilExportVo.java b/klp-wms/src/main/java/com/klp/domain/vo/WmsMaterialCoilExportVo.java
index 2cb7d63b..e7a3c264 100644
--- a/klp-wms/src/main/java/com/klp/domain/vo/WmsMaterialCoilExportVo.java
+++ b/klp-wms/src/main/java/com/klp/domain/vo/WmsMaterialCoilExportVo.java
@@ -208,4 +208,16 @@ public class WmsMaterialCoilExportVo {
*/
@ExcelProperty(value = "调拨类型")
private String transferType;
+
+ /**
+ * 理论厚度(单位:毫米)
+ */
+ @ExcelProperty(value = "理论厚度")
+ private BigDecimal theoreticalThickness;
+
+ /**
+ * 镀铬卷号
+ */
+ @ExcelProperty(value = "镀铬卷号")
+ private String chromePlateCoilNo;
}
diff --git a/klp-wms/src/main/java/com/klp/domain/vo/WmsMaterialCoilVo.java b/klp-wms/src/main/java/com/klp/domain/vo/WmsMaterialCoilVo.java
index bd8810f6..76a39b12 100644
--- a/klp-wms/src/main/java/com/klp/domain/vo/WmsMaterialCoilVo.java
+++ b/klp-wms/src/main/java/com/klp/domain/vo/WmsMaterialCoilVo.java
@@ -339,5 +339,15 @@ public class WmsMaterialCoilVo extends BaseEntity {
private Long versionId;
private String specCode;
private String versionCode;
+
+ /**
+ * 理论厚度(单位:毫米)
+ */
+ private BigDecimal theoreticalThickness;
+
+ /**
+ * 镀铬卷号
+ */
+ private String chromePlateCoilNo;
}
diff --git a/klp-wms/src/main/java/com/klp/service/impl/WmsMaterialCoilServiceImpl.java b/klp-wms/src/main/java/com/klp/service/impl/WmsMaterialCoilServiceImpl.java
index d3d8f5c8..089cbe79 100644
--- a/klp-wms/src/main/java/com/klp/service/impl/WmsMaterialCoilServiceImpl.java
+++ b/klp-wms/src/main/java/com/klp/service/impl/WmsMaterialCoilServiceImpl.java
@@ -41,6 +41,7 @@ import com.fasterxml.jackson.databind.ObjectMapper;
import java.util.*;
import java.util.stream.Collectors;
import java.math.BigDecimal;
+import java.math.RoundingMode;
import java.util.Arrays;
import java.io.IOException;
import java.net.URLEncoder;
@@ -697,6 +698,10 @@ public class WmsMaterialCoilServiceImpl implements IWmsMaterialCoilService {
qw.eq(bo.getActualWidth() != null, "mc.actual_width", bo.getActualWidth());
// 实测厚度
qw.eq(StringUtils.isNotBlank(bo.getActualThickness()), "mc.actual_thickness", bo.getActualThickness());
+ // 理论厚度
+ qw.eq(bo.getTheoreticalThickness() != null, "mc.theoretical_thickness", bo.getTheoreticalThickness());
+ // 镀铬卷号
+ qw.like(StringUtils.isNotBlank(bo.getChromePlateCoilNo()), "mc.chrome_plate_coil_no", bo.getChromePlateCoilNo());
// 生产开始时间
qw.eq(bo.getProductionStartTime() != null, "mc.production_start_time", bo.getProductionStartTime());
// 生产结束时间
@@ -1028,6 +1033,123 @@ public class WmsMaterialCoilServiceImpl implements IWmsMaterialCoilService {
return '(' + String.join(" OR ", parts) + ')';
}
+ /**
+ * 根据净重(吨)、实测长度(mm)、物品规格宽度(mm)自动计算理论厚度(mm)
+ * 公式:理论厚度 = 净重(吨) × 1000 / (7.85 × 实测长度(mm) × 宽度(mm))
+ */
+ private void calculateTheoreticalThickness(WmsMaterialCoilBo bo) {
+ if (bo.getTheoreticalThickness() != null) {
+ return;
+ }
+ if (bo.getNetWeight() == null || bo.getActualLength() == null) {
+ return;
+ }
+ if (StringUtils.isBlank(bo.getItemType()) || bo.getItemId() == null) {
+ return;
+ }
+ String specWidth = null;
+ try {
+ if ("raw_material".equals(bo.getItemType())) {
+ WmsRawMaterial rm = rawMaterialMapper.selectById(bo.getItemId());
+ if (rm != null && StringUtils.isNotBlank(rm.getSpecification())) {
+ String[] parts = rm.getSpecification().split("\\*");
+ if (parts.length >= 2) {
+ specWidth = parts[parts.length - 1].trim();
+ }
+ }
+ } else if ("product".equals(bo.getItemType())) {
+ WmsProduct p = productMapper.selectById(bo.getItemId());
+ if (p != null && StringUtils.isNotBlank(p.getSpecification())) {
+ String[] parts = p.getSpecification().split("\\*");
+ if (parts.length >= 2) {
+ specWidth = parts[parts.length - 1].trim();
+ }
+ }
+ }
+ } catch (Exception e) {
+ log.warn("查询物品规格失败, itemType: {}, itemId: {}", bo.getItemType(), bo.getItemId(), e);
+ return;
+ }
+ if (StringUtils.isBlank(specWidth)) {
+ return;
+ }
+ try {
+ BigDecimal weight = bo.getNetWeight();
+ BigDecimal length = new BigDecimal(bo.getActualLength());
+ BigDecimal width = new BigDecimal(specWidth);
+ BigDecimal numerator = weight.multiply(new BigDecimal("1000"));
+ BigDecimal denominator = new BigDecimal("7.85").multiply(length).multiply(width);
+ BigDecimal theoretical = numerator.divide(denominator, 3, RoundingMode.HALF_UP);
+ bo.setTheoreticalThickness(theoretical);
+ } catch (Exception e) {
+ log.warn("计算理论厚度失败", e);
+ }
+ }
+
+ /**
+ * 根据物品类型和ID获取规格中的宽度(规格格式:厚度*宽度,取 * 后面部分)
+ */
+ private BigDecimal getSpecWidth(String itemType, Long itemId) {
+ if (StringUtils.isBlank(itemType) || itemId == null) {
+ return null;
+ }
+ try {
+ String specification = null;
+ if ("raw_material".equals(itemType)) {
+ WmsRawMaterial rm = rawMaterialMapper.selectById(itemId);
+ if (rm != null) {
+ specification = rm.getSpecification();
+ }
+ } else if ("product".equals(itemType)) {
+ WmsProduct p = productMapper.selectById(itemId);
+ if (p != null) {
+ specification = p.getSpecification();
+ }
+ }
+ if (StringUtils.isNotBlank(specification)) {
+ String[] parts = specification.split("\\*");
+ if (parts.length >= 2) {
+ return new BigDecimal(parts[parts.length - 1].trim());
+ }
+ }
+ } catch (Exception e) {
+ log.warn("获取规格宽度失败, itemType: {}, itemId: {}", itemType, itemId, e);
+ }
+ return null;
+ }
+
+ /**
+ * 根据物品类型和ID获取规格中的厚度(规格格式:厚度*宽度,取 * 前面部分)
+ */
+ private BigDecimal getSpecThickness(String itemType, Long itemId) {
+ if (StringUtils.isBlank(itemType) || itemId == null) {
+ return null;
+ }
+ try {
+ String specification = null;
+ if ("raw_material".equals(itemType)) {
+ WmsRawMaterial rm = rawMaterialMapper.selectById(itemId);
+ if (rm != null) {
+ specification = rm.getSpecification();
+ }
+ } else if ("product".equals(itemType)) {
+ WmsProduct p = productMapper.selectById(itemId);
+ if (p != null) {
+ specification = p.getSpecification();
+ }
+ }
+ if (StringUtils.isNotBlank(specification)) {
+ String[] parts = specification.split("\\*");
+ if (parts.length >= 2) {
+ return new BigDecimal(parts[0].trim());
+ }
+ }
+ } catch (Exception e) {
+ log.warn("获取规格厚度失败, itemType: {}, itemId: {}", itemType, itemId, e);
+ }
+ return null;
+ }
+
/**
* 获取库位及其所有子库位的ID列表
* 逻辑参考 WmsActualWarehouseServiceImpl.queryList 中的拆分处理逻辑:
@@ -1333,6 +1455,7 @@ public class WmsMaterialCoilServiceImpl implements IWmsMaterialCoilService {
bo.setActualWarehouseId(null);
}
// 3. 插入钢卷数据
+ calculateTheoreticalThickness(bo);
WmsMaterialCoil add = BeanUtil.toBean(bo, WmsMaterialCoil.class);
if(bo.getDataType() != null && bo.getDataType() == 10){
add.setDataType(10);
@@ -1548,6 +1671,7 @@ public class WmsMaterialCoilServiceImpl implements IWmsMaterialCoilService {
}
}
validateCoilWeight(bo.getGrossWeight(), bo.getNetWeight());
+ calculateTheoreticalThickness(bo);
// 直接更新钢卷属性
WmsMaterialCoil updateCoil = BeanUtil.toBean(bo, WmsMaterialCoil.class);
validEntityBeforeSave(updateCoil);
@@ -1641,6 +1765,7 @@ public class WmsMaterialCoilServiceImpl implements IWmsMaterialCoilService {
baseMapper.update(null, updateWrapper);
// 2. 创建新记录
+ calculateTheoreticalThickness(bo);
WmsMaterialCoil newCoil = BeanUtil.toBean(bo, WmsMaterialCoil.class);
newCoil.setCoilId(null); // 清空ID,让数据库自动生成新ID
newCoil.setDataType(1); // 设置为当前数据
@@ -1888,6 +2013,7 @@ public class WmsMaterialCoilServiceImpl implements IWmsMaterialCoilService {
? newCoilBo.getActualWarehouseId() : null;
validateActualWarehouseForAssign(newCoilBo.getActualWarehouseId(), ignoreOccupiedId);
}
+ calculateTheoreticalThickness(newCoilBo);
WmsMaterialCoil newCoil = BeanUtil.toBean(newCoilBo, WmsMaterialCoil.class);
newCoil.setCoilId(null);
newCoil.setDataType(1);
@@ -2016,6 +2142,7 @@ public class WmsMaterialCoilServiceImpl implements IWmsMaterialCoilService {
if (bo.getActualWarehouseId() != null) {
validateActualWarehouseForAssign(bo.getActualWarehouseId(), null);
}
+ calculateTheoreticalThickness(bo);
WmsMaterialCoil newCoil = BeanUtil.toBean(bo, WmsMaterialCoil.class);
newCoil.setCoilId(null);
newCoil.setDataType(1);
@@ -4855,7 +4982,25 @@ public class WmsMaterialCoilServiceImpl implements IWmsMaterialCoilService {
validateActualWarehouseForAssign(childCoilBo.getActualWarehouseId(), null);
}
+ // 校验子卷净重不超过母卷
+ if (childCoilBo.getNetWeight() != null && parentCoil.getNetWeight() != null) {
+ if (childCoilBo.getNetWeight().compareTo(parentCoil.getNetWeight()) > 0) {
+ throw new RuntimeException("子卷净重[" + childCoilBo.getNetWeight() + "]不能超过母卷净重[" + parentCoil.getNetWeight() + "]");
+ }
+ }
+ // 校验子卷规格厚度不超过母卷
+ String childItemType = StringUtils.isNotBlank(childCoilBo.getItemType()) ? childCoilBo.getItemType() : parentCoil.getItemType();
+ Long childItemId = childCoilBo.getItemId() != null ? childCoilBo.getItemId() : parentCoil.getItemId();
+ BigDecimal parentSpecThickness = getSpecThickness(parentCoil.getItemType(), parentCoil.getItemId());
+ BigDecimal childSpecThickness = getSpecThickness(childItemType, childItemId);
+ if (parentSpecThickness != null && childSpecThickness != null) {
+ if (childSpecThickness.compareTo(parentSpecThickness) > 0) {
+ throw new RuntimeException("子卷规格厚度[" + childSpecThickness + "]不能超过母卷规格厚度[" + parentSpecThickness + "]");
+ }
+ }
+
// 5. 创建子钢卷(参考普通分卷逻辑,但不设置母卷为历史数据)
+ calculateTheoreticalThickness(childCoilBo);
WmsMaterialCoil childCoil = BeanUtil.toBean(childCoilBo, WmsMaterialCoil.class);
childCoil.setCoilId(null);
childCoil.setDataType(1); // 当前数据
@@ -4971,6 +5116,17 @@ public class WmsMaterialCoilServiceImpl implements IWmsMaterialCoilService {
.map(WmsMaterialCoil::getCurrentCoilNo)
.collect(Collectors.toList());
+ // 校验所有子卷总重不超过母卷净重
+ if (parentCoil.getNetWeight() != null) {
+ BigDecimal totalChildWeight = childCoils.stream()
+ .map(WmsMaterialCoil::getNetWeight)
+ .filter(Objects::nonNull)
+ .reduce(BigDecimal.ZERO, BigDecimal::add);
+ if (totalChildWeight.compareTo(parentCoil.getNetWeight()) > 0) {
+ throw new RuntimeException("所有子卷总重[" + totalChildWeight + "]不能超过母卷净重[" + parentCoil.getNetWeight() + "]");
+ }
+ }
+
// 如果母卷即将成为历史卷 证明已经加工完成则释放库位
if (parentCoil.getActualWarehouseId() != null){
updateActualWarehouseEnableStatus(parentCoil.getActualWarehouseId(), null);
diff --git a/klp-wms/src/main/resources/mapper/klp/WmsMaterialCoilMapper.xml b/klp-wms/src/main/resources/mapper/klp/WmsMaterialCoilMapper.xml
index 865b54e3..4ab331ef 100644
--- a/klp-wms/src/main/resources/mapper/klp/WmsMaterialCoilMapper.xml
+++ b/klp-wms/src/main/resources/mapper/klp/WmsMaterialCoilMapper.xml
@@ -42,6 +42,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+
+
@@ -128,6 +130,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
mc.is_related_to_order,
mc.exclusive_status,
mc.transfer_type,
+ mc.theoretical_thickness,
+ mc.chrome_plate_coil_no,
mc.sale_name AS saleName,
w.warehouse_name AS warehouseName,
nw.warehouse_name AS nextWarehouseName,
@@ -225,6 +229,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
mc.is_related_to_order,
mc.exclusive_status,
mc.transfer_type,
+ mc.theoretical_thickness,
+ mc.chrome_plate_coil_no,
mc.sale_name AS saleName,
su.nick_name AS saleNickName,
w.warehouse_name AS warehouseName,
@@ -554,6 +560,10 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
mc.sale_name AS saleName,
-- 调拨类型
mc.transfer_type AS transferType,
+ -- 理论厚度
+ mc.theoretical_thickness AS theoreticalThickness,
+ -- 镀铬卷号
+ mc.chrome_plate_coil_no AS chromePlateCoilNo,
-- 库存状态(中文显示)
CASE
WHEN mc.status = 0 THEN '在库'
@@ -641,6 +651,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
mc.packing_status AS packingStatus,
mc.sale_name AS saleName,
mc.transfer_type AS transferType,
+ mc.theoretical_thickness AS theoreticalThickness,
+ mc.chrome_plate_coil_no AS chromePlateCoilNo,
CASE
WHEN mc.status = 0 THEN '在库'
WHEN mc.status = 1 THEN '已发货'
@@ -759,6 +771,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
mc.packing_status AS packingStatus,
mc.sale_name AS saleName,
mc.transfer_type AS transferType,
+ mc.theoretical_thickness AS theoreticalThickness,
+ mc.chrome_plate_coil_no AS chromePlateCoilNo,
CASE
WHEN mc.status = 0 THEN '在库'
WHEN mc.status = 1 THEN '已发货'