mirror of
http://192.168.1.205:9980/cf_devdept2/cf_imes_server.git
synced 2026-08-12 21:02:08 +08:00
1、新增接入组件修改加工方案组;2、新增组件加工方案组列表接口;
This commit is contained in:
+17
-1
@@ -11,6 +11,7 @@ import com.cf.imes.module.executor.controller.admin.plan.bo.OrderRoomBodyList;
|
|||||||
import com.cf.imes.module.executor.controller.admin.plan.vo.*;
|
import com.cf.imes.module.executor.controller.admin.plan.vo.*;
|
||||||
import com.cf.imes.module.executor.controller.admin.plate.vo.OrderViewPlatePageRespVO;
|
import com.cf.imes.module.executor.controller.admin.plate.vo.OrderViewPlatePageRespVO;
|
||||||
import com.cf.imes.module.executor.service.plan.PlanService;
|
import com.cf.imes.module.executor.service.plan.PlanService;
|
||||||
|
import com.fasterxml.jackson.databind.JsonNode;
|
||||||
import io.swagger.v3.oas.annotations.Operation;
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
import io.swagger.v3.oas.annotations.Parameter;
|
import io.swagger.v3.oas.annotations.Parameter;
|
||||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
@@ -22,6 +23,7 @@ import jakarta.annotation.Resource;
|
|||||||
import jakarta.servlet.http.HttpServletResponse;
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
import jakarta.validation.Valid;
|
import jakarta.validation.Valid;
|
||||||
import jakarta.validation.constraints.NotEmpty;
|
import jakarta.validation.constraints.NotEmpty;
|
||||||
|
import jakarta.validation.constraints.Min;
|
||||||
import jakarta.validation.constraints.NotNull;
|
import jakarta.validation.constraints.NotNull;
|
||||||
import jakarta.validation.constraints.Size;
|
import jakarta.validation.constraints.Size;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@@ -202,4 +204,18 @@ public class PlanController {
|
|||||||
planService.releasePlanLock(orderPlanLockReqVO);
|
planService.releasePlanLock(orderPlanLockReqVO);
|
||||||
return success(true);
|
return success(true);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
@GetMapping("/producing/workflow-scheme/list/{page}")
|
||||||
|
@Operation(summary = "查询组件生产系统工作流方案列表")
|
||||||
|
@PreAuthorize("@ss.hasAnyPermissions('manage:order-plan:process-scheme','producePlan:order-plan:process-scheme')")
|
||||||
|
public CommonResult<JsonNode> getProducingWorkflowSchemeList(
|
||||||
|
@PathVariable @Min(value = 1, message = "页码必须大于 0") Integer page,
|
||||||
|
@RequestParam(required = false) Integer type,
|
||||||
|
@RequestParam(required = false) Long parentId,
|
||||||
|
@RequestParam(defaultValue = "20")
|
||||||
|
@Min(value = 1, message = "每页数量必须大于 0") Integer pageSize,
|
||||||
|
@RequestParam(defaultValue = "true") Boolean isPaging) {
|
||||||
|
return success(planService.getProducingWorkflowSchemeList(
|
||||||
|
page, type, parentId, pageSize, isPaging));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
+15
-1
@@ -7,6 +7,7 @@ import com.cf.imes.module.executor.controller.admin.plan.bo.OrderRoomBodyList;
|
|||||||
import com.cf.imes.module.executor.controller.admin.plan.vo.*;
|
import com.cf.imes.module.executor.controller.admin.plan.vo.*;
|
||||||
|
|
||||||
import com.cf.imes.module.executor.controller.admin.plate.vo.OrderViewPlatePageRespVO;
|
import com.cf.imes.module.executor.controller.admin.plate.vo.OrderViewPlatePageRespVO;
|
||||||
|
import com.fasterxml.jackson.databind.JsonNode;
|
||||||
import jakarta.validation.Valid;
|
import jakarta.validation.Valid;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@@ -112,4 +113,17 @@ public interface PlanService {
|
|||||||
* @param orderPlanLockReqVO
|
* @param orderPlanLockReqVO
|
||||||
*/
|
*/
|
||||||
void releasePlanLock(OrderPlanLockReqVO orderPlanLockReqVO);
|
void releasePlanLock(OrderPlanLockReqVO orderPlanLockReqVO);
|
||||||
}
|
|
||||||
|
/**
|
||||||
|
* 查询组件生产系统工作流方案列表。
|
||||||
|
*
|
||||||
|
* @param page 页码
|
||||||
|
* @param type 工作流类型,可为空
|
||||||
|
* @param parentId 父级方案 ID,可为空
|
||||||
|
* @param pageSize 每页数量
|
||||||
|
* @param isPaging 是否分页
|
||||||
|
* @return 工作流方案列表响应数据
|
||||||
|
*/
|
||||||
|
JsonNode getProducingWorkflowSchemeList(Integer page, Integer type, Long parentId,
|
||||||
|
Integer pageSize, Boolean isPaging);
|
||||||
|
}
|
||||||
|
|||||||
+16
@@ -61,6 +61,7 @@ import com.cf.imes.module.executor.enums.OrderStatusEnum;
|
|||||||
import com.cf.imes.module.executor.service.plan.producing.ProducingPlanOrderClient;
|
import com.cf.imes.module.executor.service.plan.producing.ProducingPlanOrderClient;
|
||||||
import com.cf.imes.module.executor.service.plan.producing.ProducingPlanOrderMaterialGroup;
|
import com.cf.imes.module.executor.service.plan.producing.ProducingPlanOrderMaterialGroup;
|
||||||
import com.cf.imes.module.system.api.auth.AuthApi;
|
import com.cf.imes.module.system.api.auth.AuthApi;
|
||||||
|
import com.fasterxml.jackson.databind.JsonNode;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.springframework.aop.framework.AopContext;
|
import org.springframework.aop.framework.AopContext;
|
||||||
@@ -247,6 +248,13 @@ public class PlanServiceImpl implements PlanService {
|
|||||||
Long processId = planDO.getProcessId();
|
Long processId = planDO.getProcessId();
|
||||||
if (ObjectUtil.notEqual(processId, currProcessId)) {
|
if (ObjectUtil.notEqual(processId, currProcessId)) {
|
||||||
planDO.setPreviousProcessId(processId);
|
planDO.setPreviousProcessId(processId);
|
||||||
|
if (planDO.getProducingPlanOrderId() == null) {
|
||||||
|
throw new ServiceException(PRODUCING_PLAN_ORDER_SYNC_FAILED,
|
||||||
|
"producingPlanOrderId is required");
|
||||||
|
}
|
||||||
|
producingPlanOrderClient.changeScheme(
|
||||||
|
getProducingToken(), planDO.getProducingPlanOrderId(),
|
||||||
|
currProcessId);
|
||||||
}
|
}
|
||||||
|
|
||||||
planDO.setProcessId(currProcessId);
|
planDO.setProcessId(currProcessId);
|
||||||
@@ -2169,6 +2177,14 @@ public class PlanServiceImpl implements PlanService {
|
|||||||
return authApi.getMesJwtToken().getCheckedData();
|
return authApi.getMesJwtToken().getCheckedData();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JsonNode getProducingWorkflowSchemeList(Integer page, Integer type,
|
||||||
|
Long parentId, Integer pageSize,
|
||||||
|
Boolean isPaging) {
|
||||||
|
return producingPlanOrderClient.listWorkflowSchemes(
|
||||||
|
getProducingToken(), page, type, parentId, pageSize, isPaging);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void getPlanLock(OrderPlanLockReqVO orderPlanLockReqVO) {
|
public void getPlanLock(OrderPlanLockReqVO orderPlanLockReqVO) {
|
||||||
Long planId = orderPlanLockReqVO.getPlanId();
|
Long planId = orderPlanLockReqVO.getPlanId();
|
||||||
|
|||||||
+115
-2
@@ -55,7 +55,7 @@ public class ProducingPlanOrderClient {
|
|||||||
JsonNode planOrderIdNode = result;
|
JsonNode planOrderIdNode = result;
|
||||||
if (result != null && result.isObject()) {
|
if (result != null && result.isObject()) {
|
||||||
JsonNode code = result.get("code");
|
JsonNode code = result.get("code");
|
||||||
if (code == null || !code.isIntegralNumber() || code.intValue() != 0) {
|
if (code == null || !isSuccessCode(code)) {
|
||||||
String message = result.path("message").asText("business error");
|
String message = result.path("message").asText("business error");
|
||||||
logRequestFailure("create", method, url, requestBody,
|
logRequestFailure("create", method, url, requestBody,
|
||||||
response.statusCode(), response.body(), null);
|
response.statusCode(), response.body(), null);
|
||||||
@@ -101,10 +101,112 @@ public class ProducingPlanOrderClient {
|
|||||||
validateBusinessResponse(response, "delete", method, url, null);
|
validateBusinessResponse(response, "delete", method, url, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询组件生产系统的工作流方案列表。
|
||||||
|
*
|
||||||
|
* @param token MES JWT
|
||||||
|
* @param page 页码
|
||||||
|
* @param type 工作流类型,可为空
|
||||||
|
* @param parentId 父级方案 ID,可为空
|
||||||
|
* @param pageSize 每页数量
|
||||||
|
* @param isPaging 是否分页
|
||||||
|
* @return 对方统一响应中的 data;响应没有 data 时返回完整响应对象
|
||||||
|
*/
|
||||||
|
public JsonNode listWorkflowSchemes(String token, Integer page, Integer type,
|
||||||
|
Long parentId, Integer pageSize, Boolean isPaging) {
|
||||||
|
String method = "GET";
|
||||||
|
String url = workflowSchemeListUrl(page, type, parentId, pageSize, isPaging);
|
||||||
|
HttpResponse<String> response = send(
|
||||||
|
url, token, method, null, "list-workflow-scheme");
|
||||||
|
try {
|
||||||
|
JsonNode result = objectMapper.readTree(response.body());
|
||||||
|
if (result == null) {
|
||||||
|
logRequestFailure("list-workflow-scheme", method, url, null,
|
||||||
|
response.statusCode(), response.body(), null);
|
||||||
|
throw syncError("list-workflow-scheme: empty response");
|
||||||
|
}
|
||||||
|
if (result.isObject() && result.has("code")) {
|
||||||
|
JsonNode code = result.get("code");
|
||||||
|
if (!isSuccessCode(code)) {
|
||||||
|
String message = result.path("message").asText("business error");
|
||||||
|
logRequestFailure("list-workflow-scheme", method, url, null,
|
||||||
|
response.statusCode(), response.body(), null);
|
||||||
|
throw syncError("list-workflow-scheme: " + message);
|
||||||
|
}
|
||||||
|
JsonNode data = result.get("data");
|
||||||
|
return data == null ? result : data;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
} catch (JsonProcessingException ex) {
|
||||||
|
logRequestFailure("list-workflow-scheme", method, url, null,
|
||||||
|
response.statusCode(), response.body(), ex);
|
||||||
|
throw syncError("list-workflow-scheme: invalid response");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修改组件生产排单使用的工作流方案。
|
||||||
|
*
|
||||||
|
* @param token MES JWT
|
||||||
|
* @param planOrderId 组件生产排单 ID
|
||||||
|
* @param workflowSchemeId 新工作流方案 ID
|
||||||
|
*/
|
||||||
|
public void changeScheme(String token, Long planOrderId, Long workflowSchemeId) {
|
||||||
|
String method = "PUT";
|
||||||
|
String url = resourceUrl(planOrderId, "change-scheme-id");
|
||||||
|
String requestBody = serialize(new ChangeSchemeRequest(workflowSchemeId));
|
||||||
|
HttpResponse<String> response = send(
|
||||||
|
url, token, method, requestBody, "change-scheme-id");
|
||||||
|
validateBusinessResponse(
|
||||||
|
response, "change-scheme-id", method, url, requestBody);
|
||||||
|
}
|
||||||
|
|
||||||
private String resourceUrl(Long planOrderId, String action) {
|
private String resourceUrl(Long planOrderId, String action) {
|
||||||
return properties.getBaseUrl() + "/" + planOrderId + "/" + action;
|
return properties.getBaseUrl() + "/" + planOrderId + "/" + action;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String workflowSchemeListUrl(Integer page, Integer type, Long parentId,
|
||||||
|
Integer pageSize, Boolean isPaging) {
|
||||||
|
StringBuilder url = new StringBuilder(workflowSchemeBaseUrl())
|
||||||
|
.append("/list/").append(page == null ? 1 : page);
|
||||||
|
String separator = "?";
|
||||||
|
if (type != null) {
|
||||||
|
url.append(separator).append("type=").append(type);
|
||||||
|
separator = "&";
|
||||||
|
}
|
||||||
|
if (parentId != null) {
|
||||||
|
url.append(separator).append("parentId=").append(parentId);
|
||||||
|
separator = "&";
|
||||||
|
}
|
||||||
|
if (pageSize != null) {
|
||||||
|
url.append(separator).append("pageSize=").append(pageSize);
|
||||||
|
separator = "&";
|
||||||
|
}
|
||||||
|
if (isPaging != null) {
|
||||||
|
url.append(separator).append("isPaging=").append(isPaging);
|
||||||
|
}
|
||||||
|
return url.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private String workflowSchemeBaseUrl() {
|
||||||
|
String configuredUrl = properties.getWorkflowSchemeBaseUrl();
|
||||||
|
if (configuredUrl != null && !configuredUrl.isBlank()) {
|
||||||
|
return removeTrailingSlash(configuredUrl);
|
||||||
|
}
|
||||||
|
String planOrderBaseUrl = removeTrailingSlash(properties.getBaseUrl());
|
||||||
|
String suffix = "/plan-order";
|
||||||
|
if (planOrderBaseUrl == null || !planOrderBaseUrl.endsWith(suffix)) {
|
||||||
|
throw syncError("cannot derive workflow scheme url from baseUrl");
|
||||||
|
}
|
||||||
|
return planOrderBaseUrl.substring(0, planOrderBaseUrl.length() - suffix.length())
|
||||||
|
+ "/workflow-scheme";
|
||||||
|
}
|
||||||
|
|
||||||
|
private String removeTrailingSlash(String url) {
|
||||||
|
return url != null && url.endsWith("/")
|
||||||
|
? url.substring(0, url.length() - 1) : url;
|
||||||
|
}
|
||||||
|
|
||||||
private String serialize(Object request) {
|
private String serialize(Object request) {
|
||||||
try {
|
try {
|
||||||
return objectMapper.writeValueAsString(request);
|
return objectMapper.writeValueAsString(request);
|
||||||
@@ -162,7 +264,7 @@ public class ProducingPlanOrderClient {
|
|||||||
try {
|
try {
|
||||||
JsonNode result = objectMapper.readTree(response.body());
|
JsonNode result = objectMapper.readTree(response.body());
|
||||||
JsonNode code = result == null || !result.isObject() ? null : result.get("code");
|
JsonNode code = result == null || !result.isObject() ? null : result.get("code");
|
||||||
if (code != null && code.isIntegralNumber() && code.intValue() != 0) {
|
if (code != null && !isSuccessCode(code)) {
|
||||||
String message = result.path("message").asText("business error");
|
String message = result.path("message").asText("business error");
|
||||||
logRequestFailure(operation, method, url, requestBody,
|
logRequestFailure(operation, method, url, requestBody,
|
||||||
response.statusCode(), response.body(), null);
|
response.statusCode(), response.body(), null);
|
||||||
@@ -194,6 +296,11 @@ public class ProducingPlanOrderClient {
|
|||||||
responseBodyForLog(responseBody), ex);
|
responseBodyForLog(responseBody), ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean isSuccessCode(JsonNode code) {
|
||||||
|
return code.isIntegralNumber() && code.intValue() == 0
|
||||||
|
|| code.isTextual() && "0".equals(code.textValue());
|
||||||
|
}
|
||||||
|
|
||||||
private String responseBodyForLog(String body) {
|
private String responseBodyForLog(String body) {
|
||||||
if (body == null) {
|
if (body == null) {
|
||||||
return "";
|
return "";
|
||||||
@@ -225,4 +332,10 @@ public class ProducingPlanOrderClient {
|
|||||||
private static class DeleteBlocksRequest {
|
private static class DeleteBlocksRequest {
|
||||||
private List<String> deleteBlockIds;
|
private List<String> deleteBlockIds;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@AllArgsConstructor
|
||||||
|
private static class ChangeSchemeRequest {
|
||||||
|
private Long workflowSchemeId;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+5
@@ -17,6 +17,11 @@ public class ProducingPlanOrderProperties {
|
|||||||
private String baseUrl =
|
private String baseUrl =
|
||||||
"https://chenfeng.tech:38113/api-branch=opt_split_order/api/v1/producing/plan-order";
|
"https://chenfeng.tech:38113/api-branch=opt_split_order/api/v1/producing/plan-order";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 组件生产系统工作流方案接口地址。为空时根据 {@link #baseUrl} 自动推导。
|
||||||
|
*/
|
||||||
|
private String workflowSchemeBaseUrl;
|
||||||
|
|
||||||
private Duration connectTimeout = Duration.ofSeconds(5);
|
private Duration connectTimeout = Duration.ofSeconds(5);
|
||||||
|
|
||||||
private Duration readTimeout = Duration.ofSeconds(10);
|
private Duration readTimeout = Duration.ofSeconds(10);
|
||||||
|
|||||||
+35
-5
@@ -27,6 +27,7 @@ class ProducingPlanOrderClientTest {
|
|||||||
void setUp() throws IOException {
|
void setUp() throws IOException {
|
||||||
server = HttpServer.create(new InetSocketAddress(0), 0);
|
server = HttpServer.create(new InetSocketAddress(0), 0);
|
||||||
server.createContext("/api/v1/producing/plan-order", this::handle);
|
server.createContext("/api/v1/producing/plan-order", this::handle);
|
||||||
|
server.createContext("/api/v1/producing/workflow-scheme", this::handle);
|
||||||
server.start();
|
server.start();
|
||||||
|
|
||||||
ProducingPlanOrderProperties properties = new ProducingPlanOrderProperties();
|
ProducingPlanOrderProperties properties = new ProducingPlanOrderProperties();
|
||||||
@@ -90,24 +91,53 @@ class ProducingPlanOrderClientTest {
|
|||||||
.get("deleteBlockIds").get(0).textValue()).isEqualTo("source-2");
|
.get("deleteBlockIds").get(0).textValue()).isEqualTo("source-2");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void shouldListWorkflowSchemesAndChangePlanScheme() throws Exception {
|
||||||
|
JsonNode data = client.listWorkflowSchemes(
|
||||||
|
"mes-token", 2, 1, 10L, 50, false);
|
||||||
|
client.changeScheme("mes-token", 98765L, 36L);
|
||||||
|
|
||||||
|
assertThat(data.get("list").get(0).get("id").longValue()).isEqualTo(36L);
|
||||||
|
assertThat(requests).hasSize(2);
|
||||||
|
assertThat(requests).extracting(RecordedRequest::method)
|
||||||
|
.containsExactly("GET", "PUT");
|
||||||
|
assertThat(requests).extracting(RecordedRequest::path)
|
||||||
|
.containsExactly(
|
||||||
|
"/api/v1/producing/workflow-scheme/list/2",
|
||||||
|
"/api/v1/producing/plan-order/98765/change-scheme-id");
|
||||||
|
assertThat(requests.get(0).query())
|
||||||
|
.isEqualTo("type=1&parentId=10&pageSize=50&isPaging=false");
|
||||||
|
assertThat(objectMapper.readTree(requests.get(1).body())
|
||||||
|
.get("workflowSchemeId").longValue()).isEqualTo(36L);
|
||||||
|
}
|
||||||
|
|
||||||
private void handle(HttpExchange exchange) throws IOException {
|
private void handle(HttpExchange exchange) throws IOException {
|
||||||
String body = new String(exchange.getRequestBody().readAllBytes(), StandardCharsets.UTF_8);
|
String body = new String(exchange.getRequestBody().readAllBytes(), StandardCharsets.UTF_8);
|
||||||
requests.add(new RecordedRequest(
|
requests.add(new RecordedRequest(
|
||||||
exchange.getRequestMethod(),
|
exchange.getRequestMethod(),
|
||||||
exchange.getRequestURI().getPath(),
|
exchange.getRequestURI().getPath(),
|
||||||
|
exchange.getRequestURI().getQuery(),
|
||||||
exchange.getRequestHeaders().getFirst("Authorization"),
|
exchange.getRequestHeaders().getFirst("Authorization"),
|
||||||
body));
|
body));
|
||||||
byte[] response = exchange.getRequestURI().getPath()
|
String path = exchange.getRequestURI().getPath();
|
||||||
.equals("/api/v1/producing/plan-order")
|
byte[] response;
|
||||||
? """
|
if (path.equals("/api/v1/producing/plan-order")) {
|
||||||
|
response = """
|
||||||
{"data":98765,"code":0,"message":"Request processed successfully."}
|
{"data":98765,"code":0,"message":"Request processed successfully."}
|
||||||
""".getBytes(StandardCharsets.UTF_8) : new byte[0];
|
""".getBytes(StandardCharsets.UTF_8);
|
||||||
|
} else if (path.equals("/api/v1/producing/workflow-scheme/list/2")) {
|
||||||
|
response = """
|
||||||
|
{"data":{"list":[{"id":36,"name":"scheme"}]},"code":0,"message":"success"}
|
||||||
|
""".getBytes(StandardCharsets.UTF_8);
|
||||||
|
} else {
|
||||||
|
response = new byte[0];
|
||||||
|
}
|
||||||
exchange.sendResponseHeaders(200, response.length);
|
exchange.sendResponseHeaders(200, response.length);
|
||||||
exchange.getResponseBody().write(response);
|
exchange.getResponseBody().write(response);
|
||||||
exchange.close();
|
exchange.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
private record RecordedRequest(
|
private record RecordedRequest(
|
||||||
String method, String path, String authorization, String body) {
|
String method, String path, String query, String authorization, String body) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user