2025-11-25 15:44:19 +08:00
|
|
|
|
package com.klp.service.impl;
|
|
|
|
|
|
|
|
|
|
|
|
import cn.hutool.core.bean.BeanUtil;
|
2025-12-04 17:24:55 +08:00
|
|
|
|
import com.klp.common.core.domain.entity.SysUser;
|
2025-11-25 15:44:19 +08:00
|
|
|
|
import com.klp.common.core.page.TableDataInfo;
|
|
|
|
|
|
import com.klp.common.core.domain.PageQuery;
|
|
|
|
|
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
2025-12-09 14:15:37 +08:00
|
|
|
|
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
2025-11-25 15:44:19 +08:00
|
|
|
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
2026-01-28 11:00:32 +08:00
|
|
|
|
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
2025-11-25 15:44:19 +08:00
|
|
|
|
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
2025-12-11 09:21:04 +08:00
|
|
|
|
import com.klp.common.exception.ServiceException;
|
2025-11-25 15:44:19 +08:00
|
|
|
|
import com.klp.common.utils.StringUtils;
|
2025-12-11 09:21:04 +08:00
|
|
|
|
import com.klp.domain.*;
|
2025-12-05 13:50:29 +08:00
|
|
|
|
import com.klp.domain.vo.*;
|
2025-12-11 09:21:04 +08:00
|
|
|
|
import com.klp.mapper.*;
|
2025-12-04 17:24:55 +08:00
|
|
|
|
import com.klp.system.service.ISysUserService;
|
2025-11-25 15:44:19 +08:00
|
|
|
|
import lombok.RequiredArgsConstructor;
|
|
|
|
|
|
import org.springframework.stereotype.Service;
|
|
|
|
|
|
import com.klp.domain.bo.WmsDeliveryPlanBo;
|
|
|
|
|
|
import com.klp.service.IWmsDeliveryPlanService;
|
|
|
|
|
|
|
2025-11-26 09:38:22 +08:00
|
|
|
|
import java.util.*;
|
2025-12-05 13:50:29 +08:00
|
|
|
|
import java.util.stream.Collectors;
|
2025-11-25 15:44:19 +08:00
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 发货计划Service业务层处理
|
|
|
|
|
|
*
|
|
|
|
|
|
* @author klp
|
|
|
|
|
|
* @date 2025-11-25
|
|
|
|
|
|
*/
|
|
|
|
|
|
@RequiredArgsConstructor
|
|
|
|
|
|
@Service
|
|
|
|
|
|
public class WmsDeliveryPlanServiceImpl implements IWmsDeliveryPlanService {
|
|
|
|
|
|
|
|
|
|
|
|
private final WmsDeliveryPlanMapper baseMapper;
|
|
|
|
|
|
|
2025-12-04 17:24:55 +08:00
|
|
|
|
private final ISysUserService userService;
|
|
|
|
|
|
|
2025-12-08 11:43:15 +08:00
|
|
|
|
private final WmsMaterialCoilMapper coilMapper;
|
|
|
|
|
|
|
2025-12-09 14:15:37 +08:00
|
|
|
|
private final WmsDeliveryWaybillMapper waybillMapper;
|
|
|
|
|
|
|
|
|
|
|
|
private final WmsDeliveryWaybillDetailMapper waybillDetailMapper;
|
|
|
|
|
|
|
2025-12-11 09:21:04 +08:00
|
|
|
|
private final WmsCoilPendingActionMapper coilPendingActionMapper;
|
|
|
|
|
|
|
2025-11-25 15:44:19 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 查询发货计划
|
|
|
|
|
|
*/
|
|
|
|
|
|
@Override
|
|
|
|
|
|
public WmsDeliveryPlanVo queryById(Long planId){
|
|
|
|
|
|
return baseMapper.selectVoById(planId);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 查询发货计划列表
|
|
|
|
|
|
*/
|
|
|
|
|
|
@Override
|
|
|
|
|
|
public TableDataInfo<WmsDeliveryPlanVo> queryPageList(WmsDeliveryPlanBo bo, PageQuery pageQuery) {
|
|
|
|
|
|
LambdaQueryWrapper<WmsDeliveryPlan> lqw = buildQueryWrapper(bo);
|
|
|
|
|
|
Page<WmsDeliveryPlanVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
|
2025-12-05 13:50:29 +08:00
|
|
|
|
List<WmsDeliveryPlanVo> records = result.getRecords();
|
|
|
|
|
|
Set<String> userNames = records.stream()
|
|
|
|
|
|
.flatMap(v -> java.util.stream.Stream.of(v.getCreateBy(), v.getUpdateBy()))
|
|
|
|
|
|
.filter(StringUtils::isNotBlank)
|
|
|
|
|
|
.collect(Collectors.toSet());
|
|
|
|
|
|
if (!userNames.isEmpty()) {
|
|
|
|
|
|
Map<String, String> nickMap = userService.selectNickNameMapByUserNames(records.stream()
|
|
|
|
|
|
.flatMap(v -> java.util.stream.Stream.of(v.getCreateBy(), v.getUpdateBy()))
|
|
|
|
|
|
.filter(StringUtils::isNotBlank)
|
|
|
|
|
|
.distinct()
|
|
|
|
|
|
.collect(Collectors.toList()));
|
|
|
|
|
|
records.forEach(item -> {
|
|
|
|
|
|
if (StringUtils.isNotBlank(item.getCreateBy())) {
|
|
|
|
|
|
item.setCreateByName(nickMap.getOrDefault(item.getCreateBy(), item.getCreateBy()));
|
|
|
|
|
|
}
|
|
|
|
|
|
if (StringUtils.isNotBlank(item.getUpdateBy())) {
|
|
|
|
|
|
item.setUpdateByName(nickMap.getOrDefault(item.getUpdateBy(), item.getUpdateBy()));
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
2025-12-04 17:24:55 +08:00
|
|
|
|
}
|
2025-12-05 13:50:29 +08:00
|
|
|
|
return TableDataInfo.build(result);
|
2025-12-04 17:24:55 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-11-25 15:44:19 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 查询发货计划列表
|
|
|
|
|
|
*/
|
|
|
|
|
|
@Override
|
|
|
|
|
|
public List<WmsDeliveryPlanVo> queryList(WmsDeliveryPlanBo bo) {
|
|
|
|
|
|
LambdaQueryWrapper<WmsDeliveryPlan> lqw = buildQueryWrapper(bo);
|
|
|
|
|
|
return baseMapper.selectVoList(lqw);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private LambdaQueryWrapper<WmsDeliveryPlan> buildQueryWrapper(WmsDeliveryPlanBo bo) {
|
|
|
|
|
|
Map<String, Object> params = bo.getParams();
|
|
|
|
|
|
LambdaQueryWrapper<WmsDeliveryPlan> lqw = Wrappers.lambdaQuery();
|
|
|
|
|
|
lqw.like(StringUtils.isNotBlank(bo.getPlanName()), WmsDeliveryPlan::getPlanName, bo.getPlanName());
|
|
|
|
|
|
lqw.eq(bo.getPlanDate() != null, WmsDeliveryPlan::getPlanDate, bo.getPlanDate());
|
2025-11-29 15:31:49 +08:00
|
|
|
|
lqw.eq(bo.getPlanType() != null, WmsDeliveryPlan::getPlanType, bo.getPlanType());
|
2025-12-08 14:42:28 +08:00
|
|
|
|
lqw.eq(bo.getAuditStatus() != null, WmsDeliveryPlan::getAuditStatus, bo.getAuditStatus());
|
2026-01-14 08:55:38 +08:00
|
|
|
|
// 计划根据plan_date降序排序最新的放在最前面
|
|
|
|
|
|
lqw.orderByDesc(WmsDeliveryPlan::getPlanDate);
|
2025-11-25 15:44:19 +08:00
|
|
|
|
return lqw;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 新增发货计划
|
|
|
|
|
|
*/
|
|
|
|
|
|
@Override
|
|
|
|
|
|
public Boolean insertByBo(WmsDeliveryPlanBo bo) {
|
|
|
|
|
|
WmsDeliveryPlan add = BeanUtil.toBean(bo, WmsDeliveryPlan.class);
|
|
|
|
|
|
validEntityBeforeSave(add);
|
|
|
|
|
|
boolean flag = baseMapper.insert(add) > 0;
|
|
|
|
|
|
if (flag) {
|
|
|
|
|
|
bo.setPlanId(add.getPlanId());
|
|
|
|
|
|
}
|
|
|
|
|
|
return flag;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 修改发货计划
|
|
|
|
|
|
*/
|
|
|
|
|
|
@Override
|
|
|
|
|
|
public Boolean updateByBo(WmsDeliveryPlanBo bo) {
|
|
|
|
|
|
WmsDeliveryPlan update = BeanUtil.toBean(bo, WmsDeliveryPlan.class);
|
|
|
|
|
|
validEntityBeforeSave(update);
|
|
|
|
|
|
return baseMapper.updateById(update) > 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 保存前的数据校验
|
|
|
|
|
|
*/
|
|
|
|
|
|
private void validEntityBeforeSave(WmsDeliveryPlan entity){
|
|
|
|
|
|
//TODO 做一些数据校验,如唯一约束
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 批量删除发货计划
|
|
|
|
|
|
*/
|
|
|
|
|
|
@Override
|
|
|
|
|
|
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
|
2026-01-10 11:48:38 +08:00
|
|
|
|
if (isValid) {
|
2025-12-11 09:21:04 +08:00
|
|
|
|
// 检查是否有关联的收货计划明细(actionType为401的操作记录)
|
|
|
|
|
|
for (Long planId : ids) {
|
2026-01-10 11:48:38 +08:00
|
|
|
|
// 查询与该计划关联的待操作记录
|
|
|
|
|
|
List<WmsCoilPendingAction> pendingActions = coilPendingActionMapper.selectList(
|
2025-12-11 09:21:04 +08:00
|
|
|
|
Wrappers.<WmsCoilPendingAction>lambdaQuery()
|
|
|
|
|
|
.eq(WmsCoilPendingAction::getActionType, 401)
|
|
|
|
|
|
.eq(WmsCoilPendingAction::getWarehouseId, planId)
|
|
|
|
|
|
.eq(WmsCoilPendingAction::getDelFlag, 0)
|
|
|
|
|
|
);
|
|
|
|
|
|
|
2026-01-10 11:48:38 +08:00
|
|
|
|
// 如果有待操作记录,检查这些记录关联的钢卷是否至少有一个还存在
|
|
|
|
|
|
if (!pendingActions.isEmpty()) {
|
|
|
|
|
|
boolean hasValidCoil = false;
|
|
|
|
|
|
|
|
|
|
|
|
for (WmsCoilPendingAction pendingAction : pendingActions) {
|
|
|
|
|
|
// 检查关联的钢卷是否还存在(未被删除)
|
|
|
|
|
|
WmsMaterialCoil coil = coilMapper.selectOne(
|
|
|
|
|
|
Wrappers.<WmsMaterialCoil>lambdaQuery()
|
|
|
|
|
|
.eq(WmsMaterialCoil::getCoilId, pendingAction.getCoilId())
|
|
|
|
|
|
.eq(WmsMaterialCoil::getDelFlag, 0)
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
// 如果存在任意一个未被删除的钢卷,标记为不允许删除
|
|
|
|
|
|
if (coil != null) {
|
|
|
|
|
|
hasValidCoil = true;
|
|
|
|
|
|
break; // 只要有一个存在就无需继续检查
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 只要有一个关联的钢卷还存在,就不允许删除计划
|
|
|
|
|
|
if (hasValidCoil) {
|
|
|
|
|
|
throw new ServiceException("计划下存在有效明细,无法删除");
|
|
|
|
|
|
}
|
2025-12-11 09:21:04 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-11-25 15:44:19 +08:00
|
|
|
|
}
|
2026-01-28 11:00:32 +08:00
|
|
|
|
|
|
|
|
|
|
// 对于发货计划(planType = 0),需要先级联删除相关的发货单及明细
|
|
|
|
|
|
// 遍历所有要删除的计划,对发货计划进行级联删除
|
|
|
|
|
|
for (Long planId : ids) {
|
|
|
|
|
|
WmsDeliveryPlan plan = baseMapper.selectById(planId);
|
|
|
|
|
|
if (plan != null && plan.getPlanType() != null && plan.getPlanType() == 0) { // 发货计划
|
|
|
|
|
|
// 删除关联的发货单及明细
|
|
|
|
|
|
cascadeDeleteDeliveryWaybillsByPlanId(planId);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-11-25 15:44:19 +08:00
|
|
|
|
return baseMapper.deleteBatchIds(ids) > 0;
|
|
|
|
|
|
}
|
2025-11-25 16:58:47 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 获取发货计划统计信息
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param planId 计划ID,可选
|
|
|
|
|
|
* @return 统计信息列表
|
|
|
|
|
|
*/
|
|
|
|
|
|
public List<WmsDeliveryPlanStatisticsVo> getDeliveryPlanStatistics(Long planId) {
|
|
|
|
|
|
return baseMapper.selectDeliveryPlanStatistics(planId);
|
|
|
|
|
|
}
|
2025-11-26 09:38:22 +08:00
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 获取发货报表统计信息
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param startTime 开始时间
|
|
|
|
|
|
* @param endTime 结束时间
|
2025-11-27 11:05:01 +08:00
|
|
|
|
* @return 报表统计信息(包含汇总和按类型统计)
|
2025-11-26 09:38:22 +08:00
|
|
|
|
*/
|
2025-11-27 11:05:01 +08:00
|
|
|
|
public WmsDeliveryReportResultVo getDeliveryReport(Date startTime, Date endTime) {
|
|
|
|
|
|
WmsDeliveryReportResultVo result = new WmsDeliveryReportResultVo();
|
|
|
|
|
|
|
|
|
|
|
|
// 获取汇总数据
|
|
|
|
|
|
WmsDeliveryReportSummaryVo summary = baseMapper.selectDeliveryReportSummary(startTime, endTime);
|
|
|
|
|
|
result.setSummary(summary);
|
|
|
|
|
|
|
|
|
|
|
|
// 获取按钢卷类型分类的数据
|
|
|
|
|
|
List<WmsDeliveryReportByTypeVo> details = baseMapper.selectDeliveryReportByType(startTime, endTime);
|
|
|
|
|
|
result.setDetails(details);
|
|
|
|
|
|
|
|
|
|
|
|
return result;
|
2025-11-26 09:38:22 +08:00
|
|
|
|
}
|
2025-12-08 11:43:15 +08:00
|
|
|
|
|
2025-12-12 10:38:55 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 获取收货报表统计信息
|
|
|
|
|
|
*/
|
|
|
|
|
|
@Override
|
|
|
|
|
|
public WmsReceivingReportResultVo getReceivingReport(Date startTime, Date endTime) {
|
|
|
|
|
|
WmsReceivingReportResultVo result = new WmsReceivingReportResultVo();
|
|
|
|
|
|
WmsReceivingReportSummaryVo summary = baseMapper.selectReceivingReportSummary(startTime, endTime);
|
|
|
|
|
|
result.setSummary(summary);
|
|
|
|
|
|
List<WmsReceivingReportByTypeVo> details = baseMapper.selectReceivingReportByType(startTime, endTime);
|
|
|
|
|
|
result.setDetails(details);
|
|
|
|
|
|
return result;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-12-09 14:15:37 +08:00
|
|
|
|
@Override
|
|
|
|
|
|
public List<WmsMaterialCoilVo> getSelectableCoilsByPlanId(Long planId) {
|
|
|
|
|
|
if (planId == null) {
|
|
|
|
|
|
return Collections.emptyList();
|
|
|
|
|
|
}
|
|
|
|
|
|
WmsDeliveryPlanVo planVo = baseMapper.selectVoById(planId);
|
|
|
|
|
|
if (planVo == null || StringUtils.isBlank(planVo.getCoil())) {
|
|
|
|
|
|
return Collections.emptyList();
|
|
|
|
|
|
}
|
|
|
|
|
|
Set<Long> planCoilIds = Arrays.stream(planVo.getCoil().split(","))
|
|
|
|
|
|
.map(String::trim)
|
|
|
|
|
|
.filter(StringUtils::isNotBlank)
|
|
|
|
|
|
.map(Long::valueOf)
|
|
|
|
|
|
.collect(Collectors.toSet());
|
|
|
|
|
|
|
|
|
|
|
|
if (planCoilIds.isEmpty()) {
|
|
|
|
|
|
return Collections.emptyList();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
List<WmsDeliveryWaybill> waybills = waybillMapper.selectList(
|
|
|
|
|
|
Wrappers.<WmsDeliveryWaybill>lambdaQuery().eq(WmsDeliveryWaybill::getPlanId, planId)
|
|
|
|
|
|
);
|
|
|
|
|
|
if (waybills == null || waybills.isEmpty()) {
|
|
|
|
|
|
return queryCoilsByIds(planCoilIds);
|
|
|
|
|
|
}
|
|
|
|
|
|
Set<Long> waybillIds = waybills.stream().map(WmsDeliveryWaybill::getWaybillId).collect(Collectors.toSet());
|
|
|
|
|
|
if (waybillIds.isEmpty()) {
|
|
|
|
|
|
return queryCoilsByIds(planCoilIds);
|
|
|
|
|
|
}
|
|
|
|
|
|
List<WmsDeliveryWaybillDetail> details = waybillDetailMapper.selectList(
|
|
|
|
|
|
Wrappers.<WmsDeliveryWaybillDetail>lambdaQuery().in(WmsDeliveryWaybillDetail::getWaybillId, waybillIds)
|
|
|
|
|
|
);
|
|
|
|
|
|
Set<Long> usedCoilIds = details == null ? Collections.emptySet() : details.stream()
|
|
|
|
|
|
.map(WmsDeliveryWaybillDetail::getCoilId)
|
|
|
|
|
|
.filter(Objects::nonNull)
|
|
|
|
|
|
.collect(Collectors.toSet());
|
|
|
|
|
|
|
|
|
|
|
|
planCoilIds.removeAll(usedCoilIds);
|
|
|
|
|
|
if (planCoilIds.isEmpty()) {
|
|
|
|
|
|
return Collections.emptyList();
|
|
|
|
|
|
}
|
|
|
|
|
|
return queryCoilsByIds(planCoilIds);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private List<WmsMaterialCoilVo> queryCoilsByIds(Set<Long> coilIds) {
|
|
|
|
|
|
if (coilIds == null || coilIds.isEmpty()) {
|
|
|
|
|
|
return Collections.emptyList();
|
|
|
|
|
|
}
|
|
|
|
|
|
QueryWrapper<WmsMaterialCoil> qw = new QueryWrapper<>();
|
2025-12-09 14:32:51 +08:00
|
|
|
|
qw.in("mc.coil_id", coilIds);
|
|
|
|
|
|
qw.eq("mc.del_flag", 0);
|
|
|
|
|
|
//根据创建时间倒叙
|
|
|
|
|
|
qw.orderByDesc("mc.create_time");
|
2025-12-09 14:15:37 +08:00
|
|
|
|
// 使用动态联查以返回更完整的钢卷信息
|
|
|
|
|
|
return coilMapper.selectVoListWithDynamicJoin(qw);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-01-28 11:00:32 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 级联删除发货单及其明细数据
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param planId 计划ID
|
|
|
|
|
|
*/
|
|
|
|
|
|
private void cascadeDeleteDeliveryWaybillsByPlanId(Long planId) {
|
|
|
|
|
|
// 先查询该计划下的所有发货单
|
|
|
|
|
|
List<WmsDeliveryWaybill> waybills = waybillMapper.selectList(
|
|
|
|
|
|
Wrappers.<WmsDeliveryWaybill>lambdaQuery()
|
|
|
|
|
|
.eq(WmsDeliveryWaybill::getPlanId, planId)
|
|
|
|
|
|
.eq(WmsDeliveryWaybill::getDelFlag, 0)
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
if (!waybills.isEmpty()) {
|
|
|
|
|
|
// 获取所有发货单ID
|
|
|
|
|
|
List<Long> waybillIds = waybills.stream()
|
|
|
|
|
|
.map(WmsDeliveryWaybill::getWaybillId)
|
|
|
|
|
|
.collect(Collectors.toList());
|
|
|
|
|
|
|
|
|
|
|
|
// 先删除发货单明细
|
|
|
|
|
|
if (!waybillIds.isEmpty()) {
|
|
|
|
|
|
LambdaQueryWrapper<WmsDeliveryWaybillDetail> detailWrapper =
|
|
|
|
|
|
Wrappers.<WmsDeliveryWaybillDetail>lambdaQuery()
|
|
|
|
|
|
.in(WmsDeliveryWaybillDetail::getWaybillId, waybillIds)
|
|
|
|
|
|
.eq(WmsDeliveryWaybillDetail::getDelFlag, 0);
|
|
|
|
|
|
|
|
|
|
|
|
// 直接删除
|
|
|
|
|
|
waybillDetailMapper.delete(detailWrapper);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 再删除发货单主表
|
|
|
|
|
|
LambdaQueryWrapper<WmsDeliveryWaybill> waybillWrapper =
|
|
|
|
|
|
Wrappers.<WmsDeliveryWaybill>lambdaQuery()
|
|
|
|
|
|
.in(WmsDeliveryWaybill::getWaybillId, waybillIds)
|
|
|
|
|
|
.eq(WmsDeliveryWaybill::getDelFlag, 0);
|
|
|
|
|
|
waybillMapper.delete(waybillWrapper);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-11-25 15:44:19 +08:00
|
|
|
|
}
|