feat:添加产能报表相关接口

main
HuangHuiKang 1 week ago
parent dbc47aa249
commit a7863b39b5

@ -212,6 +212,23 @@ public class DeviceLedgerController {
ExcelUtils.write(response, "设备台账.xls", "数据", DeviceLedgerRespVO.class,deviceLedgerRespVOS);
}
@GetMapping("/capacity-report/page")
@Operation(summary = "获得设备产能报表分页")
@PreAuthorize("@ss.hasPermission('mes:device-ledger:query')")
public CommonResult<PageResult<DeviceCapacityReportRespVO>> getDeviceCapacityReportPage(@Valid DeviceCapacityReportPageReqVO pageReqVO) {
return success(deviceLedgerService.getDeviceCapacityReportPage(pageReqVO));
}
@GetMapping("/capacity-report/export-excel")
@Operation(summary = "导出设备产能报表 Excel")
@PreAuthorize("@ss.hasPermission('mes:device-ledger:export')")
@ApiAccessLog(operateType = EXPORT)
public void exportDeviceCapacityReportExcel(@Valid DeviceCapacityReportPageReqVO pageReqVO,
HttpServletResponse response) throws IOException {
List<DeviceCapacityReportRespVO> list = deviceLedgerService.getDeviceCapacityReportList(pageReqVO);
ExcelUtils.write(response, "设备产能报表.xls", "数据", DeviceCapacityReportRespVO.class, list);
}

@ -0,0 +1,32 @@
package cn.iocoder.yudao.module.mes.controller.admin.deviceledger.vo;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
@Schema(description = "管理后台 - 设备产能报表分页 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class DeviceCapacityReportPageReqVO extends PageParam {
@Schema(description = "设备编码")
private String deviceCode;
@Schema(description = "设备名称")
private String deviceName;
@Schema(description = "设备类型")
private Long deviceType;
@Schema(description = "设备状态")
private Integer deviceStatus;
@Schema(description = "所属车间")
private String workshop;
@Schema(description = "导出 ids逗号分隔")
private String ids;
}

@ -0,0 +1,52 @@
package cn.iocoder.yudao.module.mes.controller.admin.deviceledger.vo;
import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.math.BigDecimal;
@Schema(description = "管理后台 - 设备产能报表 Response VO")
@Data
@ExcelIgnoreUnannotated
public class DeviceCapacityReportRespVO {
@Schema(description = "设备 id")
private Long id;
@Schema(description = "设备编码")
@ExcelProperty("编码")
private String deviceCode;
@Schema(description = "设备名称")
@ExcelProperty("名称")
private String deviceName;
@Schema(description = "设备类型名称")
@ExcelProperty("类型")
private String typeName;
@Schema(description = "设备状态")
// @ExcelProperty(value = "状态", converter = DictConvert.class)
// @DictFormat("mes_tz_status")
private Integer deviceStatus;
@Schema(description = "额定产能(计划产能)")
@ExcelProperty("额定产能(计划产能)")
private BigDecimal ratedCapacity;
@Schema(description = "报工产能")
@ExcelProperty("报工产能")
private BigDecimal reportCapacity;
@Schema(description = "实际产能")
@ExcelProperty("实际产能")
private BigDecimal actualCapacity;
@Schema(description = "所属车间")
@ExcelProperty("所属车间")
private String workshopName;
}

