Browse Source

前台约检批量上报

xy 1 week ago
parent
commit
941d4442df
14 changed files with 547 additions and 0 deletions
  1. 5 0
      tz-module-pressure2/tz-module-pressure2-biz/src/main/java/cn/start/tz/module/pressure2/controller/admin/equipboilerscheduling/EquipBoilerSchedulingController.java
  2. 23 0
      tz-module-pressure2/tz-module-pressure2-biz/src/main/java/cn/start/tz/module/pressure2/controller/admin/equipboilerscheduling/vo/BoilerRefuseItemReqVO.java
  3. 33 0
      tz-module-pressure2/tz-module-pressure2-biz/src/main/java/cn/start/tz/module/pressure2/controller/admin/equipboilerscheduling/vo/BoilerRefuseItemResultVO.java
  4. 3 0
      tz-module-pressure2/tz-module-pressure2-biz/src/main/java/cn/start/tz/module/pressure2/controller/admin/equipboilerscheduling/vo/EquipBoilerSchedulingBoilersRespVO.java
  5. 6 0
      tz-module-pressure2/tz-module-pressure2-biz/src/main/java/cn/start/tz/module/pressure2/controller/admin/equipboilerscheduling/vo/EquipBoilerSchedulingRespVO.java
  6. 5 0
      tz-module-pressure2/tz-module-pressure2-biz/src/main/java/cn/start/tz/module/pressure2/controller/admin/equippipescheduling/EquipPipeSchedulingController.java
  7. 12 0
      tz-module-pressure2/tz-module-pressure2-biz/src/main/java/cn/start/tz/module/pressure2/controller/admin/equippipescheduling/vo/EquipPipePlanSchedulingVO.java
  8. 12 0
      tz-module-pressure2/tz-module-pressure2-biz/src/main/java/cn/start/tz/module/pressure2/controller/admin/equippipescheduling/vo/EquipPipeSchedulingPipesRespVO.java
  9. 23 0
      tz-module-pressure2/tz-module-pressure2-biz/src/main/java/cn/start/tz/module/pressure2/controller/admin/equippipescheduling/vo/PipeRefuseItemReqVO.java
  10. 33 0
      tz-module-pressure2/tz-module-pressure2-biz/src/main/java/cn/start/tz/module/pressure2/controller/admin/equippipescheduling/vo/PipeRefuseItemResultVO.java
  11. 5 0
      tz-module-pressure2/tz-module-pressure2-biz/src/main/java/cn/start/tz/module/pressure2/service/equipboilerscheduling/EquipBoilerSchedulingService.java
  12. 193 0
      tz-module-pressure2/tz-module-pressure2-biz/src/main/java/cn/start/tz/module/pressure2/service/equipboilerscheduling/EquipBoilerSchedulingServiceImpl.java
  13. 5 0
      tz-module-pressure2/tz-module-pressure2-biz/src/main/java/cn/start/tz/module/pressure2/service/equippipescheduling/EquipPipeSchedulingService.java
  14. 189 0
      tz-module-pressure2/tz-module-pressure2-biz/src/main/java/cn/start/tz/module/pressure2/service/equippipescheduling/EquipPipeSchedulingServiceImpl.java

+ 5 - 0
tz-module-pressure2/tz-module-pressure2-biz/src/main/java/cn/start/tz/module/pressure2/controller/admin/equipboilerscheduling/EquipBoilerSchedulingController.java

@@ -151,4 +151,9 @@ public class EquipBoilerSchedulingController {
         return success(true);
     }
 
+    @PostMapping("/refuseItem")
+    @Operation(summary = "客户拒检设备上报(锅炉)")
+    public CommonResult<List<BoilerRefuseItemResultVO>> refuseItem(@RequestBody BoilerRefuseItemReqVO reqVO) {
+        return success(equipBoilerSchedulingService.refuseItem(reqVO));
+    }
 }

+ 23 - 0
tz-module-pressure2/tz-module-pressure2-biz/src/main/java/cn/start/tz/module/pressure2/controller/admin/equipboilerscheduling/vo/BoilerRefuseItemReqVO.java

@@ -0,0 +1,23 @@
+package cn.start.tz.module.pressure2.controller.admin.equipboilerscheduling.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.util.List;
+
+@Schema(description = "管理后台 - 锅炉设备批量上报 Request VO")
+@Data
+public class BoilerRefuseItemReqVO {
+
+    @Schema(description = "设备ID列表", requiredMode = Schema.RequiredMode.REQUIRED)
+    private List<String> equipIds;
+
+    @Schema(description = "检验类型: 100=内部检验, 200=外部检验, 300=耐压检验", requiredMode = Schema.RequiredMode.REQUIRED)
+    private Integer checkType;
+
+    @Schema(description = "拒绝原因字典值")
+    private String reasonDict;
+
+    @Schema(description = "自定义拒绝原因")
+    private String reason;
+}

+ 33 - 0
tz-module-pressure2/tz-module-pressure2-biz/src/main/java/cn/start/tz/module/pressure2/controller/admin/equipboilerscheduling/vo/BoilerRefuseItemResultVO.java

