排产相关-sjx

master
sunjianxi 1 day ago
parent 8e2a922f5b
commit df6c7b927f
  1. 4
      blade-service-api/blade-desk-api/src/main/java/org/springblade/desk/order/entity/YieldOrderCraft.java
  2. 2
      blade-service/blade-desk/src/main/java/org/springblade/desk/order/service/impl/YieldOrderServiceImpl.java
  3. 5
      blade-service/blade-scheduling/src/main/java/org/springblade/scheduling/scheduling/dto/WorkOrderDto.java
  4. 6
      blade-service/blade-scheduling/src/main/java/org/springblade/scheduling/scheduling/entity/EquipResourceEntity.java
  5. 8
      blade-service/blade-scheduling/src/main/java/org/springblade/scheduling/scheduling/entity/WorkOrderEntity.java
  6. 12
      blade-service/blade-scheduling/src/main/java/org/springblade/scheduling/scheduling/entity/WorkPlanEntity.java
  7. 18
      blade-service/blade-scheduling/src/main/java/org/springblade/scheduling/scheduling/entity/YieldOrderEntity.java
  8. 2
      blade-service/blade-scheduling/src/main/java/org/springblade/scheduling/scheduling/mapper/EquipResourceMapper.java
  9. 10
      blade-service/blade-scheduling/src/main/java/org/springblade/scheduling/scheduling/mapper/EquipResourceMapper.xml
  10. 3
      blade-service/blade-scheduling/src/main/java/org/springblade/scheduling/scheduling/mapper/WorkOrderMapper.java
  11. 18
      blade-service/blade-scheduling/src/main/java/org/springblade/scheduling/scheduling/mapper/WorkOrderMapper.xml
  12. 1
      blade-service/blade-scheduling/src/main/java/org/springblade/scheduling/scheduling/mapper/YieldOrderMapper.java
  13. 14
      blade-service/blade-scheduling/src/main/java/org/springblade/scheduling/scheduling/mapper/YieldOrderMapper.xml
  14. 2
      blade-service/blade-scheduling/src/main/java/org/springblade/scheduling/scheduling/service/IEquipResourceService.java
  15. 2
      blade-service/blade-scheduling/src/main/java/org/springblade/scheduling/scheduling/service/IYieldOrderService.java
  16. 10
      blade-service/blade-scheduling/src/main/java/org/springblade/scheduling/scheduling/service/impl/EquipResourceServiceImpl.java
  17. 430
      blade-service/blade-scheduling/src/main/java/org/springblade/scheduling/scheduling/service/impl/WorkOrderServiceImpl.java
  18. 5
      blade-service/blade-scheduling/src/main/java/org/springblade/scheduling/scheduling/service/impl/YieldOrderServiceImpl.java

