fix:添加甘特图返回字段,修改bom物料信息取消合并

ck
HuangHuiKang 1 month ago
parent d4d3ad4f57
commit 50a0b97572

@ -34,6 +34,10 @@ public class DevicePlanGanttRespVO {
private LocalDateTime latestStartTime; private LocalDateTime latestStartTime;
@Schema(description = "计划数量") @Schema(description = "计划数量")
private Long planNumber; private Long planNumber;
@Schema(description = "计划编码")
private String planCode;
@Schema(description = "任务单编码")
private String taskCode;
@Schema(description = "产品名称") @Schema(description = "产品名称")
private String productName; private String productName;
@Schema(description = "产品编码") @Schema(description = "产品编码")
@ -42,5 +46,20 @@ public class DevicePlanGanttRespVO {
private String deviceName; private String deviceName;
@Schema(description = "设备编码") @Schema(description = "设备编码")
private String deviceCode; private String deviceCode;
@Schema(description = "来源HISTORY-历史计划CURRENT-本次排产", example = "CURRENT")
private String sourceType;
@Schema(description = "计划开始时间(yyyy-MM-dd HH:mm:ss)")
private String planStartTimeStr;
@Schema(description = "计划结束时间(yyyy-MM-dd HH:mm:ss)")
private String planEndTimeStr;
@Schema(description = "最晚开工时间(yyyy-MM-dd HH:mm:ss)")
private String latestStartTimeStr;
@Schema(description = "交货日期(yyyy-MM-dd)")
private String deliveryDateStr;
} }
} }

@ -151,4 +151,10 @@ public class PlanRespVO {
@Schema(description = "设备名称") @Schema(description = "设备名称")
private String deviceName; private String deviceName;
@Schema(description = "最晚开工时间")
private LocalDateTime latestStartTime;
@Schema(description = "交货日期")
private LocalDateTime deliveryDate;
} }