@@ -0,0 +1,33 @@
+package cn.start.tz.module.pressure2.controller.admin.equipboilerscheduling.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+@Schema(description = "管理后台 - 锅炉设备批量上报单个结果 VO")
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class BoilerRefuseItemResultVO {
+
+    @Schema(description = "设备ID")
+    private String equipId;
+
+    @Schema(description = "设备编码")
+    private String equipCode;
+
+    @Schema(description = "是否成功")
+    private Boolean success;
+
+    @Schema(description = "消息")
+    private String message;
+
+    public static BoilerRefuseItemResultVO success(String equipId, String equipCode) {
+        return new BoilerRefuseItemResultVO(equipId, equipCode, true, "操作成功");
+    }
+
+    public static BoilerRefuseItemResultVO fail(String equipId, String equipCode, String message) {
+        return new BoilerRefuseItemResultVO(equipId, equipCode, false, message);
+    }
+}

+ 3 - 0
tz-module-pressure2/tz-module-pressure2-biz/src/main/java/cn/start/tz/module/pressure2/controller/admin/equipboilerscheduling/vo/EquipBoilerSchedulingBoilersRespVO.java

@@ -102,4 +102,7 @@ public class EquipBoilerSchedulingBoilersRespVO {
     private String type;
 
     private String relatedDepartment;
+
+    @Schema(description = "拒绝原因字典值")
+    private String refuseReasonDict;
 }

+ 6 - 0
tz-module-pressure2/tz-module-pressure2-biz/src/main/java/cn/start/tz/module/pressure2/controller/admin/equipboilerscheduling/vo/EquipBoilerSchedulingRespVO.java

@@ -93,4 +93,10 @@ public class EquipBoilerSchedulingRespVO {
 
     @Schema(description = "相关部门")
     private String relatedDepartment;
+
+    @Schema(description = "拒绝原因字典值")
+    private String refuseReasonDict;
+
+    @Schema(description = "拒绝原因")
+    private String refuseReason;
 }

+ 5 - 0
tz-module-pressure2/tz-module-pressure2-biz/src/main/java/cn/start/tz/module/pressure2/controller/admin/equippipescheduling/EquipPipeSchedulingController.java

@@ -241,4 +241,9 @@ public class EquipPipeSchedulingController {
         return success(true);
     }
 
+    @PostMapping("/refuseItem")
+    @Operation(summary = "客户拒检设备上报(管道)")
+    public CommonResult<List<PipeRefuseItemResultVO>> refuseItem(@RequestBody PipeRefuseItemReqVO reqVO) {
+        return success(equipPipeSchedulingService.refuseItem(reqVO));
+    }
 }

+ 12 - 0
tz-module-pressure2/tz-module-pressure2-biz/src/main/java/cn/start/tz/module/pressure2/controller/admin/equippipescheduling/vo/EquipPipePlanSchedulingVO.java

@@ -89,4 +89,16 @@ public class EquipPipePlanSchedulingVO {
 
     @Schema(description = "管道状态")
     private String useStatus;
+
+    @Schema(description = "拒绝原因字典")
+    private String refuseReasonDict;
+
+    @Schema(description = "拒绝对应的检验类型: 100=定期检验, 200=年度检查")
+    private Integer refuseCheckType;
+
+    @Schema(description = "定期检验拒检原因(100)")
+    private String legalRefuseReasonDict;
+
+    @Schema(description = "年度检查拒检原因(200)")
+    private String yearRefuseReasonDict;
 }

+ 12 - 0
tz-module-pressure2/tz-module-pressure2-biz/src/main/java/cn/start/tz/module/pressure2/controller/admin/equippipescheduling/vo/EquipPipeSchedulingPipesRespVO.java

@@ -90,6 +90,18 @@ public class EquipPipeSchedulingPipesRespVO {
     @Schema(description = "关联部门名称")
     private String relationDeptName;
 
+    @Schema(description = "拒绝原因字典")
+    private String refuseReasonDict;
+
+    @Schema(description = "拒绝原因")
+    private String refuseReason;
+
+    @Schema(description = "所有管线是否都已拒检(定期检验=100)")
+    private Boolean allLegalRefused;
+
+    @Schema(description = "所有管线是否都已拒检(年度检查=200)")
+    private Boolean allYearRefused;
+
     @ExcelIgnore
     private List<EquipPipePlanSchedulingVO> pipes = new ArrayList<>();
 }

+ 23 - 0
tz-module-pressure2/tz-module-pressure2-biz/src/main/java/cn/start/tz/module/pressure2/controller/admin/equippipescheduling/vo/PipeRefuseItemReqVO.java

@@ -0,0 +1,23 @@
+package cn.start.tz.module.pressure2.controller.admin.equippipescheduling.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.util.List;
+
+@Schema(description = "管理后台 - 管道设备批量上报 Request VO")
+@Data
+public class PipeRefuseItemReqVO {
+
+    @Schema(description = "管道明细ID列表(EquipPipeDetailDO.id)", requiredMode = Schema.RequiredMode.REQUIRED)
+    private List<String> equipDetailIds;
+
+    @Schema(description = "检验类型: 100=定期检验, 200=年度检查", requiredMode = Schema.RequiredMode.REQUIRED)
+    private Integer checkType;
+
+    @Schema(description = "拒绝原因字典值")
+    private String reasonDict;
+
+    @Schema(description = "自定义拒绝原因")
+    private String reason;
+}

+ 33 - 0
tz-module-pressure2/tz-module-pressure2-biz/src/main/java/cn/start/tz/module/pressure2/controller/admin/equippipescheduling/vo/PipeRefuseItemResultVO.java

@@ -0,0 +1,33 @@
+package cn.start.tz.module.pressure2.controller.admin.equippipescheduling.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+@Schema(description = "管理后台 - 管道设备批量上报单个结果 VO")
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class PipeRefuseItemResultVO {
+
+    @Schema(description = "管道明细ID")
+    private String equipDetailId;
+
+    @Schema(description = "管道注册代码")
+    private String pipeRegCode;
+
+    @Schema(description = "是否成功")
+    private Boolean success;
+
+    @Schema(description = "消息")
+    private String message;
+
+    public static PipeRefuseItemResultVO success(String equipDetailId, String pipeRegCode) {
+        return new PipeRefuseItemResultVO(equipDetailId, pipeRegCode, true, "操作成功");
+    }
+
+    public static PipeRefuseItemResultVO fail(String equipDetailId, String pipeRegCode, String message) {
+        return new PipeRefuseItemResultVO(equipDetailId, pipeRegCode, false, message);
+    }
+}

+ 5 - 0
tz-module-pressure2/tz-module-pressure2-biz/src/main/java/cn/start/tz/module/pressure2/service/equipboilerscheduling/EquipBoilerSchedulingService.java

@@ -40,4 +40,9 @@ public interface EquipBoilerSchedulingService extends IService<EquipBoilerSchedu
     void equipUpdate(BoilerEquipUpdateVO equipUpdateVO);
 
     void updateEquipContainerBatch(BoilerContactUpdateVO contactUpdateVO);
+
+    /**
+     * 客户拒检设备上报(锅炉)
+     */
+    List<BoilerRefuseItemResultVO> refuseItem(BoilerRefuseItemReqVO reqVO);
 }

+ 193 - 0
tz-module-pressure2/tz-module-pressure2-biz/src/main/java/cn/start/tz/module/pressure2/service/equipboilerscheduling/EquipBoilerSchedulingServiceImpl.java

@@ -6,6 +6,7 @@ import cn.start.tz.framework.common.pojo.CommonResult;
 import cn.start.tz.framework.ip.core.Area;
 import cn.start.tz.framework.ip.core.utils.AreaUtils;
 import cn.start.tz.framework.mybatis.core.query.LambdaQueryWrapperX;
+import cn.start.tz.framework.web.core.util.WebFrameworkUtils;
 import cn.start.tz.module.pressure.enums.AcceptOrderStatusEnum;
 import cn.start.tz.module.pressure.enums.TaskOrderStatusEnum;
 import cn.start.tz.module.pressure2.controller.admin.appointmentconfirmorder.vo.AppointmentSubmitVO;
@@ -21,6 +22,10 @@ import cn.start.tz.module.pressure2.dal.dataobject.equipboilerschedulingitem.Equ
 import cn.start.tz.module.pressure2.dal.dataobject.equipboilerschedulingitem.EquipBoilerSchedulingItemDO;
 import cn.start.tz.module.pressure2.dal.dataobject.equipboilerschedulinguser.EquipBoilerSchedulingUserDO;
 import cn.start.tz.module.pressure2.dal.mysql.appointmentconfirmorder.AppointmentConfirmOrderMapper;
+import cn.start.tz.module.pressure2.dal.mysql.appointmentconfirmorderrefuseitem.AppointmentConfirmOrderRefuseItemMapper;
+import cn.start.tz.module.pressure2.dal.dataobject.appointmentconfirmorderrefuseitem.AppointmentConfirmOrderRefuseItemDO;
+import cn.start.tz.module.pressure2.controller.admin.equipboilerscheduling.vo.BoilerRefuseItemReqVO;
+import cn.start.tz.module.pressure2.controller.admin.equipboilerscheduling.vo.BoilerRefuseItemResultVO;
 import cn.start.tz.module.pressure2.dal.mysql.boilerappointmentconfirmorderitem.BoilerAppointmentConfirmOrderItemMapper;
 import cn.start.tz.module.pressure2.dal.mysql.boilerappointmentconfirmorderuser.BoilerAppointmentConfirmOrderUserMapper;
 import cn.start.tz.module.pressure2.dal.mysql.equipboiler.EquipBoilerMapper;
@@ -41,9 +46,12 @@ import cn.start.tz.module.system.api.clientunit.ClientUnitApi;
 import cn.start.tz.module.system.api.clientunit.dto.ClientUnitDTO;
 import cn.start.tz.module.system.api.dept.DeptApi;
 import cn.start.tz.module.system.api.dept.dto.DeptRespDTO;
+import cn.start.tz.module.system.api.dict.DictDataApi;
+import cn.start.tz.module.system.api.dict.dto.DictDataRespDTO;
 import cn.start.tz.module.system.api.user.AdminUserApi;
 import cn.start.tz.module.system.api.user.dto.AdminUserRespDTO;
 import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
+import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.context.annotation.Lazy;
@@ -55,6 +63,7 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 
 import java.math.BigDecimal;
 import java.time.LocalDate;
+import java.time.LocalDateTime;
 import java.util.*;
 import java.util.concurrent.atomic.AtomicReference;
 import java.util.function.Function;
@@ -81,6 +90,7 @@ import static cn.start.tz.module.system.enums.ErrorCodeConstants.EQUIP_CONTAINER
  */
 @Service
 @Validated
