插单修改

parent a84189b4
......@@ -418,6 +418,58 @@ public class ResourceGanttController {
return R.ok("插单成功");
}
@PostMapping("/orderInsertAuto")
@Operation(
summary = "自动插单",
description = "创建新工单并按基准时间+冻结期自动排程。若锚点被占用,则占位工单及后续工单后移;若前面有空挡,新工单自动前移到设备最早可用时间",
requestBody = @io.swagger.v3.oas.annotations.parameters.RequestBody(
description = "自动插单参数",
required = true,
content = @io.swagger.v3.oas.annotations.media.Content(
mediaType = "application/json",
examples = {
@io.swagger.v3.oas.annotations.media.ExampleObject(
name = "自动插单示例",
summary = "基础示例",
value = "{\n" +
" \"sceneId\": \"B571EF6682DB463AB2977B1055A74112\",\n" +
" \"newOrder\": {\n" +
" \"orderCode\": \"AUTO_20260326_001\",\n" +
" \"materialId\": \"d5d0dd08-cfb5-2b45-85e9-aba470895423\",\n" +
" \"quantity\": 610000\n" +
" }\n" +
"}"
),
@io.swagger.v3.oas.annotations.media.ExampleObject(
name = "大批量示例",
summary = "大批量订单",
value = "{\n" +
" \"sceneId\": \"B571EF6682DB463AB2977B1055A74112\",\n" +
" \"newOrder\": {\n" +
" \"orderCode\": \"AUTO_20260326_002\",\n" +
" \"materialId\": \"cbd0dd08-49b1-0146-83bd-ec6185316c16\",\n" +
" \"quantity\": 1200000\n" +
" }\n" +
"}"
)
}
)
)
)
public R<String> insertOrderAuto(@RequestBody Map<String, Object> params) {
log.info("insertOrderAuto 请求参数: {}", params);
String sceneId = ParamValidator.getString(params, "sceneId", "场景ID");
@SuppressWarnings("unchecked")
Map<String, Object> newOrderData = (Map<String, Object>) params.get("newOrder");
ParamValidator.validateSceneExists(sceneService, sceneId);
planResultService.InsertOrderAuto(sceneId, newOrderData);
return R.ok("自动插单成功");
}
@PostMapping("/ordermerge")
@Operation(summary = "订单合并", description = "订单合并")
public R<String> orderMerge(@RequestBody Map<String, Object> params) {
......
......@@ -1340,74 +1340,110 @@ public class PlanResultService {
return releasedCount;
}
private long countMachineAvailabilitySegments(Chromosome chromosome, Long machineId) {
if (chromosome == null || machineId == null || chromosome.getInitMachines() == null) {
return 0;
public Chromosome InsertOrderAuto(String sceneId, Map<String, Object> newOrderData) {
if (newOrderData == null) {
throw new RuntimeException("newOrder 不能为空");
}
return chromosome.getInitMachines().stream()
.filter(Objects::nonNull)
.filter(m -> m.getId() == machineId)
.findFirst()
.map(m -> m.getAvailability() == null ? 0L : (long) m.getAvailability().size())
.orElse(0L);
String orderCode = String.valueOf(newOrderData.get("orderCode"));
String materialId = String.valueOf(newOrderData.get("materialId"));
Object qtyObj = newOrderData.get("quantity");
if (orderCode == null || orderCode.trim().isEmpty()) {
throw new RuntimeException("orderCode 不能为空");
}
if (materialId == null || materialId.trim().isEmpty()) {
throw new RuntimeException("materialId 不能为空");
}
if (qtyObj == null) {
throw new RuntimeException("quantity 不能为空");
}
Double quantity = Double.valueOf(String.valueOf(qtyObj));
private long countMachineUsedMaintenanceSegments(Chromosome chromosome, Long machineId) {
if (chromosome == null || machineId == null || chromosome.getInitMachines() == null) {
return 0;
// 1. 创建新订单(沿用现有创建逻辑)
R<String> insertResp = lanuchService.insertOrder(sceneId, orderCode, materialId, null, null, 1, quantity);
String insertMsg = insertResp != null ? insertResp.getData() : null;
if (insertMsg == null || insertMsg.trim().isEmpty()) {
throw new RuntimeException("创建订单失败:未返回订单ID");
}
return chromosome.getInitMachines().stream()
.filter(Objects::nonNull)
.filter(m -> m.getId() == machineId)
.findFirst()
.map(m -> m.getAvailability() == null ? 0L : m.getAvailability().stream()
.filter(Objects::nonNull)
.filter(seg -> seg.getType() == SegmentType.MAINTENANCE && seg.isUsed())
.count())
.orElse(0L);
String newOrderId = insertMsg;
if (insertMsg.contains("订单ID:")) {
newOrderId = insertMsg.substring(insertMsg.indexOf("订单ID:") + 5).trim();
}
private long countMachineUsedSegments(Chromosome chromosome, Long machineId, SegmentType type) {
if (chromosome == null || machineId == null || chromosome.getInitMachines() == null) {
return 0;
// 2. 读取场景排产结果
Chromosome chromosome = _sceneService.loadChromosomeFromFile(sceneId);
if (chromosome == null) {
throw new RuntimeException("场景不存在或排产结果未初始化");
}
return chromosome.getInitMachines().stream()
.filter(Objects::nonNull)
.filter(m -> m.getId() == machineId)
.findFirst()
.map(m -> m.getAvailability() == null ? 0L : m.getAvailability().stream()
.filter(Objects::nonNull)
.filter(TimeSegment::isUsed)
.filter(seg -> type == null || seg.getType() == type)
.count())
.orElse(0L);
// 3. 查询新订单及其工序
ProdLaunchOrder newLaunchOrder = _prodLaunchOrderService.lambdaQuery()
.eq(ProdLaunchOrder::getSceneId, sceneId)
.eq(ProdLaunchOrder::getOrderId, newOrderId)
.one();
if (newLaunchOrder == null) {
throw new RuntimeException("新订单不存在:" + newOrderId);
}
private String machineSegmentSnapshot(Chromosome chromosome, Long machineId, int limit) {
if (chromosome == null || machineId == null || chromosome.getInitMachines() == null) {
return "[]";
List<ProdProcessExec> newProcessExecs = _prodProcessExecService.lambdaQuery()
.eq(ProdProcessExec::getSceneId, sceneId)
.eq(ProdProcessExec::getOrderId, newOrderId)
.orderByAsc(ProdProcessExec::getTaskSeq)
.list();
if (newProcessExecs == null || newProcessExecs.isEmpty()) {
throw new RuntimeException("新订单没有工序:" + newOrderId);
}
Machine machine = chromosome.getInitMachines().stream()
// 3.1 查询新工序对应设备(与InitEntrys对齐:execId -> prod_equipment)
List<String> execIds = newProcessExecs.stream()
.map(ProdProcessExec::getExecId)
.filter(Objects::nonNull)
.filter(m -> m.getId() == machineId)
.findFirst()
.orElse(null);
.distinct()
.collect(Collectors.toList());
if (machine == null || machine.getAvailability() == null || machine.getAvailability().isEmpty()) {
return "[]";
List<ProdEquipment> newProdEquipments = execIds.isEmpty()
? new ArrayList<>()
: _prodEquipmentService.lambdaQuery()
.eq(ProdEquipment::getSceneId, sceneId)
.in(ProdEquipment::getExecId, execIds)
.list();
if (newProdEquipments == null || newProdEquipments.isEmpty()) {
throw new RuntimeException("自动插单失败:新工单未生成可选设备,请检查PROD_EQUIPMENT");
}
return machine.getAvailability().stream()
.filter(Objects::nonNull)
.sorted(Comparator.comparing(TimeSegment::getStart))
.limit(Math.max(limit, 1))
.map(seg -> String.format("%s|used=%s|%s~%s", seg.getType(), seg.isUsed(), seg.getStart(), seg.getEnd()))
.collect(Collectors.joining("; "));
// 4. 计算锚点时间:基准时间 + 冻结期
LocalDateTime baseTime = chromosome.getBaseTime();
LambdaQueryWrapper<ApsTimeConfig> queryWrapper = new LambdaQueryWrapper<>();
ApsTimeConfig apsTimeConfig = apsTimeConfigMapper.selectOne(queryWrapper);
long freezeSeconds = 0L;
if (apsTimeConfig != null && apsTimeConfig.getFreezeDate() != null) {
freezeSeconds = apsTimeConfig.getFreezeDate().longValue();
}
if (apsTimeConfig != null && apsTimeConfig.getBaseTime() != null) {
baseTime = apsTimeConfig.getBaseTime();
}
LocalDateTime anchorTime = baseTime.plusSeconds(Math.max(freezeSeconds, 0L));
// 5. 自动插单(占位后推 + 空挡前移)
GlobalParam globalParam = InitGlobalParam();
ScheduleOperationService scheduleOperation = new ScheduleOperationService(materialRequirementService, this);
scheduleOperation.InsertOrderAuto(
chromosome,
newOrderId,
newLaunchOrder,
newProcessExecs,
newProdEquipments,
anchorTime,
globalParam
);
// 6. 保存
WriteScheduleSummary(chromosome);
_sceneService.saveChromosomeToFile(chromosome, sceneId);
return chromosome;
}
public Chromosome Move(String SceneId,List<Integer> opId, LocalDateTime newStartTime,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment