|
|
@@ -33,6 +33,7 @@ import cn.iocoder.yudao.module.pms.dal.mysql.iotrydailyreportdetail.IotRyDailyRe
|
|
|
import cn.iocoder.yudao.module.pms.service.iotprojectinfo.IotProjectInfoService;
|
|
|
import cn.iocoder.yudao.module.pms.service.iotprojecttask.IotProjectTaskService;
|
|
|
import cn.iocoder.yudao.module.pms.service.iotrydailyreport.IotRyDailyReportService;
|
|
|
+import cn.iocoder.yudao.module.system.controller.admin.dept.vo.dept.DeptListReqVO;
|
|
|
import cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO;
|
|
|
import cn.iocoder.yudao.module.system.dal.dataobject.dict.DictDataDO;
|
|
|
import cn.iocoder.yudao.module.system.service.dept.DeptService;
|
|
|
@@ -56,6 +57,7 @@ import java.time.LocalDateTime;
|
|
|
import java.time.temporal.ChronoUnit;
|
|
|
import java.util.*;
|
|
|
import java.util.concurrent.atomic.AtomicReference;
|
|
|
+import java.util.stream.Collectors;
|
|
|
import java.util.stream.Stream;
|
|
|
|
|
|
import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.EXPORT;
|
|
|
@@ -285,6 +287,42 @@ public class IotRyDailyReportController {
|
|
|
return success(new PageResult<>(buildRyDailyReports(pageResult.getList(), pageReqVO, "list"), pageResult.getTotal()));
|
|
|
}
|
|
|
|
|
|
+ @GetMapping("/productionBriefs")
|
|
|
+ @Operation(summary = "瑞鹰看板 组合钻井修井日报生产动态简报")
|
|
|
+ @PreAuthorize("@ss.hasPermission('pms:iot-ry-daily-report:query')")
|
|
|
+ public CommonResult<List<IotRyDailyReportRespVO>> productionBriefs(@Valid IotRyDailyReportPageReqVO pageReqVO) {
|
|
|
+ // 根据查询参数筛选出 符合条件 的记录id 再传入 分页查询
|
|
|
+ Set<Long> projectIds = new HashSet<>();
|
|
|
+ Set<Long> taskIds = new HashSet<>();
|
|
|
+ if (StrUtil.isNotBlank(pageReqVO.getContractName())) {
|
|
|
+ IotProjectInfoPageReqVO reqVO = new IotProjectInfoPageReqVO();
|
|
|
+ reqVO.setContractName(pageReqVO.getContractName());
|
|
|
+ List<IotProjectInfoDO> projects = iotProjectInfoService.getIotProjectInfos(reqVO);
|
|
|
+ if (CollUtil.isNotEmpty(projects)) {
|
|
|
+ projects.forEach(project -> {
|
|
|
+ projectIds.add(project.getId());
|
|
|
+ });
|
|
|
+ pageReqVO.setProjectIds(projectIds);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (StrUtil.isNotBlank(pageReqVO.getTaskName())) {
|
|
|
+ IotProjectTaskPageReqVO reqVO = new IotProjectTaskPageReqVO();
|
|
|
+ reqVO.setSearchKey(pageReqVO.getTaskName());
|
|
|
+ List<IotProjectTaskDO> tasks = iotProjectTaskService.projectTasks(reqVO);
|
|
|
+ if (CollUtil.isNotEmpty(tasks)) {
|
|
|
+ tasks.forEach(task -> {
|
|
|
+ taskIds.add(task.getId());
|
|
|
+ });
|
|
|
+ pageReqVO.setTaskIds(taskIds);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // 不区分钻井 修井 查询全部日报后再组装
|
|
|
+ pageReqVO.setProjectClassification(StrUtil.EMPTY);
|
|
|
+ List<IotRyDailyReportDO> reports = iotRyDailyReportService.productionBriefs(pageReqVO);
|
|
|
+
|
|
|
+ return success(buildProductionBriefs(reports, pageReqVO));
|
|
|
+ }
|
|
|
+
|
|
|
@GetMapping("/teamReports")
|
|
|
@Operation(summary = "根据井号查询瑞鹰日报列表 按照队伍分组统计工作量")
|
|
|
@PreAuthorize("@ss.hasPermission('pms:iot-ry-daily-report:query')")
|
|
|
@@ -427,6 +465,281 @@ public class IotRyDailyReportController {
|
|
|
return success(resultMap);
|
|
|
}
|
|
|
|
|
|
+ private List<IotRyDailyReportRespVO> buildProductionBriefs(List<IotRyDailyReportDO> reports, IotRyDailyReportPageReqVO pageReqVO) {
|
|
|
+ if (CollUtil.isEmpty(reports)) {
|
|
|
+ return Collections.emptyList();
|
|
|
+ }
|
|
|
+ // 设备部门信息
|
|
|
+ Map<Long, DeptDO> deptMap = deptService.getDeptMap(convertList(reports, IotRyDailyReportDO::getDeptId));
|
|
|
+ // key项目id value项目合同号
|
|
|
+ Map<Long, String> projectPair = new HashMap<>();
|
|
|
+ // key任务id value任务井号
|
|
|
+ Map<Long, String> taskPair = new HashMap<>();
|
|
|
+ // key任务id value任务施工区域
|
|
|
+ Map<Long, String> taskLocationPair = new HashMap<>();
|
|
|
+ // key任务id value设计井深
|
|
|
+ Map<Long, BigDecimal> taskExtPropertyPair = new HashMap<>();
|
|
|
+ // key任务id value额定生产时间
|
|
|
+ Map<Long, BigDecimal> taskRatedProductionTimePair = new HashMap<>();
|
|
|
+ // key任务id value套生段产管尺寸
|
|
|
+ Map<Long, String> taskCasingPipeSizePair = new HashMap<>();
|
|
|
+ // key任务id value井控级别
|
|
|
+ Map<Long, String> taskWellControlLevelPair = new HashMap<>();
|
|
|
+ // key任务id value施工工艺
|
|
|
+ Map<Long, String> taskTechniquePair = new HashMap<>();
|
|
|
+ // key任务id value主设备数量
|
|
|
+ Map<Long, Integer> taskDeviceNumPair = new HashMap<>();
|
|
|
+ // key任务id value井别
|
|
|
+ Map<Long, String> taskWellCategoryPair = new HashMap<>();
|
|
|
+ // key任务id value设计井身结构
|
|
|
+ Map<Long, String> taskWellStructPair = new HashMap<>();
|
|
|
+ // key部门id value设备型号编号
|
|
|
+ AtomicReference<Map<Long, String>> equipmentTypePair = new AtomicReference<>(new HashMap<>());
|
|
|
+ // key施工队伍id value最近完工日期
|
|
|
+ Map<Long, LocalDateTime> latestWellDoneTimePair = new HashMap<>();
|
|
|
+ // key施工队伍id value施工井数量
|
|
|
+ Map<Long, Integer> totalTasksPair = new HashMap<>();
|
|
|
+ // key施工队伍id value完工井数量
|
|
|
+ Map<Long, Integer> completedTasksPair = new HashMap<>();
|
|
|
+ // key非生产时间原因数据字典value value非生产时间原因数据字典label
|
|
|
+ Map<String, String> nptReasonPair = new HashMap<>();
|
|
|
+ // 钻井 key施工状态数据字典value value施工状态数据字典label
|
|
|
+ Map<String, String> constructStatusPair = new HashMap<>();
|
|
|
+ // 修井 key施工状态数据字典value value施工状态数据字典label
|
|
|
+ Map<String, String> repairStatusPair = new HashMap<>();
|
|
|
+ // key日报id value生产动态明细
|
|
|
+ Map<Long, List<IotRyDailyReportDetailRespVO>> reportDetailsPair = new HashMap<>();
|
|
|
+
|
|
|
+ // 钻井 施工状态 字典数据
|
|
|
+ List<DictDataDO> rigStatusDictData = dictDataService.getDictDataListByDictType("rigStatus");
|
|
|
+ // 修井 施工状态 字典数据
|
|
|
+ List<DictDataDO> repairStatusDictData = dictDataService.getDictDataListByDictType("repairStatus");
|
|
|
+ // 非生产时间原因 字典数据
|
|
|
+ List<DictDataDO> nptReasonDictData = dictDataService.getDictDataListByDictType("ryNptReason");
|
|
|
+
|
|
|
+ if (CollUtil.isNotEmpty(nptReasonDictData)) {
|
|
|
+ nptReasonDictData.forEach(data -> {
|
|
|
+ nptReasonPair.put(data.getValue(), data.getLabel());
|
|
|
+ });
|
|
|
+ }
|
|
|
+ // 钻井施工状态
|
|
|
+ if (CollUtil.isNotEmpty(rigStatusDictData)) {
|
|
|
+ rigStatusDictData.forEach(data -> {
|
|
|
+ constructStatusPair.put(data.getValue(), data.getLabel());
|
|
|
+ });
|
|
|
+ }
|
|
|
+ // 修井施工状态
|
|
|
+ if (CollUtil.isNotEmpty(repairStatusDictData)) {
|
|
|
+ repairStatusDictData.forEach(data -> {
|
|
|
+ repairStatusPair.put(data.getValue(), data.getLabel());
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ // 查询瑞鹰下所有部门 施工队伍及对应的项目部
|
|
|
+ Set<Long> deptIds = deptService.getChildDeptIdListFromCache(158l);
|
|
|
+ DeptListReqVO deptReqVO = new DeptListReqVO();
|
|
|
+ deptReqVO.setDeptIds(deptIds);
|
|
|
+ List<DeptDO> departments = deptService.getDeptList(deptReqVO);
|
|
|
+ Map<Long, String> projectNamePair = new HashMap<>();
|
|
|
+ Set<Long> teamIds = new HashSet<>();
|
|
|
+ // key队伍id value项目部id
|
|
|
+ Map<Long, Long> teamProjectPair = new HashMap<>();
|
|
|
+ // key队伍id value项目部名称
|
|
|
+ Map<Long, String> teamProjectNamePair = new HashMap<>();
|
|
|
+ // 项目部排序值
|
|
|
+ Map<Long, Integer> projectSortPair = new HashMap<>();
|
|
|
+ // 队伍排序值
|
|
|
+ Map<Long, Integer> teamSortPair = new HashMap<>();
|
|
|
+ // 找到每个施工队伍的上级部门
|
|
|
+ if (CollUtil.isNotEmpty(departments)) {
|
|
|
+ departments.forEach(dept -> {
|
|
|
+ if ("2".equals(dept.getType())) {
|
|
|
+ projectNamePair.put(dept.getId(), dept.getName());
|
|
|
+ projectSortPair.put(dept.getId(), dept.getSort());
|
|
|
+ }
|
|
|
+ if ("3".equals(dept.getType())) {
|
|
|
+ teamIds.add(dept.getId());
|
|
|
+ teamProjectPair.put(dept.getId(), dept.getParentId());
|
|
|
+ teamSortPair.put(dept.getId(), dept.getSort());
|
|
|
+ }
|
|
|
+ });
|
|
|
+ if (CollUtil.isNotEmpty(teamProjectPair)) {
|
|
|
+ teamProjectPair.forEach((teamId, projectDeptId) -> {
|
|
|
+ if (projectNamePair.containsKey(projectDeptId)) {
|
|
|
+ teamProjectNamePair.put(teamId, projectNamePair.get(projectDeptId));
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 查询施工队伍属于钻井或修井
|
|
|
+ Set<Long> zjDeptIds = new HashSet<>();
|
|
|
+ Set<Long> xjDeptIds = new HashSet<>();
|
|
|
+ IotDeptTypePageReqVO deptTypeReqVO = new IotDeptTypePageReqVO();
|
|
|
+ List<IotDeptTypeDO> deptTypes = iotDeptTypeMapper.selectList(deptTypeReqVO);
|
|
|
+ if (CollUtil.isNotEmpty(deptTypes)) {
|
|
|
+ deptTypes.forEach(deptType -> {
|
|
|
+ if ("zj".equals(deptType.getType())) {
|
|
|
+ zjDeptIds.add(deptType.getDeptId());
|
|
|
+ }
|
|
|
+ if ("xj".equals(deptType.getType())) {
|
|
|
+ xjDeptIds.add(deptType.getDeptId());
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ // 查询每个日报的生产动态明细
|
|
|
+ IotRyDailyReportDetailPageReqVO detailReqVO = new IotRyDailyReportDetailPageReqVO();
|
|
|
+ detailReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
|
|
|
+ detailReqVO.setReportIds(convertList(reports, IotRyDailyReportDO::getId));
|
|
|
+ PageResult<IotRyDailyReportDetailDO> reportDetailsPage = iotRyDailyReportDetailMapper.selectPage(detailReqVO);
|
|
|
+ List<IotRyDailyReportDetailDO> reportDetails = reportDetailsPage.getList();
|
|
|
+ if (CollUtil.isNotEmpty(reportDetails)) {
|
|
|
+ // 设置每个日报的生产动态明细
|
|
|
+ reportDetails.forEach(detail -> {
|
|
|
+ if (reportDetailsPair.containsKey(detail.getReportId())) {
|
|
|
+ List<IotRyDailyReportDetailRespVO> tempDetails = reportDetailsPair.get(detail.getReportId());
|
|
|
+ tempDetails.add(BeanUtils.toBean(detail, IotRyDailyReportDetailRespVO.class));
|
|
|
+ reportDetailsPair.put(detail.getReportId(), tempDetails);
|
|
|
+ } else {
|
|
|
+ List<IotRyDailyReportDetailRespVO> tempDetails = new ArrayList<>();
|
|
|
+ tempDetails.add(BeanUtils.toBean(detail, IotRyDailyReportDetailRespVO.class));
|
|
|
+ reportDetailsPair.put(detail.getReportId(), tempDetails);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+ DataPermissionUtils.executeIgnore(() -> {
|
|
|
+ // 查询日报关联的项目信息
|
|
|
+ IotProjectInfoPageReqVO reqVO = new IotProjectInfoPageReqVO();
|
|
|
+ reqVO.setProjectIds(convertList(reports, IotRyDailyReportDO::getProjectId));
|
|
|
+ List<IotProjectInfoDO> projects = iotProjectInfoService.getIotProjectInfos(reqVO);
|
|
|
+ if (CollUtil.isNotEmpty(projects)) {
|
|
|
+ projects.forEach(project -> {
|
|
|
+ projectPair.put(project.getId(), project.getContractName());
|
|
|
+ });
|
|
|
+ }
|
|
|
+ // 查询日报关联的任务信息
|
|
|
+ IotProjectTaskPageReqVO taskReqVO = new IotProjectTaskPageReqVO();
|
|
|
+ taskReqVO.setTaskIds(convertList(reports, IotRyDailyReportDO::getTaskId));
|
|
|
+ List<IotProjectTaskDO> tasks = iotProjectTaskService.projectTasks(taskReqVO);
|
|
|
+ if (CollUtil.isNotEmpty(tasks)) {
|
|
|
+ tasks.forEach(task -> {
|
|
|
+ taskPair.put(task.getId(), task.getWellName());
|
|
|
+ taskLocationPair.put(task.getId(), task.getLocation());
|
|
|
+ taskTechniquePair.put(task.getId(), task.getTechnique());
|
|
|
+ taskDeviceNumPair.put(task.getId(), task.getDeviceIds().size());
|
|
|
+ });
|
|
|
+ }
|
|
|
+ // 查询当前日报所属施工队伍中包含 井架 的型号
|
|
|
+ equipmentTypePair.set(iotRyDailyReportService.queryEquipmentType(convertList(reports, IotRyDailyReportDO::getDeptId)));
|
|
|
+ // 查询当前日报所属部门的 上井次完井时间 已经绑定任务的情况下
|
|
|
+ List<IotRyDailyReportDO> latestWellDoneTimes = iotRyDailyReportService.latestWellDoneTimes(null);
|
|
|
+ if (CollUtil.isNotEmpty(latestWellDoneTimes)) {
|
|
|
+ latestWellDoneTimes.forEach(time -> {
|
|
|
+ latestWellDoneTimePair.put(time.getDeptId(), time.getConstructionStartDate());
|
|
|
+ });
|
|
|
+ }
|
|
|
+ // 按施工队伍统计 钻井日报 施工井数 完工井数
|
|
|
+ List<IotRyDailyReportTaskCountVO> deptTasks = iotRyDailyReportService.countTasksByDept();
|
|
|
+ // 修井日报 不存在既填写钻井日报 又填写修井日报的队伍
|
|
|
+ if (ObjUtil.isNotEmpty(pageReqVO.getCreateTime())) {
|
|
|
+ List<IotRyDailyReportTaskCountVO> repairDeptTasks = iotRyDailyReportService.countRepairTasksByDept(pageReqVO);
|
|
|
+ if (CollUtil.isNotEmpty(repairDeptTasks)) {
|
|
|
+ repairDeptTasks.forEach(task -> {
|
|
|
+ totalTasksPair.put(task.getDeptId(), task.getTotalTaskCount());
|
|
|
+ completedTasksPair.put(task.getDeptId(), task.getCompletedTaskCount());
|
|
|
+ });
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (CollUtil.isNotEmpty(deptTasks)) {
|
|
|
+ deptTasks.forEach(task -> {
|
|
|
+ totalTasksPair.put(task.getDeptId(), task.getTotalTaskCount());
|
|
|
+ completedTasksPair.put(task.getDeptId(), task.getCompletedTaskCount());
|
|
|
+ });
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ List<IotRyDailyReportRespVO> resultList =BeanUtils.toBean(reports, IotRyDailyReportRespVO.class, (reportVO) -> {
|
|
|
+ // 油耗 精确到 2位小数
|
|
|
+ if (reportVO.getDailyFuel().compareTo(BigDecimal.ZERO) > 0) {
|
|
|
+ BigDecimal fuel = reportVO.getDailyFuel()
|
|
|
+ .divide(BigDecimal.valueOf(1), 2, RoundingMode.HALF_UP);
|
|
|
+ reportVO.setDailyFuel(fuel);
|
|
|
+ }
|
|
|
+ // 将 ‘生产配合’ 的值赋值给 ‘其他非生产时间’
|
|
|
+ if (reportVO.getRelocationTime().compareTo(BigDecimal.ZERO) > 0) {
|
|
|
+ reportVO.setOtherProductionTime(reportVO.getRelocationTime());
|
|
|
+ }
|
|
|
+ // 计算非生产时效
|
|
|
+ BigDecimal sumNpt = calculateNonProductTime(reportVO);
|
|
|
+ // 非生产时间加和
|
|
|
+ reportVO.setNonProductionTime(sumNpt);
|
|
|
+ reportVO.setNonProductionRate(sumNpt.divide(BigDecimal.valueOf(24), 4, RoundingMode.HALF_UP ));
|
|
|
+
|
|
|
+ // 日报生成日期 格式化时间为 yyyy-MM-dd
|
|
|
+ if (ObjUtil.isNotEmpty(reportVO.getCreateTime())) {
|
|
|
+ reportVO.setCreateTimeStr(LocalDateTimeUtil.format(reportVO.getCreateTime(), DatePattern.NORM_DATE_PATTERN));
|
|
|
+ }
|
|
|
+ // 上井次完井时间 格式化时间为 yyyy-MM-dd
|
|
|
+ if (ObjUtil.isNotEmpty(reportVO.getLatestWellDoneTime())) {
|
|
|
+ reportVO.setLatestWellDoneTimeStr(LocalDateTimeUtil.format(reportVO.getLatestWellDoneTime(), DatePattern.NORM_DATE_PATTERN));
|
|
|
+ }
|
|
|
+ // 2.1 拼接部门信息
|
|
|
+ findAndThen(deptMap, reportVO.getDeptId(), dept -> reportVO.setDeptName(dept.getName()));
|
|
|
+ // 队伍排序值
|
|
|
+ findAndThen(teamSortPair, reportVO.getDeptId(), sort -> reportVO.setTeamSort(sort));
|
|
|
+ // 设置项目部排序值
|
|
|
+ if (teamProjectPair.containsKey(reportVO.getDeptId())) {
|
|
|
+ Long projectDeptId = teamProjectPair.get(reportVO.getDeptId());
|
|
|
+ if (projectSortPair.containsKey(projectDeptId)) {
|
|
|
+ reportVO.setProjectSort(projectSortPair.get(projectDeptId));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // 设置 钻井 or 修井
|
|
|
+ if (zjDeptIds.contains(reportVO.getDeptId())) {
|
|
|
+ reportVO.setProjectClassification("钻井");
|
|
|
+ }
|
|
|
+ if (xjDeptIds.contains(reportVO.getDeptId())) {
|
|
|
+ reportVO.setProjectClassification("修井");
|
|
|
+ }
|
|
|
+ // 主设备数量
|
|
|
+ findAndThen(taskDeviceNumPair, reportVO.getTaskId(), deviceNum -> reportVO.setDeviceNum(deviceNum));
|
|
|
+ // 项目部名称
|
|
|
+ findAndThen(teamProjectNamePair, reportVO.getDeptId(), projectName -> reportVO.setProjectName(projectName));
|
|
|
+ // 2.2 日报关联的项目信息
|
|
|
+ findAndThen(projectPair, reportVO.getProjectId(), contractName -> reportVO.setContractName(contractName));
|
|
|
+ // 2.3 日报关联的任务信息
|
|
|
+ findAndThen(taskPair, reportVO.getTaskId(), taskName -> reportVO.setTaskName(taskName));
|
|
|
+ // 日报关联的任务施工地点
|
|
|
+ findAndThen(taskLocationPair, reportVO.getTaskId(), location -> reportVO.setLocation(location));
|
|
|
+ // 2.7 上井次完井时间
|
|
|
+ findAndThen(latestWellDoneTimePair, reportVO.getDeptId(), latestWellDoneTime -> reportVO.setLatestWellDoneTime(latestWellDoneTime));
|
|
|
+ // 2.8 总施工井数 完工井数
|
|
|
+ findAndThen(totalTasksPair, reportVO.getDeptId(), totalTaskCount -> reportVO.setTotalConstructionWells(totalTaskCount));
|
|
|
+ findAndThen(completedTasksPair, reportVO.getDeptId(), completedTaskCount -> reportVO.setCompletedWells(completedTaskCount));
|
|
|
+ // 钻井 施工状态 数据字典
|
|
|
+ findAndThen(constructStatusPair, reportVO.getRigStatus(), statusLabel -> {
|
|
|
+ if ("钻井".equals(reportVO.getProjectClassification())) {
|
|
|
+ reportVO.setConstructionStatusName(statusLabel);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ // 修井 施工状态 数据字典
|
|
|
+ findAndThen(repairStatusPair, reportVO.getRepairStatus(), statusLabel -> {
|
|
|
+ if ("修井".equals(reportVO.getProjectClassification())) {
|
|
|
+ reportVO.setConstructionStatusName(statusLabel);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ });
|
|
|
+
|
|
|
+ // 2. 拼接数据
|
|
|
+ return resultList.stream()
|
|
|
+ .sorted(Comparator.comparing(IotRyDailyReportRespVO::getProjectClassification,
|
|
|
+ Comparator.comparingInt(s -> "钻井".equals(s) ? 0 : 1)) // 1. 钻井在前
|
|
|
+ .thenComparing(IotRyDailyReportRespVO::getProjectSort) // 2. 项目部排序升序
|
|
|
+ .thenComparing(IotRyDailyReportRespVO::getTeamSort)) // 3. 队伍排序升序
|
|
|
+ .collect(Collectors.toList());
|
|
|
+ }
|
|
|
+
|
|
|
/**
|
|
|
* 瑞恒日报分页 设置关联查询信息
|
|
|
* @param reports
|