+@Slf4j
 public class EquipBoilerSchedulingServiceImpl extends ServiceImpl<EquipBoilerSchedulingMapper, EquipBoilerSchedulingDO> implements EquipBoilerSchedulingService {
 
     private static final Double tzAddressLat = 23.17578;
@@ -99,8 +109,10 @@ public class EquipBoilerSchedulingServiceImpl extends ServiceImpl<EquipBoilerSch
 
     @Resource
     private AppointmentConfirmOrderMapper appointmentConfirmOrderMapper;
+
     @Resource
     private BoilerAppointmentConfirmOrderItemMapper appointmentConfirmOrderItemMapper;
+
     @Resource
     private BoilerAppointmentConfirmOrderUserMapper appointmentConfirmOrderUserMapper;
 
@@ -128,12 +140,19 @@ public class EquipBoilerSchedulingServiceImpl extends ServiceImpl<EquipBoilerSch
 
     @Resource
     private AdminUserApi adminUserApi;
+
     @Resource
     private ClientUnitApi clientUnitApi;
 
+    @Resource
+    private DictDataApi dictDataApi;
+
     @Resource
     private DeptApi deptApi;
 
+    @Resource
+    private AppointmentConfirmOrderRefuseItemMapper appointmentConfirmOrderRefuseItemMapper;
+
     @Override
     public PageResult<EquipBoilerSchedulingRespVO> getEquipBoilerSchedulingPage(EquipBoilerSchedulingPageReqVO pageReqVO) {
 
@@ -153,6 +172,49 @@ public class EquipBoilerSchedulingServiceImpl extends ServiceImpl<EquipBoilerSch
                     item.setEquipDistrictName(area.getName());
                 }
             });
+
+            // 收集所有设备ID,批量查询拒检信息
+            Set<String> allEquipIds = new HashSet<>();
+            for (EquipBoilerSchedulingRespVO item : list) {
+                if (StringUtils.isNotBlank(item.getId())) {
+                    allEquipIds.add(item.getId());
+                }
+                if (StringUtils.isNotBlank(item.getInEquipIds())) {
+                    Arrays.stream(item.getInEquipIds().split(","))
+                            .filter(StringUtils::isNotBlank)
+                            .forEach(allEquipIds::add);
+                }
+                if (StringUtils.isNotBlank(item.getOutEquipIds())) {
+                    Arrays.stream(item.getOutEquipIds().split(","))
+                            .filter(StringUtils::isNotBlank)
+                            .forEach(allEquipIds::add);
+                }
+                if (StringUtils.isNotBlank(item.getPreEquipIds())) {
+                    Arrays.stream(item.getPreEquipIds().split(","))
+                            .filter(StringUtils::isNotBlank)
+                            .forEach(allEquipIds::add);
+                }
+            }
+
+            // 批量查询拒检记录,按equipId分组
+            Map<String, AppointmentConfirmOrderRefuseItemDO> refuseMap = new HashMap<>();
+            if (!allEquipIds.isEmpty()) {
+                List<AppointmentConfirmOrderRefuseItemDO> refuseItems = appointmentConfirmOrderRefuseItemMapper.selectList(
+                        new LambdaQueryWrapperX<AppointmentConfirmOrderRefuseItemDO>()
+                                .in(AppointmentConfirmOrderRefuseItemDO::getEquipId, allEquipIds));
+                for (AppointmentConfirmOrderRefuseItemDO refuseItem : refuseItems) {
+                    refuseMap.putIfAbsent(refuseItem.getEquipId(), refuseItem);
+                }
+            }
+
+            // 填充拒检原因到结果列表
+            for (EquipBoilerSchedulingRespVO item : list) {
+                AppointmentConfirmOrderRefuseItemDO refuseItem = refuseMap.get(item.getId());
+                if (refuseItem != null) {
+                    item.setRefuseReasonDict(refuseItem.getReasonDict());
+                    item.setRefuseReason(refuseItem.getReason());
+                }
+            }
         }
 
         pageResult.setList(list);
@@ -180,6 +242,32 @@ public class EquipBoilerSchedulingServiceImpl extends ServiceImpl<EquipBoilerSch
                     item.setEquipDistrictName(area.getName());
                 }
             });
+
+            // 批量查询拒检记录,填充 refuseReasonDict
+            List<String> equipIds = list.stream()
+                    .map(EquipBoilerSchedulingBoilersRespVO::getId)
+                    .filter(Objects::nonNull)
+                    .distinct()
+                    .toList();
+            if (!equipIds.isEmpty()) {
+                LambdaQueryWrapperX<AppointmentConfirmOrderRefuseItemDO> refuseQuery = new LambdaQueryWrapperX<>();
+                refuseQuery.in(AppointmentConfirmOrderRefuseItemDO::getEquipId, equipIds);
+                List<AppointmentConfirmOrderRefuseItemDO> refuseItems = appointmentConfirmOrderRefuseItemMapper.selectList(refuseQuery);
+                if (CollUtil.isNotEmpty(refuseItems)) {
+                    Map<String, AppointmentConfirmOrderRefuseItemDO> refuseMap = new HashMap<>();
+                    for (AppointmentConfirmOrderRefuseItemDO refuseItem : refuseItems) {
+                        if (refuseItem.getEquipId() != null) {
+                            refuseMap.putIfAbsent(refuseItem.getEquipId(), refuseItem);
+                        }
+                    }
+                    for (EquipBoilerSchedulingBoilersRespVO item : list) {
+                        AppointmentConfirmOrderRefuseItemDO refuse = refuseMap.get(item.getId());
+                        if (refuse != null) {
+                            item.setRefuseReasonDict(refuse.getReasonDict());
+                        }
+                    }
+                }
+            }
         }
 
         pageResult.setList(list);
@@ -935,4 +1023,109 @@ public class EquipBoilerSchedulingServiceImpl extends ServiceImpl<EquipBoilerSch
         }
 
     }