@ -65,32 +65,53 @@ public class ItemAnalysisServiceImpl implements ItemAnalysisService {
public List<ItemRequisitionAndStock> getItemAnalysis(TaskDO taskDO) { public List<ItemRequisitionAndStock> getItemAnalysis(TaskDO taskDO) {
List<TaskDetailDO> detailDOList = taskService.getTaskDetailListByTaskId(taskDO.getId()); List<TaskDetailDO> detailDOList = taskService.getTaskDetailListByTaskId(taskDO.getId());
Map<Long, ItemRequisitionAndStock> itemMap = new HashMap<>(); List<ItemRequisitionAndStock> itemList = new ArrayList<>();
//算物料需求
for (TaskDetailDO detail : detailDOList) {
//这里要求销售的单位和物料单位一致等于内置单位
// BomDO bomDO = bomService.selectByProductId(detail.getProductId());
// if (!bomDO.getUnitId().equals(ProductUnitEnum.Each.getUnitId())
// || !detail.getUnitId().equals(ProductUnitEnum.Each.getUnitId())) {
// log.error(UNIT_ERROR);
// throw exception(new ErrorCode(500, UNIT_ERROR));
// }
//每个taskDetail计算一次物料需求汇总到map里面 // 算物料需求:逐条追加,不合并
for (TaskDetailDO detail : detailDOList) {
List<BomDetailDO> bomDetailDOList = List<BomDetailDO> bomDetailDOList =
bomService.getBomDetailListByProductId(detail.getProductId(), detail.getNumber()); bomService.getBomDetailListByProductId(detail.getProductId(), detail.getNumber());
buildItemMap(itemMap, bomDetailDOList,detail.getProductId()); buildItemList(itemList, bomDetailDOList, detail.getProductId());
} }
//算库存
for (Long key : itemMap.keySet()) { // 算库存:每条都查并赋值(不合并情况下可能重复物料)
BigDecimal stockCount = erpStockService.getStockCount(key); for (ItemRequisitionAndStock item : itemList) {
itemMap.get(key).setStockNumber(stockCount); BigDecimal stockCount = erpStockService.getStockCount(item.getItemId());
BigDecimal stockWorkshopCount = stockWorkshopService.getStockCount(key); item.setStockNumber(stockCount);
itemMap.get(key).setStockWorkshopNumber(stockWorkshopCount); BigDecimal stockWorkshopCount = stockWorkshopService.getStockCount(item.getItemId());
item.setStockWorkshopNumber(stockWorkshopCount);
} }
List<ItemRequisitionAndStock> list = new ArrayList<>(itemMap.values());
list = buildDetailVOList(list); return buildDetailVOList(itemList);
return list;
// ============ 合并子物料版本 ===========
// List<TaskDetailDO> detailDOList = taskService.getTaskDetailListByTaskId(taskDO.getId());
// Map<Long, ItemRequisitionAndStock> itemMap = new HashMap<>();
// //算物料需求
// for (TaskDetailDO detail : detailDOList) {
// //这里要求销售的单位和物料单位一致等于内置单位
//// BomDO bomDO = bomService.selectByProductId(detail.getProductId());
//// if (!bomDO.getUnitId().equals(ProductUnitEnum.Each.getUnitId())
//// || !detail.getUnitId().equals(ProductUnitEnum.Each.getUnitId())) {
//// log.error(UNIT_ERROR);
//// throw exception(new ErrorCode(500, UNIT_ERROR));
//// }
//
// //每个taskDetail计算一次物料需求汇总到map里面
// List<BomDetailDO> bomDetailDOList =
// bomService.getBomDetailListByProductId(detail.getProductId(), detail.getNumber());
// buildItemMap(itemMap, bomDetailDOList,detail.getProductId());
// }
// //算库存
// for (Long key : itemMap.keySet()) {
// BigDecimal stockCount = erpStockService.getStockCount(key);
// itemMap.get(key).setStockNumber(stockCount);
// BigDecimal stockWorkshopCount = stockWorkshopService.getStockCount(key);
// itemMap.get(key).setStockWorkshopNumber(stockWorkshopCount);
// }
// List<ItemRequisitionAndStock> list = new ArrayList<>(itemMap.values());
// list = buildDetailVOList(list);
// return list;
} }
//分析计划的物料需求 //分析计划的物料需求
@ -174,6 +195,66 @@ public class ItemAnalysisServiceImpl implements ItemAnalysisService {
}); });
} }
private void buildItemList(List<ItemRequisitionAndStock> itemList,
List<BomDetailDO> bomDetailDOList,
Long currentProductId) {
for (BomDetailDO bomDetail : bomDetailDOList) {
Long itemId = bomDetail.getProductId();
// 可选:仅做单位冲突校验(跨产品同子物料)
// for (ItemRequisitionAndStock existed : itemList) {
// if (!Objects.equals(existed.getItemId(), itemId)) {
// continue;
// }
// if (!Objects.equals(existed.getUnitId(), bomDetail.getUnitId())) {
// BomDO currBom = bomService.getBom(bomDetail.getBomId());
// BomDO prevBom = existed.getSourceBomId() == null ? null : bomService.getBom(existed.getSourceBomId());
//
// ErpProductDO subItem = productService.getProduct(itemId);
// ErpProductDO currProduct = currentProductId == null ? null : productService.getProduct(currentProductId);
// ErpProductDO prevProduct = existed.getSourceProductId() == null ? null : productService.getProduct(existed.getSourceProductId());
//
// ErpProductUnitDO currUnit = productUnitService.getProductUnit(bomDetail.getUnitId());
// ErpProductUnitDO prevUnit = productUnitService.getProductUnit(existed.getUnitId());
//
// String currProductCode = currProduct == null ? "-" : Objects.toString(currProduct.getBarCode(), "-");
// String currProductName = currProduct == null ? "-" : Objects.toString(currProduct.getName(), "-");
// String prevProductCode = prevProduct == null ? "-" : Objects.toString(prevProduct.getBarCode(), "-");
// String prevProductName = prevProduct == null ? "-" : Objects.toString(prevProduct.getName(), "-");
//
// String currBomCode = currBom == null ? "-" : Objects.toString(currBom.getCode(), "-");
// String prevBomCode = prevBom == null ? "-" : Objects.toString(prevBom.getCode(), "-");
//
// String subItemCode = subItem == null ? "-" : Objects.toString(subItem.getBarCode(), "-");
// String subItemName = subItem == null ? "-" : Objects.toString(subItem.getName(), "-");
//
// String currUnitName = currUnit == null ? "-" : Objects.toString(currUnit.getName(), "-");
// String prevUnitName = prevUnit == null ? "-" : Objects.toString(prevUnit.getName(), "-");
//
// String msg = String.format(
// "产品[%s-%s] 的 BOM[%s] 中,子物料[%s-%s] 单位[%s] 与 产品[%s-%s] 的 BOM[%s] 中子物料单位[%s] 冲突!应改成一致的单位",
// currProductCode, currProductName, currBomCode,
// subItemCode, subItemName, currUnitName,
// prevProductCode, prevProductName, prevBomCode, prevUnitName
// );
// log.error(msg);
// throw exception(new ErrorCode(5_002, msg));
// }
// }
// 不合并:每条 BOM 明细生成一条记录
ItemRequisitionAndStock temp = new ItemRequisitionAndStock()
.setItemId(itemId)
.setNumber(bomDetail.getUsageNumber())
.setUnitId(bomDetail.getUnitId())
.setSourceBomId(bomDetail.getBomId())
.setSourceProductId(currentProductId);
itemList.add(temp);
}
}
private void buildItemMap(Map<Long, ItemRequisitionAndStock> itemMap, private void buildItemMap(Map<Long, ItemRequisitionAndStock> itemMap,
List<BomDetailDO> bomDetailDOList, List<BomDetailDO> bomDetailDOList,
Long currentProductId) { Long currentProductId) {

@ -30,6 +30,7 @@ import cn.iocoder.yudao.module.mes.dal.mysql.deviceledger.DeviceLedgerMapper;
import cn.iocoder.yudao.module.mes.dal.mysql.paigongrecord.PaigongRecordMapper; import cn.iocoder.yudao.module.mes.dal.mysql.paigongrecord.PaigongRecordMapper;
import cn.iocoder.yudao.module.mes.dal.mysql.plan.PlanMapper; import cn.iocoder.yudao.module.mes.dal.mysql.plan.PlanMapper;
import cn.iocoder.yudao.module.mes.dal.mysql.stockindetail.StockInDetailMapper; import cn.iocoder.yudao.module.mes.dal.mysql.stockindetail.StockInDetailMapper;
import cn.iocoder.yudao.module.mes.dal.mysql.task.TaskMapper;
import cn.iocoder.yudao.module.mes.dal.redis.no.MesNoRedisDAO; import cn.iocoder.yudao.module.mes.dal.redis.no.MesNoRedisDAO;
import cn.iocoder.yudao.module.mes.service.itemrequisition.ItemAnalysisService; import cn.iocoder.yudao.module.mes.service.itemrequisition.ItemAnalysisService;
import cn.iocoder.yudao.module.mes.service.itemrequisition.ItemRequisitionService; import cn.iocoder.yudao.module.mes.service.itemrequisition.ItemRequisitionService;
@ -37,6 +38,7 @@ import cn.iocoder.yudao.module.mes.service.itemrequisition.entity.ItemRequisitio
import cn.iocoder.yudao.module.mes.service.organization.OrganizationService; import cn.iocoder.yudao.module.mes.service.organization.OrganizationService;
import cn.iocoder.yudao.module.mes.service.paigongrecord.PaigongRecordService; import cn.iocoder.yudao.module.mes.service.paigongrecord.PaigongRecordService;
import cn.iocoder.yudao.module.mes.service.task.TaskService; import cn.iocoder.yudao.module.mes.service.task.TaskService;
import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO; import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO;
import cn.iocoder.yudao.module.system.service.user.AdminUserService; import cn.iocoder.yudao.module.system.service.user.AdminUserService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
@ -107,6 +109,9 @@ public class PlanServiceImpl implements PlanService {
@Lazy @Lazy
private ErpProductService erpProductService; private ErpProductService erpProductService;
@Resource
@Lazy
private TaskMapper taskMapper;
@Override @Override
@ -286,11 +291,30 @@ public class PlanServiceImpl implements PlanService {
} }
@Override @Override
public PlanRespVO getPlanRespVO(PlanDO planDO) { public PlanRespVO getPlanRespVO(PlanDO planDO) {
PlanRespVO planRespVO = BeanUtils.toBean(planDO, PlanRespVO.class); PlanRespVO planRespVO = BeanUtils.toBean(planDO, PlanRespVO.class);
planRespVO.setProductName(productService.getProduct(planDO.getProductId()).getName());
planRespVO.setTaskCode(taskService.getTask(planDO.getTaskId()).getCode()); if (planDO.getProductId() != null) {
planRespVO.setWorker(userService.getUser(planDO.getWorkerId()).getUsername()); ErpProductDO product = productService.getProduct(planDO.getProductId());
planRespVO.setFeedingPipelineName(organizationService.getOrganization(planDO.getFeedingPipeline()).getName()); planRespVO.setProductName(product == null ? null : product.getName());
}
if (planDO.getTaskId() != null) {
TaskDO task = taskService.getTask(planDO.getTaskId());
planRespVO.setTaskCode(task == null ? null : task.getCode());
}
if (planDO.getWorkerId() != null) {
AdminUserDO user = userService.getUser(planDO.getWorkerId());
planRespVO.setWorker(user == null ? null : user.getUsername());
} else {
planRespVO.setWorker(null);
}
if (planDO.getFeedingPipeline() != null) {
OrganizationDO organization = organizationService.getOrganization(planDO.getFeedingPipeline());
planRespVO.setFeedingPipelineName(organization == null ? null : organization.getName());
}
return planRespVO; return planRespVO;
} }
@ -538,14 +562,24 @@ public class PlanServiceImpl implements PlanService {
Set<Long> deviceIds = planList.stream().map(PlanDO::getDeviceId).filter(Objects::nonNull).collect(Collectors.toSet()); Set<Long> deviceIds = planList.stream().map(PlanDO::getDeviceId).filter(Objects::nonNull).collect(Collectors.toSet());
Set<Long> productIds = planList.stream().map(PlanDO::getProductId).filter(Objects::nonNull).collect(Collectors.toSet()); Set<Long> productIds = planList.stream().map(PlanDO::getProductId).filter(Objects::nonNull).collect(Collectors.toSet());
Set<Long> taskIds = planList.stream().map(PlanDO::getTaskId).filter(Objects::nonNull).collect(Collectors.toSet());
Map<Long, DeviceLedgerDO> deviceMap = deviceLedgerMapper.selectBatchIds(deviceIds).stream() Map<Long, DeviceLedgerDO> deviceMap = deviceLedgerMapper.selectBatchIds(deviceIds).stream()
.collect(Collectors.toMap(DeviceLedgerDO::getId, d -> d, (a, b) -> a)); .collect(Collectors.toMap(DeviceLedgerDO::getId, d -> d, (a, b) -> a));
Map<Long, ErpProductDO> productMap = erpProductService.getProductMap(productIds); Map<Long, ErpProductDO> productMap = erpProductService.getProductMap(productIds);
Map<Long, String> taskCodeMap = CollUtil.isEmpty(taskIds)
? Collections.emptyMap()
: taskMapper.selectBatchIds(taskIds).stream()
.collect(Collectors.toMap(TaskDO::getId, TaskDO::getCode, (a, b) -> a));
Map<Long, List<PlanDO>> group = planList.stream() Map<Long, List<PlanDO>> group = planList.stream()
.collect(Collectors.groupingBy(PlanDO::getDeviceId, LinkedHashMap::new, Collectors.toList())); .collect(Collectors.groupingBy(PlanDO::getDeviceId, LinkedHashMap::new, Collectors.toList()));
List<DevicePlanGanttRespVO> result = new ArrayList<>(); List<DevicePlanGanttRespVO> result = new ArrayList<>();
for (Map.Entry<Long, List<PlanDO>> entry : group.entrySet()) { for (Map.Entry<Long, List<PlanDO>> entry : group.entrySet()) {
Long deviceId = entry.getKey(); Long deviceId = entry.getKey();
@ -557,9 +591,13 @@ public class PlanServiceImpl implements PlanService {
vo.setDeviceCode(device == null ? null : device.getDeviceCode()); vo.setDeviceCode(device == null ? null : device.getDeviceCode());
List<DevicePlanGanttRespVO.PlanItem> plans = new ArrayList<>(); List<DevicePlanGanttRespVO.PlanItem> plans = new ArrayList<>();
DateTimeFormatter DATETIME_FMT = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
for (PlanDO plan : entry.getValue()) { for (PlanDO plan : entry.getValue()) {
DevicePlanGanttRespVO.PlanItem item = new DevicePlanGanttRespVO.PlanItem(); DevicePlanGanttRespVO.PlanItem item = new DevicePlanGanttRespVO.PlanItem();
item.setPlanId(plan.getId()); item.setPlanId(plan.getId());
item.setPlanCode(plan.getCode());
item.setTaskCode(taskCodeMap.get(plan.getTaskId()));
item.setPlanStartTime(plan.getPlanStartTime()); item.setPlanStartTime(plan.getPlanStartTime());
item.setPlanEndTime(plan.getPlanEndTime()); item.setPlanEndTime(plan.getPlanEndTime());
item.setLatestStartTime(plan.getLatestStartTime()); // 前提PlanDO已加该字段 item.setLatestStartTime(plan.getLatestStartTime()); // 前提PlanDO已加该字段
@ -569,6 +607,11 @@ public class PlanServiceImpl implements PlanService {
item.setDeviceName(device == null ? null : device.getDeviceName()); item.setDeviceName(device == null ? null : device.getDeviceName());
item.setProductCode(product == null ? null : product.getBarCode()); item.setProductCode(product == null ? null : product.getBarCode());
item.setDeviceCode(device == null ? null : device.getDeviceCode()); item.setDeviceCode(device == null ? null : device.getDeviceCode());
item.setSourceType("HISTORY");
item.setPlanStartTimeStr(plan.getPlanStartTime().format(DATETIME_FMT));
item.setPlanEndTimeStr(plan.getPlanEndTime().format(DATETIME_FMT));
item.setLatestStartTimeStr(plan.getLatestStartTime().format(DATETIME_FMT));
plans.add(item); plans.add(item);
} }
vo.setPlans(plans); vo.setPlans(plans);

@ -0,0 +1,59 @@
package cn.iocoder.yudao.module.mes.strategy.task;
import cn.iocoder.yudao.module.mes.controller.admin.plan.vo.PlanSaveReqVO;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;
import java.util.Comparator;
import java.util.List;
@Component
public class Rule1NearDueDateStrategy implements ScheduleSortStrategy {
@Override
public Integer ruleCode() {
return 1;
}
@Override
public void sort(List<PlanSaveReqVO> plans) {
if (plans == null || plans.size() <= 1) {
return;
}
plans.sort(
Comparator
// 第一排序:最晚开工时间 ASC
.comparing((PlanSaveReqVO p) -> nvlTime(p.getLatestStartTime()))
// 第二排序:订单交期 ASC
.thenComparing(p -> nvlTime(p.getDeliveryDate()))
// 第三排序:订单优先级 DESC
.thenComparing((PlanSaveReqVO p) -> nvlInt(p.getOrderPriority()), Comparator.reverseOrder())
// 第四排序:订单明细交期时间 ASC
.thenComparing(p -> nvlTime(p.getOrderDetailDeliveryDate()))
// 第五排序:订单号 ASC这里用任务单号 workOrderCode 作为订单号)
.thenComparing(p -> nvlStr(p.getWorkOrderCode()))
// 第六排序:明细行号 ASC这里用订单明细Id代替
.thenComparing(p -> nvlLong(p.getOrderDetailId()))
);
}
private LocalDateTime nvlTime(LocalDateTime value) {
return value != null ? value : LocalDateTime.MAX;
}
private Integer nvlInt(Integer value) {
// DESC 排序里null 放最后:给最小值
return value != null ? value : Integer.MIN_VALUE;
}
private Long nvlLong(Long value) {
return value != null ? value : Long.MAX_VALUE;
}
private String nvlStr(String value) {
return value != null ? value : "";
}
}
Loading…
Cancel
Save