Commit 50469fe3 authored by Tong Li's avatar Tong Li

Merge remote-tracking branch 'origin/master'

parents 2728c661 811edf6c
...@@ -363,7 +363,7 @@ public class SwaggerMapParamConfig { ...@@ -363,7 +363,7 @@ public class SwaggerMapParamConfig {
"带条件分页查询订单数据", "带条件分页查询订单数据",
"{\n" + "{\n" +
" \"sceneId\": \"SCENE001\",\n" + " \"sceneId\": \"SCENE001\",\n" +
" \"pageIndex\": 1,\n" + " \"pageIndex\": 0,\n" +
" \"pageSize\": 10,\n" + " \"pageSize\": 10,\n" +
" \"conditions\": [\n" + " \"conditions\": [\n" +
" {\n" + " {\n" +
......
...@@ -29,25 +29,25 @@ public class UserStrategyRuleController { ...@@ -29,25 +29,25 @@ public class UserStrategyRuleController {
@PostMapping("/effective") @PostMapping("/effective")
@Operation( @Operation(
summary = "获取策略详情", summary = "获取当前生效策略",
requestBody = @io.swagger.v3.oas.annotations.parameters.RequestBody( requestBody = @io.swagger.v3.oas.annotations.parameters.RequestBody(
description = "根据下拉选项 id 获取策略详情,也兼容 source + ruleId。", description = "未传 userRuleId 时按 userId 获取用户最后保存的策略;旧的 USER:id 入参会被忽略。需要指定某条用户策略时传 userRuleId。",
required = true, required = true,
content = @Content( content = @Content(
mediaType = "application/json", mediaType = "application/json",
examples = { examples = {
@ExampleObject( @ExampleObject(
name = "选择全局策略", name = "获取用户最后保存策略",
value = "{\n" + value = "{\n" +
" \"userId\": 10001,\n" + " \"userId\": 10001,\n" +
" \"id\": \"GLOBAL:1\"\n" + " \"id\": \"USER:f3d7e0f0-3b8a-4d0c-8f2a-7d4e64f4c901\"\n" +
"}" "}"
), ),
@ExampleObject( @ExampleObject(
name = "选择用户策略", name = "指定用户策略",
value = "{\n" + value = "{\n" +
" \"userId\": 10001,\n" + " \"userId\": 10001,\n" +
" \"id\": \"USER:f3d7e0f0-3b8a-4d0c-8f2a-7d4e64f4c901\"\n" + " \"userRuleId\": \"f3d7e0f0-3b8a-4d0c-8f2a-7d4e64f4c901\"\n" +
"}" "}"
) )
} }
...@@ -69,6 +69,7 @@ public class UserStrategyRuleController { ...@@ -69,6 +69,7 @@ public class UserStrategyRuleController {
" \"baseRuleId\": 1,\n" + " \"baseRuleId\": 1,\n" +
" \"sceneId\": null,\n" + " \"sceneId\": null,\n" +
" \"name\": \"交期优先-用户规则\",\n" + " \"name\": \"交期优先-用户规则\",\n" +
" \"isjit\": false,\n" +
" \"forwardScheduling\": [\n" + " \"forwardScheduling\": [\n" +
" {\n" + " {\n" +
" \"name\": \"deliveryDate\",\n" + " \"name\": \"deliveryDate\",\n" +
...@@ -116,6 +117,7 @@ public class UserStrategyRuleController { ...@@ -116,6 +117,7 @@ public class UserStrategyRuleController {
value = "{\n" + value = "{\n" +
" \"userId\": 10001,\n" + " \"userId\": 10001,\n" +
" \"id\": \"GLOBAL:1\",\n" + " \"id\": \"GLOBAL:1\",\n" +
" \"isjit\": \"true\",\n" +
" \"forwardScheduling\": [\n" + " \"forwardScheduling\": [\n" +
" {\n" + " {\n" +
" \"name\": \"deliveryDate\",\n" + " \"name\": \"deliveryDate\",\n" +
...@@ -145,6 +147,7 @@ public class UserStrategyRuleController { ...@@ -145,6 +147,7 @@ public class UserStrategyRuleController {
value = "{\n" + value = "{\n" +
" \"userId\": 10001,\n" + " \"userId\": 10001,\n" +
" \"id\": \"USER:f3d7e0f0-3b8a-4d0c-8f2a-7d4e64f4c901\",\n" + " \"id\": \"USER:f3d7e0f0-3b8a-4d0c-8f2a-7d4e64f4c901\",\n" +
" \"isjit\": \"false\",\n" +
" \"forwardScheduling\": [],\n" + " \"forwardScheduling\": [],\n" +
" \"kpiConfig\": []\n" + " \"kpiConfig\": []\n" +
"}" "}"
...@@ -210,6 +213,7 @@ public class UserStrategyRuleController { ...@@ -210,6 +213,7 @@ public class UserStrategyRuleController {
" \"name\": \"交期优先-用户规则\",\n" + " \"name\": \"交期优先-用户规则\",\n" +
" \"globalRuleId\": 1,\n" + " \"globalRuleId\": 1,\n" +
" \"globalRuleName\": \"交期优先\",\n" + " \"globalRuleName\": \"交期优先\",\n" +
" \"isjit\": false,\n" +
" \"forwardScheduling\": [\n" + " \"forwardScheduling\": [\n" +
" {\n" + " {\n" +
" \"name\": \"deliveryDate\",\n" + " \"name\": \"deliveryDate\",\n" +
...@@ -229,6 +233,7 @@ public class UserStrategyRuleController { ...@@ -229,6 +233,7 @@ public class UserStrategyRuleController {
" \"name\": \"齐套优先\",\n" + " \"name\": \"齐套优先\",\n" +
" \"globalRuleId\": 2,\n" + " \"globalRuleId\": 2,\n" +
" \"globalRuleName\": \"齐套优先\",\n" + " \"globalRuleName\": \"齐套优先\",\n" +
" \"isjit\": false,\n" +
" \"forwardScheduling\": []\n" + " \"forwardScheduling\": []\n" +
" },\n" + " },\n" +
" {\n" + " {\n" +
......
...@@ -46,9 +46,9 @@ public class ChromosomeDataController { ...@@ -46,9 +46,9 @@ public class ChromosomeDataController {
* 通用接口,根据实体名称查询Chromosome中的数据,支持分页和条件过滤 * 通用接口,根据实体名称查询Chromosome中的数据,支持分页和条件过滤
* 示例: * 示例:
* - 文件实体: POST /queryChromosome/order/page * - 文件实体: POST /queryChromosome/order/page
* Body: { "sceneId": "SCENE001", "pageIndex": 1, "pageSize": 10, "conditions": [...] } * Body: { "sceneId": "SCENE001", "pageIndex": 0, "pageSize": 10, "conditions": [...] }
* - 数据库实体: POST /queryChromosome/user/page * - 数据库实体: POST /queryChromosome/user/page
* Body: { "pageIndex": 1, "pageSize": 10, "conditions": [...] } * Body: { "pageIndex": 0, "pageSize": 10, "conditions": [...] }
* *
* @param entityName 实体名称 (如: order, entry, machine, user, department等) * @param entityName 实体名称 (如: order, entry, machine, user, department等)
* @param paged 分页和条件对象 * @param paged 分页和条件对象
...@@ -235,7 +235,7 @@ public class ChromosomeDataController { ...@@ -235,7 +235,7 @@ public class ChromosomeDataController {
* "name": "订单列表", * "name": "订单列表",
* "table": "order", * "table": "order",
* "data": { * "data": {
* "pageIndex": 1, * "pageIndex": 0,
* "pageSize": 10, * "pageSize": 10,
* "conditions": [ * "conditions": [
* { "fieldName": "sceneId", "fieldValue": "SCENE001", "conditionalType": "EQUAL" } * { "fieldName": "sceneId", "fieldValue": "SCENE001", "conditionalType": "EQUAL" }
......
...@@ -421,6 +421,73 @@ public class ResourceGanttController { ...@@ -421,6 +421,73 @@ public class ResourceGanttController {
@PostMapping("/orderInsertAuto") @PostMapping("/orderInsertAuto")
@Operation( @Operation(
summary = "自动插单", summary = "自动插单",
description = "按neworder数据结构自动插入新订单",
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 = "neworder示例",
value = "{\n" +
" \"sceneId\": \"C4EF4B6DC74E43F78D2EA4102B12066D\",\n" +
" \"neworder\": {\n" +
" \"zoneid\": \"36\",\n" +
" \"isconsume\": 0,\n" +
" \"settle\": 0,\n" +
" \"delay\": 0,\n" +
" \"part\": 0,\n" +
" \"islock\": 0,\n" +
" \"isinsert\": 0,\n" +
" \"mmid\": \"fff9efd4-8fc3-495f-acfe-dbefee3dc9cc\",\n" +
" \"mmname\": \"0.9%氯化钠注射液\",\n" +
" \"mmcode\": \"153004_ZHJ24046\",\n" +
" \"unit\": \"万袋\",\n" +
" \"unitId\": 12,\n" +
" \"series\": \"153004_ZHJ24046\",\n" +
" \"seriesId\": 648,\n" +
" \"seriesName\": \"153004_ZHJ24046\",\n" +
" \"code\": \"DDBH_20260522_2\",\n" +
" \"zone\": \"33331\",\n" +
" \"customerid\": 41,\n" +
" \"customer\": \"远景\",\n" +
" \"deliverytime\": \"2026-05-05T00:00:00.00+08:00\",\n" +
" \"prioritry\": \"5\",\n" +
" \"stockid\": 617,\n" +
" \"stock\": \"测试\",\n" +
" \"price\": 5,\n" +
" \"quantity\": 55,\n" +
" \"begintime\": \"2026-05-01T00:00:00.00+08:00\"\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");
if (newOrderData == null) {
@SuppressWarnings("unchecked")
Map<String, Object> fallbackNewOrderData = (Map<String, Object>) params.get("newOrder");
newOrderData = fallbackNewOrderData;
}
if (newOrderData == null) {
throw new IllegalArgumentException("neworder 不能为空");
}
ParamValidator.validateSceneExists(sceneService, sceneId);
planResultService.InsertOrderAuto(sceneId, convertNewOrderPayload(newOrderData));
return R.ok("插单成功");
}
@PostMapping("/orderInsertAutoOld")
@Operation(
summary = "自动插单旧接口",
description = "创建新工单并按基准时间+冻结期自动排程。若锚点被占用,则占位工单及后续工单后移;若前面有空挡,新工单自动前移到设备最早可用时间", description = "创建新工单并按基准时间+冻结期自动排程。若锚点被占用,则占位工单及后续工单后移;若前面有空挡,新工单自动前移到设备最早可用时间",
requestBody = @io.swagger.v3.oas.annotations.parameters.RequestBody( requestBody = @io.swagger.v3.oas.annotations.parameters.RequestBody(
description = "自动插单参数", description = "自动插单参数",
...@@ -456,8 +523,8 @@ public class ResourceGanttController { ...@@ -456,8 +523,8 @@ public class ResourceGanttController {
) )
) )
) )
public R<String> insertOrderAuto(@RequestBody Map<String, Object> params) { public R<String> insertOrderAutoOld(@RequestBody Map<String, Object> params) {
log.info("insertOrderAuto 请求参数: {}", params); log.info("insertOrderAutoOld 请求参数: {}", params);
String sceneId = ParamValidator.getString(params, "sceneId", "场景ID"); String sceneId = ParamValidator.getString(params, "sceneId", "场景ID");
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
...@@ -782,8 +849,8 @@ public class ResourceGanttController { ...@@ -782,8 +849,8 @@ public class ResourceGanttController {
} }
// 获取分页参数 // 获取分页参数
Integer pageindex = paged.getPageIndex(); Integer pageindex = paged.getPageIndex() != null ? Math.max(0, paged.getPageIndex()) : 0;
Integer pagesize = paged.getPageSize(); Integer pagesize = paged.getPageSize() != null ? paged.getPageSize() : 1000;
// 校验能否获取对应的文件 // 校验能否获取对应的文件
Chromosome schedule = sceneService.loadChromosomeFromFile(sceneId); Chromosome schedule = sceneService.loadChromosomeFromFile(sceneId);
...@@ -821,7 +888,7 @@ public class ResourceGanttController { ...@@ -821,7 +888,7 @@ public class ResourceGanttController {
int totalOrders = orderList.size(); int totalOrders = orderList.size();
// 执行工单分页 // 执行工单分页
int startIndex = (pageindex - 1) * pagesize; int startIndex = pageindex * pagesize;
int endIndex = Math.min(startIndex + pagesize, totalOrders); int endIndex = Math.min(startIndex + pagesize, totalOrders);
List<TaskVO> pageOrders; List<TaskVO> pageOrders;
if (startIndex < totalOrders) { if (startIndex < totalOrders) {
...@@ -886,8 +953,8 @@ public class ResourceGanttController { ...@@ -886,8 +953,8 @@ public class ResourceGanttController {
} }
// 获取分页参数 // 获取分页参数
Integer pageindex = paged.getPageIndex(); Integer pageindex = paged.getPageIndex() != null ? Math.max(0, paged.getPageIndex()) : 0;
Integer pagesize = paged.getPageSize(); Integer pagesize = paged.getPageSize() != null ? paged.getPageSize() : 1000;
// 校验能否获取对应的文件 // 校验能否获取对应的文件
Chromosome schedule = sceneService.loadChromosomeFromFile(sceneId); Chromosome schedule = sceneService.loadChromosomeFromFile(sceneId);
...@@ -902,7 +969,7 @@ public class ResourceGanttController { ...@@ -902,7 +969,7 @@ public class ResourceGanttController {
int total = productGanttVOs.size(); int total = productGanttVOs.size();
// 计算分页参数 // 计算分页参数
int startIndex = (pageindex - 1) * pagesize; int startIndex = pageindex * pagesize;
int endIndex = Math.min(startIndex + pagesize, total); int endIndex = Math.min(startIndex + pagesize, total);
// 执行分页 // 执行分页
...@@ -1108,5 +1175,49 @@ public class ResourceGanttController { ...@@ -1108,5 +1175,49 @@ public class ResourceGanttController {
return R.ok(data); return R.ok(data);
} }
private Map<String, Object> convertNewOrderPayload(Map<String, Object> source) {
Map<String, Object> target = new HashMap<>(source);
target.put("orderCode", requireValue(source, "订单编号", "orderCode", "code"));
target.put("materialId", requireValue(source, "物料ID", "materialId", "mmid"));
target.put("quantity", requireValue(source, "数量", "quantity"));
Object startDate = firstValue(source, "startDate", "begintime");
if (startDate != null) {
target.put("startDate", startDate);
}
Object endDate = firstValue(source, "endDate", "deliverytime");
if (endDate != null) {
target.put("endDate", endDate);
}
Object priority = firstValue(source, "priority", "prioritry");
if (priority != null) {
target.put("priority", priority);
}
return target;
}
private Object requireValue(Map<String, Object> source, String fieldName, String... keys) {
Object value = firstValue(source, keys);
if (value == null || String.valueOf(value).trim().isEmpty()) {
throw new IllegalArgumentException(fieldName + "不能为空");
}
return value;
}
private Object firstValue(Map<String, Object> source, String... keys) {
if (source == null || keys == null) {
return null;
}
for (String key : keys) {
Object value = source.get(key);
if (value != null && !String.valueOf(value).trim().isEmpty()) {
return value;
}
}
return null;
}
} }
...@@ -17,7 +17,7 @@ import java.util.Optional; ...@@ -17,7 +17,7 @@ import java.util.Optional;
*/ */
public class Paged { public class Paged {
private Integer pageIndex=1; //当前页 private Integer pageIndex=0; //当前页
private Integer pageSize=1000; //每页多少条 private Integer pageSize=1000; //每页多少条
private Integer total=0;// 特殊设置,总记录数,如果前台带有此值,则分页查询时不查询总数。 private Integer total=0;// 特殊设置,总记录数,如果前台带有此值,则分页查询时不查询总数。
private List<String> sortByList=new ArrayList<>(); // 多字段排序列表,格式如["type asc", "id desc"] private List<String> sortByList=new ArrayList<>(); // 多字段排序列表,格式如["type asc", "id desc"]
......
...@@ -418,7 +418,7 @@ public class ChromosomeDataService { ...@@ -418,7 +418,7 @@ public class ChromosomeDataService {
Map<String, Object> emptyResult = new HashMap<>(); Map<String, Object> emptyResult = new HashMap<>();
emptyResult.put("records", Collections.emptyList()); emptyResult.put("records", Collections.emptyList());
emptyResult.put("totalCount", 0); emptyResult.put("totalCount", 0);
emptyResult.put("pageIndex", paged.getPageIndex() != null ? paged.getPageIndex() : 1); emptyResult.put("pageIndex", paged.getPageIndex() != null ? Math.max(0, paged.getPageIndex()) : 0);
emptyResult.put("size", paged.getPageSize() != null ? paged.getPageSize() : 10); emptyResult.put("size", paged.getPageSize() != null ? paged.getPageSize() : 10);
return emptyResult; return emptyResult;
} }
...@@ -817,9 +817,9 @@ public class ChromosomeDataService { ...@@ -817,9 +817,9 @@ public class ChromosomeDataService {
} }
// 应用分页 // 应用分页
if (paged.getPageIndex() != null && paged.getPageSize() != null && paged.getPageSize() > 0) { if (paged.getPageIndex() != null && paged.getPageSize() != null && paged.getPageSize() > 0) {
int pageIndex = paged.getPageIndex(); int pageIndex = Math.max(0, paged.getPageIndex());
int pageSize = paged.getPageSize(); int pageSize = paged.getPageSize();
int start = (pageIndex - 1) * pageSize; int start = pageIndex * pageSize;
int end = Math.min(start + pageSize, result.size()); int end = Math.min(start + pageSize, result.size());
if (start >= result.size()) { if (start >= result.size()) {
return new ArrayList<>(); return new ArrayList<>();
...@@ -1573,7 +1573,7 @@ public class ChromosomeDataService { ...@@ -1573,7 +1573,7 @@ public class ChromosomeDataService {
} }
Map<String, Object> result = new HashMap<>(); Map<String, Object> result = new HashMap<>();
int page = paged.getPageIndex() != null ? paged.getPageIndex() : 1; int page = paged.getPageIndex() != null ? Math.max(0, paged.getPageIndex()) : 0;
int size = paged.getPageSize() != null ? paged.getPageSize() : 10; int size = paged.getPageSize() != null ? paged.getPageSize() : 10;
if (data instanceof List) { if (data instanceof List) {
...@@ -1601,7 +1601,7 @@ public class ChromosomeDataService { ...@@ -1601,7 +1601,7 @@ public class ChromosomeDataService {
} }
int total = dataList.size(); int total = dataList.size();
int fromIndex = (page - 1) * size; int fromIndex = page * size;
fromIndex = Math.min(fromIndex, total); fromIndex = Math.min(fromIndex, total);
int toIndex = Math.min(fromIndex + size, total); int toIndex = Math.min(fromIndex + size, total);
...@@ -1620,7 +1620,7 @@ public class ChromosomeDataService { ...@@ -1620,7 +1620,7 @@ public class ChromosomeDataService {
} else { } else {
result.put("records", data); result.put("records", data);
result.put("totalCount", 1); result.put("totalCount", 1);
result.put("pageIndex", 1); result.put("pageIndex", 0);
result.put("size", 1); result.put("size", 1);
} }
......
...@@ -65,7 +65,7 @@ public class DatabaseQueryService { ...@@ -65,7 +65,7 @@ public class DatabaseQueryService {
String orderBy = buildOrderBy(paged); String orderBy = buildOrderBy(paged);
// 分页参数 // 分页参数
int page = paged.getPageIndex() != null ? paged.getPageIndex() : 1; int page = paged.getPageIndex() != null ? Math.max(0, paged.getPageIndex()) : 0;
int size = paged.getPageSize() != null ? paged.getPageSize() : 10; int size = paged.getPageSize() != null ? paged.getPageSize() : 10;
// 返回列:fields 有值时只查指定列,否则 SELECT * // 返回列:fields 有值时只查指定列,否则 SELECT *
...@@ -157,7 +157,7 @@ public class DatabaseQueryService { ...@@ -157,7 +157,7 @@ public class DatabaseQueryService {
Map<String, Object> empty = new HashMap<>(); Map<String, Object> empty = new HashMap<>();
empty.put("records", Collections.emptyList()); empty.put("records", Collections.emptyList());
empty.put("totalCount", 0); empty.put("totalCount", 0);
empty.put("pageIndex", paged.getPageIndex() != null ? paged.getPageIndex() : 1); empty.put("pageIndex", paged.getPageIndex() != null ? Math.max(0, paged.getPageIndex()) : 0);
empty.put("size", paged.getPageSize() != null ? paged.getPageSize() : 10); empty.put("size", paged.getPageSize() != null ? paged.getPageSize() : 10);
return empty; return empty;
} }
...@@ -165,7 +165,7 @@ public class DatabaseQueryService { ...@@ -165,7 +165,7 @@ public class DatabaseQueryService {
String groupColsStr = String.join(", ", groupCols); String groupColsStr = String.join(", ", groupCols);
// 修复分组查询时的ORDER BY语法错误 // 修复分组查询时的ORDER BY语法错误
String orderBy = buildOrderByForGroupBy(paged, groupCols); String orderBy = buildOrderByForGroupBy(paged, groupCols);
int page = paged.getPageIndex() != null ? paged.getPageIndex() : 1; int page = paged.getPageIndex() != null ? Math.max(0, paged.getPageIndex()) : 0;
int size = paged.getPageSize() != null ? paged.getPageSize() : 10; int size = paged.getPageSize() != null ? paged.getPageSize() : 10;
String countSql = "SELECT COUNT(*) FROM (SELECT " + groupColsStr + " FROM " + tableName + whereClause + " GROUP BY " + groupColsStr + ")"; String countSql = "SELECT COUNT(*) FROM (SELECT " + groupColsStr + " FROM " + tableName + whereClause + " GROUP BY " + groupColsStr + ")";
...@@ -218,8 +218,9 @@ public class DatabaseQueryService { ...@@ -218,8 +218,9 @@ public class DatabaseQueryService {
} }
private String buildOraclePaginationSqlForGroupBy(String innerSql, int page, int size) { private String buildOraclePaginationSqlForGroupBy(String innerSql, int page, int size) {
int startRow = (page - 1) * size + 1; int safePage = Math.max(0, page);
int endRow = page * size; int startRow = safePage * size + 1;
int endRow = (safePage + 1) * size;
return "SELECT * FROM (SELECT a.*, ROWNUM rn FROM (" + innerSql + ") a WHERE ROWNUM <= " + endRow + ") WHERE rn >= " + startRow; return "SELECT * FROM (SELECT a.*, ROWNUM rn FROM (" + innerSql + ") a WHERE ROWNUM <= " + endRow + ") WHERE rn >= " + startRow;
} }
...@@ -441,8 +442,9 @@ public class DatabaseQueryService { ...@@ -441,8 +442,9 @@ public class DatabaseQueryService {
* 构建Oracle分页SQL;selectClause 为 null 或空时使用 *。 * 构建Oracle分页SQL;selectClause 为 null 或空时使用 *。
*/ */
private String buildOraclePaginationSql(String tableName, String whereClause, String orderBy, int page, int size, String selectClause) { private String buildOraclePaginationSql(String tableName, String whereClause, String orderBy, int page, int size, String selectClause) {
int startRow = (page - 1) * size + 1; int safePage = Math.max(0, page);
int endRow = page * size; int startRow = safePage * size + 1;
int endRow = (safePage + 1) * size;
String cols = (selectClause != null && !selectClause.trim().isEmpty()) ? selectClause : "*"; String cols = (selectClause != null && !selectClause.trim().isEmpty()) ? selectClause : "*";
StringBuilder sql = new StringBuilder(); StringBuilder sql = new StringBuilder();
......
...@@ -2000,13 +2000,8 @@ public class LanuchServiceImpl implements LanuchService { ...@@ -2000,13 +2000,8 @@ public class LanuchServiceImpl implements LanuchService {
throw new RuntimeException("物料不存在"); throw new RuntimeException("物料不存在");
} }
// 4. 查询工艺路线(按创建时间倒序,获取最新的) // 4. 查询工艺路线:插入已有场景时优先沿用场景中同物料已使用的路线,避免误取到最新但未维护完整的路线。
RoutingHeader routingHeader = routingHeaderService.lambdaQuery() RoutingHeader routingHeader = resolveRoutingHeaderForInsert(sceneId, materialId);
.eq(RoutingHeader::getMaterialId, materialId)
.eq(RoutingHeader::getIsDeleted, 0)
.orderByDesc(RoutingHeader::getCreationTime)
.last("FETCH FIRST 1 ROWS ONLY")
.one();
if (routingHeader == null) { if (routingHeader == null) {
throw new RuntimeException("物料没有配置工艺路线"); throw new RuntimeException("物料没有配置工艺路线");
} }
...@@ -2050,4 +2045,87 @@ public class LanuchServiceImpl implements LanuchService { ...@@ -2050,4 +2045,87 @@ public class LanuchServiceImpl implements LanuchService {
log.info("插单成功,场景ID: {}, 订单编码: {}", sceneId, orderCode); log.info("插单成功,场景ID: {}, 订单编码: {}", sceneId, orderCode);
return R.ok("插单成功,订单ID: " + orderId); return R.ok("插单成功,订单ID: " + orderId);
} }
private RoutingHeader resolveRoutingHeaderForInsert(String sceneId, String materialId) {
List<RoutingHeader> candidates = routingHeaderService.lambdaQuery()
.eq(RoutingHeader::getMaterialId, materialId)
.eq(RoutingHeader::getIsDeleted, 0)
.orderByDesc(RoutingHeader::getCreationTime)
.list();
if (CollectionUtils.isEmpty(candidates)) {
return null;
}
Set<Integer> sceneRoutingIds = prodLaunchOrderService.lambdaQuery()
.eq(ProdLaunchOrder::getSceneId, sceneId)
.eq(ProdLaunchOrder::getMaterialId, materialId)
.isNotNull(ProdLaunchOrder::getRoutingId)
.list()
.stream()
.map(ProdLaunchOrder::getRoutingId)
.filter(Objects::nonNull)
.collect(Collectors.toSet());
Optional<RoutingHeader> sceneRouting = candidates.stream()
.filter(header -> sceneRoutingIds.contains(header.getId()))
.filter(this::hasResolvableProcessResources)
.findFirst();
if (sceneRouting.isPresent()) {
return sceneRouting.get();
}
Optional<RoutingHeader> namedValidRouting = candidates.stream()
.filter(header -> !isUndefinedRoutingCode(header))
.filter(this::hasResolvableProcessResources)
.findFirst();
if (namedValidRouting.isPresent()) {
return namedValidRouting.get();
}
Optional<RoutingHeader> anyValidRouting = candidates.stream()
.filter(this::hasResolvableProcessResources)
.findFirst();
return anyValidRouting.orElse(candidates.get(0));
}
private boolean hasResolvableProcessResources(RoutingHeader routingHeader) {
if (routingHeader == null || routingHeader.getId() == null) {
return false;
}
Long routingHeaderId = routingHeader.getId().longValue();
List<RoutingDetail> details = routingDetailMapper.selectList(new LambdaQueryWrapper<RoutingDetail>()
.eq(RoutingDetail::getRoutingHeaderId, routingHeaderId)
.eq(RoutingDetail::getIsDeleted, 0));
if (CollectionUtils.isEmpty(details)) {
return false;
}
Map<Long, List<RoutingDetailEquip>> equipsByDetailId = routingDetailEquipService.lambdaQuery()
.eq(RoutingDetailEquip::getRoutingHeaderId, routingHeaderId)
.eq(RoutingDetailEquip::getIsdeleted, 0)
.list()
.stream()
.filter(Objects::nonNull)
.filter(equip -> equip.getRoutingDetailId() != null)
.collect(Collectors.groupingBy(RoutingDetailEquip::getRoutingDetailId));
for (RoutingDetail detail : details) {
if (detail.getEquipTypeId() != null) {
continue;
}
boolean hasDetailEquipType = equipsByDetailId.getOrDefault(detail.getId(), Collections.emptyList())
.stream()
.anyMatch(equip -> equip.getType1() != null);
if (!hasDetailEquipType) {
return false;
}
}
return true;
}
private boolean isUndefinedRoutingCode(RoutingHeader routingHeader) {
String code = routingHeader == null ? null : routingHeader.getCode();
return code != null && code.trim().toLowerCase(Locale.ROOT).startsWith("undefined");
}
} }
...@@ -19,6 +19,7 @@ import java.time.LocalDateTime; ...@@ -19,6 +19,7 @@ import java.time.LocalDateTime;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Comparator; import java.util.Comparator;
import java.util.HashMap; import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.UUID; import java.util.UUID;
...@@ -37,7 +38,9 @@ public class UserStrategyRuleServiceImpl extends ServiceImpl<UserStrategyRuleMap ...@@ -37,7 +38,9 @@ public class UserStrategyRuleServiceImpl extends ServiceImpl<UserStrategyRuleMap
Long userId = getLong(params, "userId"); Long userId = getLong(params, "userId");
String source = getSource(params); String source = getSource(params);
String ruleId = getRuleId(params); String ruleId = getRuleId(params);
String userRuleId = "USER".equalsIgnoreCase(source) ? ruleId : getString(params, "userRuleId"); // /effective 当前用于恢复用户上次保存的策略,前端旧的 id=USER:xxx 不再作为指定查询条件。
// 排产入口如果确实要指定某条用户策略,仍可显式传 userRuleId。
String userRuleId = getString(params, "userRuleId");
Long baseRuleId = resolveBaseRuleId(params, source, ruleId); Long baseRuleId = resolveBaseRuleId(params, source, ruleId);
UserStrategyRule selectedUserRule = findUserRuleById(userRuleId, userId); UserStrategyRule selectedUserRule = findUserRuleById(userRuleId, userId);
...@@ -92,7 +95,7 @@ public class UserStrategyRuleServiceImpl extends ServiceImpl<UserStrategyRuleMap ...@@ -92,7 +95,7 @@ public class UserStrategyRuleServiceImpl extends ServiceImpl<UserStrategyRuleMap
userRule.setBaseRuleId(baseRuleId); userRule.setBaseRuleId(baseRuleId);
userRule.setSceneId(null); userRule.setSceneId(null);
userRule.setName(resolveName(params, globalRule, newUserRule)); userRule.setName(resolveName(params, globalRule, newUserRule));
userRule.setForwardScheduling(toJson(params.get("forwardScheduling"), globalRule == null ? null : globalRule.getForwardScheduling())); userRule.setForwardScheduling(toForwardSchedulingJson(params, userRule, globalRule));
userRule.setKpiConfig(toJson(params.get("kpiConfig"), null)); userRule.setKpiConfig(toJson(params.get("kpiConfig"), null));
userRule.setIsDefault(1L); userRule.setIsDefault(1L);
...@@ -201,6 +204,7 @@ public class UserStrategyRuleServiceImpl extends ServiceImpl<UserStrategyRuleMap ...@@ -201,6 +204,7 @@ public class UserStrategyRuleServiceImpl extends ServiceImpl<UserStrategyRuleMap
item.put("globalRuleId", rule.getId()); item.put("globalRuleId", rule.getId());
item.put("globalRuleName", rule.getName()); item.put("globalRuleName", rule.getName());
item.put("forwardScheduling", parseForwardScheduling(rule.getForwardScheduling())); item.put("forwardScheduling", parseForwardScheduling(rule.getForwardScheduling()));
item.put("isjit", extractIsJit(rule.getForwardScheduling(), false));
return item; return item;
} }
...@@ -216,6 +220,7 @@ public class UserStrategyRuleServiceImpl extends ServiceImpl<UserStrategyRuleMap ...@@ -216,6 +220,7 @@ public class UserStrategyRuleServiceImpl extends ServiceImpl<UserStrategyRuleMap
item.put("globalRuleId", globalRule.getId()); item.put("globalRuleId", globalRule.getId());
item.put("globalRuleName", globalRule.getName()); item.put("globalRuleName", globalRule.getName());
item.put("forwardScheduling", parseForwardScheduling(rule.getForwardScheduling())); item.put("forwardScheduling", parseForwardScheduling(rule.getForwardScheduling()));
item.put("isjit", extractIsJit(rule.getForwardScheduling(), false));
return item; return item;
} }
...@@ -318,6 +323,7 @@ public class UserStrategyRuleServiceImpl extends ServiceImpl<UserStrategyRuleMap ...@@ -318,6 +323,7 @@ public class UserStrategyRuleServiceImpl extends ServiceImpl<UserStrategyRuleMap
result.put("name", rule.getName()); result.put("name", rule.getName());
result.put("forwardScheduling", parseForwardScheduling(rule.getForwardScheduling())); result.put("forwardScheduling", parseForwardScheduling(rule.getForwardScheduling()));
result.put("kpiConfig", parseJson(rule.getKpiConfig())); result.put("kpiConfig", parseJson(rule.getKpiConfig()));
result.put("isjit", extractIsJit(rule.getForwardScheduling(), false));
return result; return result;
} }
...@@ -330,6 +336,7 @@ public class UserStrategyRuleServiceImpl extends ServiceImpl<UserStrategyRuleMap ...@@ -330,6 +336,7 @@ public class UserStrategyRuleServiceImpl extends ServiceImpl<UserStrategyRuleMap
result.put("name", rule == null ? null : rule.getName()); result.put("name", rule == null ? null : rule.getName());
result.put("forwardScheduling", rule == null ? new ArrayList<StrategyScheduling>() : parseForwardScheduling(rule.getForwardScheduling())); result.put("forwardScheduling", rule == null ? new ArrayList<StrategyScheduling>() : parseForwardScheduling(rule.getForwardScheduling()));
result.put("kpiConfig", new ArrayList<>()); result.put("kpiConfig", new ArrayList<>());
result.put("isjit", rule != null && extractIsJit(rule.getForwardScheduling(), false));
return result; return result;
} }
...@@ -376,6 +383,25 @@ public class UserStrategyRuleServiceImpl extends ServiceImpl<UserStrategyRuleMap ...@@ -376,6 +383,25 @@ public class UserStrategyRuleServiceImpl extends ServiceImpl<UserStrategyRuleMap
} }
} }
private String toForwardSchedulingJson(Map<String, Object> params, UserStrategyRule userRule, StrategyRule globalRule) {
Object forwardScheduling = params.get("forwardScheduling");
String defaultValue = globalRule == null ? null : globalRule.getForwardScheduling();
Object rawIsJit = firstValue(params, "isjit", "isJit", "jit");
Boolean isJit = rawIsJit == null ? extractIsJitObject(userRule.getForwardScheduling()) : asBoolean(rawIsJit, false);
if (isJit == null) {
isJit = extractIsJitObject(defaultValue);
}
if (isJit == null) {
return toJson(forwardScheduling, defaultValue);
}
Map<String, Object> payload = new LinkedHashMap<>();
payload.put("forwardScheduling", forwardScheduling == null ? parseForwardScheduling(defaultValue) : forwardScheduling);
payload.put("isjit", isJit == null ? false : isJit);
return toJson(payload, defaultValue);
}
private String toJson(Object value, String defaultValue) { private String toJson(Object value, String defaultValue) {
if (value == null) { if (value == null) {
return defaultValue; return defaultValue;
...@@ -390,6 +416,49 @@ public class UserStrategyRuleServiceImpl extends ServiceImpl<UserStrategyRuleMap ...@@ -390,6 +416,49 @@ public class UserStrategyRuleServiceImpl extends ServiceImpl<UserStrategyRuleMap
} }
} }
private Boolean extractIsJitObject(String json) {
if (!StringUtils.hasText(json)) {
return null;
}
try {
JsonNode root = objectMapper.readTree(json);
JsonNode value = firstJsonValue(root, "isjit", "isJit", "jit");
return value == null ? null : asBoolean(value.isValueNode() ? value.asText() : value.toString(), false);
} catch (Exception e) {
return null;
}
}
private boolean extractIsJit(String json, boolean defaultValue) {
Boolean value = extractIsJitObject(json);
return value == null ? defaultValue : value;
}
private JsonNode firstJsonValue(JsonNode root, String... keys) {
if (root == null || root.isNull()) {
return null;
}
for (String key : keys) {
JsonNode value = root.get(key);
if (value != null && !value.isNull()) {
return value;
}
}
return null;
}
private Object firstValue(Map<String, Object> params, String... keys) {
if (params == null || keys == null) {
return null;
}
for (String key : keys) {
if (params.containsKey(key)) {
return params.get(key);
}
}
return null;
}
private String resolveName(Map<String, Object> params, StrategyRule globalRule, boolean newUserRule) { private String resolveName(Map<String, Object> params, StrategyRule globalRule, boolean newUserRule) {
String name = getString(params, "name"); String name = getString(params, "name");
if (StringUtils.hasText(name)) { if (StringUtils.hasText(name)) {
...@@ -466,6 +535,26 @@ public class UserStrategyRuleServiceImpl extends ServiceImpl<UserStrategyRuleMap ...@@ -466,6 +535,26 @@ public class UserStrategyRuleServiceImpl extends ServiceImpl<UserStrategyRuleMap
return Long.valueOf(value); return Long.valueOf(value);
} }
private boolean asBoolean(Object value, boolean defaultValue) {
if (value == null) {
return defaultValue;
}
if (value instanceof Boolean) {
return (Boolean) value;
}
if (value instanceof Number) {
return ((Number) value).intValue() != 0;
}
String text = String.valueOf(value).trim();
if ("1".equals(text)) {
return true;
}
if ("0".equals(text)) {
return false;
}
return text.isEmpty() ? defaultValue : Boolean.parseBoolean(text);
}
private boolean isDeleted(Number value) { private boolean isDeleted(Number value) {
return value != null && value.longValue() != 0L; return value != null && value.longValue() != 0L;
} }
......
...@@ -39,7 +39,9 @@ import java.io.IOException; ...@@ -39,7 +39,9 @@ import java.io.IOException;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.time.LocalTime; import java.time.LocalTime;
import java.time.OffsetDateTime;
import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.time.temporal.ChronoUnit; import java.time.temporal.ChronoUnit;
import java.util.*; import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.CopyOnWriteArrayList;
...@@ -1393,13 +1395,88 @@ public class PlanResultService { ...@@ -1393,13 +1395,88 @@ public class PlanResultService {
return releasedCount; return releasedCount;
} }
private String getStringValue(Map<String, Object> data, String key) {
Object value = data == null ? null : data.get(key);
if (value == null) {
return null;
}
String text = String.valueOf(value).trim();
return text.isEmpty() ? null : text;
}
private String getFirstStringValue(Map<String, Object> data, String... keys) {
if (keys == null) {
return null;
}
for (String key : keys) {
String value = getStringValue(data, key);
if (value != null) {
return value;
}
}
return null;
}
private LocalDateTime parseOrderDateTime(Object value) {
if (value == null) {
return null;
}
if (value instanceof LocalDateTime) {
return (LocalDateTime) value;
}
String text = String.valueOf(value).trim();
if (text.isEmpty()) {
return null;
}
try {
return LocalDateTime.parse(text);
} catch (DateTimeParseException ignored) {
return OffsetDateTime.parse(text).toLocalDateTime();
}
}
private Integer parseOrderPriority(Object value) {
if (value == null || String.valueOf(value).trim().isEmpty()) {
return 1;
}
return Integer.valueOf(String.valueOf(value).trim());
}
private void applyNewOrderPayload(ProdLaunchOrder launchOrder, Map<String, Object> newOrderData) {
if (launchOrder == null || newOrderData == null) {
return;
}
String materialCode = getFirstStringValue(newOrderData, "mmcode", "materialCode");
if (materialCode != null) {
launchOrder.setMaterialCode(materialCode);
}
String materialName = getFirstStringValue(newOrderData, "mmname", "materialName");
if (materialName != null) {
launchOrder.setMaterialName(materialName);
}
String serie = getFirstStringValue(newOrderData, "series", "seriesName", "serie");
if (serie != null) {
launchOrder.setSerie(serie);
}
String groupCode = getFirstStringValue(newOrderData, "zone", "zoneid", "groupCode");
if (groupCode != null) {
launchOrder.setGroupCode(groupCode);
}
try {
launchOrder.setOrderDesc(new ObjectMapper().writeValueAsString(newOrderData));
} catch (Exception e) {
launchOrder.setOrderDesc(String.valueOf(newOrderData));
}
}
public Chromosome InsertOrderAuto(String sceneId, Map<String, Object> newOrderData) { public Chromosome InsertOrderAuto(String sceneId, Map<String, Object> newOrderData) {
if (newOrderData == null) { if (newOrderData == null) {
throw new RuntimeException("newOrder 不能为空"); throw new RuntimeException("newOrder 不能为空");
} }
String orderCode = String.valueOf(newOrderData.get("orderCode")); String orderCode = getStringValue(newOrderData, "orderCode");
String materialId = String.valueOf(newOrderData.get("materialId")); String materialId = getStringValue(newOrderData, "materialId");
Object qtyObj = newOrderData.get("quantity"); Object qtyObj = newOrderData.get("quantity");
if (orderCode == null || orderCode.trim().isEmpty()) { if (orderCode == null || orderCode.trim().isEmpty()) {
throw new RuntimeException("orderCode 不能为空"); throw new RuntimeException("orderCode 不能为空");
...@@ -1411,9 +1488,13 @@ public class PlanResultService { ...@@ -1411,9 +1488,13 @@ public class PlanResultService {
throw new RuntimeException("quantity 不能为空"); throw new RuntimeException("quantity 不能为空");
} }
Double quantity = Double.valueOf(String.valueOf(qtyObj)); Double quantity = Double.valueOf(String.valueOf(qtyObj));
LocalDateTime startDate = parseOrderDateTime(newOrderData.get("startDate"));
LocalDateTime endDate = parseOrderDateTime(newOrderData.get("endDate"));
Integer priority = parseOrderPriority(newOrderData.get("priority"));
// 1. 创建新订单(沿用现有创建逻辑) // 1. 创建新订单(沿用现有创建逻辑)
R<String> insertResp = lanuchService.insertOrder(sceneId, orderCode, materialId, null, null, 1, quantity); R<String> insertResp = lanuchService.insertOrder(sceneId, orderCode, materialId,
startDate, endDate, priority, quantity);
String insertMsg = insertResp != null ? insertResp.getData() : null; String insertMsg = insertResp != null ? insertResp.getData() : null;
if (insertMsg == null || insertMsg.trim().isEmpty()) { if (insertMsg == null || insertMsg.trim().isEmpty()) {
throw new RuntimeException("创建订单失败:未返回订单ID"); throw new RuntimeException("创建订单失败:未返回订单ID");
...@@ -1438,6 +1519,8 @@ public class PlanResultService { ...@@ -1438,6 +1519,8 @@ public class PlanResultService {
if (newLaunchOrder == null) { if (newLaunchOrder == null) {
throw new RuntimeException("新订单不存在:" + newOrderId); throw new RuntimeException("新订单不存在:" + newOrderId);
} }
applyNewOrderPayload(newLaunchOrder, newOrderData);
_prodLaunchOrderService.updateById(newLaunchOrder);
List<ProdProcessExec> newProcessExecs = _prodProcessExecService.lambdaQuery() List<ProdProcessExec> newProcessExecs = _prodProcessExecService.lambdaQuery()
.eq(ProdProcessExec::getSceneId, sceneId) .eq(ProdProcessExec::getSceneId, sceneId)
...@@ -2179,6 +2262,7 @@ if(job.getGeneDetails()!=null) ...@@ -2179,6 +2262,7 @@ if(job.getGeneDetails()!=null)
GlobalParam globalParam = InitGlobalParam(); GlobalParam globalParam = InitGlobalParam();
Object kpiConfig = scheduleStrategyService.loadEffectiveKpiConfig(userId, baseRuleId, sceneId, userRuleId); Object kpiConfig = scheduleStrategyService.loadEffectiveKpiConfig(userId, baseRuleId, sceneId, userRuleId);
globalParam.applyKpiConfig(kpiConfig); globalParam.applyKpiConfig(kpiConfig);
globalParam.setJit(scheduleStrategyService.loadEffectiveIsJit(userId, baseRuleId, sceneId, userRuleId));
return globalParam; return globalParam;
} }
......
...@@ -90,6 +90,29 @@ public class ScheduleStrategyService { ...@@ -90,6 +90,29 @@ public class ScheduleStrategyService {
} }
} }
public boolean loadEffectiveIsJit(Long userId, Long baseRuleId, String sceneId, String userRuleId) {
try {
Map<String, Object> params = new HashMap<>();
Long effectiveUserId = resolveScheduleUserId(sceneId, userId);
if (effectiveUserId != null) {
params.put("userId", effectiveUserId);
}
if (baseRuleId != null) {
params.put("baseRuleId", baseRuleId);
}
if (userRuleId != null && !userRuleId.trim().isEmpty()) {
params.put("userRuleId", userRuleId);
}
Map<String, Object> effectiveRule = userStrategyRuleService.getEffectiveRule(params);
return effectiveRule != null && asBoolean(effectiveRule.get("isjit"), false);
} catch (Exception e) {
log.warn("Load JIT strategy failed, use GlobalParam default isJit=false. sceneId={}, userId={}, baseRuleId={}, userRuleId={}",
sceneId, userId, baseRuleId, userRuleId, e);
return false;
}
}
public OrderSortRule createMultiConditionRule(List<Order> orders) { public OrderSortRule createMultiConditionRule(List<Order> orders) {
return createMultiConditionRule(orders, Collections.emptyList()); return createMultiConditionRule(orders, Collections.emptyList());
} }
...@@ -241,4 +264,24 @@ public class ScheduleStrategyService { ...@@ -241,4 +264,24 @@ public class ScheduleStrategyService {
condition.setReverse(reverse); condition.setReverse(reverse);
return condition; return condition;
} }
private boolean asBoolean(Object value, boolean defaultValue) {
if (value == null) {
return defaultValue;
}
if (value instanceof Boolean) {
return (Boolean) value;
}
if (value instanceof Number) {
return ((Number) value).intValue() != 0;
}
String text = String.valueOf(value).trim();
if ("1".equals(text)) {
return true;
}
if ("0".equals(text)) {
return false;
}
return text.isEmpty() ? defaultValue : Boolean.parseBoolean(text);
}
} }
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