+
+    @Override
+    public List<BoilerRefuseItemResultVO> refuseItem(BoilerRefuseItemReqVO reqVO) {
+        List<BoilerRefuseItemResultVO> results = new ArrayList<>();
+
+        if (reqVO.getEquipIds() == null || reqVO.getEquipIds().isEmpty()) {
+            return results;
+        }
+
+        List<DictDataRespDTO> checkTypeDTOS = dictDataApi.getDictDataList("pressure_inspection_nature_boiler").getData();
+        List<DictDataRespDTO> boilerStatusDTOS = dictDataApi.getDictDataList("system_equip_boiler_status").getData();
+
+        for (String equipId : reqVO.getEquipIds()) {
+            try {
+                EquipBoilerDO boiler = equipBoilerMapper.selectById(equipId);
+                if (boiler == null) {
+                    results.add(BoilerRefuseItemResultVO.fail(equipId, null, "锅炉设备信息不存在"));
+                    continue;
+                }
+
+                String equipCode = boiler.getEquipCode();
+
+                // 检查是否已在拒检池中(审核中状态)
+                LambdaQueryWrapperX<AppointmentConfirmOrderRefuseItemDO> query = new LambdaQueryWrapperX<>();
+                query.eq(AppointmentConfirmOrderRefuseItemDO::getEquipId, equipId);
+                query.in(AppointmentConfirmOrderRefuseItemDO::getStatus, List.of(0, 1));
+                List<AppointmentConfirmOrderRefuseItemDO> existingItems = appointmentConfirmOrderRefuseItemMapper.selectList(query);
+                if (CollUtil.isNotEmpty(existingItems)) {
+                    results.add(BoilerRefuseItemResultVO.fail(equipId, equipCode, "该设备已在拒检池中,状态为【审核中】,请处理后再进行设备上报"));
+                    continue;
+                }
+
+                // 创建拒检记录
+                AppointmentConfirmOrderRefuseItemDO refuseItem = new AppointmentConfirmOrderRefuseItemDO();
+                refuseItem.setEquipId(equipId);
+
+                refuseItem.setCheckType(100); //锅炉的都是定检
+                Integer checkType = reqVO.getCheckType();
+                if (CollUtil.isNotEmpty(checkTypeDTOS)){
+                    String checkTypeName = checkTypeDTOS.stream()
+                            .filter(dict -> dict.getValue().equals(checkType.toString()))
+                            .map(DictDataRespDTO::getLabel)
+                            .findFirst()
+                            .orElse("");
+                    refuseItem.setCheckTypeName(checkTypeName);
+                }
+
+                refuseItem.setReasonDict(reqVO.getReasonDict());
+                refuseItem.setReason(reqVO.getReason());
+                refuseItem.setUnitName(boiler.getUnitName());
+                refuseItem.setUnitCode(boiler.getUnitCode());
+                refuseItem.setEquipMainType(200); // 200=锅炉
+                refuseItem.setStatus(0);
+                refuseItem.setRejectionSource(1); // 1=窗口约检
+
+                refuseItem.setSubmitId(getLoginUserId());
+                refuseItem.setSubmitTime(LocalDateTime.now());
+
+                refuseItem.setEquipCode(equipCode);
+                refuseItem.setEquipDistrict(boiler.getEquipDistrict());
+                refuseItem.setEquipStreet(boiler.getEquipStreet());
+                refuseItem.setEquipType(boiler.getType());
+                refuseItem.setAreaType(boiler.getAreaType());
+                refuseItem.setUnitCode(boiler.getUnitCode());
+                refuseItem.setUnitName(boiler.getUnitName());
+                refuseItem.setUseRegisterNo(boiler.getUseRegisterNo());
+                refuseItem.setProductNo(boiler.getProductCode());
+                refuseItem.setEquipStatus(boiler.getStatus());
+                if (CollUtil.isNotEmpty(boilerStatusDTOS)){
+                    String equipStatusName = boilerStatusDTOS.stream()
+                            .filter(dict -> dict.getValue().equals(boiler.getStatus()))
+                            .map(DictDataRespDTO::getLabel)
+                            .findFirst()
+                            .orElse("");
+                    refuseItem.setEquipStatusName(equipStatusName);
+                }
+                refuseItem.setContact(boiler.getContact());
+                refuseItem.setContactPhone(boiler.getContactPhone());
+
+                refuseItem.setIsReportCity(false);
+
+                appointmentConfirmOrderRefuseItemMapper.insert(refuseItem);
+
+                // 更新锅炉排期标识
+                EquipBoilerDO updateBoiler = new EquipBoilerDO();
+                updateBoiler.setId(equipId);
+                if (Integer.valueOf(100).equals(reqVO.getCheckType())) {
+                    updateBoiler.setHasInternal(false);
+                } else if (Integer.valueOf(200).equals(reqVO.getCheckType())) {
+                    updateBoiler.setHasExternal(false);
+                } else if (Integer.valueOf(300).equals(reqVO.getCheckType())) {
+                    updateBoiler.setHasPressure(false);
+                }
+                equipBoilerMapper.updateById(updateBoiler);
+
+                results.add(BoilerRefuseItemResultVO.success(equipId, equipCode));
+
+            } catch (Exception e) {
+                log.error("[refuseItem] 锅炉设备上报失败, equipId={}", equipId, e);
+                results.add(BoilerRefuseItemResultVO.fail(equipId, null, "处理失败: " + e.getMessage()));
+            }
+        }
+
+        return results;
+    }
 }

