更新wip-退火 缺少实际库区选择,重新占据库位能力

This commit is contained in:
2026-03-14 18:39:19 +08:00
parent 7740531fc5
commit 9a645100df
56 changed files with 3783 additions and 0 deletions

View File

@@ -0,0 +1,431 @@
package com.klp.service.impl;
import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.klp.common.core.domain.PageQuery;
import com.klp.common.core.page.TableDataInfo;
import com.klp.common.exception.ServiceException;
import com.klp.common.utils.StringUtils;
import com.klp.domain.WmsFurnace;
import com.klp.domain.WmsFurnacePlan;
import com.klp.domain.WmsFurnacePlanCoil;
import com.klp.domain.WmsMaterialCoil;
import com.klp.domain.WmsActualWarehouse;
import com.klp.domain.bo.WmsFurnacePlanBo;
import com.klp.domain.bo.WmsFurnacePlanCoilBo;
import com.klp.domain.vo.WmsFurnacePlanCoilVo;
import com.klp.domain.vo.WmsFurnacePlanVo;
import com.klp.mapper.WmsActualWarehouseMapper;
import com.klp.mapper.WmsFurnaceMapper;
import com.klp.mapper.WmsFurnacePlanCoilMapper;
import com.klp.mapper.WmsFurnacePlanMapper;
import com.klp.mapper.WmsMaterialCoilMapper;
import com.klp.service.IWmsFurnacePlanService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;
/**
* 退火计划Service业务层处理
*
* @author klp
* @date 2026-03-14
*/
@RequiredArgsConstructor
@Service
public class WmsFurnacePlanServiceImpl implements IWmsFurnacePlanService {
private final WmsFurnacePlanMapper baseMapper;
private final WmsFurnacePlanCoilMapper planCoilMapper;
private final WmsFurnaceMapper furnaceMapper;
private final WmsMaterialCoilMapper materialCoilMapper;
private final WmsActualWarehouseMapper actualWarehouseMapper;
@Override
public WmsFurnacePlanVo queryById(Long planId) {
WmsFurnacePlanVo plan = baseMapper.selectVoById(planId);
if (plan != null) {
plan.setCoilIds(queryPlanCoils(planId).stream()
.map(WmsFurnacePlanCoilVo::getCoilId)
.collect(Collectors.toList()));
fillFurnaceNames(java.util.Collections.singletonList(plan));
}
return plan;
}
@Override
public TableDataInfo<WmsFurnacePlanVo> queryPageList(WmsFurnacePlanBo bo, PageQuery pageQuery) {
LambdaQueryWrapper<WmsFurnacePlan> lqw = buildQueryWrapper(bo);
Page<WmsFurnacePlanVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
fillFurnaceNames(result.getRecords());
return TableDataInfo.build(result);
}
@Override
public List<WmsFurnacePlanVo> queryList(WmsFurnacePlanBo bo) {
LambdaQueryWrapper<WmsFurnacePlan> lqw = buildQueryWrapper(bo);
List<WmsFurnacePlanVo> list = baseMapper.selectVoList(lqw);
fillFurnaceNames(list);
return list;
}
private LambdaQueryWrapper<WmsFurnacePlan> buildQueryWrapper(WmsFurnacePlanBo bo) {
LambdaQueryWrapper<WmsFurnacePlan> lqw = Wrappers.lambdaQuery();
lqw.like(StringUtils.isNotBlank(bo.getPlanNo()), WmsFurnacePlan::getPlanNo, bo.getPlanNo());
lqw.eq(bo.getTargetFurnaceId() != null, WmsFurnacePlan::getTargetFurnaceId, bo.getTargetFurnaceId());
lqw.eq(bo.getStatus() != null, WmsFurnacePlan::getStatus, bo.getStatus());
lqw.ge(bo.getPlanStartTime() != null, WmsFurnacePlan::getPlanStartTime, bo.getPlanStartTime());
lqw.orderByDesc(WmsFurnacePlan::getPlanStartTime);
return lqw;
}
private void fillFurnaceNames(List<WmsFurnacePlanVo> plans) {
if (plans == null || plans.isEmpty()) {
return;
}
List<Long> furnaceIds = plans.stream()
.map(WmsFurnacePlanVo::getTargetFurnaceId)
.filter(id -> id != null)
.distinct()
.collect(Collectors.toList());
if (furnaceIds.isEmpty()) {
return;
}
List<WmsFurnace> furnaces = furnaceMapper.selectBatchIds(furnaceIds);
java.util.Map<Long, String> nameMap = furnaces.stream()
.collect(Collectors.toMap(WmsFurnace::getFurnaceId, WmsFurnace::getFurnaceName, (a, b) -> a));
plans.forEach(plan -> {
if (plan.getTargetFurnaceId() != null) {
plan.setTargetFurnaceName(nameMap.get(plan.getTargetFurnaceId()));
}
});
}
@Override
public Boolean insertByBo(WmsFurnacePlanBo bo) {
WmsFurnacePlan add = BeanUtil.toBean(bo, WmsFurnacePlan.class);
validEntityBeforeSave(add, true);
boolean flag = baseMapper.insert(add) > 0;
if (flag) {
bo.setPlanId(add.getPlanId());
}
return flag;
}
@Override
public Boolean updateByBo(WmsFurnacePlanBo bo) {
WmsFurnacePlan update = BeanUtil.toBean(bo, WmsFurnacePlan.class);
validEntityBeforeSave(update, false);
return baseMapper.updateById(update) > 0;
}
private void validEntityBeforeSave(WmsFurnacePlan entity, boolean isNew) {
LambdaQueryWrapper<WmsFurnacePlan> planNoQuery = Wrappers.lambdaQuery();
planNoQuery.eq(WmsFurnacePlan::getPlanNo, entity.getPlanNo());
if (!isNew) {
planNoQuery.ne(WmsFurnacePlan::getPlanId, entity.getPlanId());
}
if (baseMapper.selectCount(planNoQuery) > 0) {
throw new ServiceException("计划号已存在");
}
WmsFurnace furnace = furnaceMapper.selectById(entity.getTargetFurnaceId());
if (furnace == null || furnace.getDelFlag() != null && furnace.getDelFlag() == 1) {
throw new ServiceException("目标炉子不存在");
}
}
@Override
public Boolean updateStatus(Long planId, Integer status) {
WmsFurnacePlan plan = baseMapper.selectById(planId);
if (plan == null) {
throw new ServiceException("计划不存在");
}
WmsFurnacePlan update = new WmsFurnacePlan();
update.setPlanId(planId);
update.setStatus(status);
boolean updated = baseMapper.updateById(update) > 0;
if (updated && plan.getTargetFurnaceId() != null) {
if (status != null && (status == 2)) {
updateFurnaceBusy(plan.getTargetFurnaceId(), 1);
}
if (status != null && (status == 3 || status == 4)) {
updateFurnaceBusy(plan.getTargetFurnaceId(), 0);
}
}
return updated;
}
@Override
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
if (isValid && ids != null && !ids.isEmpty()) {
for (Long planId : ids) {
if (planCoilMapper.selectCount(Wrappers.<WmsFurnacePlanCoil>lambdaQuery()
.eq(WmsFurnacePlanCoil::getPlanId, planId)) > 0) {
throw new ServiceException("计划下存在钢卷,请先解绑");
}
}
}
return baseMapper.deleteBatchIds(ids) > 0;
}
@Override
public List<WmsFurnacePlanCoilVo> queryPlanCoils(Long planId) {
List<WmsFurnacePlanCoilVo> list = planCoilMapper.selectVoList(Wrappers.<WmsFurnacePlanCoil>lambdaQuery()
.eq(WmsFurnacePlanCoil::getPlanId, planId));
if (list == null || list.isEmpty()) {
return list;
}
List<Long> coilIds = list.stream()
.map(WmsFurnacePlanCoilVo::getCoilId)
.filter(id -> id != null)
.distinct()
.collect(Collectors.toList());
if (coilIds.isEmpty()) {
return list;
}
java.util.Map<Long, String> enterNoMap = materialCoilMapper.selectBatchIds(coilIds).stream()
.collect(Collectors.toMap(WmsMaterialCoil::getCoilId, WmsMaterialCoil::getEnterCoilNo, (a, b) -> a));
list.forEach(item -> item.setEnterCoilNo(enterNoMap.get(item.getCoilId())));
return list;
}
@Override
@Transactional(rollbackFor = Exception.class)
public Boolean bindPlanCoils(WmsFurnacePlanCoilBo bo) {
if (bo.getPlanId() == null) {
throw new ServiceException("计划ID不能为空");
}
List<Long> coilIds = parseCoilIds(bo);
if (coilIds.isEmpty()) {
throw new ServiceException("请至少选择一条钢卷");
}
WmsFurnacePlan plan = ensurePlanExist(bo.getPlanId());
if (plan.getStatus() != null && plan.getStatus() == 2) {
throw new ServiceException("计划进行中,无法再领料");
}
for (Long coilId : coilIds) {
if (planCoilMapper.selectCount(Wrappers.<WmsFurnacePlanCoil>lambdaQuery()
.eq(WmsFurnacePlanCoil::getPlanId, bo.getPlanId())
.eq(WmsFurnacePlanCoil::getCoilId, coilId)) > 0) {
continue;
}
WmsFurnacePlanCoil entity = new WmsFurnacePlanCoil();
entity.setPlanId(bo.getPlanId());
entity.setCoilId(coilId);
planCoilMapper.insert(entity);
}
return true;
}
@Override
@Transactional(rollbackFor = Exception.class)
public Boolean unbindPlanCoil(WmsFurnacePlanCoilBo bo) {
if (bo.getPlanId() == null || bo.getCoilId() == null) {
throw new ServiceException("计划ID和钢卷ID不能为空");
}
return planCoilMapper.delete(Wrappers.<WmsFurnacePlanCoil>lambdaQuery()
.eq(WmsFurnacePlanCoil::getPlanId, bo.getPlanId())
.eq(WmsFurnacePlanCoil::getCoilId, bo.getCoilId())) > 0;
}
@Override
@Transactional(rollbackFor = Exception.class)
public Boolean inFurnace(Long planId) {
WmsFurnacePlan plan = baseMapper.selectById(planId);
if (plan == null) {
throw new ServiceException("计划不存在");
}
if (plan.getActualStartTime() != null) {
throw new ServiceException("计划已入炉");
}
if (planCoilMapper.selectCount(Wrappers.<WmsFurnacePlanCoil>lambdaQuery()
.eq(WmsFurnacePlanCoil::getPlanId, planId)) <= 0) {
throw new ServiceException("计划未绑定钢卷");
}
Date now = new Date();
Date endTime = new Date(now.getTime() + 48L * 60 * 60 * 1000);
WmsFurnacePlan update = new WmsFurnacePlan();
update.setPlanId(planId);
update.setActualStartTime(now);
update.setEndTime(endTime);
update.setStatus(2);
baseMapper.updateById(update);
updateFurnaceBusy(plan.getTargetFurnaceId(), 1);
List<WmsFurnacePlanCoilVo> coils = queryPlanCoils(planId);
for (WmsFurnacePlanCoilVo coil : coils) {
releaseActualWarehouse(coil.getCoilId());
}
return true;
}
@Override
@Transactional(rollbackFor = Exception.class)
public Boolean completePlan(Long planId, List<com.klp.domain.bo.WmsFurnacePlanLocationItemBo> locations) {
WmsFurnacePlan plan = baseMapper.selectById(planId);
if (plan == null) {
throw new ServiceException("计划不存在");
}
if (plan.getStatus() == null || plan.getStatus() != 2) {
throw new ServiceException("计划未进行中,无法完成");
}
List<WmsFurnacePlanCoilVo> coils = queryPlanCoils(planId);
if (coils == null || coils.isEmpty()) {
throw new ServiceException("计划未绑定钢卷");
}
if (locations == null || locations.isEmpty()) {
throw new ServiceException("请先分配实际库位");
}
java.util.Map<Long, Long> locationMap = locations.stream()
.collect(Collectors.toMap(com.klp.domain.bo.WmsFurnacePlanLocationItemBo::getCoilId,
com.klp.domain.bo.WmsFurnacePlanLocationItemBo::getActualWarehouseId, (a, b) -> a));
for (WmsFurnacePlanCoilVo coil : coils) {
Long targetLocation = locationMap.get(coil.getCoilId());
if (targetLocation == null) {
throw new ServiceException("钢卷" + coil.getEnterCoilNo() + "未分配库位");
}
occupyActualWarehouse(coil.getCoilId(), targetLocation);
}
Date now = new Date();
WmsFurnacePlan update = new WmsFurnacePlan();
update.setPlanId(planId);
update.setStatus(3);
update.setEndTime(now);
baseMapper.updateById(update);
updateFurnaceBusy(plan.getTargetFurnaceId(), 0);
return true;
}
private void releaseActualWarehouse(Long coilId) {
WmsMaterialCoil coil = materialCoilMapper.selectById(coilId);
if (coil == null) {
return;
}
Long actualWarehouseId = coil.getActualWarehouseId();
if (actualWarehouseId != null) {
WmsActualWarehouse warehouse = new WmsActualWarehouse();
warehouse.setActualWarehouseId(actualWarehouseId);
warehouse.setIsEnabled(1);
actualWarehouseMapper.updateById(warehouse);
}
WmsMaterialCoil updateCoil = new WmsMaterialCoil();
updateCoil.setCoilId(coilId);
updateCoil.setActualWarehouseId(null);
materialCoilMapper.updateById(updateCoil);
}
private void occupyActualWarehouse(Long coilId, Long actualWarehouseId) {
if (actualWarehouseId == null) {
throw new ServiceException("实际库位不能为空");
}
WmsActualWarehouse warehouse = actualWarehouseMapper.selectById(actualWarehouseId);
if (warehouse == null || warehouse.getDelFlag() != null && warehouse.getDelFlag() == 1) {
throw new ServiceException("实际库位不存在");
}
if (warehouse.getIsEnabled() != null && warehouse.getIsEnabled() == 0) {
throw new ServiceException("实际库位已被占用");
}
WmsActualWarehouse updateWarehouse = new WmsActualWarehouse();
updateWarehouse.setActualWarehouseId(actualWarehouseId);
updateWarehouse.setIsEnabled(0);
actualWarehouseMapper.updateById(updateWarehouse);
WmsMaterialCoil updateCoil = new WmsMaterialCoil();
updateCoil.setCoilId(coilId);
updateCoil.setActualWarehouseId(actualWarehouseId);
materialCoilMapper.updateById(updateCoil);
}
private List<Long> parseCoilIds(WmsFurnacePlanCoilBo bo) {
List<Long> coilIds = new ArrayList<>();
if (bo.getCoilId() != null) {
coilIds.add(bo.getCoilId());
}
if (StringUtils.isNotBlank(bo.getCoilIds())) {
String[] parts = bo.getCoilIds().split(",");
for (String part : parts) {
if (StringUtils.isNotBlank(part)) {
coilIds.add(Long.parseLong(part.trim()));
}
}
}
if (StringUtils.isNotBlank(bo.getEnterCoilNos())) {
coilIds.addAll(resolveCoilIdsByEnterNos(bo.getEnterCoilNos()));
}
if (StringUtils.isNotBlank(bo.getCurrentCoilNos())) {
coilIds.addAll(resolveCoilIdsByCurrentNos(bo.getCurrentCoilNos()));
}
return coilIds.stream().distinct().collect(Collectors.toList());
}
private List<Long> resolveCoilIdsByEnterNos(String enterCoilNos) {
List<String> nos = splitCommaValues(enterCoilNos);
if (nos.isEmpty()) {
return new ArrayList<>();
}
return materialCoilMapper.selectList(Wrappers.<WmsMaterialCoil>lambdaQuery()
.in(WmsMaterialCoil::getEnterCoilNo, nos)
.eq(WmsMaterialCoil::getDelFlag, 0))
.stream()
.map(WmsMaterialCoil::getCoilId)
.collect(Collectors.toList());
}
private List<Long> resolveCoilIdsByCurrentNos(String currentCoilNos) {
List<String> nos = splitCommaValues(currentCoilNos);
if (nos.isEmpty()) {
return new ArrayList<>();
}
return materialCoilMapper.selectList(Wrappers.<WmsMaterialCoil>lambdaQuery()
.in(WmsMaterialCoil::getCurrentCoilNo, nos)
.eq(WmsMaterialCoil::getDelFlag, 0))
.stream()
.map(WmsMaterialCoil::getCoilId)
.collect(Collectors.toList());
}
private List<String> splitCommaValues(String values) {
List<String> result = new ArrayList<>();
if (StringUtils.isBlank(values)) {
return result;
}
String[] parts = values.split(",");
for (String part : parts) {
if (StringUtils.isNotBlank(part)) {
result.add(part.trim());
}
}
return result;
}
private WmsFurnacePlan ensurePlanExist(Long planId) {
WmsFurnacePlan plan = baseMapper.selectById(planId);
if (plan == null) {
throw new ServiceException("计划不存在");
}
return plan;
}
private void updateFurnaceBusy(Long furnaceId, Integer busyFlag) {
if (furnaceId == null) {
return;
}
WmsFurnace update = new WmsFurnace();
update.setFurnaceId(furnaceId);
update.setBusyFlag(busyFlag);
furnaceMapper.updateById(update);
}
}