Jelajahi Sumber

Merge remote-tracking branch 'origin/dev' into dev

liyuhui_ex 1 Minggu lalu
induk
melakukan
15b3802777
30 mengubah file dengan 733 tambahan dan 85 penghapusan
  1. 14 1
      build-uat/update.sql
  2. 2 0
      tz-module-pressure2/tz-module-pressure2-biz/src/main/java/cn/start/tz/module/pressure2/controller/admin/taskordernontaxapply/vo/TaskOrderNonTaxApplyRespVO.java
  3. 3 0
      tz-module-pressure2/tz-module-pressure2-biz/src/main/java/cn/start/tz/module/pressure2/controller/admin/taskordernontaxapply/vo/TaskOrderPaymentPageReqVO.java
  4. 3 0
      tz-module-pressure2/tz-module-pressure2-biz/src/main/java/cn/start/tz/module/pressure2/controller/admin/taskordernontaxapply/vo/TaskOrderPaymentRespVO.java
  5. 7 0
      tz-module-pressure2/tz-module-pressure2-biz/src/main/java/cn/start/tz/module/pressure2/dal/dataobject/boilertaskorder/BoilerTaskOrderDO.java
  6. 7 0
      tz-module-pressure2/tz-module-pressure2-biz/src/main/java/cn/start/tz/module/pressure2/dal/dataobject/pipetaskorder/PipeTaskOrderDO.java
  7. 58 0
      tz-module-pressure2/tz-module-pressure2-biz/src/main/java/cn/start/tz/module/pressure2/framework/cron/UpdateNonTaxPaymentStatusJob.java
  8. 1 1
      tz-module-pressure2/tz-module-pressure2-biz/src/main/java/cn/start/tz/module/pressure2/mq/consumer/FsPayNoticeConsumer.java
  9. 32 60
      tz-module-pressure2/tz-module-pressure2-biz/src/main/java/cn/start/tz/module/pressure2/service/appointmentconfirmorder/AppointmentConfirmOrderServiceImpl.java
  10. 15 2
      tz-module-pressure2/tz-module-pressure2-biz/src/main/java/cn/start/tz/module/pressure2/service/appointmentconfirmorder/PipeAppointmentConfirmOrderServiceImpl.java
  11. 2 2
      tz-module-pressure2/tz-module-pressure2-biz/src/main/java/cn/start/tz/module/pressure2/service/boilertaskorder/BoilerTaskOrderServiceImpl.java
  12. 29 2
      tz-module-pressure2/tz-module-pressure2-biz/src/main/java/cn/start/tz/module/pressure2/service/boilertaskorderitemreport/BoilerTaskOrderItemReportServiceImpl.java
  13. 34 8
      tz-module-pressure2/tz-module-pressure2-biz/src/main/java/cn/start/tz/module/pressure2/service/pipetaskorderitemreport/PipeTaskOrderItemReportServiceImpl.java
  14. 8 0
      tz-module-pressure2/tz-module-pressure2-biz/src/main/java/cn/start/tz/module/pressure2/service/taskordernontaxapply/TaskOrderNonTaxApplyServiceImpl.java
  15. 2 0
      tz-module-pressure2/tz-module-pressure2-biz/src/main/java/cn/start/tz/module/pressure2/service/taskordernontaxrecord/TaskOrderNonTaxRecordService.java
  16. 135 2
      tz-module-pressure2/tz-module-pressure2-biz/src/main/java/cn/start/tz/module/pressure2/service/taskordernontaxrecord/TaskOrderNonTaxRecordServiceImpl.java
  17. 7 0
      tz-module-pressure2/tz-module-pressure2-biz/src/main/resources/mapper/taskordernontaxapply/TaskOrderLeftJoinMapper.xml
  18. 1 0
      tz-module-pressure2/tz-module-pressure2-biz/src/main/resources/mapper/taskordernontaxapply/TaskOrderNonTaxApplyMapper.xml
  19. 2 1
      tz-module-system/tz-module-system-api/src/main/java/cn/start/tz/module/system/enums/ErrorCodeConstants.java
  20. 26 0
      tz-module-system/tz-module-system-biz/src/main/java/cn/start/tz/module/system/controller/admin/dept/DeptController.java
  21. 46 0
      tz-module-system/tz-module-system-biz/src/main/java/cn/start/tz/module/system/controller/admin/dept/vo/dept/DeptImportExcelVO.java
  22. 26 0
      tz-module-system/tz-module-system-biz/src/main/java/cn/start/tz/module/system/controller/admin/dept/vo/dept/DeptImportRespVO.java
  23. 17 0
      tz-module-system/tz-module-system-biz/src/main/java/cn/start/tz/module/system/controller/admin/user/UserController.java
  24. 28 0
      tz-module-system/tz-module-system-biz/src/main/java/cn/start/tz/module/system/controller/admin/user/vo/user/UserRoleImportExcelVO.java
  25. 26 0
      tz-module-system/tz-module-system-biz/src/main/java/cn/start/tz/module/system/controller/admin/user/vo/user/UserRoleImportRespVO.java
  26. 4 0
      tz-module-system/tz-module-system-biz/src/main/java/cn/start/tz/module/system/dal/mysql/dept/DeptMapper.java
  27. 10 0
      tz-module-system/tz-module-system-biz/src/main/java/cn/start/tz/module/system/service/dept/DeptService.java
  28. 95 0
      tz-module-system/tz-module-system-biz/src/main/java/cn/start/tz/module/system/service/dept/DeptServiceImpl.java
  29. 12 0
      tz-module-system/tz-module-system-biz/src/main/java/cn/start/tz/module/system/service/user/AdminUserService.java
  30. 81 6
      tz-module-system/tz-module-system-biz/src/main/java/cn/start/tz/module/system/service/user/AdminUserServiceImpl.java

+ 14 - 1
build-uat/update.sql

@@ -1537,4 +1537,17 @@ COMMENT ON COLUMN "PRESSURE2_BOILER_TASK_ORDER_ITEM_REPORT"."CONFIRMATION_TIME"
 ALTER TABLE "SYSTEM_OAUTH2_REFRESH_TOKEN" MODIFY "REFRESH_TOKEN" VARCHAR(36 CHAR) NOT NULL;
 ALTER TABLE "SYSTEM_OAUTH2_ACCESS_TOKEN" MODIFY "REFRESH_TOKEN" VARCHAR(36 CHAR) NOT NULL;
 
---已加
+--已加
+
+--20260603
+ALTER TABLE "PRESSURE_TASK_ORDER" ADD COLUMN "NO_TAX_PAYMENT_STATUS" INT DEFAULT (0);
+ALTER TABLE "PRESSURE_TASK_ORDER" ADD COLUMN "NO_TAX_PAY_TIME" DATETIME(6);
+COMMENT ON COLUMN "PRESSURE_TASK_ORDER"."NO_TAX_PAYMENT_STATUS" IS '非税缴费状态(0=待缴费,1=已缴费)';
+COMMENT ON COLUMN "PRESSURE_TASK_ORDER"."NO_TAX_PAY_TIME" IS '非税缴费时间';
+--已加
+
+ALTER TABLE "PRESSURE_TASK_ORDER" ADD COLUMN "IS_SYNC" VARCHAR(50);
+COMMENT ON COLUMN "PRESSURE_TASK_ORDER"."IS_SYNC" IS '是否是同步数据';
+
+INSERT INTO "INFRA_CONFIG" ("ID","CATEGORY","TYPE","NAME","CONFIG_KEY","VALUE","VISIBLE","REMARK","CREATOR","CREATE_TIME","UPDATER","UPDATE_TIME","DELETED" ) VALUES ('f4f25ba4fa087abf9c67d75ba4a6c0ab','定时任务开关','2','是否定时查询非税记录的缴费状态并更新','is_enable_update_no_tax_status','false',1,'true:开启 false:关闭','1','2026-06-02 18:40:46','1','2026-06-02 19:05:59',0);
+-- 已加

+ 2 - 0
tz-module-pressure2/tz-module-pressure2-biz/src/main/java/cn/start/tz/module/pressure2/controller/admin/taskordernontaxapply/vo/TaskOrderNonTaxApplyRespVO.java

@@ -147,4 +147,6 @@ public class TaskOrderNonTaxApplyRespVO {
     @ExcelProperty("申请记录")
     private String recordId;
 
+    private BigDecimal reductionRadio;
+
 }

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