+ 5 - 0
tz-module-pressure2/tz-module-pressure2-biz/src/main/java/cn/start/tz/module/pressure2/service/equippipescheduling/EquipPipeSchedulingService.java

@@ -86,4 +86,9 @@ public interface EquipPipeSchedulingService extends IService<EquipPipeScheduling
     List<PipeShiftScheduleExportRespVO> convert(List<PipeShiftScheduleRespVO> list);
 
     void setShiftSchedule(List<PipeShiftScheduleSaveRespVO> pipeShiftScheduleRespVOS);
+
+    /**
+     * 客户拒检设备上报(管道)
+     */
+    List<PipeRefuseItemResultVO> refuseItem(PipeRefuseItemReqVO reqVO);
 }

+ 189 - 0
tz-module-pressure2/tz-module-pressure2-biz/src/main/java/cn/start/tz/module/pressure2/service/equippipescheduling/EquipPipeSchedulingServiceImpl.java

@@ -8,10 +8,13 @@ import cn.start.tz.framework.common.pojo.CommonResult;
 import cn.start.tz.framework.ip.core.Area;
 import cn.start.tz.framework.ip.core.utils.AreaUtils;
 import cn.start.tz.framework.mybatis.core.query.LambdaQueryWrapperX;
+
+import java.time.LocalDateTime;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.stream.Collectors;
 
+import cn.start.tz.framework.web.core.util.WebFrameworkUtils;
 import cn.start.tz.module.pressure.enums.AcceptOrderStatusEnum;
 import cn.start.tz.module.pressure.enums.TaskOrderStatusEnum;
 import cn.start.tz.module.pressure2.controller.admin.appointmentconfirmorder.vo.AppointmentSubmitVO;
@@ -35,6 +38,10 @@ import cn.start.tz.module.pressure2.dal.dataobject.acceptorder.AcceptOrderDO;
 import cn.start.tz.module.pressure2.dal.dataobject.boilertaskorder.BoilerTaskOrderDO;
 import cn.start.tz.module.pressure2.dal.dataobject.pipetaskorderuser.PipeTaskOrderUserDO;
 import cn.start.tz.module.pressure2.dal.mysql.appointmentconfirmorder.AppointmentConfirmOrderMapper;
+import cn.start.tz.module.pressure2.dal.mysql.appointmentconfirmorderrefuseitem.AppointmentConfirmOrderRefuseItemMapper;
+import cn.start.tz.module.pressure2.dal.dataobject.appointmentconfirmorderrefuseitem.AppointmentConfirmOrderRefuseItemDO;
+import cn.start.tz.module.pressure2.controller.admin.equippipescheduling.vo.PipeRefuseItemReqVO;
+import cn.start.tz.module.pressure2.controller.admin.equippipescheduling.vo.PipeRefuseItemResultVO;
 import cn.start.tz.module.pressure2.dal.mysql.equippipe.EquipPipeMapper;
 import cn.start.tz.module.pressure2.dal.mysql.equippipedetail.EquipPipeDetailMapper;
 import cn.start.tz.module.pressure2.dal.mysql.equippipeschedulingitem.EquipPipeSchedulingCheckMapper;
@@ -60,6 +67,8 @@ import cn.start.tz.module.system.api.clientunit.ClientUnitApi;
 import cn.start.tz.module.system.api.clientunit.dto.ClientUnitDTO;
 import cn.start.tz.module.system.api.dept.DeptApi;
 import cn.start.tz.module.system.api.dept.dto.DeptRespDTO;
+import cn.start.tz.module.system.api.dict.DictDataApi;
+import cn.start.tz.module.system.api.dict.dto.DictDataRespDTO;
 import cn.start.tz.module.system.api.user.AdminUserApi;
 import cn.start.tz.module.system.api.user.dto.AdminUserRespDTO;
 import com.alibaba.cloud.commons.lang.StringUtils;
@@ -87,6 +96,7 @@ import cn.start.tz.framework.common.util.object.BeanUtils;
 import cn.start.tz.module.pressure2.dal.mysql.equippipescheduling.EquipPipeSchedulingMapper;
 
 import static cn.start.tz.framework.common.exception.util.ServiceExceptionUtil.exception;
+import static cn.start.tz.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
 import static cn.start.tz.module.pressure2.enums.ErrorCodeConstants.*;
 
 /**
@@ -96,6 +106,7 @@ import static cn.start.tz.module.pressure2.enums.ErrorCodeConstants.*;
  */
 @Service
 @Validated
