diff --git a/lms/nladmin-system/src/main/java/org/nl/wms/cockpit/rest/BigScreenController.java b/lms/nladmin-system/src/main/java/org/nl/wms/cockpit/rest/BigScreenController.java new file mode 100644 index 0000000..623ad31 --- /dev/null +++ b/lms/nladmin-system/src/main/java/org/nl/wms/cockpit/rest/BigScreenController.java @@ -0,0 +1,51 @@ +package org.nl.wms.cockpit.rest; + +import cn.dev33.satoken.annotation.SaIgnore; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.nl.modules.common.api.CommonResult; +import org.nl.modules.common.api.RestBusinessTemplate; +import org.nl.modules.logging.annotation.Log; +import org.nl.wms.cockpit.service.BigScreenService; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * @Author: lyd + * @Description: + * @Date: 2023/5/30 + */ +@RestController +@RequiredArgsConstructor +@Api(tags = "大屏数据") +@RequestMapping("/api/cockpit") +@Slf4j +public class BigScreenController { + + private final BigScreenService bigScreenService; + + /** + * 工序生产Process production + */ + @PostMapping("/processProduction") + @Log("工序生产") + @SaIgnore + @ApiOperation("工序生产") + public CommonResult processProduction() { + return RestBusinessTemplate.execute(bigScreenService::processProduction); + } + + /** + * 首页 车间情况 + */ + @PostMapping("/workshopCondition") + @Log("车间情况") + @SaIgnore + @ApiOperation("车间情况") + public CommonResult workshopCondition() { + return RestBusinessTemplate.execute(bigScreenService::workshopCondition); + } +} diff --git a/lms/nladmin-system/src/main/java/org/nl/wms/cockpit/rest/CockpitController.java b/lms/nladmin-system/src/main/java/org/nl/wms/cockpit/rest/CockpitController.java index f5394eb..6dcc5d4 100644 --- a/lms/nladmin-system/src/main/java/org/nl/wms/cockpit/rest/CockpitController.java +++ b/lms/nladmin-system/src/main/java/org/nl/wms/cockpit/rest/CockpitController.java @@ -34,7 +34,7 @@ import java.util.concurrent.ConcurrentSkipListMap; @RestController @RequiredArgsConstructor @Api(tags = "大屏数据") -@RequestMapping("/api/cockpit") +@RequestMapping("/api/cockpit2") @Slf4j public class CockpitController{ private final CockpitService cockpitService; @@ -104,17 +104,6 @@ public class CockpitController{ }); } - /** - * 車间情况 - */ - @PostMapping("/workshopCondition") - @Log("车间情况") - @SaIgnore - @ApiOperation("车间情况") - public CommonResult workshopCondition() { - return RestBusinessTemplate.execute(cockpitService::workshopCondition); - } - /** * 工序生产Process production */ @@ -125,4 +114,15 @@ public class CockpitController{ public CommonResult processProduction() { return RestBusinessTemplate.execute(cockpitService::processProduction); } + + /** + * 首页 车间情况 + */ + @PostMapping("/workshopCondition") + @Log("车间情况") + @SaIgnore + @ApiOperation("车间情况") + public CommonResult workshopCondition() { + return RestBusinessTemplate.execute(cockpitService::workshopCondition); + } } diff --git a/lms/nladmin-system/src/main/java/org/nl/wms/cockpit/service/BigScreenService.java b/lms/nladmin-system/src/main/java/org/nl/wms/cockpit/service/BigScreenService.java new file mode 100644 index 0000000..cf3d30d --- /dev/null +++ b/lms/nladmin-system/src/main/java/org/nl/wms/cockpit/service/BigScreenService.java @@ -0,0 +1,24 @@ +package org.nl.wms.cockpit.service; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +/** + * @Author: lyd + * @Description: + * @Date: 2023/5/30 + */ +public interface BigScreenService { + /** new + * 車间情况 + * + * @return 返回结果集 + */ + ConcurrentHashMap workshopCondition(); + + /** new + * 工序生产 + * @return + */ + ConcurrentHashMap processProduction(); +} diff --git a/lms/nladmin-system/src/main/java/org/nl/wms/cockpit/service/CockpitService.java b/lms/nladmin-system/src/main/java/org/nl/wms/cockpit/service/CockpitService.java index 384a292..7ea179f 100644 --- a/lms/nladmin-system/src/main/java/org/nl/wms/cockpit/service/CockpitService.java +++ b/lms/nladmin-system/src/main/java/org/nl/wms/cockpit/service/CockpitService.java @@ -54,14 +54,14 @@ public interface CockpitService{ */ DeviceDetailDto findDeviceById(Map id); - /** + /** new * 車间情况 * * @return 返回结果集 */ Map workshopCondition(); - /** + /** new * 工序生产 * @return */ diff --git a/lms/nladmin-system/src/main/java/org/nl/wms/cockpit/service/dto/FailureDeviceInfoDto.java b/lms/nladmin-system/src/main/java/org/nl/wms/cockpit/service/dto/FailureDeviceInfoDto.java new file mode 100644 index 0000000..cd90100 --- /dev/null +++ b/lms/nladmin-system/src/main/java/org/nl/wms/cockpit/service/dto/FailureDeviceInfoDto.java @@ -0,0 +1,19 @@ +package org.nl.wms.cockpit.service.dto; + +import lombok.Data; + +import java.io.Serializable; + +/** + * @Author: lyd + * @Description: 故障设备信息dto + * @Date: 2023/5/30 + */ +@Data +public class FailureDeviceInfoDto implements Serializable { + private String failure_time; + private String device_code; + private String device_name; + private String failure_info; + private String device_status_name; +} diff --git a/lms/nladmin-system/src/main/java/org/nl/wms/cockpit/service/dto/ManufacturedProductsDto.java b/lms/nladmin-system/src/main/java/org/nl/wms/cockpit/service/dto/ManufacturedProductsDto.java new file mode 100644 index 0000000..33e2572 --- /dev/null +++ b/lms/nladmin-system/src/main/java/org/nl/wms/cockpit/service/dto/ManufacturedProductsDto.java @@ -0,0 +1,18 @@ +package org.nl.wms.cockpit.service.dto; + +import lombok.Data; + +import java.io.Serializable; + +/** + * @Author: lyd + * @Description: 工业成品Dto + * @Date: 2023/5/30 + */ +@Data +public class ManufacturedProductsDto implements Serializable { + private Integer qualified_in_qty; + private Integer unqualified_in_qty; + private Integer inventory_qty; + private String material_code; +} diff --git a/lms/nladmin-system/src/main/java/org/nl/wms/cockpit/service/dto/OperationConditionDto.java b/lms/nladmin-system/src/main/java/org/nl/wms/cockpit/service/dto/OperationConditionDto.java new file mode 100644 index 0000000..1c71747 --- /dev/null +++ b/lms/nladmin-system/src/main/java/org/nl/wms/cockpit/service/dto/OperationConditionDto.java @@ -0,0 +1,19 @@ +package org.nl.wms.cockpit.service.dto; + +import lombok.Data; + +import java.io.Serializable; + +/** + * @Author: lyd + * @Description: 设备运行情况 + * @Date: 2023/5/30 + */ +@Data +public class OperationConditionDto implements Serializable { + private String device_name; + private Integer failure; + private Integer shutdown; + private Integer standby; + private Integer running; +} diff --git a/lms/nladmin-system/src/main/java/org/nl/wms/cockpit/service/enums/ColorEnum.java b/lms/nladmin-system/src/main/java/org/nl/wms/cockpit/service/enums/ColorEnum.java new file mode 100644 index 0000000..2bc813f --- /dev/null +++ b/lms/nladmin-system/src/main/java/org/nl/wms/cockpit/service/enums/ColorEnum.java @@ -0,0 +1,31 @@ +package org.nl.wms.cockpit.service.enums; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * @Author: lyd + * @Description: 颜色枚举 + * @Date: 2023/5/30 + */ +@Getter +@AllArgsConstructor +public enum ColorEnum { + GREY(0, "灰色"), + GREEN(1, "绿色"), + RED(2, "红色"), + YELLOW(3, "黄色"); + + private final Integer index; + private final String colorName; + + public static ColorEnum getColorEnumByIndex(int index) { + ColorEnum[] enums = ColorEnum.values(); + for (ColorEnum colorEnum : enums) { + if (colorEnum.getIndex() == index) { + return colorEnum; + } + } + return null; // 如果没有找到对应的枚举常量,可以根据需要返回null或者抛出异常 + } +} diff --git a/lms/nladmin-system/src/main/java/org/nl/wms/cockpit/service/enums/DeviceEnum.java b/lms/nladmin-system/src/main/java/org/nl/wms/cockpit/service/enums/DeviceEnum.java new file mode 100644 index 0000000..6ec7748 --- /dev/null +++ b/lms/nladmin-system/src/main/java/org/nl/wms/cockpit/service/enums/DeviceEnum.java @@ -0,0 +1,30 @@ +package org.nl.wms.cockpit.service.enums; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * @Author: lyd + * @Description: 设备枚举 + * @Date: 2023/5/30 + */ +@Getter +@AllArgsConstructor +public enum DeviceEnum { + HL(0, "混料"), + YZ(1, "压制"), + GZ(2, "干燥"), + BZ(3, "包装"); + private final int index; + private final String device_name; + + public static DeviceEnum getDeviceEnumByIndex(int index) { + DeviceEnum[] enums = DeviceEnum.values(); + for (DeviceEnum deviceEnum : enums) { + if (deviceEnum.getIndex() == index) { + return deviceEnum; + } + } + return null; // 如果没有找到对应的枚举常量,可以根据需要返回null或者抛出异常 + } +} diff --git a/lms/nladmin-system/src/main/java/org/nl/wms/cockpit/service/impl/BigScreenServiceImpl.java b/lms/nladmin-system/src/main/java/org/nl/wms/cockpit/service/impl/BigScreenServiceImpl.java new file mode 100644 index 0000000..073e7ac --- /dev/null +++ b/lms/nladmin-system/src/main/java/org/nl/wms/cockpit/service/impl/BigScreenServiceImpl.java @@ -0,0 +1,652 @@ +package org.nl.wms.cockpit.service.impl; + +import cn.hutool.core.util.ObjectUtil; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.nl.config.thread.ThreadPoolExecutorUtil; +import org.nl.modules.wql.WQL; +import org.nl.modules.wql.core.bean.WQLObject; +import org.nl.wms.cockpit.service.BigScreenService; +import org.nl.wms.cockpit.service.dto.*; +import org.nl.wms.cockpit.service.enums.ColorEnum; +import org.nl.wms.cockpit.service.enums.DeviceEnum; +import org.nl.wms.util.MapOf; +import org.springframework.stereotype.Service; + +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.util.*; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.CopyOnWriteArrayList; +import java.util.concurrent.ThreadPoolExecutor; + +/** + * @Author: lyd + * @Description: + * @Date: 2023/5/30 + */ +@Service +@RequiredArgsConstructor +@Slf4j +public class BigScreenServiceImpl implements BigScreenService { + /** + * 車间情况大屏信息 + * + * @author gbx + * @since 2023/3/1 + */ + @Override + public ConcurrentHashMap workshopCondition() { + ThreadPoolExecutor pool = ThreadPoolExecutorUtil.getPoll(); + ConcurrentHashMap map = new ConcurrentHashMap<>(); + // 1、当日混料生产 + CompletableFuture> mixDayProductionTask = CompletableFuture.supplyAsync(() -> { + List res = new CopyOnWriteArrayList<>(); + // 查找sql + JSONArray result = WQL.getWO("COCKPIT_PROCESS_PRODUCTION").addParamMap(MapOf.of("flag", "1", "region_code", "HL")) + .process() + .getResultJSONArray(0); + if (ObjectUtil.isNotEmpty(result)) { + res = result.toJavaList(NumberDto.class); + // 设备空数据值 + setResultCompleteInProcessProduction(res, "HL"); + } + return res; + }, pool); + mixDayProductionTask.thenAccept((result) -> { + map.put("HLDayList", result); + }).exceptionally((e) -> { + log.error("当日混料生产: {}", e.getMessage(), e); + List dtos = new ArrayList<>(); + setResultCompleteInProcessProduction(dtos, "HL"); + map.put("HLDayList", dtos); + return null; + }); + // 2、当日压制 + CompletableFuture> pressDayProductionTask = CompletableFuture.supplyAsync(() -> { + List res = new CopyOnWriteArrayList<>(); + // 查找所有混捻每周的数据 + JSONArray result = WQL.getWO("COCKPIT_PROCESS_PRODUCTION").addParamMap(MapOf.of("flag", "1", "region_code", "YZ")).process().getResultJSONArray(0); + if (ObjectUtil.isNotEmpty(result)) { + res = result.toJavaList(NumberDto.class); + setResultCompleteInProcessProduction(res, "YZ"); + } + return res; + }, pool); + pressDayProductionTask.thenAccept((result) -> { + map.put("YZDayList", result); + }).exceptionally((e) -> { + log.error("当日混料生产: {}", e.getMessage(), e); + List dtos = new ArrayList<>(); + setResultCompleteInProcessProduction(dtos, "YZ"); + map.put("YZDayList", dtos); + return null; + }); + // 3、当日成品 + CompletableFuture> manufacturedProductsDayProductionTask = CompletableFuture.supplyAsync(() -> { + List res = new ArrayList<>(); + Random random = new Random(); + // 使用随机数 + for (int i = 1; i <= 5; i++) { + ManufacturedProductsDto manufacturedProductsDto = new ManufacturedProductsDto(); + manufacturedProductsDto.setInventory_qty(random.nextInt(2000 - 100 + 1) + 100); + manufacturedProductsDto.setQualified_in_qty(random.nextInt(2000 - 100 + 1) + 100); + manufacturedProductsDto.setUnqualified_in_qty(random.nextInt(2000 - 100 + 1) + 100); + manufacturedProductsDto.setMaterial_code("成品" + i); + res.add(manufacturedProductsDto); + } + return res; + }, pool); + manufacturedProductsDayProductionTask.thenAccept((result) -> { + map.put("CPDayList", result); + }).exceptionally((e) -> { + log.error("当日成品生产: {}", e.getMessage(), e); + map.put("CPDayList", null); + return null; + }); + // 4、设备运行情况 + CompletableFuture> deviceConditionTask = CompletableFuture.supplyAsync(() -> { + List res = new ArrayList<>(); + for (int i = 0; i < 4; i++) { + DeviceEnum deviceEnumByIndex = DeviceEnum.getDeviceEnumByIndex(i); + OperationConditionDto dto = new OperationConditionDto(); + dto.setDevice_name(deviceEnumByIndex.getDevice_name()); + dto.setRunning(3); + dto.setFailure(5); + dto.setShutdown(2); + dto.setStandby(6); + res.add(dto); + } + return res; + }, pool); + deviceConditionTask.thenAccept((result) -> { + map.put("DeviceConditionList", result); + }).exceptionally((e) -> { + log.error("设备运行情况: {}", e.getMessage(), e); + map.put("DeviceConditionList", null); + return null; + }); + // 5、近一个月故障次数前5台设备 + CompletableFuture> lastMonthFailureTask = CompletableFuture.supplyAsync(() -> { + List res = new ArrayList<>(); + Random random = new Random(); + for (int i = 0; i < 5; i++) { + OperationConditionDto dto = new OperationConditionDto(); + dto.setDevice_name("机器" + (i + 1)); + dto.setFailure(random.nextInt(30 - 10 + 1) + 10); + res.add(dto); + } + return res; + }, pool); + lastMonthFailureTask.thenAccept(result -> { + map.put("LastMonthFailureList", result); + }).exceptionally((e) -> { + log.error("近一个月故障次数前5台设备: {}", e.getMessage(), e); + map.put("LastMonthFailureList", null); + return null; + }); + // 6、最近10次设备故障 + CompletableFuture> lastTenFailureTask = CompletableFuture.supplyAsync(() -> { + List res = new ArrayList<>(); + for (int i = 0; i < 5; i++) { + FailureDeviceInfoDto dto = new FailureDeviceInfoDto(); + dto.setDevice_code("hn01"); + dto.setDevice_name("混黏01"); + dto.setFailure_time("05-30 09:50:12"); + dto.setFailure_info("机器故障"); + dto.setDevice_status_name("待机"); + res.add(dto); + } + return res; + }, pool); + lastTenFailureTask.thenAccept(result -> { + map.put("LastTenFailureList", result); + }).exceptionally((e) -> { + log.error("最近10次设备故障: {}", e.getMessage(), e); + map.put("LastTenFailureList", null); + return null; + }); + // 7、码垛位情况显示 + CompletableFuture stackingPositionTask = CompletableFuture.supplyAsync(() -> { + JSONArray res = WQL.getWO("COCKPIT_PROCESS_PRODUCTION").addParamMap(MapOf.of("flag", "5", "region_code", "YZ")) + .process() + .getResultJSONArray(0); + return res; + }, pool); + stackingPositionTask.thenAccept(result -> { + for (int i = 0; i < result.size(); i++) { + JSONObject jsonObject = result.getJSONObject(i); + jsonObject.put("color_status", ColorEnum.RED.getIndex()); + } + map.put("StackingPositionList", result); + }).exceptionally((e) -> { + log.error("码垛位情况显示: {}", e.getMessage(), e); + map.put("StackingPositionList", null); + return null; + }); + // 8、压机信息显示 + CompletableFuture pressMachineTask = CompletableFuture.supplyAsync(() -> { + JSONArray res = WQL.getWO("COCKPIT_PROCESS_PRODUCTION").addParamMap(MapOf.of("flag", "6")) + .process() + .getResultJSONArray(0); + return res; + }, pool); + pressMachineTask.thenAccept(result -> { + map.put("PressMachineList", result); + }).exceptionally((e) -> { + log.error("压机信息显示: {}", e.getMessage(), e); + map.put("PressMachineList", null); + return null; + }); + // 9、混料机信息显示 + CompletableFuture mixMachineTask = CompletableFuture.supplyAsync(() -> { + JSONArray res = WQL.getWO("COCKPIT_PROCESS_PRODUCTION").addParamMap(MapOf.of("flag", "7")) + .process() + .getResultJSONArray(0); + return res; + }, pool); + mixMachineTask.thenAccept(result -> { + map.put("MixMachineList", result); + }).exceptionally((e) -> { + log.error("混料机信息显示: {}", e.getMessage(), e); + map.put("MixMachineList", null); + return null; + }); + // 10、困料货架的信息显示 + CompletableFuture trappedMaterialShelfTask = CompletableFuture.supplyAsync(() -> { + JSONArray res = WQL.getWO("COCKPIT_PROCESS_PRODUCTION").addParamMap(MapOf.of("flag", "8")) + .process() + .getResultJSONArray(0); + return res; + }, pool); + trappedMaterialShelfTask.thenAccept(result -> { + map.put("TrappedMaterialShelfList", result); + }).exceptionally((e) -> { + log.error("困料货架的信息显示: {}", e.getMessage(), e); + map.put("TrappedMaterialShelfList", null); + return null; + }); + // 11、半成品货架数据显示 + CompletableFuture semiFinishedProductShelfTask = CompletableFuture.supplyAsync(() -> { + JSONArray res = WQL.getWO("COCKPIT_PROCESS_PRODUCTION").addParamMap(MapOf.of("flag", "9")) + .process() + .getResultJSONArray(0); + return res; + }, pool); + semiFinishedProductShelfTask.thenAccept(result -> { + map.put("SemiFinishedProductShelfList", result); + }).exceptionally((e) -> { + log.error("半成品货架数据显示: {}", e.getMessage(), e); + map.put("SemiFinishedProductShelfList", null); + return null; + }); + CompletableFuture allQuery = CompletableFuture.allOf( + mixDayProductionTask, + pressDayProductionTask, + manufacturedProductsDayProductionTask, + deviceConditionTask, + lastMonthFailureTask, + stackingPositionTask, + pressMachineTask, + mixMachineTask, + trappedMaterialShelfTask, + semiFinishedProductShelfTask); + CompletableFuture> future = allQuery.thenApply((result) -> map).exceptionally((e) -> { + log.error(e.getMessage(), e); + return null; + }); + future.join(); + return map; + } + + /** + * 工序生产 + * @return + */ + @Override + public ConcurrentHashMap processProduction() { + // 工序生产:混料、压制(成型)、包装、成品 + ThreadPoolExecutor pool = ThreadPoolExecutorUtil.getPoll(); + ConcurrentHashMap map = new ConcurrentHashMap<>(); + // 1.1 获取混料当日计划与实际生产、生产率 单位(吨)需要除1000 + CompletableFuture> mixMaterialStorage = CompletableFuture.supplyAsync(() -> { + List res = new CopyOnWriteArrayList<>(); + // 查找所有混料设备的数据 + JSONArray result = WQL.getWO("COCKPIT_PROCESS_PRODUCTION").addParamMap(MapOf.of("flag", "1", "region_code", "HL")).process().getResultJSONArray(0); + if (ObjectUtil.isNotEmpty(result)) { + res = result.toJavaList(NumberDto.class); + // 设备空数据值 + setResultCompleteInProcessProduction(res, "HL"); + } + return res; + }, pool); + mixMaterialStorage.thenAccept((result) -> { + // 整理数据 + JSONObject res = new JSONObject(); + int sumRealDay = 0; + int sumPlanDay = 0; + for (NumberDto numberDto : result) { + sumRealDay += numberDto.getReal_qty(); + sumPlanDay += numberDto.getPlan_qty(); + } + res.put("hl_plan_day", BigDecimal.valueOf((double) sumPlanDay / 1000).setScale(2, RoundingMode.HALF_UP).toString()); + res.put("hl_real_day", BigDecimal.valueOf((double) sumRealDay / 1000).setScale(2, RoundingMode.HALF_UP).toString()); + res.put("hl_productivity", sumRealDay / sumPlanDay); + res.put("HLDayList", result); + if (map.containsKey("HL")) { // 如果存在 + JSONObject hl = (JSONObject) map.get("HL"); + res.put("HLWeekList", hl.getJSONArray("HLWeekList")); + map.put("HL", res); + } else { + map.put("HL", res); + } + }).exceptionally((e) -> { + log.error("获取混料设备生产信息: {}", e.getMessage(), e); + List dtos = new ArrayList<>(); + setResultCompleteInProcessProduction(dtos, "HL"); + JSONObject res = new JSONObject(); + res.put("hl_plan_day", "0.00"); + res.put("hl_real_day", "0.00"); + res.put("hl_productivity", 0); + res.put("HLDayList", dtos); + if (map.containsKey("HL")) { // 如果存在 + JSONObject hl = (JSONObject) map.get("HL"); + res.put("HLWeekList", hl.getJSONArray("HLWeekList")); + map.put("HL", res); + } else { + map.put("HL", res); + } + return null; + }); + // 1.2 获取每台混捻设备的每周数据 + CompletableFuture> mixDeviceWeekDayStorage = CompletableFuture.supplyAsync(() -> { + List res = new CopyOnWriteArrayList<>(); + // 查找所有混捻每周的数据 + JSONArray result = WQL.getWO("COCKPIT_PROCESS_PRODUCTION").addParamMap(MapOf.of("flag", "2", "region_code", "HL")).process().getResultJSONArray(0); + if (ObjectUtil.isNotEmpty(result)) { + res = result.toJavaList(NumberDto.class); + setResultCompleteInProcessProduction(res, "HL"); + } + return res; + }, pool); + mixDeviceWeekDayStorage.thenAccept((result) -> { + //每周的数据 + JSONObject res = new JSONObject(); + res.put("HLWeekList", result); + if (map.containsKey("HL")) { // 如果存在 + JSONObject hl = (JSONObject) map.get("HL"); + res.put("hl_plan_day", hl.getString("hl_plan_day")); + res.put("hl_real_day", hl.getString("hl_real_day")); + res.put("hl_productivity", hl.getString("hl_productivity")); + res.put("HLDayList", hl.getJSONArray("HLDayList")); + map.put("HL", res); + } else { + map.put("HL", res); + } + }).exceptionally((e) -> { + log.error("获取混捻(每周)信息: {}", e.getMessage(), e); + List dtos = new ArrayList<>(); + setResultCompleteInProcessProduction(dtos, "HL"); + JSONObject res = new JSONObject(); + res.put("HLWeekList", dtos); + if (map.containsKey("HL")) { // 如果存在 + JSONObject hl = (JSONObject) map.get("HL"); + res.put("hl_plan_day", hl.getString("hl_plan_day")); + res.put("hl_real_day", hl.getString("hl_real_day")); + res.put("hl_productivity", hl.getString("hl_productivity")); + res.put("HLDayList", hl.getJSONArray("HLDayList")); + map.put("HL", res); + } else { + map.put("HL", res); + } + return null; + }); + // 2.1 获取成型的计划与实际生产数量:单位万块, 每天的合格与不合格数量 + CompletableFuture> yzPlanAndRealStorage = CompletableFuture.supplyAsync(() -> { + List res = new CopyOnWriteArrayList<>(); + // 查找所有混捻每周的数据 + JSONArray result = WQL.getWO("COCKPIT_PROCESS_PRODUCTION").addParamMap(MapOf.of("flag", "1", "region_code", "YZ")).process().getResultJSONArray(0); + if (ObjectUtil.isNotEmpty(result)) { + res = result.toJavaList(NumberDto.class); + setResultCompleteInProcessProduction(res, "YZ"); + } + return res; + }, pool); + yzPlanAndRealStorage.thenAccept((result) -> { + // 整理数据 + JSONObject res = new JSONObject(); + int sumRealDay = 0; + int sumPlanDay = 0; + for (NumberDto numberDto : result) { + sumRealDay += numberDto.getReal_qty(); + sumPlanDay += numberDto.getPlan_qty(); + } + res.put("yz_plan_day", BigDecimal.valueOf((double) sumPlanDay / 10000).setScale(2, RoundingMode.HALF_UP).toString()); + res.put("yz_real_day", BigDecimal.valueOf((double) sumRealDay / 10000).setScale(2, RoundingMode.HALF_UP).toString()); + res.put("yz_productivity", sumRealDay / sumPlanDay); + res.put("YZDayList", result); + if (map.containsKey("YZ")) { // 如果存在 + JSONObject yz = (JSONObject) map.get("YZ"); + res.put("YZWeekList", yz.getJSONArray("YZWeekList")); + map.put("YZ", res); + } else { + map.put("YZ", res); + } + }).exceptionally((e) -> { + log.error("获取压制设备生产信息: {}", e.getMessage(), e); + List dtos = new ArrayList<>(); + setResultCompleteInProcessProduction(dtos, "YZ"); + JSONObject res = new JSONObject(); + res.put("yz_plan_day", "0.00"); + res.put("yz_real_day", "0.00"); + res.put("yz_productivity", 0); + res.put("YZDayList", dtos); + if (map.containsKey("YZ")) { // 如果存在 + JSONObject yz = (JSONObject) map.get("YZ"); + res.put("YZWeekList", yz.getJSONArray("YZWeekList")); + map.put("YZ", res); + } else { + map.put("YZ", res); + } + return null; + }); + // 2.2 压制每周的合格与不合格数量 + CompletableFuture> yzDeviceWeekDayStorage = CompletableFuture.supplyAsync(() -> { + List res = new CopyOnWriteArrayList<>(); + // 查找所有压制每周的数据 + JSONArray result = WQL.getWO("COCKPIT_PROCESS_PRODUCTION").addParamMap(MapOf.of("flag", "2", "region_code", "YZ")).process().getResultJSONArray(0); + if (ObjectUtil.isNotEmpty(result)) { + res = result.toJavaList(NumberDto.class); + setResultCompleteInProcessProduction(res, "YZ"); + } + return res; + }, pool); + yzDeviceWeekDayStorage.thenAccept((result) -> { + //每周的数据 + JSONObject res = new JSONObject(); + res.put("YZWeekList", result); + if (map.containsKey("YZ")) { // 如果存在 + JSONObject yz = (JSONObject) map.get("YZ"); + res.put("yz_plan_day", yz.getString("yz_plan_day")); + res.put("yz_real_day", yz.getString("yz_real_day")); + res.put("yz_productivity", yz.getString("yz_productivity")); + res.put("YZDayList", yz.getJSONArray("YZDayList")); + map.put("YZ", res); + } else { + map.put("YZ", res); + } + }).exceptionally((e) -> { + log.error("获取压制(每周)信息: {}", e.getMessage(), e); + List dtos = new ArrayList<>(); + setResultCompleteInProcessProduction(dtos, "YZ"); + JSONObject res = new JSONObject(); + res.put("YZWeekList", dtos); + if (map.containsKey("YZ")) { // 如果存在 + JSONObject yz = (JSONObject) map.get("YZ"); + res.put("yz_plan_day", yz.getString("yz_plan_day")); + res.put("yz_real_day", yz.getString("yz_real_day")); + res.put("yz_productivity", yz.getString("yz_productivity")); + res.put("YZDayList", yz.getJSONArray("YZDayList")); + map.put("YZ", res); + } else { + map.put("YZ", res); + } + return null; + }); + // 3.1 获取包装的计划与实际生产数量:单位万块, 每天的合格与不合格数量 + CompletableFuture> bzPlanAndRealStorage = CompletableFuture.supplyAsync(() -> { + List res = new CopyOnWriteArrayList<>(); + // 查找所有包装每天的数据 + JSONArray result = WQL.getWO("COCKPIT_PROCESS_PRODUCTION").addParamMap(MapOf.of("flag", "3")).process().getResultJSONArray(0); + if (ObjectUtil.isNotEmpty(result)) { + res = result.toJavaList(NumberDto.class); + } + return res; + }, pool); + bzPlanAndRealStorage.thenAccept((result) -> { + // 整理数据 + JSONObject res = new JSONObject(); + int sumRealDay = 0; + int sumPlanDay = 0; + for (NumberDto numberDto : result) { + sumRealDay += numberDto.getReal_qty(); + sumPlanDay += numberDto.getPlan_qty(); + } + res.put("bz_plan_day", BigDecimal.valueOf((double) sumPlanDay / 10000).setScale(2, RoundingMode.HALF_UP).toString()); + res.put("bz_real_day", BigDecimal.valueOf((double) sumRealDay / 10000).setScale(2, RoundingMode.HALF_UP).toString()); + res.put("bz_productivity", sumRealDay / sumPlanDay); + res.put("BZDayList", result); + if (map.containsKey("BZ")) { // 如果存在 + JSONObject bz = (JSONObject) map.get("BZ"); + res.put("BZWeekList", bz.getJSONArray("BZWeekList")); + map.put("BZ", res); + } else { + map.put("BZ", res); + } + }).exceptionally((e) -> { + log.error("获取包装设备生产信息: {}", e.getMessage(), e); + List dtos = new ArrayList<>(); + JSONObject res = new JSONObject(); + res.put("bz_plan_day", "0.00"); + res.put("bz_real_day", "0.00"); + res.put("bz_productivity", 0); + res.put("BZDayList", dtos); + if (map.containsKey("BZ")) { // 如果存在 + JSONObject bz = (JSONObject) map.get("BZ"); + res.put("BZWeekList", bz.getJSONArray("BZWeekList")); + map.put("BZ", res); + } else { + map.put("BZ", res); + } + return null; + }); + // 3.2 包装每周的合格与不合格数量 + CompletableFuture> bzDeviceWeekDayStorage = CompletableFuture.supplyAsync(() -> { + List res = new CopyOnWriteArrayList<>(); + // 查找所有包装每周的数据 + JSONArray result = WQL.getWO("COCKPIT_PROCESS_PRODUCTION").addParamMap(MapOf.of("flag", "4")).process().getResultJSONArray(0); + if (ObjectUtil.isNotEmpty(result)) { + res = result.toJavaList(NumberDto.class); + } + return res; + }, pool); + bzDeviceWeekDayStorage.thenAccept((result) -> { + //每周的数据 + JSONObject res = new JSONObject(); + res.put("BZWeekList", result); + if (map.containsKey("BZ")) { // 如果存在 + JSONObject bz = (JSONObject) map.get("BZ"); + res.put("bz_plan_day", bz.getString("bz_plan_day")); + res.put("bz_real_day", bz.getString("bz_real_day")); + res.put("bz_productivity", bz.getString("bz_productivity")); + res.put("BZDayList", bz.getJSONArray("BZDayList")); + map.put("BZ", res); + } else { + map.put("BZ", res); + } + }).exceptionally((e) -> { + log.error("获取包装(每周)信息: {}", e.getMessage(), e); + List dtos = new ArrayList<>(); + JSONObject res = new JSONObject(); + res.put("BZWeekList", dtos); + if (map.containsKey("BZ")) { // 如果存在 + JSONObject bz = (JSONObject) map.get("BZ"); + res.put("bz_plan_day", bz.getString("bz_plan_day")); + res.put("bz_real_day", bz.getString("bz_real_day")); + res.put("bz_productivity", bz.getString("bz_productivity")); + res.put("BZDayList", bz.getJSONArray("BZDayList")); + map.put("BZ", res); + } else { + map.put("BZ", res); + } + return null; + }); + // 4 成品出入库 + CompletableFuture> cpDeviceDataStorage = CompletableFuture.supplyAsync(() -> { + List res = new CopyOnWriteArrayList<>(); + // 查找所有包装每周的数据 + return res; + }, pool); + cpDeviceDataStorage.thenAccept((result) -> { + //数据 + JSONObject result1 = new JSONObject(); + JSONArray jsonArray = new JSONArray(); + for (int i = 1; i <= 5; i++) { + InventoryDto dto = new InventoryDto(); + dto.setInventory_qty(1000000); + dto.setRegion_out_qty(5000); + dto.setRegion_in_qty(9995000); + dto.setMaterial_code("成品" + i); + jsonArray.add(dto); + } + result1.put("in_qty", "100.00"); + result1.put("out_qty", "10.00"); + result1.put("inventory_qty", "90.00"); + result1.put("in_productivity", 30); + result1.put("out_productivity", 60); + result1.put("inv_productivity", 80); + result1.put("KCDayList", jsonArray); + result1.put("KCWeekList", jsonArray); + map.put("KC", result1); + }).exceptionally((e) -> { + JSONObject result = new JSONObject(); + JSONArray jsonArray = new JSONArray(); + for (int i = 1; i <= 5; i++) { + InventoryDto dto = new InventoryDto(); + dto.setInventory_qty(1000000); + dto.setRegion_out_qty(5000); + dto.setRegion_in_qty(9995000); + dto.setMaterial_code("成品" + i); + jsonArray.add(dto); + } + result.put("in_qty", "100.00"); + result.put("out_qty", "10.00"); + result.put("inventory_qty", "90.00"); + result.put("in_productivity", 30); + result.put("out_productivity", 60); + result.put("inv_productivity", 80); + result.put("KCDayList", jsonArray); + result.put("KCWeekList", jsonArray); + map.put("KC", result); + return null; + }); + CompletableFuture allQuery = CompletableFuture.allOf( + mixMaterialStorage, + mixDeviceWeekDayStorage, + yzPlanAndRealStorage, + yzDeviceWeekDayStorage, + bzPlanAndRealStorage, + bzDeviceWeekDayStorage, + cpDeviceDataStorage); + CompletableFuture> future = allQuery.thenApply((result) -> map).exceptionally((e) -> { + log.error(e.getMessage(), e); + return null; + }); + future.join(); + return map; + } + + /** + * 处理空白数据 - 工序 + * + * @param result + */ + private void setResultCompleteInProcessProduction(List result, String region_code) { + HashSet existingLabels = new HashSet<>(); // 创建一个 HashSet 对象 + // 遍历 result 列表中的每个 ProductionStatisticsDto 对象 + for (NumberDto dto : result) { + // 检查 device_code 字段是否存在于 existingLabels 集合中 + if (!existingLabels.contains(dto.getDevice_code())) { + // 将缺少的标签值添加到 existingLabels 集合中 + existingLabels.add(dto.getDevice_code()); + } + } + // 获取所有设备编码 + WQLObject deviceTab = WQLObject.getWQLObject("pdm_bi_device"); + JSONArray resultJSONArray = deviceTab.query("region_code = '" + region_code + "' AND is_workorder = '1'").getResultJSONArray(0); + for (int i = 0; i < resultJSONArray.size(); i++) { + JSONObject jsonObject = resultJSONArray.getJSONObject(i); + if (!existingLabels.contains(jsonObject.getString("device_code"))) { + NumberDto dto = new NumberDto(); + dto.setDevice_code(jsonObject.getString("device_code")); + dto.setRegion_code(jsonObject.getString("region_code")); + dto.setDevice_name(jsonObject.getString("device_name")); + dto.setPlan_qty(0); + dto.setReal_qty(0); + dto.setQualified_qty(0); + dto.setUnqualified_qty(0); + result.add(dto); + } else { + result.forEach(numberDto -> { + if (numberDto.getDevice_code().equals(jsonObject.getString("device_code"))) { + numberDto.setDevice_name(jsonObject.getString("device_name")); + } + }); + } + } + Collections.sort(result, Comparator.comparing(NumberDto::getDevice_code)); + } +} diff --git a/lms/nladmin-system/src/main/java/org/nl/wms/cockpit/service/impl/CockpitServiceImpl.java b/lms/nladmin-system/src/main/java/org/nl/wms/cockpit/service/impl/CockpitServiceImpl.java index 69e72a8..0209af4 100644 --- a/lms/nladmin-system/src/main/java/org/nl/wms/cockpit/service/impl/CockpitServiceImpl.java +++ b/lms/nladmin-system/src/main/java/org/nl/wms/cockpit/service/impl/CockpitServiceImpl.java @@ -24,10 +24,11 @@ import org.springframework.stereotype.Service; import java.math.BigDecimal; import java.math.RoundingMode; -import java.text.DecimalFormat; import java.util.*; -import java.util.concurrent.*; -import java.util.function.Consumer; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.CopyOnWriteArrayList; +import java.util.concurrent.ThreadPoolExecutor; /** * 大屏服务实现1 @@ -369,6 +370,10 @@ public class CockpitServiceImpl implements CockpitService { return hashMap; } + /** + * 工序生产 + * @return + */ @Override public ConcurrentHashMap processProduction() { // 工序生产:混料、压制(成型)、包装、成品 diff --git a/lms/nladmin-system/src/main/java/org/nl/wms/cockpit/wql/COCKPIT_PROCESS_PRODUCTION.wql b/lms/nladmin-system/src/main/java/org/nl/wms/cockpit/wql/COCKPIT_PROCESS_PRODUCTION.wql index 1c053e4..b60e1c6 100644 --- a/lms/nladmin-system/src/main/java/org/nl/wms/cockpit/wql/COCKPIT_PROCESS_PRODUCTION.wql +++ b/lms/nladmin-system/src/main/java/org/nl/wms/cockpit/wql/COCKPIT_PROCESS_PRODUCTION.wql @@ -120,3 +120,109 @@ ENDSELECT ENDPAGEQUERY ENDIF + + IF 输入.flag = "5" + PAGEQUERY + SELECT + point_code, + point_name, + region_code + FROM + `sch_base_point` + WHERE + point_type = '1' + OPTION 输入.region_code <> "" + region_code = 输入.region_code + ENDOPTION + ENDSELECT + ENDPAGEQUERY + ENDIF + + IF 输入.flag = "6" + PAGEQUERY + SELECT + "2022-04-21 16:18:03" AS open_time, + d.device_code, + d.device_name, + d.region_code, + w.material_id, + m.material_code, + w.real_qty AS now_capacity + FROM + `pdm_bi_device` d + LEFT JOIN pdm_bd_workorder w ON (w.order_status = '3' AND w.device_code = d.device_code) + LEFT JOIN md_me_materialbase m ON m.material_id = w.material_id + WHERE d.region_code = 'YZ' AND d.device_model IN ('1','2','3','4') + ORDER BY d.device_code + ENDSELECT + ENDPAGEQUERY + ENDIF + + IF 输入.flag = "7" + PAGEQUERY + SELECT + "2022-04-21 16:18:03" AS open_time, + p.point_code, + p.point_name, + p.region_code, + p.point_status, + p.device_code, + SUBSTRING(m.material_code, 6, 6) AS bom + FROM + `sch_base_point` p + LEFT JOIN pdm_bd_workorder w ON (w.order_status = '3' AND w.device_code = p.device_code) + LEFT JOIN md_me_materialbase m ON m.material_id = w.material_id + WHERE p.region_code = 'HL' + ORDER BY p.point_code + ENDSELECT + ENDPAGEQUERY + ENDIF + + IF 输入.flag = "8" + PAGEQUERY + SELECT + p.point_code, + p.point_name, + p.region_code, + p.point_status, + IF(LENGTH( vd.stand_status )> 0,vd.stand_status,'') AS stand_status, + CASE vd.stand_status + WHEN '2' THEN '困料中' + WHEN '3' THEN '困料完成' + WHEN '4' THEN '困料完成' + WHEN '5' THEN '困料超时' + ELSE '' + END AS stand_status_name, + CASE vd.stand_status + WHEN '2' THEN '1' + WHEN '3' THEN '3' + WHEN '4' THEN '3' + WHEN '5' THEN '2' + ELSE '' + END AS stand_status_color + FROM + `sch_base_point` p + LEFT JOIN st_ivt_vehicle_detail vd ON vd.vehicle_code = p.vehicle_code + AND vd.vehicle_type = p.vehicle_type + AND vd.is_delete = '0' + WHERE p.region_code = 'KLHJ' AND p.point_type IN ('1', '2') + ORDER BY p.point_type, p.point_code + ENDSELECT + ENDPAGEQUERY + ENDIF + + IF 输入.flag = "9" + PAGEQUERY + SELECT + p.point_code, + p.point_name, + p.region_code, + p.point_status + FROM + `sch_base_point` p + WHERE + p.region_code = 'BCPHJ' + ORDER BY p.point_code + ENDSELECT + ENDPAGEQUERY + ENDIF