@ -76,8 +76,8 @@ public class YieldOrderCraft extends BaseEntity {
/**
* 加工中心
*/
@TableField(value = "WORK_CENTER")
private Long workCenter;
@TableField(value = "WORK_CENTER_ID")
private Long workCenterId;
/**
* 加工班组

@ -306,7 +306,7 @@ public class YieldOrderServiceImpl extends BaseServiceImpl<YieldOrderMapper, Yie
craft.setRpId(craftJson.getLong("rpId"));
craft.setPpsId(craftJson.getLong("ppsId"));
craft.setMakeTeam(craftJson.getLong("makeTeam"));
craft.setWorkCenter(craftJson.getLong("wcId"));
craft.setWorkCenterId(craftJson.getLong("wcId"));
craft.setOcId(craftJson.getLong("ocId"));
craft.setCaId(craftJson.getLong("caId"));
craftList.add(craft);

@ -14,6 +14,10 @@ import lombok.Data;
@Data
public class WorkOrderDto {
private String woCode;
private String partCode;
private String cardNo;
private String batchNo;
private String currentProcessName;
private String processName;
private String startTime;
private String endTime;
@ -27,4 +31,5 @@ public class WorkOrderDto {
private String type;
private String orderStatus;
private String planStatus;
private String makeQty;
}

@ -145,6 +145,12 @@ public class EquipResourceEntity extends BaseEntity {
@Schema(description = "设备顺序")
private Integer equipOrder;
/**
* 设备顺序
*/
@Schema(description = "设备顺序")
private Long workCenterId;

@ -25,6 +25,7 @@
*/
package org.springblade.scheduling.scheduling.entity;
import com.baomidou.mybatisplus.annotation.TableField;
import lombok.Data;
import io.swagger.v3.oas.annotations.media.Schema;
import com.baomidou.mybatisplus.annotation.TableName;
@ -323,4 +324,11 @@ public class WorkOrderEntity extends BaseEntity {
@Schema(description = "计划开始日期")
private String planStartDate;
/**
* 零件号
*/
@Schema(description = "零件号")
private String partCode;
}

@ -230,4 +230,16 @@ public class WorkPlanEntity extends BaseEntity {
@Schema(description = "设备名称")
private String equipName;
/**
* 占用设备资源ID
*/
@Schema(description = "占用设备资源ID")
private Long equipResourceId;
/**
* 占用人力资源ID
*/
@Schema(description = "占用设备资源ID")
private String personResourceIds;
}

@ -340,4 +340,22 @@ public class YieldOrderEntity extends TenantEntity {
@TableField(value = "ERROR_INFO")
private String errorInfo;
/**
* 接收状态, 0未接收1已接收
*/
@TableField(value = "RECEIVE_STATUS")
private Integer receiveStatus;
/**
* 接收人
*/
@TableField(value = "RECEIVE_USER")
private Long receiveUser;
/**
* 接收时间
*/
@TableField(value = "RECEIVE_TIME")
private Date receiveTime;
}

@ -63,5 +63,7 @@ public interface EquipResourceMapper extends BaseMapper<EquipResourceEntity> {
List<Map<String,Object>> selectTeamByWorkCenter(@Param("workCenterId") Long workCenterId);
List<EquipResourceEntity> selectCommonCraftList();
}

@ -45,4 +45,14 @@
and a.work_center_id = #{workCenterId}
</select>
<select id="selectCommonCraftList" resultMap="equipResourceResultMap">
SELECT
*
FROM
MES_EQUIP_RESOURCE a
WHERE
CRAFT_ID = '27'
AND id > ( SELECT max( id ) FROM MES_EQUIP_RESOURCE WHERE is_used = '1' AND CRAFT_ID = '27' ) order by date_time,start_time
</select>
</mapper>

@ -64,4 +64,7 @@ public interface WorkOrderMapper extends BaseMapper<WorkOrderEntity> {
List<WorkOrderDto> selectWorkOrderList(WorkOrderDto workOrderDto);
String getMaxByCodePattern(@Param("woCode") String woCode);
}

@ -88,6 +88,11 @@
<select id="selectWorkOrderList" resultType="org.springblade.scheduling.scheduling.dto.WorkOrderDto">
SELECT
a.wo_code AS "woCode",
a.part_code AS "partCode",
a.batch_no AS "batchNo",
a.make_qty AS "makeQty",
a.card_no AS "cardNO",
f.name AS "currentProcessName",
d.name AS "processName",
to_char(b.start_time,'HH24:MI') AS "startTime",
to_char(b.end_time,'HH24:MI') AS "endTime",
@ -105,9 +110,11 @@
LEFT JOIN MES_WORK_PLAN b ON a.ID = b.WO_ID
LEFT JOIN BS_TEAM_SET c ON b.MAKE_TEAM = c.ID
LEFT JOIN BS_PROCESS_SET d ON b.pps_id = d.id
LEFT JOIN MES_WORK_PLAN e on a.wp_id = e.id
LEFT JOIN BS_PROCESS_SET f on e.pps_id = f.id
<where>
<if test="startTime !=null and startTime != ''">
and to_char(b.start_time,'YYYY-MM-DD') = #{startTime}
and (to_char(b.start_time,'YYYY-MM-DD') = #{startTime} or b.end_time <![CDATA[ > ]]> to_date(CONCAT(#{startTime},' 00:00:00'),'YYYY-MM-DD HH24:MI:SS'))
</if>
<if test="woCode !=null and woCode != ''">
and a.wo_code = #{woCode}
@ -122,4 +129,13 @@
order by a.WO_CODE,b.start_time
</select>
<select id="getMaxByCodePattern" resultType="java.lang.String">
SELECT
max(wo_code) as "woCode"
FROM
MES_WORK_ORDER
WHERE
wo_code LIKE concat(#{woCode},'%')
</select>
</mapper>

@ -61,4 +61,5 @@ public interface YieldOrderMapper extends BaseMapper<YieldOrderEntity> {
*/
List<YieldOrderExcel> export(@Param("ew") Wrapper<YieldOrderEntity> queryWrapper);
List<YieldOrderEntity> selectCommonCraftOrderList();
}

@ -85,4 +85,18 @@
SELECT * FROM MES_YIELD_ORDER ${ew.customSqlSegment}
</select>
<select id="selectCommonCraftOrderList" resultMap="yieldOrderResultMap">
SELECT
b.*
FROM
MES_YIELD_ORDER_CRAFT a
LEFT JOIN MES_YIELD_ORDER b ON a.YO_ID = b.ID
WHERE
a.WORK_CENTER_ID IN ( '122', '162', '184' )
AND b.STATUS = 3
ORDER BY
b.WORK_CENTER_ID,
b.PRIORITY_APS
</select>
</mapper>

@ -60,4 +60,6 @@ public interface IEquipResourceService extends BaseService<EquipResourceEntity>
public void initEquipResource();
List<EquipResourceEntity> selectCommonCraftList();
}

@ -59,4 +59,6 @@ public interface IYieldOrderService extends BaseService<YieldOrderEntity> {
*/
List<YieldOrderExcel> export(Wrapper<YieldOrderEntity> queryWrapper);
List<YieldOrderEntity> selectCommonCraftOrderList();
}

@ -97,10 +97,15 @@ public class EquipResourceServiceImpl extends BaseServiceImpl<EquipResourceMappe
}
}
@Override
public List<EquipResourceEntity> selectCommonCraftList() {
return null;
}
public void generateData(String day){
//获取设备能力列表
List<EquipAbilityEntity> equipAbilityList = equipAbilityService.list();
List<EquipAbilityEntity> equipAbilityList = equipAbilityService.list(Wrappers.<EquipAbilityEntity>lambdaQuery().isNotNull(EquipAbilityEntity::getStandardTime));
if(CollectionUtils.isNotEmpty(equipAbilityList)){
DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
DateTimeFormatter timeFormatter = DateTimeFormatter.ofPattern("HH:mm");
@ -135,6 +140,7 @@ public class EquipResourceServiceImpl extends BaseServiceImpl<EquipResourceMappe
equipResource.setStandardTime(equipAbility.getStandardTime());
equipResource.setIsUsed("0");
equipResource.setEquipType(equipAbility.getEquipType());
equipResource.setWorkCenterId(equipAbility.getWorkCenterId());
Long teamId = null;
for(Map<String,Object> map : teamIdList){
@ -179,7 +185,7 @@ public class EquipResourceServiceImpl extends BaseServiceImpl<EquipResourceMappe
equipResource.setStandardTime(equipAbility.getStandardTime());
equipResource.setIsUsed("0");
equipResource.setEquipType(equipAbility.getEquipType());
equipResource.setWorkCenterId(equipAbility.getWorkCenterId());
Long teamId = null;
for(Map<String,Object> map : teamIdList){

@ -30,9 +30,9 @@ import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.AllArgsConstructor;
import org.apache.commons.collections4.CollectionUtils;
import org.springblade.common.constant.YieldOrderConst;
import org.springblade.core.mp.base.BaseEntity;
import org.springblade.core.mp.base.BaseServiceImpl;
@ -112,20 +112,22 @@ public class WorkOrderServiceImpl extends BaseServiceImpl<WorkOrderMapper, WorkO
//查询待排产订单,状态是3
List<YieldOrderEntity> list = yieldOrderService.list(Wrappers.<YieldOrderEntity>lambdaQuery().eq(BaseEntity::getStatus, YieldOrderConst.STATUS_APS));
if (CollectionUtils.isNotEmpty(list)) {
//校验已排产订单
checkSchedulingOrder(list);
//初始化人员能力
List<PersonAbilityEntity> personAbilityEntityList = personAbilityService.list();
List<PersonAbilityEntity> personAbilityEntityList = personAbilityService.list(Wrappers.<PersonAbilityEntity>lambdaQuery().isNotNull(PersonAbilityEntity::getWorkCenterId).isNotNull(PersonAbilityEntity::getProcessId).isNotNull(PersonAbilityEntity::getCraftId));
Map<String, PersonAbilityEntity> personAbilityMap = new HashMap<>();
personAbilityEntityList.forEach(personAbility -> {
personAbilityMap.put(personAbility.getWorkCenterId() + "-" + personAbility.getProcessId() + "-" + personAbility.getCraftId(), personAbility);
});
//初始化主生产者
List<MainProducerEntity> mainProducerList = mainProducerService.list();
List<MainProducerEntity> mainProducerList = mainProducerService.list(Wrappers.<MainProducerEntity>lambdaQuery().isNotNull(MainProducerEntity::getProcessId));
Map<Long, String> mainProducerMap = new HashMap<>();
mainProducerList.forEach(item -> {
mainProducerMap.put(item.getProcessId(), item.getMainProducer());
});
//计算cr值
calculateCr(list);
// calculateCr(list);
//根据作业中心将订单分组,并根据优先级、cr值、订单需求数量、计划下达时间4个维度进行组内排序
Map<Long, List<YieldOrderEntity>> map =
list.stream()
@ -137,20 +139,22 @@ public class WorkOrderServiceImpl extends BaseServiceImpl<WorkOrderMapper, WorkO
list1 -> {
// 排序逻辑:优先级升序 → CR值降序 → 数量降序 → 时间升序
list1.sort(Comparator.comparingInt(YieldOrderEntity::getPriorityAps).reversed()
.thenComparing((e1, e2) -> e2.getCrValue().compareTo(e1.getCrValue()))
//.thenComparing((e1, e2) -> e2.getCrValue().compareTo(e1.getCrValue()))
.thenComparingInt(YieldOrderEntity::getYpQty).reversed()
.thenComparing(YieldOrderEntity::getReleaseDate));
return list1;
}
)
));
//处理带有公共前置工序的订单
Map<String,List<WorkPlanEntity>> planMap = dealCommonCraftOrders();
//多线程排产
ExecutorService threadPool = new ThreadPoolExecutor(
map.size(), map.size(), 0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<>(),
r -> new Thread(r, "scheduling-thread-" + System.currentTimeMillis()));
map.forEach((workcenter, orders) -> {
threadPool.execute(() -> allocateResources(orders,personAbilityMap,mainProducerMap));
threadPool.execute(() -> allocateResources(orders,personAbilityMap,mainProducerMap,planMap));
});
}
@ -186,6 +190,12 @@ public class WorkOrderServiceImpl extends BaseServiceImpl<WorkOrderMapper, WorkO
mergedDto.setWoCode(woCode);
mergedDto.setProcessName(processName);
for(WorkOrderDto dto : processList){
mergedDto.setTeamName(dto.getTeamName());
mergedDto.setCardNo(dto.getCardNo());
mergedDto.setBatchNo(dto.getBatchNo());
mergedDto.setPartCode(dto.getPartCode());
mergedDto.setCurrentProcessName(dto.getCurrentProcessName());
mergedDto.setMakeQty(dto.getMakeQty());
if(dto.getPlanStartTime().equals(minStartTime)){
mergedDto.setStartTime(dto.getStartTime());
}
@ -194,11 +204,19 @@ public class WorkOrderServiceImpl extends BaseServiceImpl<WorkOrderMapper, WorkO
mergedDto.setPlanStatus(dto.getPlanStatus());
}
}
//处理跨天的工序
if(!maxEndTime.substring(0,10).equals(minStartTime.substring(0,10))){
mergedDto.setEndTime("24:00");
if(minStartTime.substring(0,10).equals(workOrder.getStartTime())){
mergedDto.setEndTime("24:00");
}
if(maxEndTime.substring(0,10).equals(workOrder.getStartTime())){
mergedDto.setStartTime("0:00");
}
}
mergedDto.setPlanStartTime(minStartTime);
mergedDto.setPlanEndTime(maxEndTime);
mergedProcessList.add(mergedDto);
}
@ -271,6 +289,11 @@ public class WorkOrderServiceImpl extends BaseServiceImpl<WorkOrderMapper, WorkO
workOrderDto.setFactEndTime(maxFactEndTime);
workOrderDto.setTeamName(teamName);
workOrderDto.setOrderStatus(woList.get(0).getOrderStatus());
workOrderDto.setPartCode(woList.get(0).getPartCode());
workOrderDto.setBatchNo(woList.get(0).getBatchNo());
workOrderDto.setCardNo(woList.get(0).getCardNo());
workOrderDto.setCurrentProcessName(woList.get(0).getCurrentProcessName());
workOrderDto.setMakeQty(woList.get(0).getMakeQty());
list1.add(workOrderDto);
}
resultList.put(teamName,list1);
@ -342,6 +365,11 @@ public class WorkOrderServiceImpl extends BaseServiceImpl<WorkOrderMapper, WorkO
workOrderDto.setEndTime(maxEndTime);
workOrderDto.setEquipName(equipName);
workOrderDto.setOrderStatus(woList.get(0).getOrderStatus());
workOrderDto.setPartCode(woList.get(0).getPartCode());
workOrderDto.setBatchNo(woList.get(0).getBatchNo());
workOrderDto.setCardNo(woList.get(0).getCardNo());
workOrderDto.setCurrentProcessName(woList.get(0).getCurrentProcessName());
workOrderDto.setMakeQty(woList.get(0).getMakeQty());
list1.add(workOrderDto);
}
resultList.put(equipName,list1);
@ -393,61 +421,6 @@ public class WorkOrderServiceImpl extends BaseServiceImpl<WorkOrderMapper, WorkO
}
}
/**
* 处理有前置公共工序的分组WC=镀金大批量镀金小批量镀银轮流每次取指定数量进行资源匹配
*/
private void processPublicProcessGroups(Map<String, List<YieldOrderEntity>> groupedMap, int batchSize) {
// 筛选出需要处理的公共工序分组
List<String> publicProcessWC = Arrays.asList("008", "009", "012");
Map<String, Iterator<YieldOrderEntity>> wcIterators = new HashMap<>();
// 为每个公共工序分组创建迭代器
for (String wc : publicProcessWC) {
if (groupedMap.containsKey(wc)) {
wcIterators.put(wc, groupedMap.get(wc).iterator());
}
}
// 转换为List,保证迭代顺序(Map的values()顺序不保证,用List固定顺序)
List<Iterator<YieldOrderEntity>> iteratorList = wcIterators.values().stream()
.filter(Objects::nonNull) // 过滤null迭代器
.filter(Iterator::hasNext) // 过滤已耗尽的迭代器
.collect(Collectors.toList());
int batchNumber = 1;
boolean hasMoreElements = true;
while (hasMoreElements) {
hasMoreElements = false; // 默认无更多元素,后续有元素则置为true
// 遍历所有迭代器,逐个轮换处理
for (int i = 0; i < iteratorList.size(); i++) {
Iterator<YieldOrderEntity> currentIterator = iteratorList.get(i);
List<YieldOrderEntity> currentBatch = new ArrayList<>(batchSize);
// 从当前迭代器取元素:最多取5个,或取完剩余所有
int count = 0;
while (currentIterator.hasNext() && count < batchSize) {
currentBatch.add(currentIterator.next());
count++;
hasMoreElements = true; // 标记有未处理元素
}
// 若当前批次有元素,执行资源匹配
if (!currentBatch.isEmpty()) {
System.out.printf("=== 第%d批资源匹配(迭代器索引:%d,批次大小:%d)===\n",
batchNumber, i, currentBatch.size());
// allocateResources(currentBatch); // 实际业务处理
batchNumber++;
}
// 优化:若当前迭代器已耗尽,从列表中移除(避免后续无效遍历)
if (!currentIterator.hasNext()) {
iteratorList.remove(i);
i--; // 移除后索引前移,避免跳过下一个迭代器
}
}
}
}
/**
* TODO:资源匹配不含超声波水洗
@ -458,31 +431,57 @@ public class WorkOrderServiceImpl extends BaseServiceImpl<WorkOrderMapper, WorkO
* @since 2025/12/1 18:08
**/
@Transactional(rollbackFor = Exception.class)
public void allocateResources(List<YieldOrderEntity> list,Map<String, PersonAbilityEntity> personAbilityMap,Map<Long, String> mainProducerMap) {
public void allocateResources(List<YieldOrderEntity> list,Map<String, PersonAbilityEntity> personAbilityMap,Map<Long, String> mainProducerMap,Map<String,List<WorkPlanEntity>> planMap) {
for (YieldOrderEntity order : list) {
//是否可以排产
Boolean isSchecuding = false;
Boolean isSchecuding = true;
List<WorkPlanEntity> workPlanList = new ArrayList<>();
//查询所有工序
List<YieldOrderCraftEntity> craftList = yieldOrderCraftService.list(Wrappers.<YieldOrderCraftEntity>lambdaQuery().eq(YieldOrderCraftEntity::getYoId, order.getId()).orderByAsc(YieldOrderCraftEntity::getProcessNo));
List<Long> workCenterList = craftList.stream().map(YieldOrderCraftEntity::getWorkCenterId).collect(Collectors.toList());
//根据作业中心查询所有设备
List<EquipAbilityEntity> equipAbilityList = equipAbilityService.list(Wrappers.<EquipAbilityEntity>lambdaQuery().in(EquipAbilityEntity::getWorkCenterId, workCenterList));
Map<Integer,List<EquipAbilityEntity>> equipAbilityMap = equipAbilityList.stream().collect(Collectors.groupingBy(EquipAbilityEntity::getEquipOrder));
List<Long> workCenterList = craftList.stream().filter(item -> item.getWorkCenterId() != null).map(YieldOrderCraftEntity::getWorkCenterId).collect(Collectors.toList());
if(workCenterList.size() != craftList.size()){
order.setErrorInfo("工序信息不完整,含有未匹配作业中心的工序");
order.setStatus(6);
yieldOrderService.updateById(order);
continue;
}
//上一道工序结束时间
LocalDateTime prevProcessEnd = LocalDateTime.now();
//判断是否有公共工序已经处理了,如果有则重新定义workPlanList,获取公共工序的最后结束时间和当前时间做比较,取大的作为上一道工序结束时间
if(planMap.containsKey(order.getYoCode())){
workPlanList = planMap.get(order.getYoCode());
prevProcessEnd = prevProcessEnd.compareTo(workPlanList.get(workPlanList.size()-1).getEndTime()) > 0 ? prevProcessEnd : workPlanList.get(workPlanList.size()-1).getEndTime();
}
for (int i = 0; i < craftList.size(); i++) {
YieldOrderCraftEntity craft = craftList.get(i);
if ("设备".equals(mainProducerMap.get(craft.getPpsId()))) {
//根据作业中心查询所有设备
List<EquipAbilityEntity> equipAbilityList = equipAbilityService.list(Wrappers.<EquipAbilityEntity>lambdaQuery().in(EquipAbilityEntity::getWorkCenterId, craft.getWorkCenterId()));
if(CollectionUtils.isEmpty(equipAbilityList)){
order.setErrorInfo("设备未匹配到对应的设备能力");
order.setStatus(6);
yieldOrderService.updateById(order);
isSchecuding = false;
break;
}
Map<Integer,List<EquipAbilityEntity>> equipAbilityMap = equipAbilityList.stream().collect(Collectors.groupingBy(EquipAbilityEntity::getEquipOrder));
//匹配设备资源
//获取下一个整数点
LocalDateTime dateTime = getNextIntegerTime(prevProcessEnd);
for(Map.Entry<Integer,List<EquipAbilityEntity>> entry : equipAbilityMap.entrySet()){
//根据时间点获取所有设备资源
List<EquipResourceEntity> equipResourceList = equipResourceService.list(Wrappers.<EquipResourceEntity>lambdaQuery().ge(EquipResourceEntity::getStartTime, dateTime).eq(EquipResourceEntity::getIsUsed, 0).in(EquipResourceEntity::getEquipOrder, entry.getKey()));
List<EquipResourceEntity> equipResourceList = equipResourceService.list(Wrappers.<EquipResourceEntity>lambdaQuery().eq(EquipResourceEntity::getCraftId,craft.getCaId()).eq(EquipResourceEntity::getWorkCenterId,craft.getWorkCenterId()).ge(EquipResourceEntity::getStartTime, dateTime).eq(EquipResourceEntity::getIsUsed, 0).in(EquipResourceEntity::getEquipOrder, entry.getKey()));
if(CollectionUtils.isEmpty(equipResourceList)){
order.setStatus(6);
order.setErrorInfo("工序:"+craft+"未匹配到对应的设备资源");
yieldOrderService.updateById(order);
isSchecuding = false;
break;
}
//设备资源按照时间段分组并按时间排序,然后再每个组内按照剩余产能倒序排序
Map<LocalDateTime, List<EquipResourceEntity>> equipResourceMap = equipResourceList.stream()
.collect(Collectors.groupingBy(
@ -537,6 +536,7 @@ public class WorkOrderServiceImpl extends BaseServiceImpl<WorkOrderMapper, WorkO
workPlan.setHourQuota(BigDecimal.valueOf(ChronoUnit.MINUTES.between(workPlan.getStartTime(), workPlan.getEndTime())));
workPlan.setEquipCode(equipResource.getEquipCode());
workPlan.setEquipName(equipResource.getEquipName());
workPlan.setEquipResourceId(equipResource.getId());
workPlanList.add(workPlan);
//更新剩余产能
equipResource.setRestCapacity(equipResource.getRestCapacity().subtract(capacity));
@ -558,7 +558,6 @@ public class WorkOrderServiceImpl extends BaseServiceImpl<WorkOrderMapper, WorkO
prevProcessEnd = workPlan.getEndTime();
dateTime = workPlan.getEndTime();
isOccupied = true;
isSchecuding = true;
break;
}
}
@ -568,15 +567,30 @@ public class WorkOrderServiceImpl extends BaseServiceImpl<WorkOrderMapper, WorkO
}
}
}
if(!isSchecuding){
break;
}
} else {
} else if ("人".equals(mainProducerMap.get(craft.getPpsId()))) {
//匹配人资源
/* String personAbility = craft.getWorkCenterId() + "-" + craft.getPpsId() + "-" + craft.getCaId();
if (personAbilityMap.containsKey(craft.getWorkCenterId() + "-" + craft.getPpsId() + "-" + craft.getCaId())) {
WorkPlanEntity workPlan = new WorkPlanEntity();
BigDecimal totalTime = new BigDecimal(0);
totalTime = totalTime.add(BigDecimal.valueOf(order.getYpQty()).multiply(personAbilityMap.get(craft.getWorkCenterId() + "-" + craft.getPpsId() + "-" + craft.getCaId()).getStandardTime()).add(personAbilityMap.get(craft.getWorkCenterId() + "-" + craft.getPpsId() + "-" + craft.getCaId()).getPrepareTime()));
} else {
order.setStatus(6);
order.setErrorInfo("工序:"+personAbility+"未匹配到对应的人员能力");
yieldOrderService.updateById(order);
isSchecuding = false;
break;
}*/
WorkPlanEntity workPlan = new WorkPlanEntity();
BigDecimal totalTime = new BigDecimal(0);
PersonAbilityEntity ability = personAbilityMap.get(craft.getWorkCenterId() + "-" + craft.getPpsId() + "-" + craft.getCaId());
//由于客户提供的数据不全,先判断有没有对应的能力,如果没有先不计算时间
if(ability != null){
totalTime = totalTime.add(BigDecimal.valueOf(order.getYpQty()).multiply(personAbilityMap.get(craft.getWorkCenterId() + "-" + craft.getPpsId() + "-" + craft.getCaId()).getStandardTime()).add(personAbilityMap.get(craft.getWorkCenterId() + "-" + craft.getPpsId() + "-" + craft.getCaId()).getPrepareTime()));
}
if(totalTime.compareTo(new BigDecimal(0)) > 0){
//通过加锁的方式保证每次查询到的人力资源都是最新的
Long craftId = craft.getCaId();
Lock craftLock = getCraftLock(craftId);
@ -596,11 +610,17 @@ public class WorkOrderServiceImpl extends BaseServiceImpl<WorkOrderMapper, WorkO
if(isUsedIndex != -1){
personResourceList = personResourceList.subList(isUsedIndex + 1, personResourceList.size());
}
//如果size=0,说明最近3天的资源都排满了,就不需要排了
if(personResourceList.size() == 0){
break;
}
//计算加工时间占几个人力片段
int period = totalTime.divide(BigDecimal.valueOf(30),0, RoundingMode.CEILING).intValue();
//占用时间段
LocalDateTime startTime = LocalDateTime.now();
LocalDateTime endTime = LocalDateTime.now();
StringBuilder personResourceIds = new StringBuilder();
for(int j=0;j<period;j++){
PersonResourceEntity personResource = personResourceList.get(j);
@ -612,48 +632,58 @@ public class WorkOrderServiceImpl extends BaseServiceImpl<WorkOrderMapper, WorkO
}
personResource.setIsUsed("1");
personResourceService.updateById(personResource);
if(j!=period-1){
personResourceIds.append(personResource.getId()).append(",");
}else{
personResourceIds.append(personResource.getId());
}
}
workPlan.setPersonResourceIds(personResourceIds.toString());
workPlan.setStartTime(startTime);
workPlan.setEndTime(endTime);
workPlan.setMakeTeam(personResourceList.get(0).getTeamId());
prevProcessEnd = endTime;
}
}finally {
craftLock.unlock(); // 释放本地锁
}
workPlan.setWoId(order.getId());
workPlan.setCaId(craft.getCaId());
workPlan.setPpsId(craft.getPpsId());
workPlan.setWorkQty(order.getYpQty());
workPlan.setHourQuota(totalTime);
workPlan.setWorkCenterId(craft.getWorkCenterId());
workPlan.setOrders(craft.getProcessNo());
workPlan.setOem("0");
workPlan.setTestQty(0);
workPlan.setQualifiedQty(0);
workPlan.setUnqualifiedQty(0);
workPlan.setScrapQty(0);
workPlanList.add(workPlan);
} else {
order.setStatus(6);
order.setErrorInfo("未匹配到对应的人员能力");
System.out.println("未匹配到对应的人员能力!");
}
workPlan.setWoId(order.getId());
workPlan.setCaId(craft.getCaId());
workPlan.setPpsId(craft.getPpsId());
workPlan.setWorkQty(order.getYpQty());
workPlan.setHourQuota(totalTime);
workPlan.setWorkCenterId(craft.getWorkCenterId());
workPlan.setOrders(craft.getProcessNo());
workPlan.setOem("0");
workPlan.setTestQty(0);
workPlan.setQualifiedQty(0);
workPlan.setUnqualifiedQty(0);
workPlan.setScrapQty(0);
workPlanList.add(workPlan);
}else{
//未匹配到设备和人力资源,将工序状态改为6,标识为未排产
craft.setStatus(6);
yieldOrderCraftService.updateById(craft);
}
if(!isSchecuding){
break;
}
}
if(isSchecuding == false){
workPlanList.clear();
System.out.println("订单生产量超过设备最大生产量,无法生产");
if(!isSchecuding){
continue;
}
if (CollectionUtils.isNotEmpty(workPlanList)) {
//为人员工序赋值开始结束时间
WorkPlanTimeCalculator(workPlanList);
//新增车间订单和车间计划
WorkOrderEntity workOrder = new WorkOrderEntity();
workOrder.setWoCode(order.getYoCode());
workOrder.setWoCode(this.nextCode(order.getYpCode()));
workOrder.setCardNo(order.getCardNo());
workOrder.setBatchNo(order.getBatchNo());
workOrder.setYoId(order.getId());
@ -673,6 +703,7 @@ public class WorkOrderServiceImpl extends BaseServiceImpl<WorkOrderMapper, WorkO
workOrder.setPushFlag("0");
workOrder.setQuotaExceptional("0");
workOrder.setReInStore("0");
workOrder.setPartCode(order.getPartCode());
this.save(workOrder);
workPlanList.forEach(workPlanEntity -> {
@ -854,4 +885,205 @@ public class WorkOrderServiceImpl extends BaseServiceImpl<WorkOrderMapper, WorkO
.map(dt -> dt.format(dateTimeFormatter))
.orElse(null);
}
public void checkSchedulingOrder(List<YieldOrderEntity> list){
//判断待排产优先级,1级所有1级往后订单重新排产,2级订单重新排4/5级订单
List<Integer> priorityList = list.stream().map(YieldOrderEntity::getPriorityAps).collect(Collectors.toList());
if(priorityList.contains(1)){
//查询所有非一级的待生产订单
List<YieldOrderEntity> schedulingOrderList = yieldOrderService.list(Wrappers.<YieldOrderEntity>lambdaQuery().ne(YieldOrderEntity::getPriorityAps,1).eq(YieldOrderEntity::getStatus,4));
//校验已排产订单资源占用情况
checkResource(schedulingOrderList);
}
if(priorityList.contains(2)){
//查询4/5级的待生产订单
List<YieldOrderEntity> schedulingOrderList = yieldOrderService.list(Wrappers.<YieldOrderEntity>lambdaQuery().in(YieldOrderEntity::getPriorityAps,Arrays.asList("4","5")).eq(YieldOrderEntity::getStatus,4));
checkResource(schedulingOrderList);
}
}
public void checkResource(List<YieldOrderEntity> list){
if(CollectionUtils.isNotEmpty(list)){
//根据订单查询设备资源
for(YieldOrderEntity yieldOrder : list){
//查询相关车间订单
WorkOrderEntity workOrder = this.getOne(Wrappers.<WorkOrderEntity>lambdaQuery().eq(WorkOrderEntity::getYoId,yieldOrder.getId()));
List<WorkPlanEntity> schedulingPlanList = workPlanService.list(Wrappers.<WorkPlanEntity>lambdaQuery().eq(WorkPlanEntity::getWoId,workOrder.getId()));
if(CollectionUtils.isNotEmpty(schedulingPlanList)){
for(WorkPlanEntity workPlan : schedulingPlanList){
//还原设备资源
if(workPlan.getEquipResourceId() != null){
EquipResourceEntity equipResource = equipResourceService.getById(workPlan.getEquipResourceId());
equipResource.setIsUsed("0");
equipResource.setRestCapacity(equipResource.getRestCapacity().add(workPlan.getHourQuota()));
equipResourceService.updateById(equipResource);
}
//还原人力资源
if(workPlan.getPersonResourceIds() != null){
List<PersonResourceEntity> personResourceList = personResourceService.list(Wrappers.<PersonResourceEntity>lambdaQuery().in(BaseEntity::getId,workPlan.getPersonResourceIds().split(",")));
if(CollectionUtils.isNotEmpty(personResourceList)){
personResourceList.forEach(item ->{
item.setIsUsed("0");
personResourceService.updateById(item);
});
}
}
workPlan.setIsDeleted(1);
workPlanService.updateById(workPlan);
}
}
workOrder.setIsDeleted(1);
this.updateById(workOrder);
yieldOrder.setStatus(3);
yieldOrderService.updateById(yieldOrder);
}
}
}
public List<YieldOrderEntity> sortByWorkcenterIdPer5Group(List<YieldOrderEntity> list) {
// 按 workcenterId 分组(保留原列表中该 workcenterId 的顺序)
Map<Long, List<YieldOrderEntity>> groupByWorkcenter = list.stream()
.collect(Collectors.groupingBy(
YieldOrderEntity::getWorkCenterId,
LinkedHashMap::new, // 保留分组的插入顺序(可选,按业务需求)
Collectors.toList()
));
// 对每个分组按每5个拆分批次,记录所有批次
// key: workcenterId, value: 该workcenterId的批次列表(每个批次最多5个元素)
Map<Long, List<List<YieldOrderEntity>>> batchMap = new LinkedHashMap<>();
int maxBatchCount = 0; // 所有分组中最大的批次数量(用于轮询)
for (Map.Entry<Long, List<YieldOrderEntity>> entry : groupByWorkcenter.entrySet()) {
Long workCenterId = entry.getKey();
List<YieldOrderEntity> entityList = entry.getValue();
// 拆分批次(每5个一组)
List<List<YieldOrderEntity>> batches = splitListPer5(entityList);
batchMap.put(workCenterId, batches);
// 更新最大批次数量
maxBatchCount = Math.max(maxBatchCount, batches.size());
}
// 轮询每个批次,拼接最终列表
List<YieldOrderEntity> resultList = new ArrayList<>();
for (int batchIndex = 0; batchIndex < maxBatchCount; batchIndex++) {
// 遍历每个workcenterId,取当前批次的元素
for (List<List<YieldOrderEntity>> batches : batchMap.values()) {
// 若当前批次存在,则加入结果列表
if (batchIndex < batches.size()) {
resultList.addAll(batches.get(batchIndex));
}
}
}
return resultList;
}
/**
* 将列表按每5个元素拆分最后一批可不足5个
*/
private List<List<YieldOrderEntity>> splitListPer5(List<YieldOrderEntity> list) {
List<List<YieldOrderEntity>> batches = new ArrayList<>();
int size = list.size();
int batchSize = 5;
for (int i = 0; i < size; i += batchSize) {
int end = Math.min(i + batchSize, size);
batches.add(list.subList(i, end));
}
return batches;
}
public Map<String,List<WorkPlanEntity>> dealCommonCraftOrders(){
List<YieldOrderEntity> commonCraftOrderList = yieldOrderService.selectCommonCraftOrderList();
Map<String,List<WorkPlanEntity>> planMap = new HashMap<>();
if(CollectionUtils.isNotEmpty(commonCraftOrderList)){
//对订单进行排序,每5个相同workCenterId的为一组,实现负载均衡
commonCraftOrderList = sortByWorkcenterIdPer5Group(commonCraftOrderList);
//对前置公共工序进行排产
//获取公共工序设备能力,根据工艺能力查询,写死ID是27
EquipAbilityEntity equipAbility = equipAbilityService.getOne(Wrappers.<EquipAbilityEntity>lambdaQuery().eq(EquipAbilityEntity::getCraftId,27));
BigDecimal standardProcessAbility = equipAbility.getStandardProcessAbility();
//获取所有空闲的公共工序资源
List<EquipResourceEntity> equipResourceList = equipResourceService.selectCommonCraftList();
for(YieldOrderEntity order : commonCraftOrderList){
List<WorkPlanEntity> workPlanList = new ArrayList<>();
//获取相关工序
YieldOrderCraftEntity craft = yieldOrderCraftService.getOne(Wrappers.<YieldOrderCraftEntity>lambdaQuery().eq(YieldOrderCraftEntity::getYoId,order.getId()).eq(YieldOrderCraftEntity::getCaId,equipAbility.getCraftId()));
//计算订单总产能
BigDecimal sumCapacity = order.getYpArea().multiply(BigDecimal.valueOf(100)).multiply(BigDecimal.valueOf(order.getYpQty()));
//计算需要占用几个时间段
int period = sumCapacity.divide(standardProcessAbility,0, RoundingMode.CEILING).intValue();
for(int i=0;i<period;i++){
for(int j=0;j<equipResourceList.size();j++){
if(i==j){
EquipResourceEntity equipResource = equipResourceList.get(j);
equipResource.setIsUsed("1");
equipResourceService.updateById(equipResource);
WorkPlanEntity workPlan = new WorkPlanEntity();
workPlan.setStartTime(equipResource.getStartTime());
workPlan.setEndTime(equipResource.getStartTime().plusMinutes(equipResource.getStandardTime().longValue()));
workPlan.setWorkQty(order.getYpQty());
workPlan.setCaId(craft.getCaId());
workPlan.setPpsId(craft.getPpsId());
workPlan.setMakeTeam(equipResource.getTeamId());
workPlan.setWorkCenterId(craft.getWorkCenterId());
workPlan.setOrders(craft.getProcessNo());
workPlan.setWoId(order.getId());
workPlan.setOem("0");
workPlan.setTestQty(0);
workPlan.setQualifiedQty(0);
workPlan.setUnqualifiedQty(0);
workPlan.setScrapQty(0);
workPlan.setHourQuota(BigDecimal.valueOf(ChronoUnit.MINUTES.between(workPlan.getStartTime(), workPlan.getEndTime())));
workPlan.setEquipCode(equipResource.getEquipCode());
workPlan.setEquipName(equipResource.getEquipName());
workPlan.setEquipResourceId(equipResource.getId());
workPlanList.add(workPlan);
break;
}
}
}
planMap.put(order.getYoCode(),workPlanList);
}
}
return planMap;
}
public String nextCode(Object obj) {
// 自增总长度
int len = 3;
// 自增值
int num = 0;
// 编码模式
String codePattern = obj + "-R";
// 当前模式下最大编码
String woCode = baseMapper.getMaxByCodePattern(codePattern);
if (woCode != null) {
num = Integer.parseInt(woCode.substring(codePattern.length(), codePattern.length() + len));
}
num++;
// 下个编码
return codePattern + prefix(String.valueOf(num), "0", len);
}
public static final String prefix(String StringToFix, String fixChar, int targetLen) {
int len = StringToFix.length();
for(int i = 0; i < targetLen - len; i += fixChar.length()) {
StringToFix = fixChar + StringToFix;
}
return StringToFix;
}
}

@ -60,4 +60,9 @@ public class YieldOrderServiceImpl extends BaseServiceImpl<YieldOrderMapper, Yie
return yieldOrderList;
}
@Override
public List<YieldOrderEntity> selectCommonCraftOrderList() {
return baseMapper.selectCommonCraftOrderList();
}
}

Loading…
Cancel
Save