@ -57,6 +57,10 @@ public interface DeviceLedgerService {
*/
PageResult<DeviceLedgerDO> getDeviceLedgerPage(DeviceLedgerPageReqVO pageReqVO);
PageResult<DeviceCapacityReportRespVO> getDeviceCapacityReportPage(DeviceCapacityReportPageReqVO pageReqVO);
List<DeviceCapacityReportRespVO> getDeviceCapacityReportList(DeviceCapacityReportPageReqVO pageReqVO);
List<DeviceLedgerDO> getDeviceLedgerList();
/**
* VO

@ -1,6 +1,5 @@
package cn.iocoder.yudao.module.mes.service.deviceledger;
import cn.hutool.core.collection.CollStreamUtil;
import cn.hutool.core.collection.CollUtil;
import cn.iocoder.yudao.framework.common.util.collection.MapUtils;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
@ -8,36 +7,33 @@ import cn.iocoder.yudao.module.common.enums.CodeTypeEnum;
import cn.iocoder.yudao.module.common.enums.QrcodeBizTypeEnum;
import cn.iocoder.yudao.module.common.service.qrcordrecord.QrcodeRecordService;
import cn.iocoder.yudao.module.erp.controller.admin.autocode.util.AutoCodeUtil;
import cn.iocoder.yudao.module.erp.controller.admin.mold.vo.MoldRespVO;
import cn.iocoder.yudao.module.erp.controller.admin.product.vo.product.ErpProductRespVO;
import cn.iocoder.yudao.module.common.dal.dataobject.mold.MoldBrandDO;
import cn.iocoder.yudao.module.common.dal.dataobject.mold.MoldDO;
import cn.iocoder.yudao.module.common.dal.mysql.mold.MoldMapper;
import cn.iocoder.yudao.module.erp.dal.dataobject.productdevicerel.ProductDeviceRelDO;
import cn.iocoder.yudao.module.erp.dal.mysql.productdevicerel.ProductDeviceRelMapper;
import cn.iocoder.yudao.module.iot.controller.admin.device.vo.DeviceRespVO;
import cn.iocoder.yudao.module.iot.controller.admin.device.vo.DeviceSaveReqVO;
import cn.iocoder.yudao.module.iot.dal.dataobject.device.DeviceDO;
import cn.iocoder.yudao.module.iot.service.device.DeviceService;
import cn.iocoder.yudao.module.iot.service.device.TDengineService;
import cn.iocoder.yudao.module.mes.dal.dataobject.devicetype.DeviceTypeDO;
import cn.iocoder.yudao.module.mes.dal.dataobject.organization.OrganizationDO;
import cn.iocoder.yudao.module.mes.dal.dataobject.plan.PlanDO;
import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductDO;
import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductUnitDO;
import cn.iocoder.yudao.module.common.dal.mysql.mold.MoldMapper;
import cn.iocoder.yudao.module.mes.dal.mysql.devicetype.DeviceTypeMapper;
import cn.iocoder.yudao.module.common.dal.mysql.mold.MoldMapper;
import cn.iocoder.yudao.module.erp.dal.mysql.product.ErpProductMapper;
import cn.iocoder.yudao.module.erp.service.product.ErpProductUnitService;
import cn.iocoder.yudao.module.mes.controller.admin.ticketmanagement.enums.PlanTypeEnum;
import cn.iocoder.yudao.module.mes.dal.dataobject.criticalcomponent.CriticalComponentDO;
import cn.iocoder.yudao.module.mes.dal.dataobject.dvrepair.DvRepairDO;
import cn.iocoder.yudao.module.mes.dal.dataobject.dvrepair.DvRepairLineDO;
import cn.iocoder.yudao.module.mes.dal.dataobject.ticketresults.TicketResultsDO;
import cn.iocoder.yudao.module.mes.dal.mysql.criticalcomponent.CriticalComponentMapper;
import cn.iocoder.yudao.module.mes.dal.mysql.organization.OrganizationMapper;
import cn.iocoder.yudao.module.mes.dal.mysql.plan.PlanMapper;
import cn.iocoder.yudao.module.mes.dal.mysql.producereport.ProduceReportDetailMapper;
import cn.iocoder.yudao.module.mes.dal.mysql.dvrepair.DvRepairLineMapper;
import cn.iocoder.yudao.module.mes.dal.mysql.dvrepair.DvRepairMapper;
import cn.iocoder.yudao.module.mes.dal.mysql.ticketresults.TicketResultsMapper;
import cn.iocoder.yudao.module.mes.dal.mysql.workreportplan.ReportPlanSummaryMapper;
import cn.iocoder.yudao.module.mes.service.organization.OrganizationService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.extern.slf4j.Slf4j;
@ -48,9 +44,15 @@ import javax.annotation.Resource;
import org.springframework.validation.annotation.Validated;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
import cn.iocoder.yudao.module.iot.dal.mysql.device.DeviceMapper;
import cn.iocoder.yudao.module.mes.controller.admin.deviceledger.vo.*;
import cn.iocoder.yudao.module.mes.dal.dataobject.deviceledger.DeviceLedgerDO;
@ -61,7 +63,6 @@ import cn.iocoder.yudao.module.mes.dal.mysql.deviceledger.DeviceLedgerMapper;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.*;
import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*;
/**
@ -99,6 +100,27 @@ public class DeviceLedgerServiceImpl implements DeviceLedgerService {
@Resource
private ProductDeviceRelMapper productDeviceRelMapper;
@Resource
@Lazy
private DeviceMapper deviceMapper;
@Resource
private PlanMapper planMapper;
@Resource
private ProduceReportDetailMapper produceReportDetailMapper;
@Resource
private ReportPlanSummaryMapper reportPlanSummaryMapper;
@Resource
@Lazy
private OrganizationService organizationService;
@Resource
@Lazy
private OrganizationMapper organizationMapper;
@Resource
private ErpProductUnitService productUnitService;
@ -114,6 +136,9 @@ public class DeviceLedgerServiceImpl implements DeviceLedgerService {
@Autowired
private AutoCodeUtil autoCodeUtil;
@Resource
private TDengineService tdengineService;
@Override
public Long createDeviceLedger(DeviceLedgerSaveReqVO createReqVO) throws UnsupportedEncodingException {
DeviceLedgerDO deviceLedger = BeanUtils.toBean(createReqVO, DeviceLedgerDO.class);
@ -347,6 +372,165 @@ public class DeviceLedgerServiceImpl implements DeviceLedgerService {
return deviceLedgerDOPageResult;
}
@Override
public PageResult<DeviceCapacityReportRespVO> getDeviceCapacityReportPage(DeviceCapacityReportPageReqVO pageReqVO) {
DeviceLedgerPageReqVO queryReqVO = buildDeviceCapacityQuery(pageReqVO);
PageResult<DeviceLedgerDO> pageResult = deviceLedgerMapper.selectPage(queryReqVO);
List<DeviceCapacityReportRespVO> reportList = buildDeviceCapacityReportList(pageResult.getList());
return new PageResult<>(reportList, pageResult.getTotal());
}
@Override
public List<DeviceCapacityReportRespVO> getDeviceCapacityReportList(DeviceCapacityReportPageReqVO pageReqVO) {
DeviceLedgerPageReqVO queryReqVO = buildDeviceCapacityQuery(pageReqVO);
List<DeviceLedgerDO> list = deviceLedgerMapper.selectPage(queryReqVO).getList();
return buildDeviceCapacityReportList(list);
}
private DeviceLedgerPageReqVO buildDeviceCapacityQuery(DeviceCapacityReportPageReqVO pageReqVO) {
DeviceLedgerPageReqVO queryReqVO = new DeviceLedgerPageReqVO();
queryReqVO.setPageNo(pageReqVO.getPageNo());
queryReqVO.setPageSize(pageReqVO.getPageSize());
queryReqVO.setDeviceCode(pageReqVO.getDeviceCode());
queryReqVO.setDeviceName(pageReqVO.getDeviceName());
queryReqVO.setDeviceType(pageReqVO.getDeviceType());
queryReqVO.setDeviceStatus(pageReqVO.getDeviceStatus() == null ? null : String.valueOf(pageReqVO.getDeviceStatus()));
queryReqVO.setWorkshop(pageReqVO.getWorkshop());
queryReqVO.setIds(pageReqVO.getIds());
queryReqVO.setIsScheduled(1);
return queryReqVO;
}
private List<DeviceCapacityReportRespVO> buildDeviceCapacityReportList(List<DeviceLedgerDO> deviceList) {
if (CollUtil.isEmpty(deviceList)) {
return Collections.emptyList();
}
Set<Long> deviceIds = deviceList.stream().map(DeviceLedgerDO::getId).filter(Objects::nonNull).collect(Collectors.toSet());
Set<Long> deviceTypeIds = deviceList.stream().map(DeviceLedgerDO::getDeviceType).filter(Objects::nonNull).collect(Collectors.toSet());
Set<Long> workshopIds = deviceList.stream()
.map(DeviceLedgerDO::getWorkshop)
.filter(StringUtils::isNotBlank)
.map(String::trim)
.filter(item -> item.matches("\\d+"))
.map(Long::valueOf)
.collect(Collectors.toSet());
Map<Long, DeviceTypeDO> deviceTypeMap = deviceTypeIds.isEmpty() ? Collections.emptyMap()
: deviceTypeMapper.selectBatchIds(deviceTypeIds).stream()
.collect(Collectors.toMap(DeviceTypeDO::getId, Function.identity(), (a, b) -> a));
Map<Long, OrganizationDO> organizationMap = workshopIds.isEmpty() ? Collections.emptyMap()
: organizationService.getMapWithDeleted(workshopIds);
List<PlanDO> planList = planMapper.selectList(new LambdaQueryWrapperX<PlanDO>()
.in(PlanDO::getDeviceId, deviceIds));
Map<Long, BigDecimal> reportCapacityMap = planList.stream()
.filter(item -> item.getDeviceId() != null)
.collect(Collectors.groupingBy(
PlanDO::getDeviceId,
Collectors.mapping(
item -> BigDecimal.valueOf(Optional.ofNullable(item.getWangongNumber()).orElse(0L)),
Collectors.reducing(BigDecimal.ZERO, BigDecimal::add)
)
));
Map<Long, Long> machineDvMap = organizationMapper.selectList(
new LambdaQueryWrapper<OrganizationDO>()
.in(OrganizationDO::getMachineId, deviceIds)
.select(OrganizationDO::getMachineId, OrganizationDO::getDvId))
.stream()
.filter(item -> item.getMachineId() != null && item.getDvId() != null)
.collect(Collectors.toMap(
OrganizationDO::getMachineId,
OrganizationDO::getDvId,
(a, b) -> a
));
LocalDate endDate = LocalDate.now().minusDays(1);
LocalDate startDate = endDate.minusMonths(6);
List<LocalDate> statDays = listStatDays(startDate, endDate);
Map<Long, Integer> actualCapacityMap = new HashMap<>();
if (CollUtil.isNotEmpty(statDays)) {
LocalDateTime beginTime = statDays.get(0).atStartOfDay();
LocalDateTime endTime = statDays.get(statDays.size() - 1).plusDays(1).atStartOfDay();
Set<Long> collectDeviceIds = deviceMapper.selectList(new LambdaQueryWrapper<DeviceDO>()
.select(DeviceDO::getId))
.stream()
.map(DeviceDO::getId)
.filter(Objects::nonNull)
.collect(Collectors.toSet());
actualCapacityMap = queryDeviceCollectionAverageMap(collectDeviceIds, statDays, beginTime, endTime);
}
List<DeviceCapacityReportRespVO> result = new ArrayList<>();
for (DeviceLedgerDO device : deviceList) {
DeviceCapacityReportRespVO respVO = new DeviceCapacityReportRespVO();
respVO.setId(device.getId());
respVO.setDeviceCode(device.getDeviceCode());
respVO.setDeviceName(device.getDeviceName());
respVO.setDeviceStatus(device.getDeviceStatus());
respVO.setRatedCapacity(BigDecimal.valueOf(Optional.ofNullable(device.getRatedCapacity()).orElse(0)));
MapUtils.findAndThen(deviceTypeMap, device.getDeviceType(), item -> respVO.setTypeName(item.getName()));
if (StringUtils.isNotBlank(device.getWorkshop()) && device.getWorkshop().trim().matches("\\d+")) {
MapUtils.findAndThen(organizationMap, Long.valueOf(device.getWorkshop().trim()), item -> {
String workshopName = item.getName();
if (Boolean.TRUE.equals(item.getDeleted())) {
workshopName += "(已被删除)";
}
respVO.setWorkshopName(workshopName);
});
}
respVO.setReportCapacity(reportCapacityMap.getOrDefault(device.getId(), BigDecimal.ZERO));
Long collectDeviceId = machineDvMap.get(device.getId());
respVO.setActualCapacity(BigDecimal.valueOf(actualCapacityMap.getOrDefault(collectDeviceId, 0)));
result.add(respVO);
}
return result;
}
private Map<Long, Integer> queryDeviceCollectionAverageMap(Set<Long> deviceIds, List<LocalDate> statDays,
LocalDateTime beginTime, LocalDateTime endTime) {
Map<Long, Integer> result = new HashMap<>();
if (CollUtil.isEmpty(deviceIds) || CollUtil.isEmpty(statDays) || beginTime == null || endTime == null) {
return result;
}
Set<LocalDate> validDays = new HashSet<>(statDays);
Map<Long, Map<LocalDate, Double>> rawMap = tdengineService.queryDailyLatestCapacityValues(deviceIds, beginTime, endTime);
BigDecimal divisor = BigDecimal.valueOf(statDays.size());
for (Long deviceId : deviceIds) {
Map<LocalDate, Double> dayMap = rawMap.getOrDefault(deviceId, Collections.emptyMap());
BigDecimal total = BigDecimal.ZERO;
for (Map.Entry<LocalDate, Double> entry : dayMap.entrySet()) {
if (entry.getKey() == null || entry.getValue() == null || !validDays.contains(entry.getKey())) {
continue;
}
total = total.add(BigDecimal.valueOf(entry.getValue()));
}
result.put(deviceId, total.divide(divisor, 0, RoundingMode.HALF_UP).intValue());
}
return result;
}
private List<LocalDate> listStatDays(LocalDate startDate, LocalDate endDate) {
List<LocalDate> days = new ArrayList<>();
if (startDate == null || endDate == null || startDate.isAfter(endDate)) {
return days;
}
LocalDate cursor = startDate;
while (!cursor.isAfter(endDate)) {
days.add(cursor);
cursor = cursor.plusDays(1);
}
return days;
}
@Override
public List<DeviceLedgerDO> getDeviceLedgerList() {
return deviceLedgerMapper.selectList();

Loading…
Cancel
Save