@@ -34,6 +34,9 @@ public class TaskOrderPaymentPageReqVO extends PageParam {
     @Schema(description = "缴费状态(0=待缴费,1=已缴费)", example = "2")
     private Integer paymentStatus;
 
+    @Schema(description = "非税缴费状态(0=待缴费,1=已缴费)", example = "2")
+    private Integer noTaxPaymentStatus;
+
     @Schema(description = "跟进人id")
     private String followId;
 

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

@@ -71,6 +71,9 @@ public class TaskOrderPaymentRespVO implements Serializable {
     @Schema(description = "缴费状态(0=待缴费,1=已缴费)")
     private Integer paymentStatus;
 
+    @Schema(description = "非税缴费状态(0=待缴费,1=已缴费)")
+    private Integer noTaxPaymentStatus;
+
     @Schema(description = "跟进人id")
     private String followId;
 

+ 7 - 0
tz-module-pressure2/tz-module-pressure2-biz/src/main/java/cn/start/tz/module/pressure2/dal/dataobject/boilertaskorder/BoilerTaskOrderDO.java

@@ -332,4 +332,11 @@ public class BoilerTaskOrderDO extends BaseDO {
      * 企业类型
      */
     private String enterpriseType;
+
+    /**
+     * 非税缴费状态(0=待缴费,1=已缴费)
+     */
+    private Integer noTaxPaymentStatus;
+
+    private LocalDateTime noTaxPayTime;
 }

+ 7 - 0
tz-module-pressure2/tz-module-pressure2-biz/src/main/java/cn/start/tz/module/pressure2/dal/dataobject/pipetaskorder/PipeTaskOrderDO.java

@@ -337,4 +337,11 @@ public class PipeTaskOrderDO extends BaseDO {
      */
     private String enterpriseType;
 
+    /**
+     * 非税缴费状态(0=待缴费,1=已缴费)
+     */
+    private Integer noTaxPaymentStatus;
+
+    private LocalDateTime noTaxPayTime;
+
 }

+ 58 - 0
tz-module-pressure2/tz-module-pressure2-biz/src/main/java/cn/start/tz/module/pressure2/framework/cron/UpdateNonTaxPaymentStatusJob.java

@@ -0,0 +1,58 @@
+package cn.start.tz.module.pressure2.framework.cron;
+
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.date.DateTime;
+import cn.hutool.core.date.DateUtil;
+import cn.start.tz.framework.mybatis.core.query.LambdaQueryWrapperX;
+import cn.start.tz.module.infra.api.config.ConfigApi;
+import cn.start.tz.module.pressure2.dal.dataobject.boilertaskorder.BoilerTaskOrderDO;
+import cn.start.tz.module.pressure2.dal.dataobject.taskordernontaxrecord.TaskOrderNonTaxRecordDO;
+import cn.start.tz.module.pressure2.dal.dataobject.taskordernontaxrecorditem.TaskOrderNonTaxRecordItemDO;
+import cn.start.tz.module.pressure2.service.synchronization.SynchronizationService;
+import cn.start.tz.module.pressure2.service.taskordernontaxrecord.TaskOrderNonTaxRecordService;
+import cn.start.tz.module.pressure2.service.thirdparty.financialsystem.vo.IncomepaymentData;
+import jakarta.annotation.Resource;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.stereotype.Component;
+
+import java.time.LocalDateTime;
+import java.util.List;
+
+/**
+ * 设备更新定时任务类
+ * 负责定期执行设备数据同步任务,包括锅炉和管道设备数据的更新
+ */
+@Component
+@Slf4j
+public class UpdateNonTaxPaymentStatusJob {
+
+    @Resource
+    private TaskOrderNonTaxRecordService taskOrderNonTaxRecordService;
+
+    @Resource
+    ConfigApi configApi;
+    /**
+     * 非税缴费状态查询定时任务
+     * 定时查询非税记录的缴费状态并更新 30分钟执行一次
+     */
+    @Scheduled(cron = "0 0/30 * * * ?")
+    public void execute() {
+        String enable = configApi.getConfigValueByKey("is_enable_update_no_tax_status").getCheckedData();
+        if (!"true".equals(enable)) {
+            return;
+        }
+        log.info("========== 开始执行非税缴费状态查询定时任务 ==========");
+        long startTime = System.currentTimeMillis();
+
+        try {
+            taskOrderNonTaxRecordService.queryAndUpdatePaymentStatus();
+        } catch (Exception e) {
+            log.error("非税缴费状态查询任务执行异常", e);
+        }
+
+        long endTime = System.currentTimeMillis();
+        log.info("========== 非税缴费状态查询任务完成,总耗时: {}ms ==========", endTime - startTime);
+    }
+
+}

+ 1 - 1
tz-module-pressure2/tz-module-pressure2-biz/src/main/java/cn/start/tz/module/pressure2/mq/consumer/FsPayNoticeConsumer.java

@@ -20,7 +20,7 @@ import org.springframework.stereotype.Component;
 @Component
 @RocketMQMessageListener(
         topic = "tjy_fs_pay_notice",
-        consumerGroup = "tjy_fs_pay_notice" + "_" + "${spring.profiles.active}"
+        consumerGroup = "tjy_fs_pay_notice" + "_pressure2_" + "${spring.profiles.active}"
 )
 @Slf4j
 public class FsPayNoticeConsumer implements RocketMQListener<FsPayNoticeMessage> {

+ 32 - 60
tz-module-pressure2/tz-module-pressure2-biz/src/main/java/cn/start/tz/module/pressure2/service/appointmentconfirmorder/AppointmentConfirmOrderServiceImpl.java

@@ -23,6 +23,7 @@ import cn.start.tz.module.member.api.templatesendlog.dto.TemplateSendLogDto;
 import cn.start.tz.module.member.api.templatesendlog.dto.TemplateSendLogRespDto;
 import cn.start.tz.module.pressure2.controller.admin.boilerorderexception.vo.BoilerOrderExceptionSaveReqVO;
 import cn.start.tz.module.pressure2.dal.dataobject.acceptorder.AcceptOrderDO;
+import cn.start.tz.module.pressure2.dal.mysql.equipboilerscheduling.EquipBoilerSchedulingMapper;
 import cn.start.tz.module.pressure2.enums.RedisKeyEnums;
 import cn.start.tz.module.pressure2.controller.admin.appointmentconfirmorder.vo.*;
 import cn.start.tz.module.pressure2.controller.app.appointmentconfirmorder.vo.AppAppointmentRefuseVO;
@@ -68,11 +69,13 @@ import cn.start.tz.module.system.api.dict.dto.DictDataRespDTO;
 import cn.start.tz.module.system.api.orgcontact.OrgContactApi;
 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 jakarta.annotation.Resource;
 import lombok.extern.slf4j.Slf4j;
 
 import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Lazy;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.validation.annotation.Validated;
@@ -180,6 +183,10 @@ public class AppointmentConfirmOrderServiceImpl implements AppointmentConfirmOrd
     @Resource
     private OrderReportService orderReportService;
 
+    @Resource
+    @Lazy
+    private EquipBoilerSchedulingMapper equipBoilerSchedulingMapper;
+
     @Override
     public String create(AppointmentConfirmOrderDO appointmentConfirmOrderDO) {
 
@@ -215,10 +222,10 @@ public class AppointmentConfirmOrderServiceImpl implements AppointmentConfirmOrd
         // 校验存在
         validateAppointmentConfirmOrderExists(updateReqVO.getId());
 
-        // 删除现有组员
-        appointmentConfirmOrderUserMapper.delete(BoilerAppointmentConfirmOrderUserDO::getOrderId, updateReqVO.getId());
-        List<BoilerAppointmentConfirmOrderUserDO> acceptOrderUserList = new ArrayList<>();
         if (CollUtil.isNotEmpty(updateReqVO.getTeamList())) {
+            // 删除现有组员
+            appointmentConfirmOrderUserMapper.delete(BoilerAppointmentConfirmOrderUserDO::getOrderId, updateReqVO.getId());
+            List<BoilerAppointmentConfirmOrderUserDO> acceptOrderUserList = new ArrayList<>();
             updateReqVO.getTeamList().forEach(team -> {
                 BoilerAppointmentConfirmOrderUserDO leader = new BoilerAppointmentConfirmOrderUserDO();
                 leader.setOrderId(updateReqVO.getId());
@@ -577,6 +584,28 @@ public class AppointmentConfirmOrderServiceImpl implements AppointmentConfirmOrd
                     eq(EquipBoilerSchedulingItemDO::getSchedulingId, appointmentConfirmOrderDO.getSchedulingId()).
                     in(EquipBoilerSchedulingItemDO::getEquipId, appointmentRefuseVO.getEquipIds())
             );
+            Long count = equipBoilerSchedulingItemMapper.selectCount(EquipBoilerSchedulingItemDO::getSchedulingId, appointmentConfirmOrderDO.getSchedulingId());
+            if (count == null || count == 0) {
+                equipBoilerSchedulingMapper.deleteById(appointmentConfirmOrderDO.getSchedulingId());
+            }
+
+            // 恢复设备状态
+            if (appointmentConfirmOrderDO.getCheckType() == 100){
+                equipBoilerMapper.update(new LambdaUpdateWrapper<EquipBoilerDO>().
+                        in(EquipBoilerDO::getId, appointmentRefuseVO.getEquipIds()).
+                        set(EquipBoilerDO::getHasInternal, false)
+                );
+            }else if (appointmentConfirmOrderDO.getCheckType() == 200){
+                equipBoilerMapper.update(new LambdaUpdateWrapper<EquipBoilerDO>().
+                        in(EquipBoilerDO::getId, appointmentRefuseVO.getEquipIds()).
+                        set(EquipBoilerDO::getHasExternal, false)
+                );
+            }else if (appointmentConfirmOrderDO.getCheckType() == 300){
+                equipBoilerMapper.update(new LambdaUpdateWrapper<EquipBoilerDO>().
+                        in(EquipBoilerDO::getId, appointmentRefuseVO.getEquipIds()).
+                        set(EquipBoilerDO::getHasPressure, false)
+                );
+            }
 
         }
         if (300 == appointmentRefuseVO.getType()) {
@@ -602,63 +631,6 @@ public class AppointmentConfirmOrderServiceImpl implements AppointmentConfirmOrd
             return;
         }
         // 拒绝检验
-/*        if(200 == appointmentRefuseVO.getType()){
-
-            List<AppointmentConfirmRefuseYearItemDO> list = equipContainerDOS.stream().map(item -> {
-                AppointmentConfirmRefuseYearItemDO appointmentConfirmOrderRefuseItemDO = new AppointmentConfirmRefuseYearItemDO();
-                appointmentConfirmOrderRefuseItemDO.setOrderId(appointmentRefuseVO.getOrderId());
-                appointmentConfirmOrderRefuseItemDO.setEquipId(item.getId());
-                if (appointmentRefuseVO.getCheckType() == 100 && item.getNextInCheckDate() != null) {
-                    appointmentConfirmOrderRefuseItemDO.setNextCheckDate(LocalDate.from(item.getNextInCheckDate()));
-                }
-                if (appointmentRefuseVO.getCheckType() == 200 && item.getNextOutCheckDate() != null) {
-                    appointmentConfirmOrderRefuseItemDO.setNextCheckDate(LocalDate.from(item.getNextOutCheckDate()));
-                }
-                if (appointmentRefuseVO.getCheckType() == 300 && item.getNextPressureCheckDate() != null) {
-                    appointmentConfirmOrderRefuseItemDO.setNextCheckDate(LocalDate.from(item.getNextPressureCheckDate()));
-                }
-                appointmentConfirmOrderRefuseItemDO.setUnitCode(item.getUnitCode());
-                appointmentConfirmOrderRefuseItemDO.setUnitName(item.getUnitName());
-                appointmentConfirmOrderRefuseItemDO.setCheckType(appointmentRefuseVO.getCheckType());
-                appointmentConfirmOrderRefuseItemDO.setOrderNo(appointmentRefuseVO.getOrderNo());
-                appointmentConfirmOrderRefuseItemDO.setSubmitId(getLoginUserId());
-                appointmentConfirmOrderRefuseItemDO.setSubmitTime(LocalDateTime.now());
-                appointmentConfirmOrderRefuseItemDO.setReasonDict(appointmentRefuseVO.getReasonDict());
-                //appointmentConfirmOrderRefuseItemDO.setBeDistrict(item.getBeDistrict());
-                //appointmentConfirmOrderRefuseItemDO.setEquipType(item.getEquipType());
-
-                if (appointmentConfirmOrderDO != null) {
-                    appointmentConfirmOrderRefuseItemDO.setCheckDate(appointmentConfirmOrderDO.getAppointmentDate());
-                    appointmentConfirmOrderRefuseItemDO.setOrderNo(appointmentConfirmOrderDO.getAppointmentNo());
-                }
-
-                appointmentConfirmOrderRefuseItemDO.setReason(appointmentRefuseVO.getReason());
-                return appointmentConfirmOrderRefuseItemDO;
-            }).toList();
-
-            appointmentConfirmRefuseYearItemMapper.insert(list);
-
-            appointmentConfirmOrderItemMapper.delete(new LambdaQueryWrapperX<BoilerAppointmentConfirmOrderItemDO>().
-                    eq(BoilerAppointmentConfirmOrderItemDO::getOrderId, appointmentRefuseVO.getOrderId()).
-                    in(BoilerAppointmentConfirmOrderItemDO::getEquipId, appointmentRefuseVO.getEquipIds())
-            );
-
-            if (StringUtils.isNotBlank(appointmentRefuseVO.getOrderId())) {
-                Long count = appointmentConfirmOrderItemMapper.selectCount(BoilerAppointmentConfirmOrderItemDO::getOrderId, appointmentRefuseVO.getOrderId());
-                AppointmentConfirmOrderDO updateOrder = new AppointmentConfirmOrderDO();
-                updateOrder.setId(appointmentRefuseVO.getOrderId());
-                if (count == null || count == 0) {
-                    updateOrder.setStatus(500);
-                    updateOrder.setEquipNumBoiler(0);
-                }
-                if (count != null){
-                    updateOrder.setEquipNumBoiler(Math.toIntExact(count));
-                }
-                appointmentConfirmOrderMapper.updateById(updateOrder);
-            }
-
-            return ;
-        }*/
 
         Map<String, Object> processInstanceVariables = new HashMap<>();
 

+ 15 - 2
tz-module-pressure2/tz-module-pressure2-biz/src/main/java/cn/start/tz/module/pressure2/service/appointmentconfirmorder/PipeAppointmentConfirmOrderServiceImpl.java

@@ -90,6 +90,7 @@ import cn.start.tz.module.system.api.orgcontact.OrgContactApi;
 import cn.start.tz.module.system.api.orgcontact.dto.OrgContactDTO;
 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 jakarta.annotation.Resource;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.lang3.StringUtils;
@@ -263,9 +264,9 @@ public class PipeAppointmentConfirmOrderServiceImpl implements PipeAppointmentCo
 //        }
 
         // 删除现有组员
-        pipeAppointmentConfirmOrderUserMapper.delete(PipeAppointmentConfirmOrderUserDO::getOrderId, updateReqVO.getId());
-        List<PipeAppointmentConfirmOrderUserDO> acceptOrderUserList = new ArrayList<>();
         if (CollUtil.isNotEmpty(updateReqVO.getTeamList())) {
+            pipeAppointmentConfirmOrderUserMapper.delete(PipeAppointmentConfirmOrderUserDO::getOrderId, updateReqVO.getId());
+            List<PipeAppointmentConfirmOrderUserDO> acceptOrderUserList = new ArrayList<>();
             updateReqVO.getTeamList().forEach(team -> {
                 PipeAppointmentConfirmOrderUserDO leader = new PipeAppointmentConfirmOrderUserDO();
                 leader.setOrderId(updateReqVO.getId());
@@ -633,6 +634,18 @@ public class PipeAppointmentConfirmOrderServiceImpl implements PipeAppointmentCo
                 equipPipeSchedulingMapper.deleteById(appointmentConfirmOrderDO.getSchedulingId());
             }
 
+            if (appointmentConfirmOrderDO.getCheckType() == 100) {
+                equipPipeDetailMapper.update(new LambdaUpdateWrapper<EquipPipeDetailDO>().
+                        in(EquipPipeDetailDO::getId, equipDetailIds).
+                        set(EquipPipeDetailDO::getHasLegalScheduling, false)
+                );
+            } else if (appointmentConfirmOrderDO.getCheckType() == 200) {
+                equipPipeDetailMapper.update(new LambdaUpdateWrapper<EquipPipeDetailDO>().
+                        in(EquipPipeDetailDO::getId, equipDetailIds).
+                        set(EquipPipeDetailDO::getHasYearScheduling, false)
+                );
+            }
+
         }
 
         if (300 == appointmentRefuseVO.getType()) {

+ 2 - 2
tz-module-pressure2/tz-module-pressure2-biz/src/main/java/cn/start/tz/module/pressure2/service/boilertaskorder/BoilerTaskOrderServiceImpl.java

@@ -6478,8 +6478,8 @@ public class BoilerTaskOrderServiceImpl extends ServiceImpl<BoilerTaskOrderMappe
             }
             BoilerTaskOrderDO updateOrder = new BoilerTaskOrderDO();
             updateOrder.setId(item.getOrderId());
-            updateOrder.setPaymentStatus(1);
-            updateOrder.setPayTime(updateRecord.getPayDate());
+            updateOrder.setNoTaxPaymentStatus(1);
+            updateOrder.setNoTaxPayTime(updateRecord.getPayDate());
             boilerTaskOrderMapper.updateById(updateOrder);
         }
 

+ 29 - 2
tz-module-pressure2/tz-module-pressure2-biz/src/main/java/cn/start/tz/module/pressure2/service/boilertaskorderitemreport/BoilerTaskOrderItemReportServiceImpl.java

@@ -20,6 +20,7 @@ import cn.start.tz.module.pressure2.dal.dataobject.boilertaskorderitemreportreco
 import cn.start.tz.module.pressure2.dal.dataobject.equipboiler.EquipBoilerDO;
 import cn.start.tz.module.pressure2.dal.dataobject.equipboilercheckhistory.EquipBoilerCheckHistoryDO;
 import cn.start.tz.module.pressure2.dal.dataobject.boilertaskorderitemreport.BoilerTaskOrderItemReportDO;
+import cn.start.tz.module.pressure2.dal.dataobject.pipetaskorderitemreport.PipeTaskOrderItemReportDO;
 import cn.start.tz.module.pressure2.dal.dataobject.reporttemplate.ReportTemplateDO;
 import cn.start.tz.module.pressure2.dal.mysql.boilertaskorder.BoilerTaskOrderMapper;
 import cn.start.tz.module.pressure2.dal.mysql.boilertaskorderitem.BoilerTaskOrderItemMapper;
@@ -533,12 +534,25 @@ public class BoilerTaskOrderItemReportServiceImpl extends ServiceImpl<BoilerTask
                 .max(Comparator.comparing(ExternalOACommentInfoRes::getCreateDate))
                 .ifPresent(approval -> {
                     List<AdminUserRespDTO> userList = adminUserApi.getUserListByNickname(approval.getUserName()).getCheckedData();
+                    if (userList.isEmpty()) {
+                        AdminUserRespDTO checkedData = adminUserApi.getUserByEmployeeNo(approval.getUserName()).getCheckedData();
+                        if (checkedData == null) {
+                            if (userList.isEmpty()) {
+                                AdminUserRespDTO checkedData1 = adminUserApi.getUserByEmployeeNo(approval.getUserCode()).getCheckedData();
+                                if (checkedData1 != null) {
+                                    userList.add(checkedData1);
+                                }
+                            }
+                        } else {
+                            userList.add(checkedData);
+                        }
+                    }
                     if (!userList.isEmpty()) {
                         reportUpdateWrapper.set(BoilerTaskOrderItemReportDO::getApprovalId, userList.get(0).getId());
                         reportUpdateWrapper.set(BoilerTaskOrderItemReportDO::getApprovalTime, approval.getCreateDate());
-                        reportUpdateWrapper.set(BoilerTaskOrderItemReportDO::getTaskStatus, TaskOrderStatusEnum.REPORT_RATIFY.getStatus());
-                        needUpdateReport.set(true);
                     }
+                    reportUpdateWrapper.set(BoilerTaskOrderItemReportDO::getTaskStatus, TaskOrderStatusEnum.REPORT_RATIFY.getStatus());
+                    needUpdateReport.set(true);
                 });
 
         // 找最新的"审批人员"节点的【同意】或【已阅】评论
@@ -551,6 +565,19 @@ public class BoilerTaskOrderItemReportServiceImpl extends ServiceImpl<BoilerTask
                 .max(Comparator.comparing(ExternalOACommentInfoRes::getCreateDate))
                 .ifPresent(ratify -> {
                     List<AdminUserRespDTO> userList = adminUserApi.getUserListByNickname(ratify.getUserName()).getCheckedData();
+                    if (userList.isEmpty()) {
+                        AdminUserRespDTO checkedData = adminUserApi.getUserByEmployeeNo(ratify.getUserName()).getCheckedData();
+                        if (checkedData == null) {
+                            if (userList.isEmpty()) {
+                                AdminUserRespDTO checkedData1 = adminUserApi.getUserByEmployeeNo(ratify.getUserCode()).getCheckedData();
+                                if (checkedData1 != null) {
+                                    userList.add(checkedData1);
+                                }
+                            }
+                        } else {
+                            userList.add(checkedData);
+                        }
+                    }
                     if (!userList.isEmpty()) {
                         reportUpdateWrapper.set(BoilerTaskOrderItemReportDO::getRatifyId, userList.get(0).getId());
                         reportUpdateWrapper.set(BoilerTaskOrderItemReportDO::getRatifyTime, ratify.getCreateDate());

+ 34 - 8
tz-module-pressure2/tz-module-pressure2-biz/src/main/java/cn/start/tz/module/pressure2/service/pipetaskorderitemreport/PipeTaskOrderItemReportServiceImpl.java

@@ -320,12 +320,25 @@ public class PipeTaskOrderItemReportServiceImpl extends ServiceImpl<PipeTaskOrde
                 .max(Comparator.comparing(ExternalOACommentInfoRes::getCreateDate))
                 .ifPresent(approval -> {
                     List<AdminUserRespDTO> userList = adminUserApi.getUserListByNickname(approval.getUserName()).getCheckedData();
+                    if (userList.isEmpty()) {
+                        AdminUserRespDTO checkedData = adminUserApi.getUserByEmployeeNo(approval.getUserName()).getCheckedData();
+                        if (checkedData == null) {
+                            if (userList.isEmpty()) {
+                                AdminUserRespDTO checkedData1 = adminUserApi.getUserByEmployeeNo(approval.getUserCode()).getCheckedData();
+                                if (checkedData1 != null) {
+                                    userList.add(checkedData1);
+                                }
+                            }
+                        } else {
+                            userList.add(checkedData);
+                        }
+                    }
                     if (!userList.isEmpty()) {
                         reportUpdateWrapper.set(PipeTaskOrderItemReportDO::getApprovalId, userList.get(0).getId());
                         reportUpdateWrapper.set(PipeTaskOrderItemReportDO::getApprovalTime, approval.getCreateDate());
-                        reportUpdateWrapper.set(PipeTaskOrderItemReportDO::getTaskStatus, TaskOrderStatusEnum.REPORT_RATIFY.getStatus());
-                        needUpdateReport.set(true);
                     }
+                    reportUpdateWrapper.set(PipeTaskOrderItemReportDO::getTaskStatus, TaskOrderStatusEnum.REPORT_RATIFY.getStatus());
+                    needUpdateReport.set(true);
                 });
 
         // 找最新的"审批人员"节点的【同意】或【已阅】评论
@@ -338,6 +351,19 @@ public class PipeTaskOrderItemReportServiceImpl extends ServiceImpl<PipeTaskOrde
                 .max(Comparator.comparing(ExternalOACommentInfoRes::getCreateDate))
                 .ifPresent(ratify -> {
                     List<AdminUserRespDTO> userList = adminUserApi.getUserListByNickname(ratify.getUserName()).getCheckedData();
+                    if (userList.isEmpty()) {
+                        AdminUserRespDTO checkedData = adminUserApi.getUserByEmployeeNo(ratify.getUserName()).getCheckedData();
+                        if (checkedData == null) {
+                            if (userList.isEmpty()) {
+                                AdminUserRespDTO checkedData1 = adminUserApi.getUserByEmployeeNo(ratify.getUserCode()).getCheckedData();
+                                if (checkedData1 != null) {
+                                    userList.add(checkedData1);
+                                }
+                            }
+                        } else {
+                            userList.add(checkedData);
+                        }
+                    }
                     if (!userList.isEmpty()) {
                         reportUpdateWrapper.set(PipeTaskOrderItemReportDO::getRatifyId, userList.get(0).getId());
                         reportUpdateWrapper.set(PipeTaskOrderItemReportDO::getRatifyTime, ratify.getCreateDate());
@@ -504,13 +530,13 @@ public class PipeTaskOrderItemReportServiceImpl extends ServiceImpl<PipeTaskOrde
                     .orElse(null);
 
             if (approval != null) {
-                if (approval.getUserCode() != null){
+                if (approval.getUserCode() != null) {
                     AdminUserRespDTO userRespDTO = adminUserApi.getUserByEmployeeNo(approval.getUserCode()).getCheckedData();
                     if (userRespDTO != null) {
                         approvalId = userRespDTO.getId();
                         approvalName = userRespDTO.getNickname();
                         approvalTime = approval.getCreateDate();
-                    }else {
+                    } else {
                         List<AdminUserRespDTO> userListByNickname = adminUserApi.getUserListByNickname(approval.getUserName()).getCheckedData();
                         if (!userListByNickname.isEmpty()) {
                             AdminUserRespDTO approvalUser = userListByNickname.get(0);
@@ -519,7 +545,7 @@ public class PipeTaskOrderItemReportServiceImpl extends ServiceImpl<PipeTaskOrde
                             approvalTime = approval.getCreateDate();
                         }
                     }
-                }else {
+                } else {
                     List<AdminUserRespDTO> userListByNickname = adminUserApi.getUserListByNickname(approval.getUserName()).getCheckedData();
                     if (!userListByNickname.isEmpty()) {
                         AdminUserRespDTO approvalUser = userListByNickname.get(0);
@@ -531,13 +557,13 @@ public class PipeTaskOrderItemReportServiceImpl extends ServiceImpl<PipeTaskOrde
             }
 
             if (ratify != null) {
-                if (ratify.getUserCode() != null){
+                if (ratify.getUserCode() != null) {
                     AdminUserRespDTO userRespDTO = adminUserApi.getUserByEmployeeNo(ratify.getUserCode()).getCheckedData();
                     if (userRespDTO != null) {
                         ratifyId = userRespDTO.getId();
                         ratifyName = userRespDTO.getNickname();
                         ratifyTime = ratify.getCreateDate();
-                    }else {
+                    } else {
                         List<AdminUserRespDTO> userListByNickname = adminUserApi.getUserListByNickname(ratify.getUserName()).getCheckedData();
                         if (!userListByNickname.isEmpty()) {
                             AdminUserRespDTO ratifyUser = userListByNickname.get(0);
@@ -546,7 +572,7 @@ public class PipeTaskOrderItemReportServiceImpl extends ServiceImpl<PipeTaskOrde
                             ratifyTime = ratify.getCreateDate();
                         }
                     }
-                }else {
+                } else {
                     List<AdminUserRespDTO> userListByNickname = adminUserApi.getUserListByNickname(ratify.getUserName()).getCheckedData();
                     if (!userListByNickname.isEmpty()) {
                         AdminUserRespDTO ratifyUser = userListByNickname.get(0);

+ 8 - 0
tz-module-pressure2/tz-module-pressure2-biz/src/main/java/cn/start/tz/module/pressure2/service/taskordernontaxapply/TaskOrderNonTaxApplyServiceImpl.java

@@ -277,6 +277,14 @@ public class TaskOrderNonTaxApplyServiceImpl extends ServiceImpl<TaskOrderNonTax
                 item.setRegstateCn(regstateCnMap.get(item.getUnitCode()));
             }
 
+            //应收金额计算减免比例
+            BigDecimal reduceRadioFee = item.getShouldAmount();
+            if (item.getReductionRadio() != null){
+                double v = 1 - item.getReductionRadio().doubleValue();
+                reduceRadioFee = reduceRadioFee.multiply(new BigDecimal(v)).setScale(2, RoundingMode.HALF_UP);
+                item.setShouldAmount(reduceRadioFee);
+            }
+
         });
 
         return pageResult;

+ 2 - 0
tz-module-pressure2/tz-module-pressure2-biz/src/main/java/cn/start/tz/module/pressure2/service/taskordernontaxrecord/TaskOrderNonTaxRecordService.java

@@ -80,4 +80,6 @@ public interface TaskOrderNonTaxRecordService extends IService<TaskOrderNonTaxRe
     Boolean sendNonTaxPaymentEmail(String id, String email);
 
     Boolean nonTaxPayStatus(NonTaxPayStatusDTO nonTaxPayStatusDTO);
+
+    void queryAndUpdatePaymentStatus();
 }

+ 135 - 2
tz-module-pressure2/tz-module-pressure2-biz/src/main/java/cn/start/tz/module/pressure2/service/taskordernontaxrecord/TaskOrderNonTaxRecordServiceImpl.java

@@ -862,11 +862,144 @@ public class TaskOrderNonTaxRecordServiceImpl extends ServiceImpl<TaskOrderNonTa
             }
             BoilerTaskOrderDO updateOrder = new BoilerTaskOrderDO();
             updateOrder.setId(item.getOrderId());
-            updateOrder.setPaymentStatus(1);
-            updateOrder.setPayTime(updateRecord.getPayDate());
+            updateOrder.setNoTaxPaymentStatus(1);
+            updateOrder.setNoTaxPayTime(updateRecord.getPayDate());
             taskOrderMapper.updateById(updateOrder);
         }
 
         return true;
     }
+
+    /**
+     * 查询并更新缴费状态
+     */
+    @Override
+    public void queryAndUpdatePaymentStatus() {
+
+        if(EnvConstants.ENV_UAT.equals(env) || EnvConstants.ENV_PROD.equals(env)){
+
+            log.info("开始查询并更新非税缴费状态");
+
+            // 查询条件:status=200 且 payStatus=100
+            LambdaQueryWrapperX<TaskOrderNonTaxRecordDO> queryWrapper = new LambdaQueryWrapperX<>();
+            queryWrapper.eq(TaskOrderNonTaxRecordDO::getStatus, 200)
+                    .eq(TaskOrderNonTaxRecordDO::getPayStatus, 100)
+                    .isNotNull(TaskOrderNonTaxRecordDO::getPaymentInstructionNo);
+
+            // 查询符合条件的记录
+            List<TaskOrderNonTaxRecordDO> records = taskOrderNonTaxRecordMapper.selectList(queryWrapper);
+
+            if (CollUtil.isEmpty(records)) {
+                log.info("没有需要查询缴费状态的记录");
+                return;
+            }
+
+            log.info("查询到 {} 条需要更新缴费状态的记录", records.size());
+
+            int successCount = 0;
+            int failCount = 0;
+            int paidCount = 0;
+
+            // 遍历每条记录,查询财务系统缴费状态
+            for (TaskOrderNonTaxRecordDO record : records) {
+                try {
+                    String paymentInstructionNo = record.getPaymentInstructionNo();
+
+                    if (paymentInstructionNo == null || paymentInstructionNo.trim().isEmpty()) {
+                        log.warn("记录 {} 的缴费通知书号为空,跳过", record.getId());
+                        failCount++;
+                        continue;
+                    }
+
+                    log.info("正在查询缴费通知书号 {} 的缴费状态", paymentInstructionNo);
+
+                    // 调用财务系统接口查询缴费状态
+                    // tag=2:按单位编码和缴款码查询
+                    IncomepaymentData queryData = new IncomepaymentData();
+                    queryData.setIncomepaymentData(paymentInstructionNo);
+                    IncomepaymentData result = financialSystemService.queryFinancialOutFeeInfo("2", queryData);
+
+                    if (result == null) {
+                        log.warn("查询缴费通知书号 {} 返回结果为空", paymentInstructionNo);
+                        failCount++;
+                        continue;
+                    }
+
+                    String paynoteStatus = result.getPaynoteStatus();
+                    log.info("缴费通知书号 {} 的状态: {}", paymentInstructionNo, paynoteStatus);
+
+                    // 判断是否已缴款(PaynoteStatus=3)
+                    if ("3".equals(paynoteStatus)) {
+                        log.info("缴费通知书号 {} 已缴款,开始更新记录", paymentInstructionNo);
+
+                        // 更新记录的缴费状态为已缴款(200)
+                        TaskOrderNonTaxRecordDO updateRecord = new TaskOrderNonTaxRecordDO();
+                        updateRecord.setId(record.getId());
+                        updateRecord.setPayStatus(200); // 已缴款
+
+                        // 设置缴费日期
+                        LocalDateTime payTime = result.getPayTime();
+                        if (payTime != null) {
+                            updateRecord.setPayDate(payTime);
+                        }else{
+                            payTime = LocalDateTime.now();
+                            updateRecord.setPayDate(payTime);
+                        }
+                        taskOrderNonTaxRecordMapper.updateById(updateRecord);
+
+                        log.info("成功更新记录 {} 的缴费状态为已缴款", record.getId());
+
+                        // 查询关联的task_order_non_tax_record_item记录
+                        LambdaQueryWrapperX<TaskOrderNonTaxRecordItemDO> itemQueryWrapper = new LambdaQueryWrapperX<>();
+                        itemQueryWrapper.eq(TaskOrderNonTaxRecordItemDO::getRecordId, record.getId());
+                        List<TaskOrderNonTaxRecordItemDO> itemList = taskOrderNonTaxRecordItemMapper.selectList(itemQueryWrapper);
+
+                        if (CollUtil.isNotEmpty(itemList)) {
+                            log.info("记录 {} 关联了 {} 个任务单", record.getId(), itemList.size());
+
+                            // 更新关联的task_order的支付状态
+                            for (TaskOrderNonTaxRecordItemDO item : itemList) {
+                                String orderId = item.getOrderId();
+                                if (orderId != null && !orderId.trim().isEmpty()) {
+                                    try {
+                                        BoilerTaskOrderDO taskOrder = taskOrderMapper.selectById(orderId);
+                                        if (taskOrder != null) {
+                                            // 更新任务单的缴费状态
+                                            BoilerTaskOrderDO updateTaskOrder = new BoilerTaskOrderDO();
+                                            updateTaskOrder.setId(orderId);
+                                            updateTaskOrder.setNoTaxPaymentStatus(1); // 1=已缴费
+                                            updateTaskOrder.setNoTaxPayTime(payTime);
+
+                                            taskOrderMapper.updateById(updateTaskOrder);
+                                            log.info("成功更新任务单 {} 的缴费状态为已缴费", orderId);
+                                        } else {
+                                            log.warn("任务单 {} 不存在", orderId);
+                                        }
+                                    } catch (Exception e) {
+                                        log.error("更新任务单 {} 缴费状态时发生异常: {}", orderId, e.getMessage(), e);
+                                    }
+                                }
+                            }
+                        } else {
+                            log.info("记录 {} 没有关联的任务单", record.getId());
+                        }
+
+                        paidCount++;
+                        successCount++;
+                    } else {
+                        log.debug("缴费通知书号 {} 尚未缴款,当前状态: {}", paymentInstructionNo, paynoteStatus);
+                        successCount++;
+                    }
+
+                } catch (Exception e) {
+                    log.error("处理记录 {} 时发生异常: {}", record.getId(), e.getMessage(), e);
+                    failCount++;
+                }
+            }
+
+            log.info("非税缴费状态查询完成。成功: {}, 已缴款: {}, 失败: {}", successCount, paidCount, failCount);
+        }
+
+    }
+
 }

+ 7 - 0
tz-module-pressure2/tz-module-pressure2-biz/src/main/resources/mapper/taskordernontaxapply/TaskOrderLeftJoinMapper.xml

@@ -24,6 +24,7 @@
         t.equip_num AS equipNum,
         t.check_date AS checkDate,
         t.payment_status AS paymentStatus,
+        t.no_tax_payment_status AS noTaxPaymentStatus,
         t.confirm_date AS confirmDate,
         t.reduction_radio AS reductionRadio,
         t.equip_main_type AS equipMainType,
@@ -49,6 +50,9 @@
         <if test="reqVO.paymentStatus != null">
             AND t.payment_status = #{reqVO.paymentStatus}
         </if>
+        <if test="reqVO.noTaxPaymentStatus != null">
+            AND t.no_tax_payment_status = #{reqVO.noTaxPaymentStatus}
+        </if>
 
         <if test="reqVO.feeType != null">
             AND t.fee_type = #{reqVO.feeType}
@@ -116,6 +120,9 @@
         <if test="reqVO.paymentStatus != null">
             AND t.payment_status = #{reqVO.paymentStatus}
         </if>
+        <if test="reqVO.noTaxPaymentStatus != null">
+            AND t.no_tax_payment_status = #{reqVO.noTaxPaymentStatus}
+        </if>
         <if test="reqVO.feeType != null">
             AND t.fee_type = #{reqVO.feeType}
         </if>

+ 1 - 0
tz-module-pressure2/tz-module-pressure2-biz/src/main/resources/mapper/taskordernontaxapply/TaskOrderNonTaxApplyMapper.xml

@@ -38,6 +38,7 @@
         task_order.check_type,
         task_order.service_amount,
         task_order.should_amount,
+        task_order.reduction_radio,
         task_order.payer_contact_name as recipient,
         task_order.payer_contact as recipient_phone,
         task_order.payer_mail as recipient_email,

+ 2 - 1
tz-module-system/tz-module-system-api/src/main/java/cn/start/tz/module/system/enums/ErrorCodeConstants.java

@@ -55,7 +55,8 @@ public interface ErrorCodeConstants {
     ErrorCode DEPT_EXITS_CHILDREN = new ErrorCode(1_002_004_003, "存在子部门,无法删除");
     ErrorCode DEPT_PARENT_ERROR = new ErrorCode(1_002_004_004, "不能设置自己为父部门");
     ErrorCode DEPT_NOT_ENABLE = new ErrorCode(1_002_004_006, "部门({})不处于开启状态,不允许选择");
-    ErrorCode DEPT_PARENT_IS_CHILD = new ErrorCode(1_002_004_007, "不能设置自己的子部门为父部门");
+    ErrorCode DEPT_PARENT_IS_CHILD = new ErrorCode(1_002_004_005, "不能设置自己的子部门为父部门");
+    ErrorCode DEPT_IMPORT_LIST_IS_EMPTY = new ErrorCode(1_002_004_006, "导入部门数据不能为空!");
 
     // ========== 岗位模块 1-002-005-000 ==========
     ErrorCode POST_NOT_FOUND = new ErrorCode(1_002_005_000, "当前岗位不存在");

+ 26 - 0
tz-module-system/tz-module-system-biz/src/main/java/cn/start/tz/module/system/controller/admin/dept/DeptController.java

@@ -3,10 +3,13 @@ package cn.start.tz.module.system.controller.admin.dept;
 import cn.start.tz.framework.common.enums.CommonStatusEnum;
 import cn.start.tz.framework.common.pojo.CommonResult;
 import cn.start.tz.framework.common.util.object.BeanUtils;
+import cn.start.tz.framework.excel.core.util.ExcelUtils;
 import cn.start.tz.module.system.controller.admin.dept.vo.dept.DeptListReqVO;
 import cn.start.tz.module.system.controller.admin.dept.vo.dept.DeptRespVO;
 import cn.start.tz.module.system.controller.admin.dept.vo.dept.DeptSaveReqVO;
 import cn.start.tz.module.system.controller.admin.dept.vo.dept.DeptSimpleRespVO;
+import cn.start.tz.module.system.controller.admin.dept.vo.dept.DeptImportExcelVO;
+import cn.start.tz.module.system.controller.admin.dept.vo.dept.DeptImportRespVO;
 import cn.start.tz.module.system.dal.dataobject.dept.DeptDO;
 import cn.start.tz.module.system.service.dept.DeptService;
 import io.swagger.v3.oas.annotations.Operation;
@@ -14,9 +17,13 @@ import io.swagger.v3.oas.annotations.Parameter;
 import io.swagger.v3.oas.annotations.tags.Tag;
 import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
 
 import jakarta.annotation.Resource;
+import jakarta.servlet.http.HttpServletResponse;
 import jakarta.validation.Valid;
+import java.io.IOException;
+import java.util.Arrays;
 import java.util.List;
 
 import static cn.start.tz.framework.common.pojo.CommonResult.success;
@@ -80,4 +87,23 @@ public class DeptController {
         return success(BeanUtils.toBean(dept, DeptRespVO.class));
     }
 
+    @GetMapping("/get-import-template")
+    @Operation(summary = "获得导入部门模板")
+    public void importTemplate(HttpServletResponse response) throws IOException {
+        List<DeptImportExcelVO> list = Arrays.asList(
+                DeptImportExcelVO.builder().name("技术部").code("10001").parentName("").sort(1)
+                        .leader("").phone("").email("").tenantId("").build(),
+                DeptImportExcelVO.builder().name("前端组").code("10002").parentName("技术部").sort(1)
+                        .leader("").phone("").email("").tenantId("").build()
+        );
+        ExcelUtils.write(response, "部门导入模板.xls", "部门列表", DeptImportExcelVO.class, list);
+    }
+
+    @PostMapping("/import")
+    @Operation(summary = "导入部门")
+    public CommonResult<DeptImportRespVO> importExcel(@RequestParam("file") MultipartFile file) throws Exception {
+        List<DeptImportExcelVO> list = ExcelUtils.read(file, DeptImportExcelVO.class);
+        return success(deptService.importDeptList(list));
+    }
+
 }

+ 46 - 0
tz-module-system/tz-module-system-biz/src/main/java/cn/start/tz/module/system/controller/admin/dept/vo/dept/DeptImportExcelVO.java

@@ -0,0 +1,46 @@
+package cn.start.tz.module.system.controller.admin.dept.vo.dept;
+
+import com.alibaba.excel.annotation.ExcelProperty;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import lombok.experimental.Accessors;
+
+/**
+ * 部门导入 Excel VO
+ *
+ * @author tz
+ */
+@Data
+@Builder
+@AllArgsConstructor
+@NoArgsConstructor
+@Accessors(chain = false)
+public class DeptImportExcelVO {
+
+    @ExcelProperty("部门名称")
+    private String name;
+
+    @ExcelProperty("部门代码")
+    private String code;
+
+    @ExcelProperty("父部门名称")
+    private String parentName;
+
+    @ExcelProperty("显示顺序")
+    private Integer sort;
+
+    @ExcelProperty("负责人用户名")
+    private String leader;
+
+    @ExcelProperty("联系电话")
+    private String phone;
+
+    @ExcelProperty("邮箱")
+    private String email;
+
+    @ExcelProperty("租户编号")
+    private String tenantId;
+
+}

+ 26 - 0
tz-module-system/tz-module-system-biz/src/main/java/cn/start/tz/module/system/controller/admin/dept/vo/dept/DeptImportRespVO.java

@@ -0,0 +1,26 @@
+package cn.start.tz.module.system.controller.admin.dept.vo.dept;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Builder;
+import lombok.Data;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 部门导入 Response VO
+ *
+ * @author tz
+ */
+@Schema(description = "管理后台 - 部门导入 Response VO")
+@Data
+@Builder
+public class DeptImportRespVO {
+
+    @Schema(description = "创建成功的部门名称数组", requiredMode = Schema.RequiredMode.REQUIRED)
+    private List<String> createDeptNames;
+
+    @Schema(description = "导入失败的部门集合,key 为部门名称,value 为失败原因", requiredMode = Schema.RequiredMode.REQUIRED)
+    private Map<String, String> failureDeptNames;
+
+}

+ 17 - 0
tz-module-system/tz-module-system-biz/src/main/java/cn/start/tz/module/system/controller/admin/user/UserController.java

@@ -204,6 +204,23 @@ public class UserController {
         return success(userService.importUserList(list, updateSupport));
     }
 
+    @GetMapping("/get-import-role-template")
+    @Operation(summary = "获得导入用户角色关联模板")
+    public void importRoleTemplate(HttpServletResponse response) throws IOException {
+        List<UserRoleImportExcelVO> list = Arrays.asList(
+                UserRoleImportExcelVO.builder().username("dexdev").roleCode("super_admin").build(),
+                UserRoleImportExcelVO.builder().username("admin").roleCode("admin").build()
+        );
+        ExcelUtils.write(response, "用户角色关联导入模板.xls", "用户角色关联", UserRoleImportExcelVO.class, list);
+    }
+
+    @PostMapping("/import-role")
+    @Operation(summary = "导入用户角色关联")
+    public CommonResult<UserRoleImportRespVO> importUserRoleExcel(@RequestParam("file") MultipartFile file) throws Exception {
+        List<UserRoleImportExcelVO> list = ExcelUtils.read(file, UserRoleImportExcelVO.class);
+        return success(userService.importUserRoleList(list));
+    }
+
     @PostMapping("/assign-role")
     @Operation(summary = "分配用户角色", description = "给单个用户或整个部门的用户分配角色")
     public CommonResult<Boolean> assignRole(@Valid @RequestBody UserAssignRoleReqVO reqVO) {

+ 28 - 0
tz-module-system/tz-module-system-biz/src/main/java/cn/start/tz/module/system/controller/admin/user/vo/user/UserRoleImportExcelVO.java

@@ -0,0 +1,28 @@
+package cn.start.tz.module.system.controller.admin.user.vo.user;
+
+import com.alibaba.excel.annotation.ExcelProperty;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import lombok.experimental.Accessors;
+
+/**
+ * 用户角色关联导入 Excel VO
+ *
+ * @author tz
+ */
+@Data
+@Builder
+@AllArgsConstructor
+@NoArgsConstructor
+@Accessors(chain = false)
+public class UserRoleImportExcelVO {
+
+    @ExcelProperty("用户名")
+    private String username;
+
+    @ExcelProperty("角色标识")
+    private String roleCode;
+
+}

+ 26 - 0
tz-module-system/tz-module-system-biz/src/main/java/cn/start/tz/module/system/controller/admin/user/vo/user/UserRoleImportRespVO.java

@@ -0,0 +1,26 @@
+package cn.start.tz.module.system.controller.admin.user.vo.user;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Builder;
+import lombok.Data;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 用户角色关联导入 Response VO
+ *
+ * @author tz
+ */
+@Schema(description = "管理后台 - 用户角色关联导入 Response VO")
+@Data
+@Builder
+public class UserRoleImportRespVO {
+
+    @Schema(description = "关联成功的用户名数组", requiredMode = Schema.RequiredMode.REQUIRED)
+    private List<String> createUsernames;
+
+    @Schema(description = "关联失败的用户集合,key 为用户名,value 为失败原因", requiredMode = Schema.RequiredMode.REQUIRED)
+    private Map<String, String> failureUsernames;
+
+}

+ 4 - 0
tz-module-system/tz-module-system-biz/src/main/java/cn/start/tz/module/system/dal/mysql/dept/DeptMapper.java

@@ -24,6 +24,10 @@ public interface DeptMapper extends BaseMapperX<DeptDO> {
         return selectOne(DeptDO::getParentId, parentId, DeptDO::getName, name);
     }
 
+    default DeptDO selectByCode(String code) {
+        return selectOne(DeptDO::getCode, code);
+    }
+
     default Long selectCountByParentId(String parentId) {
         return selectCount(DeptDO::getParentId, parentId);
     }

+ 10 - 0
tz-module-system/tz-module-system-biz/src/main/java/cn/start/tz/module/system/service/dept/DeptService.java

@@ -3,6 +3,8 @@ package cn.start.tz.module.system.service.dept;
 import cn.start.tz.framework.common.util.collection.CollectionUtils;
 import cn.start.tz.module.system.controller.admin.dept.vo.dept.DeptListReqVO;
 import cn.start.tz.module.system.controller.admin.dept.vo.dept.DeptSaveReqVO;
+import cn.start.tz.module.system.controller.admin.dept.vo.dept.DeptImportExcelVO;
+import cn.start.tz.module.system.controller.admin.dept.vo.dept.DeptImportRespVO;
 import cn.start.tz.module.system.dal.dataobject.dept.DeptDO;
 
 import java.util.*;
@@ -121,4 +123,12 @@ public interface DeptService {
     DeptDO getDeptByCode(String code);
 
     DeptDO getDeptByName(String name);
+
+    /**
+     * 导入部门列表
+     *
+     * @param importDepts  导入的部门列表
+     * @return 导入结果
+     */
+    DeptImportRespVO importDeptList(List<DeptImportExcelVO> importDepts);
 }

+ 95 - 0
tz-module-system/tz-module-system-biz/src/main/java/cn/start/tz/module/system/service/dept/DeptServiceImpl.java

@@ -10,8 +10,12 @@ import cn.start.tz.framework.mybatis.core.query.LambdaQueryWrapperX;
 import cn.start.tz.framework.mybatis.core.query.QueryWrapperX;
 import cn.start.tz.module.system.controller.admin.dept.vo.dept.DeptListReqVO;
 import cn.start.tz.module.system.controller.admin.dept.vo.dept.DeptSaveReqVO;
+import cn.start.tz.module.system.controller.admin.dept.vo.dept.DeptImportExcelVO;
+import cn.start.tz.module.system.controller.admin.dept.vo.dept.DeptImportRespVO;
 import cn.start.tz.module.system.dal.dataobject.dept.DeptDO;
+import cn.start.tz.module.system.dal.dataobject.user.AdminUserDO;
 import cn.start.tz.module.system.dal.mysql.dept.DeptMapper;
+import cn.start.tz.module.system.dal.mysql.user.AdminUserMapper;
 import cn.start.tz.module.system.dal.redis.RedisKeyConstants;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.google.common.annotations.VisibleForTesting;
@@ -20,6 +24,7 @@ import lombok.extern.slf4j.Slf4j;
 import org.springframework.cache.annotation.CacheEvict;
 import org.springframework.cache.annotation.Cacheable;
 import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
 import org.springframework.validation.annotation.Validated;
 
 import java.util.*;
@@ -41,6 +46,9 @@ public class DeptServiceImpl implements DeptService {
     @Resource
     private DeptMapper deptMapper;
 
+    @Resource
+    private AdminUserMapper adminUserMapper;
+
     @Override
     @CacheEvict(cacheNames = RedisKeyConstants.DEPT_CHILDREN_ID_LIST,
             allEntries = true) // allEntries 清空所有缓存,因为操作一个部门,涉及到多个缓存
@@ -258,4 +266,91 @@ public class DeptServiceImpl implements DeptService {
         return deptDO;
     }
 
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public DeptImportRespVO importDeptList(List<DeptImportExcelVO> importDepts) {
+        if (CollUtil.isEmpty(importDepts)) {
+            throw exception(DEPT_IMPORT_LIST_IS_EMPTY);
+        }
+
+        DeptImportRespVO respVO = DeptImportRespVO.builder()
+                .createDeptNames(new ArrayList<>())
+                .failureDeptNames(new LinkedHashMap<>())
+                .build();
+
+        importDepts.forEach(importDept -> {
+            try {
+                // 1. 基本字段非空校验
+                if (importDept.getName() == null || importDept.getName().trim().isEmpty()) {
+                    respVO.getFailureDeptNames().put(importDept.getName() == null ? "未知" : importDept.getName(), "部门名称不能为空");
+                    return;
+                }
+                if (importDept.getCode() == null || importDept.getCode().trim().isEmpty()) {
+                    respVO.getFailureDeptNames().put(importDept.getName(), "部门代码不能为空");
+                    return;
+                }
+
+                // 2. 部门代码唯一性校验
+                DeptDO existByCode = deptMapper.selectByCode(importDept.getCode().trim());
+                if (existByCode != null) {
+                    respVO.getFailureDeptNames().put(importDept.getName(), "部门代码已存在: " + importDept.getCode());
+                    return;
+                }
+
+                // 3. 解析父部门
+                String parentId = DeptDO.PARENT_ID_ROOT;
+                if (importDept.getParentName() != null && !importDept.getParentName().trim().isEmpty()) {
+                    DeptDO parentDept = deptMapper.selectOne(
+                            new LambdaQueryWrapperX<DeptDO>()
+                                    .eq(DeptDO::getName, importDept.getParentName().trim()), false);
+                    if (parentDept == null) {
+                        respVO.getFailureDeptNames().put(importDept.getName(), "父部门不存在: " + importDept.getParentName());
+                        return;
+                    }
+                    parentId = parentDept.getId();
+                }
+
+                // 4. 同父部门下名称唯一性校验
+                DeptDO existByName = deptMapper.selectByParentIdAndName(parentId, importDept.getName().trim());
+                if (existByName != null) {
+                    respVO.getFailureDeptNames().put(importDept.getName(), "同父部门下部门名称已存在");
+                    return;
+                }
+
+                // 5.负责人账号
+                String leaderUserId = "";
+                if (importDept.getLeader() != null && !importDept.getLeader().trim().isEmpty()){
+                    AdminUserDO leaderUser = adminUserMapper.selectByUsername(importDept.getLeader());
+                    if (leaderUser == null) {
+                        respVO.getFailureDeptNames().put(importDept.getName(), "负责人用户名不存在");
+                        return;
+                    }else{
+                        leaderUserId = leaderUser.getId();
+                    }
+                }
+
+                // 6. 构建并插入
+                DeptDO dept = new DeptDO();
+                dept.setName(importDept.getName().trim());
+                dept.setCode(importDept.getCode().trim());
+                dept.setParentId(parentId);
+                dept.setSort(importDept.getSort() != null ? importDept.getSort() : 0);
+                dept.setPhone(importDept.getPhone());
+                dept.setEmail(importDept.getEmail());
+                dept.setTenantId(importDept.getTenantId());
+                dept.setLeaderUserId(leaderUserId);
+                dept.setStatus(CommonStatusEnum.ENABLE.getStatus()); // 默认启用
+
+                deptMapper.insert(dept);
+                respVO.getCreateDeptNames().add(importDept.getName());
+
+            } catch (Exception e) {
+                log.error("[importDeptList] 导入部门失败: {}", importDept.getName(), e);
+                respVO.getFailureDeptNames().put(importDept.getName(), "系统异常: " + e.getMessage());
+            }
+        });
+
+        return respVO;
+    }
+
 }

+ 12 - 0
tz-module-system/tz-module-system-biz/src/main/java/cn/start/tz/module/system/service/user/AdminUserService.java

@@ -8,6 +8,10 @@ import cn.start.tz.module.system.controller.admin.auth.vo.AuthRegisterReqVO;
 import cn.start.tz.module.system.controller.admin.user.vo.profile.UserProfileUpdatePasswordReqVO;
 import cn.start.tz.module.system.controller.admin.user.vo.profile.UserProfileUpdateReqVO;
 import cn.start.tz.module.system.controller.admin.user.vo.user.*;
+import cn.start.tz.module.system.controller.admin.user.vo.user.UserImportExcelVO;
+import cn.start.tz.module.system.controller.admin.user.vo.user.UserImportRespVO;
+import cn.start.tz.module.system.controller.admin.user.vo.user.UserRoleImportExcelVO;
+import cn.start.tz.module.system.controller.admin.user.vo.user.UserRoleImportRespVO;
 import cn.start.tz.module.system.dal.dataobject.user.AdminUserDO;
 import jakarta.validation.Valid;
 
@@ -197,6 +201,14 @@ public interface AdminUserService {
      */
     UserImportRespVO importUserList(List<UserImportExcelVO> importUsers, boolean isUpdateSupport);
 
+    /**
+     * 导入用户角色关联列表
+     *
+     * @param importList 导入的用户角色关联列表
+     * @return 导入结果
+     */
+    UserRoleImportRespVO importUserRoleList(List<UserRoleImportExcelVO> importList);
+
     /**
      * 获得指定状态的用户们
      *

+ 81 - 6
tz-module-system/tz-module-system-biz/src/main/java/cn/start/tz/module/system/service/user/AdminUserServiceImpl.java

@@ -20,10 +20,12 @@ import cn.start.tz.module.system.controller.admin.user.vo.profile.UserProfileUpd
 import cn.start.tz.module.system.controller.admin.user.vo.user.*;
 import cn.start.tz.module.system.dal.dataobject.dept.DeptDO;
 import cn.start.tz.module.system.dal.dataobject.dept.UserPostDO;
+import cn.start.tz.module.system.dal.dataobject.permission.RoleDO;
 import cn.start.tz.module.system.dal.dataobject.permission.UserRoleDO;
 import cn.start.tz.module.system.dal.dataobject.user.AdminUserDO;
 import cn.start.tz.module.system.dal.dataobject.userqualifications.UserQualificationsDO;
 import cn.start.tz.module.system.dal.mysql.dept.UserPostMapper;
+import cn.start.tz.module.system.dal.mysql.permission.RoleMapper;
 import cn.start.tz.module.system.dal.mysql.permission.UserRoleMapper;
 import cn.start.tz.module.system.dal.mysql.user.AdminUserMapper;
 import cn.start.tz.module.system.dal.mysql.userqualifications.UserQualificationsMapper;
@@ -89,6 +91,9 @@ public class AdminUserServiceImpl implements AdminUserService {
     @Resource
     private UserRoleMapper userRoleMapper;
 
+    @Resource
+    private RoleMapper roleMapper;
+
     @Resource
     private FileApi fileApi;
     @Resource
@@ -411,9 +416,9 @@ public class AdminUserServiceImpl implements AdminUserService {
             // 校验用户名唯一
             validateUsernameUnique(id, username);
             // 校验手机号唯一
-            validateMobileUnique(id, mobile);
+//            validateMobileUnique(id, mobile);
             // 校验邮箱唯一
-            validateEmailUnique(id, email);
+//            validateEmailUnique(id, email);
             // 校验部门处于开启状态
             deptService.validateDeptListByCodes(CollectionUtils.singleton(deptId));
             // 校验岗位处于开启状态
@@ -512,15 +517,22 @@ public class AdminUserServiceImpl implements AdminUserService {
             throw exception(USER_IMPORT_LIST_IS_EMPTY);
         }
         // 1.2 初始化密码不能为空
-        String initPassword = configApi.getConfigValueByKey(USER_INIT_PASSWORD_KEY).getCheckedData();
-        if (StrUtil.isEmpty(initPassword)) {
-            throw exception(USER_IMPORT_INIT_PASSWORD);
-        }
+//        String initPassword = configApi.getConfigValueByKey(USER_INIT_PASSWORD_KEY).getCheckedData();
+//        if (StrUtil.isEmpty(initPassword)) {
+//            throw exception(USER_IMPORT_INIT_PASSWORD);
+//        }
 
         // 2. 遍历,逐个创建 or 更新
         UserImportRespVO respVO = UserImportRespVO.builder().createUsernames(new ArrayList<>())
                 .updateUsernames(new ArrayList<>()).failureUsernames(new LinkedHashMap<>()).build();
         importUsers.forEach(importUser -> {
+
+            //根据用户名定义密码
+            String initPassword = "BW@";
+            if (importUser.getUsername() != null){
+                initPassword += importUser.getUsername();
+            }
+
             // 2.1.1 校验字段是否符合要求
             try {
                 ValidationUtils.validate(BeanUtils.toBean(importUser, UserSaveReqVO.class).setPassword(initPassword));
@@ -565,6 +577,69 @@ public class AdminUserServiceImpl implements AdminUserService {
         return respVO;
     }
 
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public UserRoleImportRespVO importUserRoleList(List<UserRoleImportExcelVO> importList) {
+        if (CollUtil.isEmpty(importList)) {
+            throw exception(USER_IMPORT_LIST_IS_EMPTY);
+        }
+
+        UserRoleImportRespVO respVO = UserRoleImportRespVO.builder()
+                .createUsernames(new ArrayList<>())
+                .failureUsernames(new LinkedHashMap<>())
+                .build();
+
+        importList.forEach(item -> {
+            try {
+                if (item.getUsername() == null || item.getUsername().trim().isEmpty()) {
+                    respVO.getFailureUsernames().put(item.getUsername() == null ? "未知" : item.getUsername(), "用户名不能为空");
+                    return;
+                }
+                if (item.getRoleCode() == null || item.getRoleCode().trim().isEmpty()) {
+                    respVO.getFailureUsernames().put(item.getUsername(), "角色标识不能为空");
+                    return;
+                }
+
+                // 1. 校验用户名是否存在
+                AdminUserDO user = userMapper.selectByUsername(item.getUsername().trim());
+                if (user == null) {
+                    respVO.getFailureUsernames().put(item.getUsername(), "用户不存在");
+                    return;
+                }
+
+                // 2. 校验角色标识是否存在
+                RoleDO role = roleMapper.selectByCode(item.getRoleCode().trim());
+                if (role == null) {
+                    respVO.getFailureUsernames().put(item.getUsername(), "角色标识不存在: " + item.getRoleCode());
+                    return;
+                }
+
+                // 3. 检查是否已关联
+                List<UserRoleDO> existList = userRoleMapper.selectList(
+                        new LambdaQueryWrapperX<UserRoleDO>()
+                                .eq(UserRoleDO::getUserId, user.getId())
+                                .eq(UserRoleDO::getRoleId, role.getId()));
+                if (CollUtil.isNotEmpty(existList)) {
+                    respVO.getFailureUsernames().put(item.getUsername(), "用户已拥有该角色");
+                    return;
+                }
+
+                // 4. 插入关联
+                UserRoleDO userRole = new UserRoleDO();
+                userRole.setUserId(user.getId());
+                userRole.setRoleId(role.getId());
+                userRoleMapper.insert(userRole);
+                respVO.getCreateUsernames().add(item.getUsername());
+
+            } catch (Exception e) {
+                log.error("[importUserRoleList] 导入用户角色关联失败: {}", item.getUsername(), e);
+                respVO.getFailureUsernames().put(item.getUsername(), "系统异常: " + e.getMessage());
+            }
+        });
+
+        return respVO;
+    }
+
     @Override
     public List<AdminUserDO> getUserListByStatus(Integer status) {
         return userMapper.selectListByStatus(status);