+@Slf4j
 public class EquipPipeSchedulingServiceImpl extends ServiceImpl<EquipPipeSchedulingMapper, EquipPipeSchedulingDO> implements EquipPipeSchedulingService {
 
     @Resource
@@ -119,6 +130,9 @@ public class EquipPipeSchedulingServiceImpl extends ServiceImpl<EquipPipeSchedul
     @Resource
     private AppointmentConfirmOrderMapper appointmentConfirmOrderMapper;
 
+    @Resource
+    private AppointmentConfirmOrderRefuseItemMapper appointmentConfirmOrderRefuseItemMapper;
+
     @Resource
     private PipeAppointmentConfirmOrderItemMapper appointmentConfirmOrderItemMapper;
 
@@ -162,18 +176,25 @@ public class EquipPipeSchedulingServiceImpl extends ServiceImpl<EquipPipeSchedul
 
     @Resource
     private PipeAppointmentConfirmOrderUserMapper pipeAppointmentConfirmOrderUserMapper;
+
     @Resource
     private PipeAcceptOrderUserMapper pipeAcceptOrderUserMapper;
+
     @Resource
     private AcceptOrderMapper acceptOrderMapper;
+
     @Resource
     private BoilerTaskOrderMapper boilerTaskOrderMapper;
+
     @Resource
     private PipeTaskOrderUserMapper pipeTaskOrderUserMapper;
 
     @Resource
     private DeptApi deptApi;
 
+    @Resource
+    private DictDataApi dictDataApi;
+
     private static final Double tzAddressLat = 23.17578;
     private static final Double tzAddressLng = 113.44788;
 
@@ -1082,6 +1103,77 @@ public class EquipPipeSchedulingServiceImpl extends ServiceImpl<EquipPipeSchedul
                         pipesRespVO.setPipeCount(pipesRespVO.getPipes().size());
                     }
                 }
+
+                // 批量查询拒检记录,按检验类型分别建 Map
+                List<String> pipeDetailIds = equipPipePlanSchedulingVOS.stream()
+                        .map(EquipPipePlanSchedulingVO::getId)
+                        .filter(Objects::nonNull)
+                        .distinct()
+                        .toList();
+
+                if (!pipeDetailIds.isEmpty()) {
+                    List<AppointmentConfirmOrderRefuseItemDO> refuseItems = appointmentConfirmOrderRefuseItemMapper.selectList(
+                            new LambdaQueryWrapperX<AppointmentConfirmOrderRefuseItemDO>()
+                                    .in(AppointmentConfirmOrderRefuseItemDO::getEquipId, pipeDetailIds));
+
+                    // 按检验类型分别建立 Map: checkType=100(定期), checkType=200(年度)
+                    Map<String, AppointmentConfirmOrderRefuseItemDO> legalRefuseMap = new HashMap<>(); // 定期检验 100
+                    Map<String, AppointmentConfirmOrderRefuseItemDO> yearRefuseMap = new HashMap<>();   // 年度检查 200
+                    if (refuseItems != null && !refuseItems.isEmpty()) {
+                        for (AppointmentConfirmOrderRefuseItemDO refuseItem : refuseItems) {
+                            if (refuseItem.getEquipId() == null) continue;
+                            if (Integer.valueOf(100).equals(refuseItem.getCheckType())) {
+                                legalRefuseMap.putIfAbsent(refuseItem.getEquipId(), refuseItem);
+                            } else if (Integer.valueOf(200).equals(refuseItem.getCheckType())) {
+                                yearRefuseMap.putIfAbsent(refuseItem.getEquipId(), refuseItem);
+                            }
+                        }
+                    }
+
+                    // 为每个子管线填充拒检信息(分别取定期和年度)
+                    for (EquipPipePlanSchedulingVO pipe : equipPipePlanSchedulingVOS) {
+                        if (pipe.getId() == null) continue;
+                        AppointmentConfirmOrderRefuseItemDO legalRefuse = legalRefuseMap.get(pipe.getId());
+                        AppointmentConfirmOrderRefuseItemDO yearRefuse = yearRefuseMap.get(pipe.getId());
+                        if (legalRefuse != null) {
+                            pipe.setLegalRefuseReasonDict(legalRefuse.getReasonDict());
+                        }
+                        if (yearRefuse != null) {
+                            pipe.setYearRefuseReasonDict(yearRefuse.getReasonDict());
+                        }
+                        // 保留兼容字段(优先定期)
+                        AppointmentConfirmOrderRefuseItemDO refuse = legalRefuse != null ? legalRefuse : yearRefuse;
+                        if (refuse != null) {
+                            pipe.setRefuseReasonDict(refuse.getReasonDict());
+                            pipe.setRefuseCheckType(refuse.getCheckType());
+                        }
+                    }
+
+                    // 为每个父行计算 allLegalRefused 和 allYearRefused
+                    for (EquipPipeSchedulingPipesRespVO parent : list) {
+                        List<EquipPipePlanSchedulingVO> pipes = parent.getPipes();
+                        if (pipes == null || pipes.isEmpty()) {
+                            parent.setAllLegalRefused(false);
+                            parent.setAllYearRefused(false);
+                            continue;
+                        }
+                        parent.setAllLegalRefused(pipes.stream().allMatch(p -> legalRefuseMap.containsKey(p.getId())));
+                        parent.setAllYearRefused(pipes.stream().allMatch(p -> yearRefuseMap.containsKey(p.getId())));
+
+                        // 取第一条有拒检记录的子管线的拒检原因作为父级展示
+                        if (Boolean.TRUE.equals(parent.getAllLegalRefused()) || Boolean.TRUE.equals(parent.getAllYearRefused())) {
+                            for (EquipPipePlanSchedulingVO pipe : pipes) {
+                                AppointmentConfirmOrderRefuseItemDO refuse = legalRefuseMap.get(pipe.getId());
+                                if (refuse == null) refuse = yearRefuseMap.get(pipe.getId());
+                                if (refuse != null) {
+                                    parent.setRefuseReasonDict(refuse.getReasonDict());
+                                    parent.setRefuseReason(refuse.getReason());
+                                    break;
+                                }
+                            }
+                        }
+                    }
+                }
             }
         }
 
@@ -2109,4 +2201,101 @@ public class EquipPipeSchedulingServiceImpl extends ServiceImpl<EquipPipeSchedul
         };
     }
 
