package org.jeecg.modules.mes.service.impl;
|
|
import cn.hutool.core.collection.CollectionUtil;
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
import com.baomidou.mybatisplus.core.metadata.IPage;
|
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
import org.jeecg.common.constant.CommonConstant;
|
import org.jeecg.common.exception.JeecgBootException;
|
import org.jeecg.modules.base.entity.Factory;
|
import org.jeecg.modules.base.entity.LineSideWarehouse;
|
import org.jeecg.modules.base.entity.Shift;
|
import org.jeecg.modules.base.entity.ShiftGroup;
|
import org.jeecg.modules.base.service.IFactoryService;
|
import org.jeecg.modules.base.service.ILineSideWarehouseService;
|
import org.jeecg.modules.base.service.IShiftGroupService;
|
import org.jeecg.modules.base.service.IShiftService;
|
import org.jeecg.modules.lsw.entity.LswMaterialInventory;
|
import org.jeecg.modules.lsw.service.ILswMaterialInventoryService;
|
import org.jeecg.modules.lsw.vo.LswMaterialInventoryVo;
|
import org.jeecg.modules.mes.dto.MesProductionWorkScheduleRequest;
|
import org.jeecg.modules.mes.entity.MesKittingCompletenessCheck;
|
import org.jeecg.modules.mes.entity.MesProductionOrder;
|
import org.jeecg.modules.mes.enums.ProductionOrderStatus;
|
import org.jeecg.modules.mes.service.IMesProductionOrderService;
|
import org.jeecg.modules.mes.service.IMesProductionWorkOrderService;
|
import org.jeecg.modules.mes.entity.MesProductionWorkOrder;
|
import org.jeecg.modules.mes.mapper.MesProductionWorkOrderMapper;
|
import org.jeecg.modules.pms.entity.PmsProcessBillMaterials;
|
import org.jeecg.modules.pms.entity.PmsProcessBillMaterialsDetail;
|
import org.jeecg.modules.pms.service.IPmsProcessBillMaterialsDetailService;
|
import org.jeecg.modules.pms.service.IPmsProcessBillMaterialsService;
|
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.stereotype.Service;
|
|
import java.math.BigDecimal;
|
import java.math.RoundingMode;
|
import java.time.LocalDate;
|
import java.time.ZoneId;
|
import java.time.temporal.ChronoUnit;
|
import java.util.*;
|
import java.util.stream.Collectors;
|
import java.util.stream.Stream;
|
|
/**
|
* @Description: 排产工单
|
* @Author: jeecg-boot
|
* @Date: 2025-07-04
|
* @Version: V1.0
|
*/
|
@Service
|
public class MesProductionWorkOrderServiceImpl extends ServiceImpl<MesProductionWorkOrderMapper, MesProductionWorkOrder> implements IMesProductionWorkOrderService {
|
@Autowired
|
private IShiftService shiftService;
|
@Autowired
|
private IShiftGroupService shiftGroupService;
|
@Autowired
|
private IFactoryService factoryService;
|
@Autowired
|
private IMesProductionOrderService mesProductionOrderService;
|
@Autowired
|
private IPmsProcessBillMaterialsService pmsProcessBillMaterialsService;
|
@Autowired
|
private IPmsProcessBillMaterialsDetailService pmsProcessBillMaterialsDetailService;
|
@Autowired
|
private ILswMaterialInventoryService lswMaterialInventoryService;
|
@Autowired
|
private ILineSideWarehouseService lineSideWarehouseService;
|
|
@Override
|
public List<MesProductionWorkOrder> schedule(MesProductionWorkScheduleRequest request) {
|
//查询起止日期范围内的排产计划,先排除
|
//查询该产线下所有的班次
|
Map<String, ShiftGroup> shiftGroupMap = shiftGroupService.list(new LambdaQueryWrapper<ShiftGroup>()
|
.eq(ShiftGroup::getFactoryId, request.getFactoryId())
|
.eq(ShiftGroup::getDelFlag, CommonConstant.DEL_FLAG_0))
|
.stream().collect(Collectors.toMap(ShiftGroup::getShiftId, v1 -> v1, (v1, v2) -> v1));
|
Factory factory = factoryService.getById(request.getFactoryId());
|
Map<String, Shift> shiftNameMap = new HashMap<>();
|
List<Shift> shifts = shiftService.list(new LambdaQueryWrapper<Shift>()
|
.in(Shift::getId, shiftGroupMap.keySet()));
|
shifts.forEach(shift -> shiftNameMap.put(shift.getId(), shift));
|
|
LocalDate startDate = request.getStartDate().toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
|
LocalDate endDate = request.getEndDate().toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
|
// 使用日期范围进行遍历处理
|
List<LocalDate> dateRange = Stream.iterate(startDate, date -> date.plusDays(1))
|
.limit(ChronoUnit.DAYS.between(startDate, endDate) + 1)
|
.collect(Collectors.toList());
|
List<MesProductionWorkOrder> newProductionWorkOrderList = CollectionUtil.newArrayList();
|
|
for (LocalDate date : dateRange) {
|
for (String shiftId : shiftGroupMap.keySet()) {
|
Date workOrderDate = Date.from(date.atStartOfDay(ZoneId.systemDefault()).toInstant());
|
//查询该产线、班次在该日期下是否有排产计划
|
Optional<MesProductionWorkOrder> optional = list(new LambdaQueryWrapper<MesProductionWorkOrder>()
|
.eq(MesProductionWorkOrder::getWorkOrderDate, workOrderDate)
|
.eq(MesProductionWorkOrder::getFactoryId, request.getFactoryId())
|
.eq(MesProductionWorkOrder::getShiftId, shiftId))
|
.stream().findAny();
|
if (!optional.isPresent()) {
|
ShiftGroup shiftGroup = shiftGroupMap.get(shiftId);
|
//没有,生成新排产计划
|
MesProductionWorkOrder mesProductionWorkOrder = new MesProductionWorkOrder()
|
.setFactoryId(factory.getId())
|
.setFactoryCode(factory.getFactoryCode())
|
.setFactoryName(factory.getFactoryName())
|
.setShiftId(shiftId)
|
.setShiftCode(shiftNameMap.get(shiftId).getShiftCode())
|
.setShiftName(shiftNameMap.get(shiftId).getShiftName())
|
.setGroupId(shiftGroup.getId())
|
.setGroupName(shiftGroup.getGroupName())
|
.setWorkOrderDate(workOrderDate);
|
|
newProductionWorkOrderList.add(mesProductionWorkOrder);
|
}
|
}
|
}
|
//如果为空,默认给一条,用于手动新增时表格的初始化
|
if (newProductionWorkOrderList.isEmpty()) {
|
MesProductionWorkOrder mesProductionWorkOrder = new MesProductionWorkOrder()
|
.setFactoryId(factory.getId())
|
.setFactoryCode(factory.getFactoryCode())
|
.setFactoryName(factory.getFactoryName());
|
newProductionWorkOrderList.add(mesProductionWorkOrder);
|
}
|
return newProductionWorkOrderList;
|
}
|
|
@Override
|
public IPage<MesProductionWorkOrder> queryPageList(Page<MesProductionWorkOrder> page, Map<String, String[]> parameterMap) {
|
QueryWrapper<MesProductionWorkOrder> queryWrapper = Wrappers.query();
|
String[] factoryIds = parameterMap.get("factoryId");
|
if (factoryIds != null && factoryIds.length > 0) {
|
queryWrapper.eq("t1.factory_id", factoryIds[0]);
|
}
|
String[] startDates = parameterMap.get("startDate");
|
String[] endDates = parameterMap.get("endDate");
|
if (startDates != null && startDates.length > 0) {
|
queryWrapper.ge("t1.work_order_date", startDates[0]);
|
}
|
if (endDates != null && endDates.length > 0) {
|
queryWrapper.le("t1.work_order_date", endDates[0]);
|
}
|
String[] workOrderStatuses = parameterMap.get("workOrderStatus");
|
if (workOrderStatuses != null && workOrderStatuses.length > 0) {
|
queryWrapper.eq("t1.work_order_status", workOrderStatuses[0]);
|
}
|
queryWrapper.eq("t1.del_flag", CommonConstant.DEL_FLAG_0);
|
queryWrapper.orderByAsc("t1.work_order_date");
|
return this.baseMapper.queryPageList(page, queryWrapper);
|
}
|
|
@Override
|
public List<MesKittingCompletenessCheck> workOrderCompletenessCheck(MesProductionWorkOrder workOrder) {
|
//根据当前排产工单确定生产订单
|
List<MesProductionOrder> orderList = mesProductionOrderService.list(new LambdaQueryWrapper<MesProductionOrder>()
|
.eq(MesProductionOrder::getMaterialNumber, workOrder.getMaterialNumber())
|
.eq(MesProductionOrder::getOrderStatus, ProductionOrderStatus.REL.name())
|
.eq(MesProductionOrder::getDelFlag, CommonConstant.DEL_FLAG_0)
|
.orderByAsc(MesProductionOrder::getPlanStart));
|
if (orderList.isEmpty()) {
|
throw new JeecgBootException("未找到该物料的关联生产订单!");
|
}
|
//默认取时间最早未完成的订单,也就是第一项
|
MesProductionOrder order = orderList.get(0);
|
//根据生产订单id和物料编码查询订单BOM
|
PmsProcessBillMaterials processBillMaterials = pmsProcessBillMaterialsService.list(new LambdaQueryWrapper<PmsProcessBillMaterials>()
|
.eq(PmsProcessBillMaterials::getOrderId, order.getId())
|
.eq(PmsProcessBillMaterials::getMaterialNumber, workOrder.getMaterialNumber()))
|
.stream().findFirst().orElse(null);
|
if (processBillMaterials == null) {
|
throw new JeecgBootException("未找到与该物料关联的订单BOM!");
|
}
|
//查询工单所属产线对应的线边仓
|
LineSideWarehouse lineSideWarehouse = lineSideWarehouseService.list(new LambdaQueryWrapper<LineSideWarehouse>()
|
.eq(LineSideWarehouse::getFactoryId, workOrder.getFactoryId())
|
.eq(LineSideWarehouse::getDelFlag, CommonConstant.DEL_FLAG_0)
|
.eq(LineSideWarehouse::getWarehouseStatus, CommonConstant.DEFAULT_1))
|
.stream().findFirst().orElse(null);
|
if (lineSideWarehouse == null) {
|
throw new JeecgBootException("该产线未配置线边仓!");
|
}
|
//订单BOM明细
|
List<PmsProcessBillMaterialsDetail> processBillMaterialsDetails = pmsProcessBillMaterialsDetailService.queryByMaterialId(processBillMaterials.getId());
|
//查询订单BOM明细中的物料在该产线线边仓中的库存
|
List<String> bomMaterialNumberList = processBillMaterialsDetails.stream()
|
.map(PmsProcessBillMaterialsDetail::getMaterialNumber).collect(Collectors.toList());
|
Map<String, LswMaterialInventoryVo> lswMaterialInventoryMap = lswMaterialInventoryService
|
.selectLineSideMaterialInventoryByMaterialNumber(bomMaterialNumberList, lineSideWarehouse.getId()).stream()
|
.collect(Collectors.toMap(LswMaterialInventoryVo::getMaterialNumber, v1 -> v1, (v1, v2) -> v1));
|
List<MesKittingCompletenessCheck> completenessCheckResultList = CollectionUtil.newArrayList();
|
//根据订单BOM明细列出齐套检查结果
|
for (PmsProcessBillMaterialsDetail processBillMaterialsDetail : processBillMaterialsDetails) {
|
LswMaterialInventoryVo materialInventoryVo = lswMaterialInventoryMap.get(processBillMaterialsDetail.getMaterialNumber());
|
MesKittingCompletenessCheck completenessCheckItem = new MesKittingCompletenessCheck()
|
.setMaterialNumber(processBillMaterialsDetail.getMaterialNumber())
|
.setMaterialName(processBillMaterialsDetail.getMaterialName())
|
//需求数量 = (bom明细的需求数量 / bom订单的数量) * 排产工单计划生产数量
|
.setRequiredQuantity(processBillMaterialsDetail.getUsageQuantity()
|
.divide(processBillMaterials.getProductionQuantity(), 2, RoundingMode.HALF_UP)
|
.multiply(workOrder.getPlanQuantity()))
|
.setActualQuantity(materialInventoryVo == null ? BigDecimal.ZERO : materialInventoryVo.getStockQuantity())
|
.setProductionUnit(processBillMaterialsDetail.getProductionUnit());
|
completenessCheckResultList.add(completenessCheckItem);
|
}
|
completenessCheckResultList.forEach(item -> {
|
if (item.getRequiredQuantity().compareTo(item.getActualQuantity()) > 0) {
|
item.setCheckFlag(CommonConstant.DEFAULT_0);
|
} else {
|
item.setCheckFlag(CommonConstant.DEFAULT_1);
|
}
|
});
|
return completenessCheckResultList;
|
}
|
}
|