Files
klp-oa/klp-wms/src/main/java/com/klp/service/impl/WmsMaterialCoilServiceImpl.java
Joshi db691a68a7 feat(wms): 新增物料卷质量与包装相关字段变更记录
- 记录质量状态字段变更历史
- 记录切边要求字段变更历史
- 记录打包状态字段变更历史
- 记录包装要求字段变更历史
2025-11-14 10:31:55 +08:00

1263 lines
58 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package com.klp.service.impl;
import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.klp.common.core.page.TableDataInfo;
import com.klp.common.core.domain.PageQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.klp.common.helper.LoginHelper;
import com.klp.common.utils.StringUtils;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.klp.domain.bo.WmsMaterialCoilBo;
import com.klp.domain.bo.WmsGenerateRecordBo;
import com.klp.domain.vo.WmsMaterialCoilVo;
import com.klp.domain.vo.WmsGenerateRecordVo;
import com.klp.domain.vo.WmsWarehouseVo;
import com.klp.domain.vo.WmsRawMaterialVo;
import com.klp.domain.vo.WmsBomItemVo;
import com.klp.domain.bo.WmsBomItemBo;
import com.klp.domain.WmsMaterialCoil;
import com.klp.domain.bo.WmsStockBo;
import com.klp.domain.vo.WmsStockVo;
import com.klp.mapper.WmsMaterialCoilMapper;
import com.klp.mapper.WmsStockMapper;
import com.klp.service.IWmsMaterialCoilService;
import com.klp.service.IWmsStockService;
import com.klp.service.IWmsGenerateRecordService;
import com.klp.service.IWmsWarehouseService;
import com.klp.service.IWmsActualWarehouseService;
import com.klp.service.IWmsRawMaterialService;
import com.klp.service.IWmsBomItemService;
import com.klp.domain.vo.WmsActualWarehouseVo;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.util.List;
import java.util.Collection;
import java.util.ArrayList;
import java.util.Map;
import java.util.HashMap;
import java.util.stream.Collectors;
import java.util.HashSet;
import java.util.Set;
import java.math.BigDecimal;
/**
* 钢卷物料表Service业务层处理
*
* @author Joshi
* @date 2025-07-18
*/
@RequiredArgsConstructor
@Service
public class WmsMaterialCoilServiceImpl implements IWmsMaterialCoilService {
private final WmsMaterialCoilMapper baseMapper;
private final IWmsStockService stockService;
private final IWmsGenerateRecordService generateRecordService;
private final IWmsWarehouseService warehouseService;
private final IWmsActualWarehouseService actualWarehouseService;
private final IWmsRawMaterialService rawMaterialService;
private final IWmsBomItemService bomItemService;
/**
* 查询钢卷物料表
*/
@Override
public WmsMaterialCoilVo queryById(Long coilId) {
WmsMaterialCoilVo vo = baseMapper.selectVoById(coilId);
if (vo == null) {
return null;
}
// 查询关联对象
fillRelatedObjects(vo);
return vo;
}
/**
* 填充关联对象信息
*/
private void fillRelatedObjects(WmsMaterialCoilVo vo) {
// 查询所在库区信息
if (vo.getWarehouseId() != null) {
WmsWarehouseVo warehouse = warehouseService.queryById(vo.getWarehouseId());
vo.setWarehouse(warehouse);
}
// 查询下一库区信息
if (vo.getNextWarehouseId() != null) {
WmsWarehouseVo nextWarehouse = warehouseService.queryById(vo.getNextWarehouseId());
vo.setNextWarehouse(nextWarehouse);
}
// 查询实际库区信息
if (vo.getActualWarehouseId() != null) {
WmsActualWarehouseVo actualWarehouse = actualWarehouseService.queryById(vo.getActualWarehouseId());
if (actualWarehouse != null) {
vo.setActualWarehouseName(actualWarehouse.getActualWarehouseName());
}
}
// 查询二维码信息
if (vo.getQrcodeRecordId() != null) {
WmsGenerateRecordVo qrcodeRecord = generateRecordService.queryById(vo.getQrcodeRecordId());
vo.setQrcodeRecord(qrcodeRecord);
}
// 查询原材料信息当itemType为raw_material时
if ("raw_material".equals(vo.getItemType()) && vo.getItemId() != null) {
WmsRawMaterialVo rawMaterial = rawMaterialService.queryById(vo.getItemId());
vo.setRawMaterial(rawMaterial);
// 查询原材料对应的BOM信息通过bomId查询BomItem列表
if (rawMaterial != null && rawMaterial.getBomId() != null) {
WmsBomItemBo bomItemBo = new WmsBomItemBo();
bomItemBo.setBomId(rawMaterial.getBomId());
List<WmsBomItemVo> bomItemList = bomItemService.queryList(bomItemBo);
vo.setBomItemList(bomItemList);
}
}
// 查询产品信息当itemType为product时
if ("product".equals(vo.getItemType()) && vo.getItemId() != null) {
// 产品和原材料的查询逻辑相同都通过itemId查询
WmsRawMaterialVo rawMaterial = rawMaterialService.queryById(vo.getItemId());
// 查询原材料对应的BOM信息通过bomId查询BomItem列表
if (rawMaterial != null && rawMaterial.getBomId() != null) {
WmsBomItemBo bomItemBo = new WmsBomItemBo();
bomItemBo.setBomId(rawMaterial.getBomId());
List<WmsBomItemVo> bomItemList = bomItemService.queryList(bomItemBo);
vo.setBomItemList(bomItemList);
}
}
}
/**
* 查询钢卷物料表列表
*/
@Override
public TableDataInfo<WmsMaterialCoilVo> queryPageList(WmsMaterialCoilBo bo, PageQuery pageQuery) {
QueryWrapper<WmsMaterialCoil> qw = buildQueryWrapperPlus(bo);
Page<WmsMaterialCoilVo> result = baseMapper.selectVoPagePlus(pageQuery.build(), qw);
return TableDataInfo.build(result);
}
private QueryWrapper<WmsMaterialCoil> buildQueryWrapperPlus(WmsMaterialCoilBo bo) {
QueryWrapper<WmsMaterialCoil> qw = Wrappers.query();
qw.like(StringUtils.isNotBlank(bo.getEnterCoilNo()), "mc.enter_coil_no", bo.getEnterCoilNo());
qw.like(StringUtils.isNotBlank(bo.getCurrentCoilNo()), "mc.current_coil_no", bo.getCurrentCoilNo());
qw.like(StringUtils.isNotBlank(bo.getSupplierCoilNo()), "mc.supplier_coil_no", bo.getSupplierCoilNo());
qw.eq(bo.getDataType() != null, "mc.data_type", bo.getDataType());
qw.eq(bo.getMaterialType() != null, "mc.material_type", bo.getMaterialType());
qw.eq(bo.getWarehouseId() != null, "mc.warehouse_id", bo.getWarehouseId());
qw.eq(bo.getHasMergeSplit() != null, "mc.has_merge_split", bo.getHasMergeSplit());
qw.eq(bo.getStatus() != null, "mc.status", bo.getStatus());
qw.eq(bo.getActualWarehouseId() != null, "mc.actual_warehouse_id", bo.getActualWarehouseId());
qw.eq(StringUtils.isNotBlank(bo.getItemType()), "mc.item_type", bo.getItemType());
// 修改itemId筛选逻辑支持逗号分隔的多个ID查询
if (StringUtils.isNotBlank(bo.getItemIds())) {
String[] itemIdArray = bo.getItemIds().split(",");
List<Long> itemIdList = new ArrayList<>();
for (String itemIdStr : itemIdArray) {
if (StringUtils.isNotBlank(itemIdStr)) {
try {
itemIdList.add(Long.parseLong(itemIdStr.trim()));
} catch (NumberFormatException e) {
// 忽略无效的ID格式
}
}
}
if (!itemIdList.isEmpty()) {
qw.in("mc.item_id", itemIdList);
}
} else if (bo.getItemId() != null) {
// 兼容原来的itemId单值查询
qw.eq("mc.item_id", bo.getItemId());
}
//逻辑删除
qw.eq("mc.del_flag", 0);
//把team字段作为筛选条件
qw.eq(StringUtils.isNotBlank(bo.getTeam()), "mc.team", bo.getTeam());
//根据开始时间和结束时间筛选修改时间
qw.ge(bo.getStartTime() != null, "mc.update_time", bo.getStartTime());
qw.le(bo.getEndTime() != null, "mc.update_time", bo.getEndTime());
return qw;
}
/**
* 查询钢卷物料表列表
*/
@Override
public List<WmsMaterialCoilVo> queryList(WmsMaterialCoilBo bo) {
QueryWrapper<WmsMaterialCoil> lqw = buildQueryWrapperPlus(bo);
return baseMapper.selectVoListWithDynamicJoin(lqw);
}
/**
* 新增钢卷物料表
*/
@Override
@Transactional(rollbackFor = Exception.class)
public Boolean insertByBo(WmsMaterialCoilBo bo) {
// 1. 生成二维码
Long qrcodeRecordId = generateQrcodeForInsert(bo);
bo.setQrcodeRecordId(qrcodeRecordId);
// 2. 查找或创建stock
findOrCreateStock(bo);
// 3. 插入钢卷数据
WmsMaterialCoil add = BeanUtil.toBean(bo, WmsMaterialCoil.class);
add.setDataType(1); // 新增的钢卷默认为当前数据
validEntityBeforeSave(add);
boolean flag = baseMapper.insert(add) > 0;
if (flag) {
bo.setCoilId(add.getCoilId());
// 4. 更新二维码内容中的coilId
updateQrcodeCoilId(qrcodeRecordId, add.getCoilId());
}
return flag;
}
/**
* 生成二维码(新增)
*/
private Long generateQrcodeForInsert(WmsMaterialCoilBo bo) {
try {
Map<String, Object> contentMap = new HashMap<>();
String currentCoilNo = bo.getCurrentCoilNo() != null ? bo.getCurrentCoilNo() : bo.getEnterCoilNo();
contentMap.put("enter_coil_no", bo.getEnterCoilNo()); // 入场钢卷号(唯一不变)
contentMap.put("current_coil_no", currentCoilNo); // 当前钢卷号(可变)
contentMap.put("coil_id", "null"); // 初始钢卷ID新增时暂时为null插入后更新
contentMap.put("current_coil_id", "null"); // 当前有效的钢卷ID新增时暂时为null插入后更新
// 创建steps数组
List<Map<String, Object>> steps = new ArrayList<>();
Map<String, Object> step1 = new HashMap<>();
step1.put("step", 1);
step1.put("action", "新增");
step1.put("current_coil_no", currentCoilNo);
// 判断是合卷还是分卷
if (bo.getHasMergeSplit() != null && bo.getHasMergeSplit() == 2) {
// 合卷:父编号字符串用逗号分隔
step1.put("operation", "合卷");
step1.put("parent_coil_nos", bo.getParentCoilNos());
} else if (bo.getHasMergeSplit() != null && bo.getHasMergeSplit() == 1) {
// 分卷:多个当前钢卷号用逗号分隔
step1.put("operation", "分卷");
step1.put("current_coil_nos", currentCoilNo);
} else {
// 默认:当前钢卷号
step1.put("operation", "新增");
}
steps.add(step1);
contentMap.put("steps", steps);
ObjectMapper objectMapper = new ObjectMapper();
String contentJson = objectMapper.writeValueAsString(contentMap);
WmsGenerateRecordBo recordBo = new WmsGenerateRecordBo();
recordBo.setContent(contentJson);
recordBo.setSerialNumber(bo.getEnterCoilNo()); // 使用入场钢卷号作为编号
recordBo.setQrcodeType(0L);
recordBo.setIsEnabled(0L);
recordBo.setSize(200L);
recordBo.setStatus(1); // 1=当前有效码
WmsGenerateRecordVo record = generateRecordService.insertByBo(recordBo);
return record.getRecordId();
} catch (Exception e) {
throw new RuntimeException("生成二维码失败: " + e.getMessage());
}
}
/**
* 查找或创建stock
*/
private void findOrCreateStock(WmsMaterialCoilBo bo) {
if (bo.getItemType() == null || bo.getItemId() == null) {
throw new RuntimeException("物品类型和物品ID不能为空");
}
// 查询是否存在相同的stock匹配itemType和itemId
WmsStockBo stockBo = new WmsStockBo();
stockBo.setItemType(bo.getItemType());
stockBo.setItemId(bo.getItemId());
List<WmsStockVo> stockList = stockService.queryList(stockBo);
if (stockList.isEmpty()) {
// 如果没有找到匹配的stock新增一条stock记录
WmsStockBo newStockBo = new WmsStockBo();
newStockBo.setItemType(bo.getItemType());
newStockBo.setItemId(bo.getItemId());
// 调用stockService新增stock
Boolean insertResult = stockService.insertByBo(newStockBo);
if (!insertResult) {
throw new RuntimeException("新增库存记录失败");
}
}
// 如果已存在stock记录则不需要重复创建
}
/**
* 修改钢卷物料表
* 如果newCoils不为空则进行批量更新分卷/合卷)
* 如果newCoils为空则进行单个更新
*/
@Override
@Transactional(rollbackFor = Exception.class)
public Boolean updateByBo(WmsMaterialCoilBo bo) {
// 判断是否批量更新
if (bo.getNewCoils() != null && !bo.getNewCoils().isEmpty()) {
// 批量更新逻辑(分卷/合卷)
return updateByBatch(bo);
} else {
// 单个更新逻辑需要coilId
if (bo.getCoilId() == null) {
throw new RuntimeException("钢卷ID不能为空");
}
return updateBySingle(bo);
}
}
/**
* 简单更新钢卷物料表
* 直接更新属性内容,不进行历史记录处理
*/
@Override
@Transactional(rollbackFor = Exception.class)
public Boolean updateSimple(WmsMaterialCoilBo bo) {
if (bo.getCoilId() == null) {
throw new RuntimeException("钢卷ID不能为空");
}
// 查询原钢卷是否存在
WmsMaterialCoil oldCoil = baseMapper.selectById(bo.getCoilId());
if (oldCoil == null) {
throw new RuntimeException("钢卷不存在");
}
// 直接更新钢卷属性
WmsMaterialCoil updateCoil = BeanUtil.toBean(bo, WmsMaterialCoil.class);
validEntityBeforeSave(updateCoil);
// 使用MyBatis-Plus的updateById方法直接更新
boolean flag = baseMapper.updateById(updateCoil) > 0;
return flag;
}
/**
* 单个更新
*/
private Boolean updateBySingle(WmsMaterialCoilBo bo) {
// 查询原钢卷
WmsMaterialCoil oldCoil = baseMapper.selectById(bo.getCoilId());
if (oldCoil == null) {
throw new RuntimeException("原钢卷不存在");
}
// 1. 将原钢卷标记为历史数据dataType = 0
LambdaUpdateWrapper<WmsMaterialCoil> updateWrapper = new LambdaUpdateWrapper<>();
updateWrapper.eq(WmsMaterialCoil::getCoilId, oldCoil.getCoilId())
.set(WmsMaterialCoil::getDataType, 0); // 设置为历史数据
baseMapper.update(null, updateWrapper);
// 2. 创建新记录
WmsMaterialCoil newCoil = BeanUtil.toBean(bo, WmsMaterialCoil.class);
newCoil.setCoilId(null); // 清空ID让数据库自动生成新ID
newCoil.setDataType(1); // 设置为当前数据
newCoil.setQrcodeRecordId(oldCoil.getQrcodeRecordId()); // 继续使用原二维码
// 继承原记录的关键字段
if (newCoil.getEnterCoilNo() == null) {
newCoil.setEnterCoilNo(oldCoil.getEnterCoilNo());
}
if (newCoil.getSupplierCoilNo() == null) {
newCoil.setSupplierCoilNo(oldCoil.getSupplierCoilNo());
}
validEntityBeforeSave(newCoil);
// 插入新记录
boolean flag = baseMapper.insert(newCoil) > 0;
if (flag) {
// 3. 更新二维码内容添加更新步骤并更新current_coil_id
if (oldCoil.getQrcodeRecordId() != null) {
updateQrcodeContentForNormalUpdate(oldCoil, bo, newCoil.getCoilId());
}
}
return flag;
}
/**
* 生成二维码(更新时库区变化)
*/
private Long generateQrcodeForUpdate(WmsMaterialCoil oldCoil, WmsMaterialCoilBo bo) {
try {
// 1. 将原二维码标记为历史码status = 0
if (oldCoil.getQrcodeRecordId() != null) {
WmsGenerateRecordBo oldQrBo = new WmsGenerateRecordBo();
oldQrBo.setRecordId(oldCoil.getQrcodeRecordId());
oldQrBo.setStatus(0); // 0=历史码
generateRecordService.updateByBo(oldQrBo);
}
Map<String, Object> contentMap = new HashMap<>();
String currentCoilNo = bo.getCurrentCoilNo() != null ? bo.getCurrentCoilNo() : oldCoil.getCurrentCoilNo();
contentMap.put("enter_coil_no", oldCoil.getEnterCoilNo()); // 入场钢卷号(始终不变)
contentMap.put("current_coil_no", currentCoilNo); // 当前钢卷号
contentMap.put("coil_id", String.valueOf(oldCoil.getCoilId())); // 初始钢卷ID记录最初的ID
contentMap.put("current_coil_id", "null"); // 当前钢卷ID更新时暂时为null插入后更新
// 复制原钢卷的历史steps
List<Map<String, Object>> steps = new ArrayList<>();
if (oldCoil.getQrcodeRecordId() != null) {
WmsGenerateRecordVo oldRecord = generateRecordService.queryById(oldCoil.getQrcodeRecordId());
if (oldRecord != null) {
ObjectMapper objectMapper = new ObjectMapper();
@SuppressWarnings("unchecked")
Map<String, Object> oldContentMap = objectMapper.readValue(oldRecord.getContent(), Map.class);
@SuppressWarnings("unchecked")
List<Map<String, Object>> oldSteps = (List<Map<String, Object>>) oldContentMap.get("steps");
if (oldSteps != null) {
steps.addAll(oldSteps);
}
}
}
// 添加更新步骤(库区变化)
Map<String, Object> updateStep = new HashMap<>();
updateStep.put("step", steps.size() + 1);
updateStep.put("action", "更新");
updateStep.put("operation", "库区变更");
updateStep.put("old_warehouse_id", String.valueOf(oldCoil.getWarehouseId()));
updateStep.put("new_warehouse_id", String.valueOf(bo.getWarehouseId()));
//放入真实库区
updateStep.put("old_actual_warehouse_id", String.valueOf(oldCoil.getActualWarehouseId()));
updateStep.put("new_actual_warehouse_id", String.valueOf(bo.getActualWarehouseId()));
updateStep.put("old_coil_id", String.valueOf(oldCoil.getCoilId()));
updateStep.put("current_coil_no", currentCoilNo);
updateStep.put("operator", LoginHelper.getUsername()); // 操作者
steps.add(updateStep);
contentMap.put("steps", steps);
ObjectMapper objectMapper = new ObjectMapper();
String contentJson = objectMapper.writeValueAsString(contentMap);
// 2. 生成新的二维码status = 1
WmsGenerateRecordBo recordBo = new WmsGenerateRecordBo();
recordBo.setContent(contentJson);
recordBo.setSerialNumber(oldCoil.getEnterCoilNo() + "-W" + bo.getWarehouseId()); // 使用入场钢卷号+库区ID作为编号
recordBo.setQrcodeType(0L);
recordBo.setIsEnabled(0L);
recordBo.setSize(200L);
recordBo.setStatus(1); // 1=当前有效码
WmsGenerateRecordVo record = generateRecordService.insertByBo(recordBo);
return record.getRecordId();
} catch (Exception e) {
throw new RuntimeException("生成更新二维码失败: " + e.getMessage());
}
}
/**
* 批量更新(分卷/合卷)
*/
private Boolean updateByBatch(WmsMaterialCoilBo bo) {
// 查询原钢卷(分卷时需要,合卷时可能不需要)
WmsMaterialCoil oldCoil = null;
if (bo.getCoilId() != null) {
oldCoil = baseMapper.selectById(bo.getCoilId());
if (oldCoil == null) {
throw new RuntimeException("原钢卷不存在");
}
}
// 判断是分卷还是合卷
boolean isSplit = false;
boolean isMerge = false;
// 检查bo本身是否为合卷
if (bo.getHasMergeSplit() != null && bo.getHasMergeSplit() == 2) {
isMerge = true;
} else if (bo.getNewCoils() != null && !bo.getNewCoils().isEmpty()) {
// 检查newCoils中是否有分卷
for (WmsMaterialCoilBo newCoilBo : bo.getNewCoils()) {
if (newCoilBo.getHasMergeSplit() != null && newCoilBo.getHasMergeSplit() == 1) {
isSplit = true;
break;
}
}
}
// 1. 将原数据更新为历史数据data_type=0
// 注意合卷时bo的coilId可能为空因为bo是合卷后的新钢卷
if (bo.getCoilId() != null) {
LambdaUpdateWrapper<WmsMaterialCoil> updateWrapper = new LambdaUpdateWrapper<>();
updateWrapper.eq(WmsMaterialCoil::getCoilId, bo.getCoilId())
.set(WmsMaterialCoil::getDataType, 0); // 设置为历史数据
baseMapper.update(null, updateWrapper);
}
// 2. 插入多条新的当前数据data_type=1
List<WmsMaterialCoil> newCoils = new ArrayList<>();
List<String> allNewCoilNos = new ArrayList<>();
// 收集所有新钢卷号
for (WmsMaterialCoilBo newCoilBo : bo.getNewCoils()) {
allNewCoilNos.add(newCoilBo.getCurrentCoilNo());
}
if (isSplit) {
// 分卷将bo作为被分卷的原始对象newCoils中的对象作为分卷后产生的新钢卷
if (oldCoil == null) {
throw new RuntimeException("分卷操作需要原钢卷信息");
}
// 1. 将原始钢卷的二维码标记为失效status=0
if (oldCoil.getQrcodeRecordId() != null) {
WmsGenerateRecordBo oldQrBo = new WmsGenerateRecordBo();
oldQrBo.setRecordId(oldCoil.getQrcodeRecordId());
oldQrBo.setStatus(0); // 0=失效
generateRecordService.updateByBo(oldQrBo);
}
// 2. 将原始钢卷标记为历史数据,并记录所有子卷号
// 在母卷的 parent_coil_nos 字段中记录所有子卷号(用逗号分隔)
String childCoilNos = String.join(",", allNewCoilNos);
LambdaUpdateWrapper<WmsMaterialCoil> motherUpdateWrapper = new LambdaUpdateWrapper<>();
motherUpdateWrapper.eq(WmsMaterialCoil::getCoilId, oldCoil.getCoilId())
.set(WmsMaterialCoil::getParentCoilNos, childCoilNos); // 记录子卷号
baseMapper.update(null, motherUpdateWrapper);
// 3. 为每个分卷后的子钢卷生成独立的二维码并插入数据库
for (WmsMaterialCoilBo newCoilBo : bo.getNewCoils()) {
WmsMaterialCoil newCoil = BeanUtil.toBean(newCoilBo, WmsMaterialCoil.class);
newCoil.setCoilId(null);
newCoil.setDataType(1);
// 继承原钢卷的基本信息(强制继承,不能修改的字段)
newCoil.setEnterCoilNo(oldCoil.getEnterCoilNo());
newCoil.setSupplierCoilNo(oldCoil.getSupplierCoilNo()); // 保留厂家原料卷号
// materialType, itemType 和 itemId 使用前端传递的值,不强制继承
if (newCoil.getItemType() == null) {
newCoil.setItemType(oldCoil.getItemType());
}
if (newCoil.getItemId() == null) {
newCoil.setItemId(oldCoil.getItemId());
}
// 如果前端没传team使用原钢卷的team
if (newCoil.getTeam() == null) {
newCoil.setTeam(oldCoil.getTeam());
}
// 如果没有指定库区,使用原库区
if (newCoil.getWarehouseId() == null) {
newCoil.setWarehouseId(oldCoil.getWarehouseId());
}
if (newCoil.getActualWarehouseId() == null){
newCoil.setActualWarehouseId(oldCoil.getActualWarehouseId());
}
// 在子卷的 parent_coil_nos 字段中记录母卷号
newCoil.setParentCoilNos(oldCoil.getCurrentCoilNo());
// 为每个子钢卷生成独立二维码
Long newQrcodeId = generateQrcodeForSplit(oldCoil, newCoilBo, allNewCoilNos);
newCoil.setQrcodeRecordId(newQrcodeId);
validEntityBeforeSave(newCoil);
baseMapper.insert(newCoil);
newCoils.add(newCoil);
// 更新二维码内容中的coilId
updateQrcodeCoilId(newQrcodeId, newCoil.getCoilId());
}
} else if (isMerge) {
// 合卷将bo作为合卷后的新钢卷newCoils中的对象作为参与合卷的原始钢卷
// 1. 将参与合卷的原始钢卷的二维码标记为失效,并将钢卷标记为历史数据
for (WmsMaterialCoilBo originalCoilBo : bo.getNewCoils()) {
if (originalCoilBo.getCoilId() != null) {
WmsMaterialCoil originalCoil = baseMapper.selectById(originalCoilBo.getCoilId());
if (originalCoil != null) {
// 标记二维码为失效
if (originalCoil.getQrcodeRecordId() != null) {
WmsGenerateRecordBo oldQrBo = new WmsGenerateRecordBo();
oldQrBo.setRecordId(originalCoil.getQrcodeRecordId());
oldQrBo.setStatus(0); // 0=失效
generateRecordService.updateByBo(oldQrBo);
}
// 标记钢卷为历史数据
LambdaUpdateWrapper<WmsMaterialCoil> originalUpdateWrapper = new LambdaUpdateWrapper<>();
originalUpdateWrapper.eq(WmsMaterialCoil::getCoilId, originalCoilBo.getCoilId())
.set(WmsMaterialCoil::getDataType, 0); // 设置为历史数据
baseMapper.update(null, originalUpdateWrapper);
}
}
}
// 2. 生成合卷后的新钢卷二维码
Long mergedQrcodeId = generateQrcodeForMerge(bo, bo.getNewCoils());
// 3. 插入合卷后的新钢卷
WmsMaterialCoil newCoil = BeanUtil.toBean(bo, WmsMaterialCoil.class);
newCoil.setCoilId(null);
newCoil.setDataType(1);
// 从第一个参与合卷的原始钢卷获取基本信息
if (!bo.getNewCoils().isEmpty()) {
WmsMaterialCoil firstOriginalCoil = baseMapper.selectById(bo.getNewCoils().get(0).getCoilId());
if (firstOriginalCoil != null) {
// 继承基本信息
if (newCoil.getEnterCoilNo() == null) {
newCoil.setEnterCoilNo(firstOriginalCoil.getEnterCoilNo());
}
if (newCoil.getSupplierCoilNo() == null) {
newCoil.setSupplierCoilNo(firstOriginalCoil.getSupplierCoilNo()); // 保留厂家原料卷号
}
if (newCoil.getItemType() == null) {
newCoil.setItemType(firstOriginalCoil.getItemType());
}
if (newCoil.getItemId() == null) {
newCoil.setItemId(firstOriginalCoil.getItemId());
}
if (newCoil.getTeam() == null) {
newCoil.setTeam(firstOriginalCoil.getTeam());
}
}
}
newCoil.setQrcodeRecordId(mergedQrcodeId);
validEntityBeforeSave(newCoil);
baseMapper.insert(newCoil);
newCoils.add(newCoil);
// 更新二维码内容中的coilId
updateQrcodeCoilId(mergedQrcodeId, newCoil.getCoilId());
}
return true;
}
/**
* 为分卷生成新二维码(每个子钢卷一个)
*/
private Long generateQrcodeForSplit(WmsMaterialCoil oldCoil, WmsMaterialCoilBo newCoilBo, List<String> allNewCoilNos) {
try {
Map<String, Object> contentMap = new HashMap<>();
contentMap.put("enter_coil_no", oldCoil.getEnterCoilNo());
contentMap.put("current_coil_no", newCoilBo.getCurrentCoilNo());
contentMap.put("coil_id", String.valueOf(oldCoil.getCoilId())); // 初始钢卷ID记录原钢卷的ID
contentMap.put("current_coil_id", "null"); // 当前钢卷ID分卷时暂时为null插入后更新
// 复制原钢卷的历史steps
List<Map<String, Object>> steps = new ArrayList<>();
if (oldCoil.getQrcodeRecordId() != null) {
WmsGenerateRecordVo oldRecord = generateRecordService.queryById(oldCoil.getQrcodeRecordId());
if (oldRecord != null) {
ObjectMapper objectMapper = new ObjectMapper();
@SuppressWarnings("unchecked")
Map<String, Object> oldContentMap = objectMapper.readValue(oldRecord.getContent(), Map.class);
@SuppressWarnings("unchecked")
List<Map<String, Object>> oldSteps = (List<Map<String, Object>>) oldContentMap.get("steps");
if (oldSteps != null) {
steps.addAll(oldSteps);
}
}
}
// 添加分卷步骤
Map<String, Object> splitStep = new HashMap<>();
splitStep.put("step", steps.size() + 1);
splitStep.put("action", "更新");
splitStep.put("operation", "分卷");
splitStep.put("old_current_coil_no", oldCoil.getCurrentCoilNo());
splitStep.put("old_coil_id", String.valueOf(oldCoil.getCoilId()));
splitStep.put("new_current_coil_nos", String.join(",", allNewCoilNos));
splitStep.put("child_coils", allNewCoilNos);
splitStep.put("operator", LoginHelper.getUsername()); // 操作者
steps.add(splitStep);
contentMap.put("steps", steps);
ObjectMapper objectMapper = new ObjectMapper();
String contentJson = objectMapper.writeValueAsString(contentMap);
WmsGenerateRecordBo recordBo = new WmsGenerateRecordBo();
recordBo.setContent(contentJson);
recordBo.setSerialNumber(oldCoil.getEnterCoilNo() + "-" + newCoilBo.getCurrentCoilNo());
recordBo.setQrcodeType(0L);
recordBo.setIsEnabled(0L);
recordBo.setSize(200L);
recordBo.setStatus(1); // 1=当前有效码
WmsGenerateRecordVo record = generateRecordService.insertByBo(recordBo);
return record.getRecordId();
} catch (Exception e) {
throw new RuntimeException("生成分卷二维码失败: " + e.getMessage());
}
}
/**
* 为合卷生成新二维码(合并多个父钢卷的二维码信息)
*/
private Long generateQrcodeForMerge(WmsMaterialCoilBo mergedCoilBo, List<WmsMaterialCoilBo> originalCoils) {
try {
if (mergedCoilBo == null) {
throw new RuntimeException("合卷后的钢卷数据不能为空");
}
Map<String, Object> contentMap = new HashMap<>();
// 获取enterCoilNo优先使用mergedCoilBo的如果没有则从原始钢卷中获取
String enterCoilNo = mergedCoilBo.getEnterCoilNo();
if (enterCoilNo == null && originalCoils != null && !originalCoils.isEmpty()) {
WmsMaterialCoil firstOriginalCoil = baseMapper.selectById(originalCoils.get(0).getCoilId());
if (firstOriginalCoil != null) {
enterCoilNo = firstOriginalCoil.getEnterCoilNo();
}
}
contentMap.put("enter_coil_no", enterCoilNo);
contentMap.put("current_coil_no", mergedCoilBo.getCurrentCoilNo());
contentMap.put("coil_id", "null"); // 初始钢卷ID合卷时为null
contentMap.put("current_coil_id", "null"); // 当前钢卷ID合卷时暂时为null插入后更新
// 合并所有参与合卷的原始钢卷的历史steps
List<Map<String, Object>> steps = new ArrayList<>();
// 从参与合卷的原始钢卷中获取二维码信息并合并
if (originalCoils != null && !originalCoils.isEmpty()) {
for (WmsMaterialCoilBo originalCoilBo : originalCoils) {
if (originalCoilBo.getCoilId() != null) {
// 查询原始钢卷的二维码信息
WmsMaterialCoil originalCoil = baseMapper.selectById(originalCoilBo.getCoilId());
if (originalCoil != null && originalCoil.getQrcodeRecordId() != null) {
WmsGenerateRecordVo originalQr = generateRecordService.queryById(originalCoil.getQrcodeRecordId());
if (originalQr != null) {
ObjectMapper objectMapper = new ObjectMapper();
@SuppressWarnings("unchecked")
Map<String, Object> originalContentMap = objectMapper.readValue(originalQr.getContent(), Map.class);
@SuppressWarnings("unchecked")
List<Map<String, Object>> originalSteps = (List<Map<String, Object>>) originalContentMap.get("steps");
if (originalSteps != null) {
steps.addAll(originalSteps);
}
}
}
}
}
}
// 添加合卷步骤
Map<String, Object> mergeStep = new HashMap<>();
mergeStep.put("step", steps.size() + 1);
mergeStep.put("action", "更新");
mergeStep.put("operation", "合卷");
// 收集参与合卷的原始钢卷号和ID
List<String> originalCoilNos = new ArrayList<>();
List<String> originalCoilIds = new ArrayList<>();
if (originalCoils != null && !originalCoils.isEmpty()) {
for (WmsMaterialCoilBo originalCoilBo : originalCoils) {
if (originalCoilBo.getCurrentCoilNo() != null) {
originalCoilNos.add(originalCoilBo.getCurrentCoilNo());
}
if (originalCoilBo.getCoilId() != null) {
originalCoilIds.add(originalCoilBo.getCoilId().toString());
}
}
}
mergeStep.put("parent_coil_nos", String.join(",", originalCoilNos));
mergeStep.put("parent_coil_ids", String.join(",", originalCoilIds));
mergeStep.put("new_current_coil_no", mergedCoilBo.getCurrentCoilNo());
mergeStep.put("operator", LoginHelper.getUsername()); // 操作者
steps.add(mergeStep);
contentMap.put("steps", steps);
// 将父钢卷ID也存储到顶层方便快速查询
contentMap.put("parent_coil_ids", String.join(",", originalCoilIds));
ObjectMapper objectMapper = new ObjectMapper();
String contentJson = objectMapper.writeValueAsString(contentMap);
WmsGenerateRecordBo recordBo = new WmsGenerateRecordBo();
recordBo.setContent(contentJson);
recordBo.setSerialNumber(enterCoilNo + "-" + mergedCoilBo.getCurrentCoilNo());
recordBo.setQrcodeType(0L);
recordBo.setIsEnabled(0L);
recordBo.setSize(200L);
recordBo.setStatus(1); // 1=当前有效码
WmsGenerateRecordVo record = generateRecordService.insertByBo(recordBo);
return record.getRecordId();
} catch (Exception e) {
throw new RuntimeException("生成合卷二维码失败: " + e.getMessage());
}
}
/**
* 更新二维码内容中的coilId
*/
private void updateQrcodeCoilId(Long qrcodeRecordId, Long coilId) {
try {
// 获取二维码记录
WmsGenerateRecordVo record = generateRecordService.queryById(qrcodeRecordId);
if (record == null) {
throw new RuntimeException("二维码记录不存在");
}
// 解析现有content
ObjectMapper objectMapper = new ObjectMapper();
Map<String, Object> contentMap = objectMapper.readValue(record.getContent(), Map.class);
// 如果是第一次设置coilId从"null"变为实际ID则同时设置coil_id和current_coil_id
if ("null".equals(contentMap.get("coil_id"))) {
contentMap.put("coil_id", String.valueOf(coilId)); // 初始ID不再改变
}
// 始终更新current_coil_id为最新的钢卷ID
contentMap.put("current_coil_id", String.valueOf(coilId));
// 更新二维码记录
String newContentJson = objectMapper.writeValueAsString(contentMap);
WmsGenerateRecordBo updateBo = new WmsGenerateRecordBo();
updateBo.setRecordId(qrcodeRecordId);
updateBo.setContent(newContentJson);
generateRecordService.updateByBo(updateBo);
} catch (Exception e) {
throw new RuntimeException("更新二维码coilId失败: " + e.getMessage());
}
}
/**
* 更新二维码内容正常更新添加step
* @param oldCoil 旧钢卷记录
* @param bo 更新数据
* @param newCoilId 新钢卷ID如果创建了新记录
*/
private void updateQrcodeContentForNormalUpdate(WmsMaterialCoil oldCoil, WmsMaterialCoilBo bo, Long newCoilId) {
try {
// 获取原二维码记录
WmsGenerateRecordVo oldRecord = generateRecordService.queryById(oldCoil.getQrcodeRecordId());
if (oldRecord == null) {
throw new RuntimeException("二维码记录不存在");
}
// 解析现有content
ObjectMapper objectMapper = new ObjectMapper();
@SuppressWarnings("unchecked")
Map<String, Object> contentMap = objectMapper.readValue(oldRecord.getContent(), Map.class);
// 获取现有steps
@SuppressWarnings("unchecked")
List<Map<String, Object>> steps = (List<Map<String, Object>>) contentMap.get("steps");
if (steps == null) {
steps = new ArrayList<>();
}
// 添加新的step记录更新信息
Map<String, Object> newStep = new HashMap<>();
newStep.put("step", steps.size() + 1);
newStep.put("action", "更新");
newStep.put("operation", "信息更新");
newStep.put("old_current_coil_no", oldCoil.getCurrentCoilNo());
newStep.put("new_current_coil_no", bo.getCurrentCoilNo());
newStep.put("old_coil_id", String.valueOf(oldCoil.getCoilId()));
newStep.put("new_coil_id", String.valueOf(newCoilId));
newStep.put("operator", LoginHelper.getUsername());
// 记录具体的变更字段
List<String> changedFields = new ArrayList<>();
if (bo.getCurrentCoilNo() != null && !bo.getCurrentCoilNo().equals(oldCoil.getCurrentCoilNo())) {
changedFields.add("钢卷号: " + oldCoil.getCurrentCoilNo() + "" + bo.getCurrentCoilNo());
}
if (bo.getTeam() != null && !bo.getTeam().equals(oldCoil.getTeam())) {
changedFields.add("班组: " + oldCoil.getTeam() + "" + bo.getTeam());
}
if (bo.getWarehouseId() != null && !bo.getWarehouseId().equals(oldCoil.getWarehouseId())) {
changedFields.add("逻辑库区ID: " + oldCoil.getWarehouseId() + "" + bo.getWarehouseId());
}
if (bo.getActualWarehouseId() != null && !bo.getActualWarehouseId().equals(oldCoil.getActualWarehouseId())) {
changedFields.add("真实库区ID: " + oldCoil.getActualWarehouseId() + "" + bo.getActualWarehouseId());
}
if (bo.getGrossWeight() != null && !bo.getGrossWeight().equals(oldCoil.getGrossWeight())) {
changedFields.add("毛重: " + oldCoil.getGrossWeight() + "" + bo.getGrossWeight());
}
if (bo.getNetWeight() != null && !bo.getNetWeight().equals(oldCoil.getNetWeight())) {
changedFields.add("净重: " + oldCoil.getNetWeight() + "" + bo.getNetWeight());
}
if (bo.getRemark() != null && !bo.getRemark().equals(oldCoil.getRemark())) {
changedFields.add("备注: " + oldCoil.getRemark() + "" + bo.getRemark());
}
if (bo.getQualityStatus() != null && !bo.getQualityStatus().equals(oldCoil.getQualityStatus())) {
changedFields.add("质量状态: " + oldCoil.getQualityStatus() + "" + bo.getQualityStatus());
}
if (bo.getTrimmingRequirement() != null && !bo.getTrimmingRequirement().equals(oldCoil.getTrimmingRequirement())) {
changedFields.add("切边要求: " + oldCoil.getTrimmingRequirement() + "" + bo.getTrimmingRequirement());
}
if (bo.getPackingStatus() != null && !bo.getPackingStatus().equals(oldCoil.getPackingStatus())) {
changedFields.add("打包状态: " + oldCoil.getPackingStatus() + "" + bo.getPackingStatus());
}
if (bo.getPackagingRequirement() != null && !bo.getPackagingRequirement().equals(oldCoil.getPackagingRequirement())) {
changedFields.add("包装要求: " + oldCoil.getPackagingRequirement() + "" + bo.getPackagingRequirement());
}
newStep.put("changed_fields", String.join("; ", changedFields));
newStep.put("update_time", new java.util.Date());
steps.add(newStep);
contentMap.put("steps", steps);
// 更新当前钢卷号
if (bo.getCurrentCoilNo() != null) {
contentMap.put("current_coil_no", bo.getCurrentCoilNo());
}
// 更新 current_coil_id 为新记录的ID
if (newCoilId != null) {
contentMap.put("current_coil_id", String.valueOf(newCoilId));
}
// 更新二维码记录
String newContentJson = objectMapper.writeValueAsString(contentMap);
WmsGenerateRecordBo updateBo = new WmsGenerateRecordBo();
updateBo.setRecordId(oldCoil.getQrcodeRecordId());
updateBo.setContent(newContentJson);
generateRecordService.updateByBo(updateBo);
} catch (Exception e) {
throw new RuntimeException("更新二维码失败: " + e.getMessage());
}
}
/**
* 保存前的数据校验
*/
private void validEntityBeforeSave(WmsMaterialCoil entity) {
//TODO 做一些数据校验,如唯一约束
}
/**
* 批量删除钢卷物料表
*/
@Override
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
if (isValid) {
//TODO 做一些业务上的校验,判断是否需要校验
}
return baseMapper.deleteBatchIds(ids) > 0;
}
/**
* 钢卷溯源查询
* 根据入场钢卷号查询二维码解析content中的steps然后根据steps中的钢卷号反向查询数据库
*
* @param enterCoilNo 入场钢卷号
* @param currentCoilNo 当前钢卷号(可选,用于查询特定子钢卷)
* @return 溯源结果(包含二维码信息和数据库记录)
*/
@Override
public Map<String, Object> queryTrace(String enterCoilNo, String currentCoilNo) {
try {
// 1. 查询所有相关的二维码记录(包括分卷后的独立二维码)
List<WmsGenerateRecordVo> allQrRecords = new ArrayList<>();
// 首先查询主二维码(以入场钢卷号为序列号的)
WmsGenerateRecordBo qrBo = new WmsGenerateRecordBo();
qrBo.setSerialNumber(enterCoilNo);
List<WmsGenerateRecordVo> mainQrRecords = generateRecordService.queryList(qrBo);
allQrRecords.addAll(mainQrRecords);
// 然后查询所有以该入场钢卷号开头的二维码(分卷后的二维码)
WmsGenerateRecordBo splitQrBo = new WmsGenerateRecordBo();
List<WmsGenerateRecordVo> allRecords = generateRecordService.queryList(splitQrBo);
for (WmsGenerateRecordVo record : allRecords) {
if (record.getSerialNumber() != null &&
record.getSerialNumber().startsWith(enterCoilNo + "-") &&
!allQrRecords.contains(record)) {
allQrRecords.add(record);
}
}
if (allQrRecords.isEmpty()) {
throw new RuntimeException("未找到对应的二维码记录");
}
// 2. 合并所有二维码的steps信息去重并重新编号
Map<String, Map<String, Object>> uniqueSteps = new HashMap<>(); // 用于去重
Set<String> allCoilNos = new HashSet<>();
for (WmsGenerateRecordVo qrRecord : allQrRecords) {
ObjectMapper objectMapper = new ObjectMapper();
@SuppressWarnings("unchecked")
Map<String, Object> contentMap = objectMapper.readValue(qrRecord.getContent(), Map.class);
@SuppressWarnings("unchecked")
List<Map<String, Object>> steps = (List<Map<String, Object>>) contentMap.get("steps");
if (steps != null) {
for (Map<String, Object> step : steps) {
// 创建唯一标识:操作类型 + 相关钢卷号
String stepKey = createStepKey(step);
// 如果是新的步骤,添加到唯一步骤集合中
if (!uniqueSteps.containsKey(stepKey)) {
Map<String, Object> uniqueStep = new HashMap<>(step);
uniqueStep.put("qrcode_serial", qrRecord.getSerialNumber());
uniqueStep.put("qrcode_id", qrRecord.getRecordId());
uniqueSteps.put(stepKey, uniqueStep);
}
// 提取钢卷号
extractCoilNo(step, "current_coil_no", allCoilNos);
extractCoilNo(step, "new_current_coil_no", allCoilNos);
extractCoilNo(step, "old_current_coil_no", allCoilNos);
extractCoilNo(step, "new_current_coil_nos", allCoilNos);
extractCoilNo(step, "merged_from", allCoilNos);
extractCoilNo(step, "parent_coil_nos", allCoilNos);
extractCoilId(step, "coil_id", allCoilNos);
extractCoilId(step, "old_coil_id", allCoilNos);
extractCoilId(step, "parent_coil_ids", allCoilNos);
}
}
}
// 转换为列表并按原始步骤号排序(保持时间顺序)
List<Map<String, Object>> allSteps = new ArrayList<>(uniqueSteps.values());
// 按原始步骤号排序,保持实际操作的时间顺序
allSteps.sort((a, b) -> {
Integer stepA = (Integer) a.get("step");
Integer stepB = (Integer) b.get("step");
if (stepA == null) stepA = 0;
if (stepB == null) stepB = 0;
return stepA.compareTo(stepB);
});
// 重新编号(保持连续性)
for (int i = 0; i < allSteps.size(); i++) {
allSteps.get(i).put("display_step", i + 1);
// 保留原始步骤号用于调试
allSteps.get(i).put("original_step", allSteps.get(i).get("step"));
}
// 3. 如果指定了当前钢卷号,过滤出相关的钢卷号
Set<String> filteredCoilNos = allCoilNos;
if (currentCoilNo != null && !currentCoilNo.trim().isEmpty()) {
final String filterValue = currentCoilNo;
filteredCoilNos = allCoilNos.stream()
.filter(coilNo -> coilNo.contains(filterValue))
.collect(Collectors.toSet());
}
// 4. 根据提取的钢卷号反向查询数据库
List<WmsMaterialCoilVo> result = new ArrayList<>();
if (!filteredCoilNos.isEmpty()) {
LambdaQueryWrapper<WmsMaterialCoil> lqw = Wrappers.lambdaQuery();
lqw.eq(WmsMaterialCoil::getEnterCoilNo, enterCoilNo);
// 查询包含提取出的钢卷号的记录
final Set<String> finalCoilNos = filteredCoilNos;
lqw.and(wrapper -> {
int count = 0;
for (String coilNo : finalCoilNos) {
if (count == 0) {
wrapper.eq(WmsMaterialCoil::getCurrentCoilNo, coilNo);
} else {
wrapper.or().eq(WmsMaterialCoil::getCurrentCoilNo, coilNo);
}
count++;
}
});
lqw.orderByAsc(WmsMaterialCoil::getCreateTime);
result = baseMapper.selectVoList(lqw);
// 填充每个记录的关联对象信息(如库区)
for (WmsMaterialCoilVo vo : result) {
fillRelatedObjects(vo);
}
}
// 如果没有找到记录,尝试查询所有相关的钢卷(包括历史数据)
if (result.isEmpty()) {
LambdaQueryWrapper<WmsMaterialCoil> lqw = Wrappers.lambdaQuery();
lqw.eq(WmsMaterialCoil::getEnterCoilNo, enterCoilNo);
lqw.orderByAsc(WmsMaterialCoil::getCreateTime);
result = baseMapper.selectVoList(lqw);
// 填充每个记录的关联对象信息
for (WmsMaterialCoilVo vo : result) {
fillRelatedObjects(vo);
}
}
// 5. 构建返回结果
Map<String, Object> resultMap = new HashMap<>();
resultMap.put("qrcode", allQrRecords.get(0)); // 主二维码
resultMap.put("all_qrcodes", allQrRecords); // 所有相关二维码
resultMap.put("steps", allSteps); // 所有步骤
resultMap.put("records", result); // 所有钢卷记录
return resultMap;
} catch (Exception e) {
throw new RuntimeException("溯源查询失败: " + e.getMessage());
}
}
/**
* 创建步骤唯一标识
*/
private String createStepKey(Map<String, Object> step) {
StringBuilder keyBuilder = new StringBuilder();
// 使用操作类型和主要标识符创建唯一key
String operation = (String) step.get("operation");
keyBuilder.append(operation).append("-");
// 根据操作类型使用不同的标识符
if ("分卷".equals(operation)) {
// 分卷:使用原钢卷号 + 分卷列表
keyBuilder.append(step.get("old_current_coil_no")).append("->");
keyBuilder.append(step.get("new_current_coil_nos"));
} else if ("合卷".equals(operation)) {
// 合卷:使用父钢卷列表 + 新钢卷号
keyBuilder.append(step.get("parent_coil_nos")).append("->");
keyBuilder.append(step.get("new_current_coil_no"));
} else if ("新增".equals(operation)) {
// 新增:使用当前钢卷号
keyBuilder.append(step.get("current_coil_no"));
} else {
// 其他更新:使用原钢卷号 -> 新钢卷号
keyBuilder.append(step.get("old_current_coil_no")).append("->");
keyBuilder.append(step.get("new_current_coil_no"));
}
return keyBuilder.toString();
}
/**
* 从step中提取钢卷号
*/
private void extractCoilNo(Map<String, Object> step, String fieldName, Set<String> coilNos) {
Object value = step.get(fieldName);
if (value != null) {
String strValue = value.toString();
if (strValue.contains(",")) {
// 如果是逗号分隔的多个钢卷号,分割后添加
String[] coilArray = strValue.split(",");
for (String coilNo : coilArray) {
coilNos.add(coilNo.trim());
}
} else {
coilNos.add(strValue.trim());
}
}
}
/**
* 从step中提取钢卷ID
*/
private void extractCoilId(Map<String, Object> step, String fieldName, Set<String> coilNos) {
Object value = step.get(fieldName);
if (value != null) {
String strValue = value.toString();
if (strValue.contains(",")) {
// 如果是逗号分隔的多个钢卷ID分割后添加
String[] coilArray = strValue.split(",");
for (String coilId : coilArray) {
coilNos.add(coilId.trim());
}
} else {
coilNos.add(strValue.trim());
}
}
}
/**
* 查询各个库区中不同类型的钢卷分布情况
* 按库区分组统计每种物品类型和物品ID的钢卷数量和重量
*
* @param itemType 物品类型(可选)
* @param itemId 物品ID可选
* @return 分布情况列表包含库区信息、物品类型、物品ID、数量、重量等
*/
@Override
public List<WmsMaterialCoilVo> getDistributionByWarehouse(String itemType, Long itemId) {
List<Map<String, Object>> mapList = baseMapper.getDistributionByWarehouse(itemType, itemId);
return convertMapListToVoList(mapList);
}
@Override
public List<WmsMaterialCoilVo> getDistributionByActualWarehouse(String itemType, Long itemId) {
List<Map<String, Object>> mapList = baseMapper.getDistributionByActualWarehouse(itemType, itemId);
return convertMapListToVoListActual(mapList);
}
private List<WmsMaterialCoilVo> convertMapListToVoListActual(List<Map<String, Object>> mapList) {
List<WmsMaterialCoilVo> voList = new ArrayList<>();
for (Map<String, Object> map : mapList) {
WmsMaterialCoilVo vo = new WmsMaterialCoilVo();
vo.setActualWarehouseId(map.get("actual_warehouse_id") != null ? Long.valueOf(map.get("actual_warehouse_id").toString()) : null);
vo.setActualWarehouseName(map.get("actual_warehouse_name") != null ? map.get("actual_warehouse_name").toString() : null);
vo.setItemType(map.get("item_type") != null ? map.get("item_type").toString() : null);
vo.setItemId(map.get("item_id") != null ? Long.valueOf(map.get("item_id").toString()) : null);
vo.setCoilCount(map.get("coil_count") != null ? Long.valueOf(map.get("coil_count").toString()) : 0L);
vo.setTotalGrossWeight(map.get("total_gross_weight") != null ? new BigDecimal(map.get("total_gross_weight").toString()) : BigDecimal.ZERO);
vo.setTotalNetWeight(map.get("total_net_weight") != null ? new BigDecimal(map.get("total_net_weight").toString()) : BigDecimal.ZERO);
voList.add(vo);
}
return voList;
}
/**
* 查询不同类型的钢卷在不同库区的分布情况
* 按物品类型和物品ID分组统计每个库区的钢卷数量和重量
*
* @param itemType 物品类型(可选)
* @param itemId 物品ID可选
* @return 分布情况列表包含物品类型、物品ID、库区信息、数量、重量等
*/
@Override
public List<WmsMaterialCoilVo> getDistributionByItemType(String itemType, Long itemId) {
List<Map<String, Object>> mapList = baseMapper.getDistributionByItemType(itemType, itemId);
return convertMapListToVoList(mapList);
}
/**
* 将Map列表转换为WmsMaterialCoilVo列表
*/
private List<WmsMaterialCoilVo> convertMapListToVoList(List<Map<String, Object>> mapList) {
List<WmsMaterialCoilVo> voList = new ArrayList<>();
for (Map<String, Object> map : mapList) {
WmsMaterialCoilVo vo = new WmsMaterialCoilVo();
vo.setWarehouseId(map.get("warehouse_id") != null ? Long.valueOf(map.get("warehouse_id").toString()) : null);
vo.setWarehouseName(map.get("warehouse_name") != null ? map.get("warehouse_name").toString() : null);
vo.setItemType(map.get("item_type") != null ? map.get("item_type").toString() : null);
vo.setItemId(map.get("item_id") != null ? Long.valueOf(map.get("item_id").toString()) : null);
vo.setCoilCount(map.get("coil_count") != null ? Long.valueOf(map.get("coil_count").toString()) : 0L);
vo.setTotalGrossWeight(map.get("total_gross_weight") != null ? new BigDecimal(map.get("total_gross_weight").toString()) : BigDecimal.ZERO);
vo.setTotalNetWeight(map.get("total_net_weight") != null ? new BigDecimal(map.get("total_net_weight").toString()) : BigDecimal.ZERO);
voList.add(vo);
}
return voList;
}
}