+    @Override
+    public List<PipeRefuseItemResultVO> refuseItem(PipeRefuseItemReqVO reqVO) {
+        List<PipeRefuseItemResultVO> results = new ArrayList<>();
+
+        if (reqVO.getEquipDetailIds() == null || reqVO.getEquipDetailIds().isEmpty()) {
+            return results;
+        }
+
+        List<EquipPipeDetailDO> equipPipeDetailDOS = equipPipeDetailMapper.selectByIds(reqVO.getEquipDetailIds());
+        List<DictDataRespDTO> checkTypeDTOS = dictDataApi.getDictDataList("pressure_inspection_nature_pipe").getData();
+        List<DictDataRespDTO> pipeStatusDTOS = dictDataApi.getDictDataList("PIPE_USE_STATUS").getData();
+
+        for (EquipPipeDetailDO pipeDetail : equipPipeDetailDOS) {
+            try {
+
+                if (pipeDetail == null) {
+                    results.add(PipeRefuseItemResultVO.fail("", null, "管道明细信息不存在"));
+                    continue;
+                }
+
+                String projectNo = pipeDetail.getProjectNo();
+
+                // 检查是否已在拒检池中(审核中状态,匹配对应检验类型)
+                LambdaQueryWrapperX<AppointmentConfirmOrderRefuseItemDO> query = new LambdaQueryWrapperX<>();
+                query.eq(AppointmentConfirmOrderRefuseItemDO::getEquipId, pipeDetail.getId());
+                query.eq(AppointmentConfirmOrderRefuseItemDO::getCheckType, reqVO.getCheckType());
+                query.in(AppointmentConfirmOrderRefuseItemDO::getStatus, List.of(0, 1));
+                List<AppointmentConfirmOrderRefuseItemDO> existingItems = appointmentConfirmOrderRefuseItemMapper.selectList(query);
+                if (CollUtil.isNotEmpty(existingItems)) {
+                    results.add(PipeRefuseItemResultVO.fail(pipeDetail.getId(), projectNo, "该管道已在拒检池中,状态为【审核中】,请处理后再进行设备上报"));
+                    continue;
+                }
+
+                // 获取父级工程信息
+                EquipPipeDO equipPipe = equipPipeMapper.selectById(pipeDetail.getEquipPipeId());
+
+                // 创建拒检记录
+                AppointmentConfirmOrderRefuseItemDO refuseItem = new AppointmentConfirmOrderRefuseItemDO();
+                refuseItem.setEquipId(pipeDetail.getId());
+                refuseItem.setCheckType(reqVO.getCheckType());
+                Integer checkType = reqVO.getCheckType();
+                if (CollUtil.isNotEmpty(checkTypeDTOS)){
+                    String checkTypeName = checkTypeDTOS.stream()
+                            .filter(dict -> dict.getValue().equals(checkType.toString()))
+                            .map(DictDataRespDTO::getLabel)
+                            .findFirst()
+                            .orElse("");
+                    refuseItem.setCheckTypeName(checkTypeName);
+                }
+                refuseItem.setReasonDict(reqVO.getReasonDict());
+                refuseItem.setReason(reqVO.getReason());
+                refuseItem.setEquipCode(projectNo);
+                refuseItem.setEquipMainType(300); // 300=管道
+                refuseItem.setStatus(0);
+                refuseItem.setRejectionSource(1); // 1=窗口约检
+
+                refuseItem.setSubmitId(getLoginUserId());
+                refuseItem.setSubmitTime(LocalDateTime.now());
+
+                if (equipPipe != null) {
+
+                    refuseItem.setProductNo(pipeDetail.getProjectNo());
+                    refuseItem.setEquipCode(pipeDetail.getPipeRegCode());
+                    refuseItem.setUseRegisterNo(pipeDetail.getCertificateNo());
+
+                    refuseItem.setUseRegisterNo(equipPipe.getCertificateNo());
+                    refuseItem.setEquipDistrict(equipPipe.getEquipDistrict());
+                    refuseItem.setEquipStreet(equipPipe.getEquipStreet());
+                    refuseItem.setEquipType(equipPipe.getPipeCategory());
+                    refuseItem.setUnitCode(equipPipe.getUnitCode());
+                    refuseItem.setUnitName(equipPipe.getUnitName());
+                    refuseItem.setEquipStatus(equipPipe.getUseStatus());
+                    if (CollUtil.isNotEmpty(pipeStatusDTOS)){
+                        String equipStatusName = pipeStatusDTOS.stream()
+                                .filter(dict -> dict.getValue().equals(equipPipe.getUseStatus()))
+                                .map(DictDataRespDTO::getLabel)
+                                .findFirst()
+                                .orElse("");
+                        refuseItem.setEquipStatusName(equipStatusName);
+                    }
+                    refuseItem.setContact(equipPipe.getContact());
+                    refuseItem.setContactPhone(equipPipe.getContactPhone());
+                }
+
+                appointmentConfirmOrderRefuseItemMapper.insert(refuseItem);
+
+                results.add(PipeRefuseItemResultVO.success(pipeDetail.getId(), projectNo));
+
+            } catch (Exception e) {
+                assert pipeDetail != null;
+                log.error("[refuseItem] 管道设备上报失败, equipDetailId={}", pipeDetail.getId(), e);
+                results.add(PipeRefuseItemResultVO.fail(pipeDetail.getId(), null, "处理失败: " + e.getMessage()));
+            }
+        }
+
+        return results;
+    }
 }