zhoulisky 7 miesięcy temu
rodzic
commit
b0e3a6e6cd
28 zmienionych plików z 486 dodań i 183 usunięć
  1. 2 0
      kd-service-api/kd-scientific-api/src/main/java/org/sky/scientific/pojo/vo/HighTechCostSummary.java
  2. 24 0
      kd-service-api/kd-scientific-api/src/main/java/org/sky/scientific/pojo/vo/TorchDevYBVO.java
  3. 7 0
      kd-service/kd-scientific/src/main/java/org/sky/scientific/controller/EnterpriseController.java
  4. 7 9
      kd-service/kd-scientific/src/main/java/org/sky/scientific/controller/SettingController.java
  5. 8 1
      kd-service/kd-scientific/src/main/java/org/sky/scientific/controller/TechnicianController.java
  6. 86 0
      kd-service/kd-scientific/src/main/java/org/sky/scientific/excel/listener/XmTechnicianImportListener.java
  7. 1 1
      kd-service/kd-scientific/src/main/java/org/sky/scientific/mapper/XmMapper.xml
  8. 6 0
      kd-service/kd-scientific/src/main/java/org/sky/scientific/service/IEnterpriseInfoService.java
  9. 1 0
      kd-service/kd-scientific/src/main/java/org/sky/scientific/service/ITechnicianService.java
  10. 6 0
      kd-service/kd-scientific/src/main/java/org/sky/scientific/service/IXmService.java
  11. 7 9
      kd-service/kd-scientific/src/main/java/org/sky/scientific/service/SettingService.java
  12. 0 21
      kd-service/kd-scientific/src/main/java/org/sky/scientific/service/impl/AttendanceServiceImpl.java
  13. 31 0
      kd-service/kd-scientific/src/main/java/org/sky/scientific/service/impl/EnterpriseInfoServiceImpl.java
  14. 6 0
      kd-service/kd-scientific/src/main/java/org/sky/scientific/service/impl/HoursSyncServiceImpl.java
  15. 5 5
      kd-service/kd-scientific/src/main/java/org/sky/scientific/service/impl/SettingServiceImpl.java
  16. 43 9
      kd-service/kd-scientific/src/main/java/org/sky/scientific/service/impl/TechnicianServiceImpl.java
  17. 16 15
      kd-service/kd-scientific/src/main/java/org/sky/scientific/service/impl/XmAssetHoursServiceImpl.java
  18. 17 0
      kd-service/kd-scientific/src/main/java/org/sky/scientific/service/impl/XmCostDetailsServiceImpl.java
  19. 12 0
      kd-service/kd-scientific/src/main/java/org/sky/scientific/service/impl/XmDesignCostServiceImpl.java
  20. 15 4
      kd-service/kd-scientific/src/main/java/org/sky/scientific/service/impl/XmDirectCostServiceImpl.java
  21. 37 39
      kd-service/kd-scientific/src/main/java/org/sky/scientific/service/impl/XmFixedAssetServiceImpl.java
  22. 22 15
      kd-service/kd-scientific/src/main/java/org/sky/scientific/service/impl/XmGoodsServiceImpl.java
  23. 39 32
      kd-service/kd-scientific/src/main/java/org/sky/scientific/service/impl/XmIntangibleAssetServiceImpl.java
  24. 16 0
      kd-service/kd-scientific/src/main/java/org/sky/scientific/service/impl/XmOtherCostServiceImpl.java
  25. 24 11
      kd-service/kd-scientific/src/main/java/org/sky/scientific/service/impl/XmServiceImpl.java
  26. 28 12
      kd-service/kd-scientific/src/main/java/org/sky/scientific/service/impl/XmTechnicianHoursServiceImpl.java
  27. 19 0
      kd-service/kd-scientific/src/main/java/org/sky/scientific/service/impl/XmWwxmCostServiceImpl.java
  28. 1 0
      kd-service/kd-scientific/src/main/java/org/sky/scientific/service/impl/XmWwxmServiceImpl.java

+ 2 - 0
kd-service-api/kd-scientific-api/src/main/java/org/sky/scientific/pojo/vo/HighTechCostSummary.java

@@ -54,4 +54,6 @@ public class HighTechCostSummary {
 
 	@Schema(description = "1-8项合计")
 	private BigDecimal total = BigDecimal.ZERO;
+
+
 }

+ 24 - 0
kd-service-api/kd-scientific-api/src/main/java/org/sky/scientific/pojo/vo/TorchDevYBVO.java

@@ -0,0 +1,24 @@
+package org.sky.scientific.pojo.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+
+@Data
+public class TorchDevYBVO implements Serializable {
+
+	@Schema(description = "企业是否为经过认定的高新技术企业")
+	private String qb11;
+
+	@Schema(description = "高新技术企业认定证书编号")
+	private String qb13;
+
+	@Schema(description = "研发费用")
+	private BigDecimal qc236;
+
+	@Schema(description = "享受高新技术企业所得税减免")
+	private BigDecimal qc20_1;
+
+}

+ 7 - 0
kd-service/kd-scientific/src/main/java/org/sky/scientific/controller/EnterpriseController.java

@@ -221,4 +221,11 @@ public class EnterpriseController extends KdController {
 
 	}
 
+	@GetMapping("hjfznb")
+	@ApiOperationSupport(order = 50)
+	@Operation(summary = "火炬发展年报")
+	public R<TorchDevYBVO> torchDevYB(String year) {
+		return R.data(enterpriseInfoService.torchDevYB(year));
+	}
+
 }

+ 7 - 9
kd-service/kd-scientific/src/main/java/org/sky/scientific/controller/SettingController.java

@@ -13,8 +13,6 @@ import org.sky.scientific.pojo.entity.SettingEntity;
 import org.sky.scientific.service.SettingService;
 import org.springframework.web.bind.annotation.*;
 
-import java.util.List;
-
 /**
  * 出勤时间设置 控制器
  *
@@ -37,13 +35,13 @@ public class SettingController extends KdController {
 		return R.data(detail);
 	}
 
-	@GetMapping("/torch-dev/list")
-	@ApiOperationSupport(order = 1)
-	@Operation(summary = "火炬发展年报")
-	public R<List<SettingEntity>> torchDevList(String yearMin, String yearMax) {
-		List<SettingEntity> list = service.torchDevList(yearMin,yearMax);
- 		return R.data(list);
-	}
+//	@GetMapping("/torch-dev/list")
+//	@ApiOperationSupport(order = 1)
+//	@Operation(summary = "火炬发展年报")
+//	public R<List<SettingEntity>> torchDevList(String yearMin, String yearMax) {
+//		List<SettingEntity> list = service.torchDevList(yearMin,yearMax);
+// 		return R.data(list);
+//	}
 
 	@PostMapping("/submit")
 	@ApiOperationSupport(order = 3)

+ 8 - 1
kd-service/kd-scientific/src/main/java/org/sky/scientific/controller/TechnicianController.java

@@ -114,12 +114,19 @@ public class TechnicianController extends KdController {
 	}
 
 	@GetMapping("xm/monthly/page")
-	@ApiOperationSupport(order = 20)
+	@ApiOperationSupport(order = 15)
 	@Operation(summary = "每月实际参研人员名单-分页")
 	public R<IPage<XmTechnicianEntity>> meiyueshijicanyuanrenyuanmingdan(XmTechnicianDto entity, Query query) {
 		return R.data(technicianService.meiyueshijicanyuanrenyuanmingdan(Condition.getPage(query), entity));
 	}
 
+	@PostMapping("xm/monthly/import")
+	@ApiOperationSupport(order = 20)
+	@Operation(summary = "每月实际参研人员名单-导入")
+	public R importXmTechnicianMonthly(MultipartFile file, String yearAndMonth) {
+		return R.status(technicianService.importXmTechnicianMonthly(file, yearAndMonth));
+	}
+
 	@GetMapping("xm/monthly/yyysbmd")
 	@ApiOperationSupport(order = 21)
 	@Operation(summary = "每月实际参研人员名单-直接引用预算表名单", description = "传入xmId、yearAndMonth")

+ 86 - 0
kd-service/kd-scientific/src/main/java/org/sky/scientific/excel/listener/XmTechnicianImportListener.java

@@ -0,0 +1,86 @@
+package org.sky.scientific.excel.listener;
+
+import com.alibaba.excel.context.AnalysisContext;
+import com.alibaba.excel.read.listener.ReadListener;
+import com.alibaba.excel.util.ListUtils;
+import lombok.Data;
+import lombok.extern.slf4j.Slf4j;
+import org.sky.core.log.exception.ServiceException;
+import org.sky.core.tool.utils.Func;
+import org.sky.scientific.pojo.entity.XmTechnicianEntity;
+import org.sky.scientific.utils.ImportResult;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.atomic.AtomicInteger;
+
+
+@Data
+@Slf4j
+public class XmTechnicianImportListener implements ReadListener<Map<Integer, String>> {
+
+	private List<ImportResult<XmTechnicianEntity>> resultList = new ArrayList<>();
+	private List<XmTechnicianEntity> dataList = ListUtils.newArrayList();
+	private final AtomicInteger successCount = new AtomicInteger(0);
+	private final AtomicInteger errorCount = new AtomicInteger(0);
+
+	@Override
+	public void invoke(Map<Integer, String> map, AnalysisContext context) {
+		int rowIndex = context.readRowHolder().getRowIndex() + 1;
+
+		ImportResult<XmTechnicianEntity> result = convertAndValidate(map, rowIndex);
+		resultList.add(result);
+		if (result.isSuccess()) {
+			dataList.add(result.getData());
+			successCount.incrementAndGet();
+		} else {
+			errorCount.incrementAndGet();
+		}
+	}
+
+	private ImportResult<XmTechnicianEntity> convertAndValidate(Map<Integer, String> data, int rowIndex) {
+
+		List<String> errors = new ArrayList<>();
+
+		XmTechnicianEntity excel = new XmTechnicianEntity();
+		excel.setXmbh(data.get(2));
+		if(Func.isBlank(excel.getXmbh())){
+			errors.add("项目编号不能为空");
+		}
+		excel.setNumber(data.get(5));
+		excel.setIdCard(data.get(6));
+		if(Func.isAnyBlank(excel.getNumber(), excel.getIdCard())){
+			errors.add("工号和身份证号不能同时为空");
+		}
+		return ImportResult.success(rowIndex, excel);
+	}
+
+	@Override
+	public void doAfterAllAnalysed(AnalysisContext analysisContext) {
+		log.info("=== 每月参研人员,解析完成 ===");
+		log.info("成功: {}条,失败:{}条", successCount.get(), errorCount.get());
+		// 打印错误详情
+		if (errorCount.get() > 0) {
+			StringBuilder sb = new StringBuilder();
+			sb.append("成功: ").append(successCount.get()).append("条,失败:").append(errorCount.get()).append("条");
+			log.info("错误详情:");
+			sb.append("\n错误详情");
+			for (ImportResult<XmTechnicianEntity> result : resultList) {
+				if (!result.isSuccess()) {
+					sb.append("\n第").append(result.getRowIndex()).append("行: ").append(String.join("; ", result.getErrors()));
+					log.info("第{}行: {}", result.getRowIndex(), String.join("; ", result.getErrors()));
+				}
+			}
+			throw new ServiceException(sb.toString());
+		}
+	}
+
+	public int getSuccessCount() {
+		return successCount.get();
+	}
+
+	public int getErrorCount() {
+		return errorCount.get();
+	}
+}

+ 1 - 1
kd-service/kd-scientific/src/main/java/org/sky/scientific/mapper/XmMapper.xml

@@ -180,7 +180,7 @@
     </select>
 
     <select id="getXmStatusByXmId" parameterType="java.lang.Long" resultType="java.lang.Integer">
-        SELECT COALESCE(get_xm_info(xm.id,'STATUS', null),STATUS) FROM kd_xm where id = #{xmId}
+        SELECT COALESCE(get_xm_info(id,'STATUS', null),STATUS) FROM kd_xm where id = #{xmId}
     </select>
 
     <select id="getXmIdByXmmcOrXmbh" resultType="java.lang.Long">

+ 6 - 0
kd-service/kd-scientific/src/main/java/org/sky/scientific/service/IEnterpriseInfoService.java

@@ -138,4 +138,10 @@ public interface IEnterpriseInfoService extends BaseService<EnterpriseInfoEntity
 	 */
 	void exportGqnb(OutputStream os, HighTechYBVO techYBVO);
 
+	/**
+	 * 火炬发展年报
+	 * @param year
+	 * @return
+	 */
+    TorchDevYBVO torchDevYB(String year);
 }

+ 1 - 0
kd-service/kd-scientific/src/main/java/org/sky/scientific/service/ITechnicianService.java

@@ -186,4 +186,5 @@ public interface ITechnicianService extends BaseService<TechnicianEntity> {
 
 	void exportNdgkjryhzb(OutputStream os, List<TechnicianVO> list, String yearAndMonth);
 
+	boolean importXmTechnicianMonthly(MultipartFile file, String yearAndMonth);
 }

+ 6 - 0
kd-service/kd-scientific/src/main/java/org/sky/scientific/service/IXmService.java

@@ -39,6 +39,12 @@ public interface IXmService extends BaseService<XmEntity> {
 	List<XmEntity> selectXmListByYear(String year);
 
 	/**
+	 * 判断项目是否已结题
+	 * @param xmId
+	 */
+	boolean judgeXmIsOver(Long xmId, boolean isThrowEx);
+
+	/**
 	 * 立项
 	 * @param xm
 	 * @return 项目id

+ 7 - 9
kd-service/kd-scientific/src/main/java/org/sky/scientific/service/SettingService.java

@@ -3,8 +3,6 @@ package org.sky.scientific.service;
 
 import org.sky.scientific.pojo.entity.SettingEntity;
 
-import java.util.List;
-
 /**
  *  设置 服务类
  *
@@ -19,11 +17,11 @@ public interface SettingService {
 
 	Boolean fetchLastYearData(SettingEntity settingEntity);
 
-	/**
-	 * 火炬发展年报
-	 * @param yearMin
-	 * @param yearMax
-	 * @return
-	 */
-	List<SettingEntity> torchDevList(String yearMin, String yearMax);
+//	/**
+//	 * 火炬发展年报
+//	 * @param yearMin
+//	 * @param yearMax
+//	 * @return
+//	 */
+//	List<SettingEntity> torchDevList(String yearMin, String yearMax);
 }

+ 0 - 21
kd-service/kd-scientific/src/main/java/org/sky/scientific/service/impl/AttendanceServiceImpl.java

@@ -397,27 +397,6 @@ public class AttendanceServiceImpl extends BaseServiceImpl<AttendanceMapper, Att
 			insertList.add(attendance);
 		}
 		return this.saveBatch(insertList);
-//		if(Func.isEmpty(existsUnicodeList)){
-//			return this.saveBatch(insertList);
-//		}else {
-////			List<AttendanceEntity> deduplicationList = insertList.stream().filter(item -> !existsUnicodeList.contains(item.getUnicode())).toList();
-//			List<String> insertUnicodeList = unicodeList.stream().filter(item -> !existsUnicodeList.contains(item)).toList();
-//			if(Func.isEmpty(insertUnicodeList)){
-//				throw new ServiceException("本月参研人员已全部引用");
-//			}
-//			return this.saveBatch(deduplicationList);
-//		}
-//		List<AttendanceEntity> insertList = new ArrayList<>();
-//		for (XmTechnicianEntity xmTechnician : list) {
-//			AttendanceEntity attendance = new AttendanceEntity();
-//			attendance.setUnicode(xmTechnician.getUnicode());
-//			attendance.setWorkDate(yearAndMonth + "01");
-//			attendance.setWorkHours(0.0);
-//			attendance.setTenantId(SecureUtil.getTenantId());
-//			insertList.add(attendance);
-//		}
-
-
 	}
 
 	@Override

+ 31 - 0
kd-service/kd-scientific/src/main/java/org/sky/scientific/service/impl/EnterpriseInfoServiceImpl.java

@@ -1050,4 +1050,35 @@ public class EnterpriseInfoServiceImpl extends BaseServiceImpl<EnterpriseInfoMap
 		templateService.processTemplate("年度高新技术企业发展情况报表.ftl", techYBVO, new OutputStreamWriter(os));
 	}
 
+    @Override
+    public TorchDevYBVO torchDevYB(String year) {
+		TorchDevYBVO vo = new TorchDevYBVO();
+
+		//企业概况
+		EnterpriseInfoEntity enterpriseInfo = enterpriseInfoMapper.selectOne(Wrappers.<EnterpriseInfoEntity>lambdaQuery().eq(EnterpriseInfoEntity::getYearAndMonth, year));
+		if (Func.notNull(enterpriseInfo)) {
+			vo.setQb13(enterpriseInfo.getHighTechNumber());
+			vo.setQb11("是");
+		}else {
+			vo.setQb11("否");
+		}
+
+		//经济概况
+		//研发费用
+		XmCostDetailsDTO dto = new XmCostDetailsDTO();
+		dto.setYearAndMonth(year+"12");
+		List<HighTechCostSummary> list = xmCostDetailsService.highTechCostSummary(Condition.getPage(new Query().setCurrent(1).setSize(Integer.MAX_VALUE)), dto).getRecords();
+		list.forEach(item -> {
+ 			item.setTotal(item.getRyrgTotal().add(item.getZjtrTotal()).add(item.getZjfyycqdtfyTotal()).add(item.getSjfTotal()).add(item.getWxzctxTotal()).add(item.getZbtsfyysyfyTotal()).add(item.getQtfyAdjust()).add(item.getWwyfTotal()));
+		});
+		vo.setQc236(list.stream().map(HighTechCostSummary::getTotal).reduce(BigDecimal.ZERO, BigDecimal::add).multiply(new BigDecimal("0.001")));
+
+		//享受高新技术企业所得税减免
+		A107041 a107041 = a107041Mapper.selectOne(Wrappers.<A107041>lambdaQuery().eq(A107041::getYearAndMonth, year));
+		if(Func.notNull(a107041)){
+			vo.setQc20_1(a107041.getD31());
+		}
+		return vo;
+    }
+
 }

+ 6 - 0
kd-service/kd-scientific/src/main/java/org/sky/scientific/service/impl/HoursSyncServiceImpl.java

@@ -19,6 +19,7 @@ import org.sky.scientific.pojo.entity.TechnicianEntity;
 import org.sky.scientific.pojo.entity.XmTechnicianHours;
 import org.sky.scientific.pojo.vo.XmVO;
 import org.sky.scientific.service.IHoursSyncService;
+import org.sky.scientific.service.IXmService;
 import org.sky.system.feign.ISysClient;
 import org.sky.system.pojo.entity.Tenant;
 import org.springframework.http.*;
@@ -40,6 +41,7 @@ public class HoursSyncServiceImpl implements IHoursSyncService {
 	private final RestTemplate restTemplate;
 	private final ISysClient sysClient;
 	private final XmMapper xmMapper;
+	private final IXmService xmService;
 	private final TechnicianMapper technicianMapper;
 	private static final String BASE_URL = "https://yanfa.jishutao.com/prod-api";
 	private static final String URL_LOGIN = BASE_URL + "/login";
@@ -216,6 +218,10 @@ public class HoursSyncServiceImpl implements IHoursSyncService {
 						if (xmId <= 0L) {
 							continue;
 						}
+//						if (xmService.judgeXmIsOver(xmId, false)) {
+//							continue;
+//						}
+
 						String identifier = SecureUtil.getTenantId() + ":" + xmId + ":" + tenantAndUnicode.get(1) + ":" + recordTime;
 						if (identifierList.contains(identifier)) {
 							//现有的,做修改

+ 5 - 5
kd-service/kd-scientific/src/main/java/org/sky/scientific/service/impl/SettingServiceImpl.java

@@ -100,9 +100,9 @@ public class SettingServiceImpl implements SettingService {
 		}
 	}
 
-	@Override
-	public List<SettingEntity> torchDevList(String yearMin, String yearMax) {
-		return mapper.selectList(Wrappers.<SettingEntity>lambdaQuery()
-				.between(SettingEntity::getYearAndMonth, yearMin, yearMax));
-	}
+//	@Override
+//	public List<SettingEntity> torchDevList(String yearMin, String yearMax) {
+//		return mapper.selectList(Wrappers.<SettingEntity>lambdaQuery()
+//				.between(SettingEntity::getYearAndMonth, yearMin, yearMax));
+//	}
 }

+ 43 - 9
kd-service/kd-scientific/src/main/java/org/sky/scientific/service/impl/TechnicianServiceImpl.java

@@ -27,6 +27,7 @@ import org.sky.scientific.e.XmStatusEnum;
 import org.sky.scientific.excel.TechnicianExcel;
 import org.sky.scientific.excel.handle.MergeCellRangeWriteHandler;
 import org.sky.scientific.excel.handle.XmcyryhzmExcel;
+import org.sky.scientific.excel.listener.XmTechnicianImportListener;
 import org.sky.scientific.mapper.*;
 import org.sky.scientific.pojo.dto.TechnicianDTO;
 import org.sky.scientific.pojo.dto.XmSalaryDto;
@@ -34,12 +35,14 @@ import org.sky.scientific.pojo.dto.XmTechnicianDto;
 import org.sky.scientific.pojo.entity.*;
 import org.sky.scientific.pojo.vo.*;
 import org.sky.scientific.service.ITechnicianService;
+import org.sky.scientific.service.IXmService;
 import org.sky.system.cache.DictCache;
 import org.sky.system.pojo.enums.DictEnum;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.web.multipart.MultipartFile;
 
+import java.io.BufferedInputStream;
 import java.io.InputStream;
 import java.io.OutputStream;
 import java.math.BigDecimal;
@@ -67,7 +70,7 @@ public class TechnicianServiceImpl extends BaseServiceImpl<TechnicianMapper, Tec
 	private final DepartmentMapper departmentMapper;
 	private final SalaryMapper salaryMapper;
 	private final AttendanceMapper attendanceMapper;
-	private final XmJtbMapper xmJtbMapper;
+	private final IXmService xmService;
 
 	@Override
 	public boolean insertTechnician(TechnicianEntity technician) {
@@ -387,11 +390,8 @@ public class TechnicianServiceImpl extends BaseServiceImpl<TechnicianMapper, Tec
 
 	@Override
 	public boolean submitXmTechnicianMonthly(XmTechnicianEntity entity) {
+		xmService.judgeXmIsOver(entity.getXmId(), true);
 
-		Integer status = xmMapper.getXmStatusByXmId(entity.getXmId());
-		if (Func.equals(status, XmStatusEnum.已结题.getCode())) {
-			throw new ServiceException("项目已结题,不可操作");
-		}
 		int affectNum = 0;
 		entity.setId(null);
 		entity.setYearAndMonth(entity.getYearAndMonth());
@@ -420,10 +420,7 @@ public class TechnicianServiceImpl extends BaseServiceImpl<TechnicianMapper, Tec
 			throw new ServiceException("数据不存在");
 		}
 
-		Integer status = xmMapper.getXmStatusByXmId(dbXmTechnician.getXmId());
-		if (Func.equals(status, XmStatusEnum.已结题.getCode())) {
-			throw new ServiceException("项目已结题,不可操作");
-		}
+		xmService.judgeXmIsOver(dbXmTechnician.getXmId(), true);
 
 		//每月研发人员工资
 		if (salaryMapper.selectCount(Wrappers.<SalaryEntity>lambdaQuery().eq(SalaryEntity::getYearAndMonth, dbXmTechnician.getYearAndMonth()).eq(SalaryEntity::getUnicode, dbXmTechnician.getUnicode())) > 0) {
@@ -809,4 +806,41 @@ public class TechnicianServiceImpl extends BaseServiceImpl<TechnicianMapper, Tec
 		}
 	}
 
+	@SneakyThrows
+	@Override
+	public boolean importXmTechnicianMonthly(MultipartFile file, String yearAndMonth) {
+		XmTechnicianImportListener listener = new XmTechnicianImportListener();
+		EasyExcel.read(new BufferedInputStream(file.getInputStream()))
+			.registerReadListener(listener)
+			.sheet(0)
+			.headRowNumber(2) // 重要:设置表头行数(0-based)
+			.doRead();
+		List<XmTechnicianEntity> dataList = listener.getDataList();
+		if (CollectionUtil.isEmpty(dataList)) {
+			throw new ServiceException("未能从模板中读取数据,请检查模板格式是否正确");
+		}
+		for (XmTechnicianEntity excel : dataList) {
+			String unicode = baseMapper.getUnicodeByNumberAndIdentityCard(excel.getNumber(), excel.getIdCard());
+			if(Func.isBlank(unicode)){
+				throw new ServiceException("工号["+excel.getNumber()+"]/身份证["+excel.getIdCard()+"]不存在");
+			}
+			Long xmId = xmMapper.getXmIdByXmmcOrXmbh(null, null, excel.getXmbh());
+			if (Func.isNull(xmId)) {
+				throw new ServiceException("项目不存在,请检查数据");
+			}
+			xmService.judgeXmIsOver(xmId, true);
+
+			LambdaQueryWrapper<XmTechnicianEntity> wrapper = Wrappers.<XmTechnicianEntity>lambdaQuery().
+				eq(XmTechnicianEntity::getYearAndMonth, yearAndMonth).
+				eq(XmTechnicianEntity::getUnicode, unicode).
+				eq(XmTechnicianEntity::getXmId, xmId);
+			if (xmTechnicianMapper.selectCount(wrapper) == 0) {
+				xmTechnicianMapper.insert(excel);
+			} else {
+				throw new ServiceException("科技人员已是参研人员,请勿重复添加");
+			}
+		}
+		return true;
+	}
+
 }

+ 16 - 15
kd-service/kd-scientific/src/main/java/org/sky/scientific/service/impl/XmAssetHoursServiceImpl.java

@@ -7,7 +7,7 @@ import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
-import jakarta.annotation.Resource;
+import lombok.AllArgsConstructor;
 import lombok.SneakyThrows;
 import lombok.extern.slf4j.Slf4j;
 import org.sky.core.log.exception.ServiceException;
@@ -29,6 +29,7 @@ import org.sky.scientific.pojo.entity.XmAssetHoursEntity;
 import org.sky.scientific.pojo.vo.DailyAttendance;
 import org.sky.scientific.pojo.vo.XmAssetHoursVO;
 import org.sky.scientific.service.IXmAssetHoursService;
+import org.sky.scientific.service.IXmService;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.web.multipart.MultipartFile;
@@ -49,13 +50,12 @@ import java.util.concurrent.atomic.AtomicInteger;
  */
 @Slf4j
 @Service
+@AllArgsConstructor
 public class XmAssetHoursServiceImpl extends BaseServiceImpl<XmAssetHoursMapper, XmAssetHoursEntity> implements IXmAssetHoursService {
 
-	@Resource
-	private XmMapper xmMapper;
-
-	@Resource
-	private AssetMapper assetMapper;
+	private final XmMapper xmMapper;
+	private final AssetMapper assetMapper;
+	private final IXmService xmService;
 
 	@SneakyThrows
 	@Transactional(rollbackFor = Exception.class)
@@ -90,6 +90,7 @@ public class XmAssetHoursServiceImpl extends BaseServiceImpl<XmAssetHoursMapper,
 			if (xmId == null) {
 				throw new ServiceException("序号为[" + record.getSerialNumber() + "]的研发项目不存在");
 			}
+			xmService.judgeXmIsOver(xmId, true);
 
 			if (StringUtil.isBlank(record.getZcbm())) {
 				throw new ServiceException("序号为[" + record.getSerialNumber() + "]的资产编码为空");
@@ -158,6 +159,7 @@ public class XmAssetHoursServiceImpl extends BaseServiceImpl<XmAssetHoursMapper,
 	}
 
 	@Override
+	@Transactional
 	public boolean batchSubmitXmAssetHours(XmAssetHoursDto dto) {
 		if (StringUtil.isBlank(dto.getYearAndMonth())) {
 			throw new ServiceException("参数yearAndMonth不能为空");
@@ -165,6 +167,7 @@ public class XmAssetHoursServiceImpl extends BaseServiceImpl<XmAssetHoursMapper,
 		if (dto.getXmId() == null) {
 			throw new ServiceException("参数xmId不能为空");
 		}
+		xmService.judgeXmIsOver(dto.getXmId(), true);
 		if (dto.getAssetId() == null) {
 			throw new ServiceException("参数assetId不能为空");
 		}
@@ -175,7 +178,6 @@ public class XmAssetHoursServiceImpl extends BaseServiceImpl<XmAssetHoursMapper,
 		}
 
 		if (dto.getZgs() != null) {
-
 			//不能大于当月工作天数(自然天数)X24小时
 			// 解析年份和月份
 			int year = Integer.parseInt(dto.getYearAndMonth().substring(0, 4));
@@ -188,11 +190,6 @@ public class XmAssetHoursServiceImpl extends BaseServiceImpl<XmAssetHoursMapper,
 				throw new ServiceException("总工时不能大于当月工作天数X24小时");
 			}
 
-			//总工时未填,且两次工时不一致
-//			if(dbAsset.getZgs()!=null && !Objects.equals(dbAsset.getZgs(),dto.getZgs())){
-//				throw new ServiceException("该资产在["+dto.getYearAndMonth()+"]已有总工时["+dbAsset.getZgs()+"]");
-//			}
-
 			dbAsset.setZgs(dto.getZgs());
 			assetMapper.updateById(dbAsset);
 		}
@@ -242,9 +239,13 @@ public class XmAssetHoursServiceImpl extends BaseServiceImpl<XmAssetHoursMapper,
 		if (xmAndAssetIdList == null || xmAndAssetIdList.isEmpty()) {
 			throw new ServiceException("参数xmAndAssetIdList不能为空");
 		}
-		for (Object xmAndAssetId : xmAndAssetIdList) {
-			Map<String, String> map = (HashMap<String, String>) xmAndAssetId;
-			baseMapper.clearXmAssetHours(dto.getString("yearAndMonth"), Long.valueOf(map.get("xmId")), Long.valueOf(map.get("assetId")));
+		for (int i = 0; i < xmAndAssetIdList.size(); i++) {
+			JSONObject object = xmAndAssetIdList.getJSONObject(i);
+			Long xmId = object.getLong("xmId");
+			xmService.judgeXmIsOver(xmId, true);
+			Long assetId = object.getLong("assetId");
+			String yearAndMonth = dto.getString("yearAndMonth");
+			baseMapper.clearXmAssetHours(yearAndMonth, xmId, assetId);
 		}
 		return true;
 	}

+ 17 - 0
kd-service/kd-scientific/src/main/java/org/sky/scientific/service/impl/XmCostDetailsServiceImpl.java

@@ -34,9 +34,11 @@ import org.sky.scientific.pojo.entity.SubjectEnterprise;
 import org.sky.scientific.pojo.entity.XmCostDetailsEntity;
 import org.sky.scientific.pojo.vo.*;
 import org.sky.scientific.service.IXmCostDetailsService;
+import org.sky.scientific.service.IXmService;
 import org.sky.system.feign.ISysClient;
 import org.sky.system.pojo.entity.Tenant;
 import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
 import org.springframework.web.multipart.MultipartFile;
 
 import java.io.InputStream;
@@ -61,6 +63,7 @@ public class XmCostDetailsServiceImpl extends BaseServiceImpl<XmCostDetailsMappe
 	private final SubjectEnterpriseMapper subjectEnterpriseMapper;
 	private final DeductionCostQtMapper qtMapper;
 	private final ISysClient sysClient;
+	private final IXmService xmService;
 
 	@Override
 	public IPage<XmCostDetailsEntity> selectXmCostDetailsPage(IPage<XmCostDetailsEntity> page, XmCostDetailsDTO dto) {
@@ -86,6 +89,11 @@ public class XmCostDetailsServiceImpl extends BaseServiceImpl<XmCostDetailsMappe
 		if (judged != null) {
 			throw new ServiceException(judged);
 		}
+		if (Func.isNull(xmCostDetails.getXmId())) {
+			throw new ServiceException("参数xmId不能为空");
+		}
+		xmService.judgeXmIsOver(xmCostDetails.getXmId(), true);
+
 		if (Func.isEmpty(xmCostDetails.getId())) {
 			//新增
 			result = this.save(xmCostDetails);
@@ -97,7 +105,14 @@ public class XmCostDetailsServiceImpl extends BaseServiceImpl<XmCostDetailsMappe
 	}
 
 	@Override
+	@Transactional
 	public boolean physicalDeleteByIds(List<Long> ids) {
+		for (Long id : ids) {
+			XmCostDetailsEntity entity = baseMapper.selectById(id);
+			if (Func.notNull(entity)) {
+				xmService.judgeXmIsOver(entity.getXmId(), true);
+			}
+		}
 		return baseMapper.physicalDeleteByIds(ids) > 0;
 	}
 
@@ -136,6 +151,8 @@ public class XmCostDetailsServiceImpl extends BaseServiceImpl<XmCostDetailsMappe
 			if (xmId == null) {
 				throw new ServiceException("研发项目编号[" + excel.getXmbh() + "]不存在,请检查模板数据");
 			}
+			xmService.judgeXmIsOver(xmId, true);
+
 			entity.setXmId(xmId);
 
 			//根据企业科目代码查询id

+ 12 - 0
kd-service/kd-scientific/src/main/java/org/sky/scientific/service/impl/XmDesignCostServiceImpl.java

@@ -21,6 +21,7 @@ import org.sky.scientific.pojo.dto.XmDesignCostQuery;
 import org.sky.scientific.pojo.entity.XmDesignCostEntity;
 import org.sky.scientific.pojo.vo.XmDesignCostVO;
 import org.sky.scientific.service.IXmDesignCostService;
+import org.sky.scientific.service.IXmService;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.web.multipart.MultipartFile;
@@ -41,6 +42,7 @@ import java.util.concurrent.atomic.AtomicInteger;
 public class XmDesignCostServiceImpl extends BaseServiceImpl<XmDesignCostMapper, XmDesignCostEntity> implements IXmDesignCostService {
 
 	private final XmMapper xmMapper;
+	private final IXmService xmService;
 
 	@Override
 	public IPage<XmDesignCostVO> selectXmDesignCostPage(IPage<XmDesignCostVO> page, XmDesignCostQuery param) {
@@ -88,6 +90,8 @@ public class XmDesignCostServiceImpl extends BaseServiceImpl<XmDesignCostMapper,
 				throw new ServiceException("序号[" + data.getXh() + "]的研发项目不存在,请检查模板数据");
 			}
 
+			xmService.judgeXmIsOver(xmId, true);
+
 			XmDesignCostEntity entity = Objects.requireNonNull(BeanUtil.copyProperties(data, XmDesignCostEntity.class));
 			entity.setXmId(xmId);
 			entity.setYearAndMonth(yearAndMonth);
@@ -99,7 +103,14 @@ public class XmDesignCostServiceImpl extends BaseServiceImpl<XmDesignCostMapper,
 	}
 
 	@Override
+	@Transactional
 	public boolean physicalDeleteByIds(List<Long> ids) {
+		for (Long id : ids) {
+			XmDesignCostEntity entity = baseMapper.selectById(id);
+			if(Func.notNull(entity)){
+				xmService.judgeXmIsOver(entity.getXmId(), true);
+			}
+		}
 		return baseMapper.physicalDeleteByIds(ids) > 0;
 	}
 
@@ -138,6 +149,7 @@ public class XmDesignCostServiceImpl extends BaseServiceImpl<XmDesignCostMapper,
 		if (judged != null) {
 			throw new ServiceException(judged);
 		}
+		xmService.judgeXmIsOver(xmDesignCost.getXmId(), true);
 		return this.saveOrUpdate(xmDesignCost);
 	}
 

+ 15 - 4
kd-service/kd-scientific/src/main/java/org/sky/scientific/service/impl/XmDirectCostServiceImpl.java

@@ -7,8 +7,8 @@ import com.alibaba.excel.support.ExcelTypeEnum;
 import com.alibaba.excel.write.metadata.WriteSheet;
 import com.alibaba.excel.write.metadata.fill.FillConfig;
 import com.baomidou.mybatisplus.core.metadata.IPage;
-import jakarta.annotation.Resource;
 import jakarta.servlet.http.HttpServletResponse;
+import lombok.AllArgsConstructor;
 import lombok.SneakyThrows;
 import org.sky.core.excel.util.ExcelUtil;
 import org.sky.core.log.exception.ServiceException;
@@ -20,8 +20,10 @@ import org.sky.scientific.mapper.XmMapper;
 import org.sky.scientific.pojo.entity.XmDirectCostEntity;
 import org.sky.scientific.pojo.vo.XmDirectCostSummary;
 import org.sky.scientific.service.IXmDirectCostService;
+import org.sky.scientific.service.IXmService;
 import org.sky.system.cache.DictCache;
 import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
 import org.springframework.web.multipart.MultipartFile;
 
 import java.io.InputStream;
@@ -38,10 +40,11 @@ import java.util.concurrent.atomic.AtomicInteger;
  * @since 2025-07-17
  */
 @Service
+@AllArgsConstructor
 public class XmDirectCostServiceImpl extends BaseServiceImpl<XmDirectCostMapper, XmDirectCostEntity> implements IXmDirectCostService {
 
-	@Resource
-	private XmMapper xmMapper;
+	private final XmMapper xmMapper;
+	private final IXmService xmService;
 
 	@Override
 	public IPage<XmDirectCostEntity> selectXmDirectCostPage(IPage<XmDirectCostEntity> page, XmDirectCostEntity dto) {
@@ -104,8 +107,8 @@ public class XmDirectCostServiceImpl extends BaseServiceImpl<XmDirectCostMapper,
 				if (xmId == null) {
 					throw new ServiceException("研发项目[" + excel.getXmbh() + "]不存在,请检查模板数据");
 				}
+				xmService.judgeXmIsOver(xmId, true);
 				entity.setXmId(xmId);
-
 			}
 			entity.setYearAndMonth(yearAndMonth);
 			insertList.add(entity);
@@ -114,7 +117,14 @@ public class XmDirectCostServiceImpl extends BaseServiceImpl<XmDirectCostMapper,
 	}
 
 	@Override
+	@Transactional
 	public boolean physicalDeleteByIds(List<Long> ids) {
+		for (Long id : ids) {
+			XmDirectCostEntity entity = baseMapper.selectById(id);
+			if(Func.notNull(entity)){
+				xmService.judgeXmIsOver(entity.getXmId(), true);
+			}
+		}
 		return baseMapper.physicalDeleteByIds(ids) > 0;
 	}
 
@@ -123,6 +133,7 @@ public class XmDirectCostServiceImpl extends BaseServiceImpl<XmDirectCostMapper,
 		if (StringUtil.isBlank(xmDirectCost.getYearAndMonth())) {
 			throw new ServiceException("参数yearAndMonth不能为空");
 		}
+		xmService.judgeXmIsOver(xmDirectCost.getXmId(), true);
 		String judged = DateUtil.judgeDate(xmDirectCost.getUseDate(), xmDirectCost.getYearAndMonth());
 		if (judged != null) {
 			throw new ServiceException(judged);

+ 37 - 39
kd-service/kd-scientific/src/main/java/org/sky/scientific/service/impl/XmFixedAssetServiceImpl.java

@@ -7,8 +7,8 @@ import com.alibaba.excel.write.metadata.WriteSheet;
 import com.alibaba.excel.write.metadata.fill.FillConfig;
 import com.alibaba.fastjson.JSONObject;
 import com.baomidou.mybatisplus.core.metadata.IPage;
-import jakarta.annotation.Resource;
 import jakarta.servlet.http.HttpServletResponse;
+import lombok.AllArgsConstructor;
 import lombok.SneakyThrows;
 import lombok.extern.slf4j.Slf4j;
 import org.sky.core.excel.util.ExcelUtil;
@@ -19,7 +19,6 @@ import org.sky.core.mp.support.Query;
 import org.sky.core.secure.utils.SecureUtil;
 import org.sky.core.tool.utils.*;
 import org.sky.scientific.e.AssetStatusEnum;
-import org.sky.scientific.e.XmStatusEnum;
 import org.sky.scientific.excel.XmFixedAssetExcel;
 import org.sky.scientific.mapper.AssetMapper;
 import org.sky.scientific.mapper.XmFixedAssetMapper;
@@ -31,6 +30,7 @@ import org.sky.scientific.pojo.entity.XmFixedAsset;
 import org.sky.scientific.pojo.entity.YsZjfyycqdtfyEntity;
 import org.sky.scientific.pojo.vo.XmFixedAssetCostVo;
 import org.sky.scientific.service.IXmFixedAssetService;
+import org.sky.scientific.service.IXmService;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.web.multipart.MultipartFile;
@@ -50,14 +50,13 @@ import java.util.concurrent.atomic.AtomicInteger;
  */
 @Slf4j
 @Service
+@AllArgsConstructor
 public class XmFixedAssetServiceImpl extends BaseServiceImpl<XmFixedAssetMapper, XmFixedAsset> implements IXmFixedAssetService {
 
-	@Resource
-	private YsZjfyycqdtfyMapper ysZjfyycqdtfyMapper;
-	@Resource
-	private XmMapper xmMapper;
-	@Resource
-	private AssetMapper assetMapper;
+	private final YsZjfyycqdtfyMapper ysZjfyycqdtfyMapper;
+	private final XmMapper xmMapper;
+	private final AssetMapper assetMapper;
+	private final IXmService xmService;
 
 	@Override
 	public IPage<XmFixedAsset> selectXmFixAssetPage(IPage<XmFixedAsset> page, XmAssetQueryParam param, String zclb) {
@@ -85,23 +84,26 @@ public class XmFixedAssetServiceImpl extends BaseServiceImpl<XmFixedAssetMapper,
 		Date lastDate = DateUtil.minusMonths(DateUtil.parse(yearAndMonth, DateUtil.PATTERN_YYYYMM), 1);
 		//获取上个月数据
 		List<XmFixedAsset> lastMonthList = baseMapper.selectXmFixedAssetByYearAndMonth(DateUtil.format(lastDate, DateUtil.PATTERN_YYYYMM), zclb);
-		List<Long> list = lastMonthList.stream().map(XmFixedAsset::getXmId).toList();
-		for (Long xmId : list) {
-			Integer xmStatus = xmMapper.getXmStatusByXmId(xmId);
-			if (Func.equals(xmStatus, XmStatusEnum.已结题.getCode())) {
-				throw new ServiceException("项目已结题,不可操作");
-			}
-		}
 		//获取本月数据
 		List<XmFixedAsset> thisMonthList = baseMapper.selectXmFixedAssetByYearAndMonth(yearAndMonth, zclb);
-
 		List<String> zcbmList = thisMonthList.stream().map(XmFixedAsset::getZcbm).toList();
+
+		//已结题项目列表
+		List<Long> jtXmIdList = new ArrayList<>();
+		//待新增的数据
+		List<XmFixedAsset> insertList = new ArrayList<>();
 		if (!CollectionUtil.isEmpty(lastMonthList)) {
 			//复制上个月数据到本月
-			List<XmFixedAsset> insertList = new ArrayList<>();
 			for (XmFixedAsset dbAsset : lastMonthList) {
 				//dbAsset已存在,则跳过
-				if (CollectionUtil.isNotEmpty(zcbmList) && zcbmList.contains(dbAsset.getZcbm())) {
+				if (zcbmList.contains(dbAsset.getZcbm())) {
+					continue;
+				}
+				if (jtXmIdList.contains(dbAsset.getXmId())) {
+					continue;
+				}
+				if(xmService.judgeXmIsOver(dbAsset.getXmId(), false)){
+					jtXmIdList.add(dbAsset.getXmId());
 					continue;
 				}
 				XmFixedAsset asset = new XmFixedAsset();
@@ -110,31 +112,34 @@ public class XmFixedAssetServiceImpl extends BaseServiceImpl<XmFixedAssetMapper,
 				asset.setZcbm(dbAsset.getZcbm());
 				insertList.add(asset);
 			}
-			if (CollectionUtil.isNotEmpty(insertList)) {
-				return this.saveBatch(insertList);
-			}
 		} else {
 			//若无,则获取预算表中的资产,研发项目周期(含变更)包含本月的
 			List<YsZjfyycqdtfyEntity> ysList = ysZjfyycqdtfyMapper.selectByYearAndMonth(yearAndMonth, zclb);
 			if (CollectionUtil.isEmpty(ysList)) {
 				throw new ServiceException("项目预算表中无" + zclb);
 			}
-			List<XmFixedAsset> insertList = new ArrayList<>();
 			for (YsZjfyycqdtfyEntity ys : ysList) {
 				if (CollectionUtil.isNotEmpty(zcbmList) && zcbmList.contains(ys.getZcbm())) {
 					continue;
 				}
+				if (jtXmIdList.contains(ys.getXmId())) {
+					continue;
+				}
+				if(xmService.judgeXmIsOver(ys.getXmId(), false)){
+					jtXmIdList.add(ys.getXmId());
+					continue;
+				}
 				XmFixedAsset asset = new XmFixedAsset();
 				asset.setYearAndMonth(yearAndMonth);
 				asset.setXmId(ys.getXmId());
 				asset.setZcbm(ys.getZcbm());
 				insertList.add(asset);
 			}
-			if (CollectionUtil.isNotEmpty(insertList)) {
-				return this.saveBatch(insertList);
-			}
 		}
-		return true;
+		if (CollectionUtil.isEmpty(insertList)) {
+			throw new ServiceException("数据已全部引用");
+		}
+		return this.saveBatch(insertList);
 	}
 
 	@Override
@@ -158,7 +163,7 @@ public class XmFixedAssetServiceImpl extends BaseServiceImpl<XmFixedAssetMapper,
 			if (CollectionUtil.isNotEmpty(zcbmList) && zcbmList.contains(excel.getZcbm())) {
 				continue;
 			}
-			if (StringUtil.isBlank(excel.getXmbh())) {
+			if (Func.isBlank(excel.getXmbh())) {
 				throw new ServiceException("序号为[" + excel.getXh() + "]的项目研发编号为空");
 			}
 			String xmkey = "xm:" + excel.getXmbh();
@@ -168,10 +173,8 @@ public class XmFixedAssetServiceImpl extends BaseServiceImpl<XmFixedAssetMapper,
 				if (xmId == null) {
 					throw new ServiceException("序号为[" + excel.getXh() + "]的项目不存在");
 				}
-				Integer status = xmMapper.getXmStatusByXmId(xmId);
-				if (Func.equals(status, XmStatusEnum.已结题.getCode())) {
-					throw new ServiceException("项目已结题,不可操作");
-				}
+
+				xmService.judgeXmIsOver(xmId, true);
 			}
 
 			xmIdMap.put(xmkey, xmId);
@@ -208,10 +211,7 @@ public class XmFixedAssetServiceImpl extends BaseServiceImpl<XmFixedAssetMapper,
 	public boolean physicalDeleteByIds(List<Long> ids) {
 		for (Long id : ids) {
 			XmFixedAsset fixedAsset = baseMapper.selectById(id);
-			Integer status = xmMapper.getXmStatusByXmId(fixedAsset.getXmId());
-			if (Func.equals(status, XmStatusEnum.已结题.getCode())) {
-				throw new ServiceException("项目已结题,不可操作");
-			}
+			xmService.judgeXmIsOver(fixedAsset.getXmId(), true);
 		}
 		return baseMapper.physicalDeleteByIds(ids);
 	}
@@ -221,10 +221,8 @@ public class XmFixedAssetServiceImpl extends BaseServiceImpl<XmFixedAssetMapper,
 		if (StringUtil.isBlank(xmAsset.getYearAndMonth())) {
 			throw new ServiceException("参数yearAndMonth不能为空");
 		}
-		Integer status = xmMapper.getXmStatusByXmId(xmAsset.getXmId());
-		if (Func.equals(status, XmStatusEnum.已结题.getCode())) {
-			throw new ServiceException("项目已结题,不可操作");
-		}
+
+		xmService.judgeXmIsOver(xmAsset.getXmId(), true);
 		//获取本月数据
 		List<XmFixedAsset> thisMonthList = baseMapper.selectXmFixedAssetByYearAndMonth(xmAsset.getYearAndMonth(), zclb);
 

+ 22 - 15
kd-service/kd-scientific/src/main/java/org/sky/scientific/service/impl/XmGoodsServiceImpl.java

@@ -8,7 +8,7 @@ import com.alibaba.excel.write.metadata.WriteSheet;
 import com.alibaba.excel.write.metadata.fill.FillConfig;
 import com.alibaba.fastjson.JSONObject;
 import com.baomidou.mybatisplus.core.metadata.IPage;
-import jakarta.annotation.Resource;
+import lombok.AllArgsConstructor;
 import lombok.SneakyThrows;
 import lombok.extern.slf4j.Slf4j;
 import org.sky.core.excel.util.ExcelUtil;
@@ -22,7 +22,9 @@ import org.sky.scientific.pojo.dto.XmGoodsDTO;
 import org.sky.scientific.pojo.entity.XmGoodsEntity;
 import org.sky.scientific.pojo.vo.XmGoodsVO;
 import org.sky.scientific.service.IXmGoodsService;
+import org.sky.scientific.service.IXmService;
 import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
 import org.springframework.web.multipart.MultipartFile;
 
 import java.io.InputStream;
@@ -40,10 +42,11 @@ import java.util.stream.Collectors;
  */
 @Slf4j
 @Service
+@AllArgsConstructor
 public class XmGoodsServiceImpl extends BaseServiceImpl<XmGoodsMapper, XmGoodsEntity> implements IXmGoodsService {
 
-	@Resource
-	private XmMapper xmMapper;
+	private final XmMapper xmMapper;
+	private final IXmService xmService;
 
 	@Override
 	public IPage<XmGoodsVO> selectXmGoodsPage(IPage<XmGoodsVO> page, XmGoodsDTO dto) {
@@ -57,16 +60,16 @@ public class XmGoodsServiceImpl extends BaseServiceImpl<XmGoodsMapper, XmGoodsEn
 	@Override
 	public void exportXmGoods(OutputStream os, List<XmGoodsVO> list, String yearAndMonth) {
 		InputStream templateFileName = this.getClass().getClassLoader().getResourceAsStream("export-template/研发领料燃料动力明细清单.xls");
-		 AtomicInteger index = new AtomicInteger(1);
+		AtomicInteger index = new AtomicInteger(1);
 		List<XmGoodsExcel> resultList = new ArrayList<>();
 		for (XmGoodsVO vo : list) {
 			XmGoodsExcel excel = BeanUtil.copyProperties(vo, XmGoodsExcel.class);
 			assert excel != null;
 			excel.setXh(index.getAndIncrement() + "");
-			if(excel.getUnitPrice()==null){
+			if (excel.getUnitPrice() == null) {
 				excel.setUnitPrice(BigDecimal.ZERO);
 			}
-			if(excel.getUseQuantity()==null){
+			if (excel.getUseQuantity() == null) {
 				excel.setUseQuantity(0);
 			}
 			excel.setAmount(excel.getUnitPrice().multiply(new BigDecimal(excel.getUseQuantity())));
@@ -111,8 +114,9 @@ public class XmGoodsServiceImpl extends BaseServiceImpl<XmGoodsMapper, XmGoodsEn
 				//根据项目名称或编号查询xmId
 				Long xmId = xmMapper.getXmIdByXmmcOrXmbh(null, null, excel.getXmbh());
 				if (xmId == null) {
-					throw new ServiceException("研发项目[" + excel.getXmbh()+"]不存在,请检查模板数据");
+					throw new ServiceException("研发项目[" + excel.getXmbh() + "]不存在,请检查模板数据");
 				}
+				xmService.judgeXmIsOver(xmId, true);
 				entity.setXmId(xmId);
 			}
 			entity.setYearAndMonth(yearAndMonth);
@@ -122,7 +126,14 @@ public class XmGoodsServiceImpl extends BaseServiceImpl<XmGoodsMapper, XmGoodsEn
 	}
 
 	@Override
+	@Transactional
 	public boolean physicalDeleteByIds(List<Long> ids) {
+		for (Long id : ids) {
+			XmGoodsEntity entity = baseMapper.selectById(id);
+			if (Func.notNull(entity)) {
+				xmService.judgeXmIsOver(entity.getXmId(), true);
+			}
+		}
 		return baseMapper.physicalDeleteByIds(ids) > 0;
 	}
 
@@ -132,6 +143,8 @@ public class XmGoodsServiceImpl extends BaseServiceImpl<XmGoodsMapper, XmGoodsEn
 			throw new ServiceException("参数yearAndMonth不能为空");
 		}
 
+		xmService.judgeXmIsOver(xmGoods.getXmId(), true);
+
 		if (Func.notNull(xmGoods.getUseQuantity()) && Func.notNull(xmGoods.getUnitPrice())) {
 			xmGoods.setAmount(xmGoods.getUnitPrice().multiply(new BigDecimal(xmGoods.getUseQuantity())));
 		}
@@ -154,7 +167,6 @@ public class XmGoodsServiceImpl extends BaseServiceImpl<XmGoodsMapper, XmGoodsEn
 			throw new ServiceException("参数type为空,或者不在[材料、燃料、动力]之列");
 		}
 		List<XmGoodsVO> list = baseMapper.yanfalingliaodan(dto);
-
 		List<JSONObject> result = new ArrayList<>();
 		if (CollectionUtil.isEmpty(list)) {
 			return result;
@@ -162,12 +174,9 @@ public class XmGoodsServiceImpl extends BaseServiceImpl<XmGoodsMapper, XmGoodsEn
 		Map<Long, List<XmGoodsVO>> mapByXmId = list.stream().collect(Collectors.groupingBy(XmGoodsVO::getXmId));
 		for (Long xmId : mapByXmId.keySet()) {
 			List<XmGoodsVO> listByXmId = mapByXmId.get(xmId);
-
 			for (XmGoodsVO vo : listByXmId) {
 				String key = xmId + ":" + DateUtil.format(vo.getUseDate(), DateUtil.PATTERN_DATE);
-
 				if (result.isEmpty()) {
-
 					ArrayList<XmGoodsVO> vos = new ArrayList<>();
 					vos.add(vo);
 					JSONObject o = new JSONObject();
@@ -227,10 +236,10 @@ public class XmGoodsServiceImpl extends BaseServiceImpl<XmGoodsMapper, XmGoodsEn
 			assert excel != null;
 			excel.setXh(index.getAndIncrement() + "");
 			excel.setUseDateStr(Func.notNull(temp.getUseDate()) ? DateUtil.format(temp.getUseDate(), DateUtil.PATTERN_DATE) : null);
-			if(excel.getUseQuantity()==null){
+			if (excel.getUseQuantity() == null) {
 				excel.setUseQuantity(0);
 			}
-			if(excel.getUnitPrice()==null){
+			if (excel.getUnitPrice() == null) {
 				excel.setUnitPrice(BigDecimal.ZERO);
 			}
 			excel.setAmount(BigDecimal.valueOf(excel.getUseQuantity()).multiply(excel.getUnitPrice()));
@@ -259,6 +268,4 @@ public class XmGoodsServiceImpl extends BaseServiceImpl<XmGoodsMapper, XmGoodsEn
 			templateFileName.close();
 		}
 	}
-
-
 }

+ 39 - 32
kd-service/kd-scientific/src/main/java/org/sky/scientific/service/impl/XmIntangibleAssetServiceImpl.java

@@ -20,7 +20,6 @@ import org.sky.core.mp.support.Query;
 import org.sky.core.secure.utils.SecureUtil;
 import org.sky.core.tool.utils.*;
 import org.sky.scientific.e.AssetStatusEnum;
-import org.sky.scientific.e.XmStatusEnum;
 import org.sky.scientific.excel.XmIntangibleAssetExcel;
 import org.sky.scientific.mapper.AssetMapper;
 import org.sky.scientific.mapper.XmIntangibleAssetMapper;
@@ -55,9 +54,9 @@ import java.util.stream.Collectors;
 public class XmIntangibleAssetServiceImpl extends BaseServiceImpl<XmIntangibleAssetMapper, XmIntangibleAsset> implements IXmIntangibleAssetService {
 
 	private final YsWxzctxfyMapper ysWxzctxfyMapper;
- 	private final XmMapper xmMapper;
- 	private final AssetMapper assetMapper;
- 	private final IXmService xmService;
+	private final XmMapper xmMapper;
+	private final AssetMapper assetMapper;
+	private final IXmService xmService;
 
 	@Override
 	public IPage<XmIntangibleAsset> selectPage(IPage<XmIntangibleAsset> page, XmAssetQueryParam param) {
@@ -91,50 +90,61 @@ public class XmIntangibleAssetServiceImpl extends BaseServiceImpl<XmIntangibleAs
 		//获取上个月数据
 		List<XmIntangibleAsset> lastMonthList = baseMapper.selectListByYearAndMonth(DateUtil.format(lastDate, DateUtil.PATTERN_YYYYMM));
 
- 		Map<Long, List<XmIntangibleAsset>> c1 = thisMonthList.stream().collect(Collectors.groupingBy(XmIntangibleAsset::getXmId));
-
+		Map<Long, List<XmIntangibleAsset>> c1 = thisMonthList.stream().collect(Collectors.groupingBy(XmIntangibleAsset::getXmId));
+		//已结题项目列表
+		List<Long> jtXmIdList = new ArrayList<>();
+		//待新增的数据
+		List<XmIntangibleAsset> insertList = new ArrayList<>();
 		if (!CollectionUtil.isEmpty(lastMonthList)) {
 			//复制上个月数据到本月
-			List<XmIntangibleAsset> insertList = new ArrayList<>();
 			for (XmIntangibleAsset dbAsset : lastMonthList) {
 				//本月为包含dbAsset,新增
- 				if (Func.isNotEmpty(c1.get(dbAsset.getXmId())) && c1.get(dbAsset.getXmId()).stream().anyMatch(item -> Func.equals(item.getZcbm(), dbAsset.getZcbm()))) {
+				if (Func.isNotEmpty(c1.get(dbAsset.getXmId())) && c1.get(dbAsset.getXmId()).stream().anyMatch(item -> Func.equals(item.getZcbm(), dbAsset.getZcbm()))) {
+					continue;
+				}
+				if (jtXmIdList.contains(dbAsset.getXmId())) {
+					continue;
+				}
+				if(xmService.judgeXmIsOver(dbAsset.getXmId(), false)){
+					jtXmIdList.add(dbAsset.getXmId());
 					continue;
 				}
- 				XmIntangibleAsset asset = new XmIntangibleAsset();
+				XmIntangibleAsset asset = new XmIntangibleAsset();
 				asset.setYearAndMonth(yearAndMonth);
 				asset.setXmId(dbAsset.getXmId());
- 				asset.setZcbm(dbAsset.getZcbm());
+				asset.setZcbm(dbAsset.getZcbm());
 				insertList.add(asset);
- 			}
-			if (CollectionUtil.isNotEmpty(insertList)) {
-				return this.saveBatch(insertList);
-			} else {
-				throw new ServiceException("无数据可引入");
 			}
+
 		} else {
 			//若无,则获取预算表中的无形资产,研发项目周期(含变更)包含本月的
 			List<YsWxzctxfyVO> ysList = ysWxzctxfyMapper.selectByYearAndMonth(yearAndMonth);
 			if (CollectionUtil.isEmpty(ysList)) {
 				throw new ServiceException("项目预算表中没有无形资产");
 			}
-			List<XmIntangibleAsset> insertList = new ArrayList<>();
 			for (YsWxzctxfyVO ys : ysList) {
 				if (Func.isNotEmpty(c1.get(ys.getXmId())) && c1.get(ys.getXmId()).stream().anyMatch(item -> Func.equals(item.getZcbm(), ys.getZcbm()))) {
 					continue;
 				}
+				if (jtXmIdList.contains(ys.getXmId())) {
+					continue;
+				}
+				if(xmService.judgeXmIsOver(ys.getXmId(), false)){
+					jtXmIdList.add(ys.getXmId());
+					continue;
+				}
 				XmIntangibleAsset asset = new XmIntangibleAsset();
 				asset.setYearAndMonth(yearAndMonth);
 				asset.setXmId(ys.getXmId());
 				asset.setZcbm(ys.getZcEntity().getZcbm());
- 				insertList.add(asset);
-			}
-			if (CollectionUtil.isNotEmpty(insertList)) {
-				return this.saveBatch(insertList);
-			} else {
-				throw new ServiceException("无数据可引入");
+				insertList.add(asset);
 			}
 		}
+		if (CollectionUtil.isEmpty(insertList)) {
+			throw new ServiceException("数据已全部引用");
+		}
+		return this.saveBatch(insertList);
+
 	}
 
 	@Override
@@ -162,17 +172,14 @@ public class XmIntangibleAssetServiceImpl extends BaseServiceImpl<XmIntangibleAs
 			if (StringUtil.isBlank(excel.getXmbh())) {
 				throw new ServiceException("序号为[" + excel.getXh() + "]的项目研发编号为空");
 			}
-			String xmkey = "xm:" + excel.getXmbh() ;
+			String xmkey = "xm:" + excel.getXmbh();
 			Long xmId = xmIdMap.get(xmkey);
 			if (xmId == null) {
 				xmId = xmMapper.getXmIdByXmmcOrXmbh(null, null, excel.getXmbh());
 				if (xmId == null) {
 					throw new ServiceException("序号为[" + excel.getXh() + "]的项目不存在");
 				}
-				Integer status = xmMapper.getXmStatusByXmId(xmId);
-				if (Func.equals(status, XmStatusEnum.已结题.getCode())) {
-					throw new ServiceException("项目已结题,不可操作");
-				}
+				xmService.judgeXmIsOver(xmId, true);
 			}
 			xmIdMap.put(xmkey, xmId);
 
@@ -193,7 +200,7 @@ public class XmIntangibleAssetServiceImpl extends BaseServiceImpl<XmIntangibleAs
 			XmIntangibleAsset xmAsset = new XmIntangibleAsset();
 			xmAsset.setYearAndMonth(yearAndMonth);
 			xmAsset.setXmId(xmId);
- 			xmAsset.setZcbm(dbAsset.getZcbm());
+			xmAsset.setZcbm(dbAsset.getZcbm());
 			insertList.add(xmAsset);
 		}
 		if (CollectionUtil.isEmpty(insertList)) {
@@ -207,10 +214,7 @@ public class XmIntangibleAssetServiceImpl extends BaseServiceImpl<XmIntangibleAs
 	public boolean physicalDeleteByIds(List<Long> ids) {
 		for (Long id : ids) {
 			XmIntangibleAsset intangibleAsset = baseMapper.selectById(id);
-			Integer status = xmMapper.getXmStatusByXmId(intangibleAsset.getXmId());
-			if (Func.equals(status, XmStatusEnum.已结题.getCode())) {
-				throw new ServiceException("项目已结题,不可操作");
-			}
+			xmService.judgeXmIsOver(intangibleAsset.getXmId(), true);
 		}
 		return baseMapper.physicalDeleteByIds(ids);
 	}
@@ -220,6 +224,8 @@ public class XmIntangibleAssetServiceImpl extends BaseServiceImpl<XmIntangibleAs
 		if (StringUtil.isBlank(xmAsset.getYearAndMonth())) {
 			throw new ServiceException("参数yearAndMonth不能为空");
 		}
+		xmService.judgeXmIsOver(xmAsset.getXmId(), true);
+
 		//获取本月数据
 		List<XmIntangibleAsset> thisMonthList = baseMapper.selectListByYearAndMonth(xmAsset.getYearAndMonth());
 		List<String> zcbmList = thisMonthList.stream().map(XmIntangibleAsset::getZcbm).toList();
@@ -235,6 +241,7 @@ public class XmIntangibleAssetServiceImpl extends BaseServiceImpl<XmIntangibleAs
 		if (null == xmAsset.getId()) {
 			throw new ServiceException("参数id不能为空");
 		}
+		xmService.judgeXmIsOver(xmAsset.getId(), true);
 		return this.updateById(xmAsset);
 	}
 

+ 16 - 0
kd-service/kd-scientific/src/main/java/org/sky/scientific/service/impl/XmOtherCostServiceImpl.java

@@ -23,6 +23,7 @@ import org.sky.scientific.pojo.dto.XmOtherCostQuery;
 import org.sky.scientific.pojo.entity.Subject;
 import org.sky.scientific.pojo.entity.XmOtherCostEntity;
 import org.sky.scientific.service.IXmOtherCostService;
+import org.sky.scientific.service.IXmService;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.web.multipart.MultipartFile;
@@ -44,6 +45,7 @@ public class XmOtherCostServiceImpl extends BaseServiceImpl<XmOtherCostMapper, X
 
 	private final XmMapper xmMapper;
 	private final SubjectMapper subjectMapper;
+	private final IXmService xmService;
 
 	@Override
 	public IPage<XmOtherCostEntity> selectPageByCondition(IPage<XmOtherCostEntity> page, XmOtherCostQuery param) {
@@ -102,6 +104,8 @@ public class XmOtherCostServiceImpl extends BaseServiceImpl<XmOtherCostMapper, X
 				throw new ServiceException("序号[" + data.getXh() + "]的研发项目不存在,请检查模板数据");
 			}
 
+			xmService.judgeXmIsOver(xmId, true);
+
 			entity.setXmId(xmId);
 			entity.setYearAndMonth(yearAndMonth);
 			entity.setSubjectId(subjectId);
@@ -116,6 +120,11 @@ public class XmOtherCostServiceImpl extends BaseServiceImpl<XmOtherCostMapper, X
 		if (StringUtil.isBlank(entity.getYearAndMonth())) {
 			throw new ServiceException("参数yearAndMonth不能为空");
 		}
+		if (Func.isNull(entity.getXmId())) {
+			throw new ServiceException("参数xmId不能为空");
+		}
+		xmService.judgeXmIsOver(entity.getXmId(), true);
+
 		String judged = DateUtil.judgeDate(entity.getRecordDate(), entity.getYearAndMonth());
 		if (judged != null) {
 			throw new ServiceException(judged);
@@ -124,7 +133,14 @@ public class XmOtherCostServiceImpl extends BaseServiceImpl<XmOtherCostMapper, X
 	}
 
 	@Override
+	@Transactional
 	public boolean physicalDeleteByIds(List<Long> ids) {
+		for (Long id : ids) {
+			XmOtherCostEntity entity = baseMapper.selectById(id);
+			if (Func.notNull(entity)) {
+				xmService.judgeXmIsOver(entity.getXmId(), true);
+			}
+		}
 		return baseMapper.physicalDeleteByIds(ids);
 	}
 

+ 24 - 11
kd-service/kd-scientific/src/main/java/org/sky/scientific/service/impl/XmServiceImpl.java

@@ -8,9 +8,7 @@ import com.alibaba.excel.write.metadata.WriteSheet;
 import com.alibaba.excel.write.metadata.fill.FillConfig;
 import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONObject;
-import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
-import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import jakarta.servlet.http.HttpServletResponse;
 import lombok.AllArgsConstructor;
 import lombok.SneakyThrows;
@@ -37,7 +35,6 @@ import org.sky.scientific.utils.TemplateService;
 import org.sky.system.feign.ISysClient;
 import org.sky.system.pojo.entity.Tenant;
 import org.springframework.stereotype.Service;
-import org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer;
 
 import java.io.InputStream;
 import java.io.OutputStream;
@@ -61,7 +58,6 @@ public class XmServiceImpl extends BaseServiceImpl<XmMapper, XmEntity> implement
 	private final TechnicianMapper technicianMapper;
 	private final DepartmentMapper departmentMapper;
 	private final XmCostDetailsMapper xmCostDetailsMapper;
-	private final FreeMarkerConfigurer freeMarkerConfigurer;
 	private final ISysClient sysClient;
 	private final TemplateService templateService;
 
@@ -81,25 +77,37 @@ public class XmServiceImpl extends BaseServiceImpl<XmMapper, XmEntity> implement
 		return baseMapper.selectXmListByYear(year);
 	}
 
+	/**
+	 * 判断项目是否已结题
+	 * @param xmId
+	 */
+	public boolean judgeXmIsOver(Long xmId, boolean isThrowEx) {
+		Integer status = baseMapper.getXmStatusByXmId(xmId);
+		if (Func.equals(status, XmStatusEnum.已结题.getCode())) {
+			if(isThrowEx){
+				throw new ServiceException("项目已结题,不可操作");
+			}else {
+				return true;
+			}
+		}
+		return false;
+	}
+
 	@Override
 	public Long approval(XmDTO xm) {
 
 		this.judgeXmmcAvailable(xm.getXmmc());
 
-//		if(XmStatusEnum.暂存.getCode() == xm.getStatus()){
-//
-//		}
+		judgeXmIsOver(xm.getId(), true);
 
 		//检查项目名称是否重复(xm);
-		LambdaQueryWrapper<XmEntity> queryWrapper = Wrappers.<XmEntity>lambdaQuery().eq(XmEntity::getXmmc, xm.getXmmc());
 		Long xmIdByXmmc = baseMapper.getXmIdByXmmcOrXmbh(null, xm.getXmmc(), null);
-		if (xmIdByXmmc!=null && !xmIdByXmmc.equals(xm.getId())) {
+		if (xmIdByXmmc != null && !xmIdByXmmc.equals(xm.getId())) {
 			throw new ServiceException("研发项目名称已存在");
 		}
 
-//		queryWrapper = Wrappers.<XmEntity>lambdaQuery().eq(XmEntity::getXmbh, xm.getXmbh());
 		Long xmIdByXmbh = baseMapper.getXmIdByXmmcOrXmbh(null, null, xm.getXmbh());
-		if (xmIdByXmbh!=null && !xmIdByXmbh.equals(xm.getId())) {
+		if (xmIdByXmbh != null && !xmIdByXmbh.equals(xm.getId())) {
 			throw new ServiceException("研发项目编号已存在");
 		}
 
@@ -119,6 +127,11 @@ public class XmServiceImpl extends BaseServiceImpl<XmMapper, XmEntity> implement
 	@Override
 	public XmVO selectApprovalInfo(Long xmId) {
 		XmEntity xm = baseMapper.selectById(xmId);
+		if (Func.isNull(xm)) {
+			throw new ServiceException("项目不存在");
+		}
+		Integer status = baseMapper.getXmStatusByXmId(xmId);
+		xm.setStatus(status);
 		xm.setXmfzrxm(Func.toStr(technicianMapper.getNameById(xm.getXmfzr()), ""));
 		xm.setXmsqdw(Func.toStr(departmentMapper.getFullNameById(xm.getXmsqdwid()), ""));
 		return BeanUtil.copyProperties(xm, XmVO.class);

+ 28 - 12
kd-service/kd-scientific/src/main/java/org/sky/scientific/service/impl/XmTechnicianHoursServiceImpl.java

@@ -31,6 +31,7 @@ import org.sky.scientific.pojo.vo.DailyAttendance;
 import org.sky.scientific.pojo.vo.DailyHours;
 import org.sky.scientific.pojo.vo.TechnicianHoursMonthlyVO;
 import org.sky.scientific.pojo.vo.XmTechnicianHoursVO;
+import org.sky.scientific.service.IXmService;
 import org.sky.scientific.service.IXmTechnicianHoursService;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
@@ -61,6 +62,7 @@ public class XmTechnicianHoursServiceImpl extends BaseServiceImpl<XmTechnicianHo
 	private final AttendanceMapper attendanceMapper;
 	private final TechnicianMapper technicianMapper;
 	private final XmTechnicianMapper xmTechnicianMapper;
+	private final IXmService xmService;
 
 	@SneakyThrows
 	@Transactional(rollbackFor = Exception.class)
@@ -234,6 +236,8 @@ public class XmTechnicianHoursServiceImpl extends BaseServiceImpl<XmTechnicianHo
 			throw new ServiceException("参数unicode不能为空");
 		}
 
+		xmService.judgeXmIsOver(dto.getXmId(), true);
+
 		//获取考勤数据,具体人员在某个月的考勤明细
 		List<DailyAttendance> dailyAttendanceList = attendanceMapper.selectDailyAttendanceByUnicodeAndMonth(dto.getUnicode(), dto.getYearAndMonth());
 		if (CollectionUtil.isEmpty(dailyAttendanceList)) {
@@ -304,22 +308,30 @@ public class XmTechnicianHoursServiceImpl extends BaseServiceImpl<XmTechnicianHo
 		if (xmAndUnicodeList == null || xmAndUnicodeList.isEmpty()) {
 			throw new ServiceException("参数xmAndUnicodeList不能为空");
 		}
-		for (Object xmAndUnicode : xmAndUnicodeList) {
-			Map<String, String> map = (HashMap<String, String>) xmAndUnicode;
-			baseMapper.clearByXmUnicodeMonth(dto.getString("yearAndMonth"), Long.valueOf(map.get("xmId")), map.get("unicode"));
+		for (int i = 0; i < xmAndUnicodeList.size(); i++) {
+			JSONObject object = xmAndUnicodeList.getJSONObject(i);
+			Long xmId = object.getLong("xmId");
+			xmService.judgeXmIsOver(xmId, true);
+			String unicode = object.getString("unicode");
+			String yearAndMonth = dto.getString("yearAndMonth");
+			baseMapper.clearByXmUnicodeMonth(yearAndMonth, xmId, unicode);
 		}
 		return true;
 	}
 
 	@Override
 	public boolean deleteHours(JSONObject dto) {
-		JSONArray xmAndUnicodeList = dto.getJSONArray("xmAndUnicodeList");
+ 		JSONArray xmAndUnicodeList = dto.getJSONArray("xmAndUnicodeList");
 		if (xmAndUnicodeList == null || xmAndUnicodeList.isEmpty()) {
 			throw new ServiceException("参数xmAndUnicodeList不能为空");
 		}
-		for (Object xmAndUnicode : xmAndUnicodeList) {
-			Map<String, String> map = (HashMap<String, String>) xmAndUnicode;
-			baseMapper.deleteByXmUnicodeMonth(dto.getString("yearAndMonth"), Long.valueOf(map.get("xmId")), map.get("unicode"));
+		for (int i = 0; i < xmAndUnicodeList.size(); i++) {
+			JSONObject object = xmAndUnicodeList.getJSONObject(i);
+			Long xmId = object.getLong("xmId");
+			xmService.judgeXmIsOver(xmId, true);
+			String unicode = object.getString("unicode");
+			String yearAndMonth = dto.getString("yearAndMonth");
+			baseMapper.deleteByXmUnicodeMonth(yearAndMonth, xmId, unicode);
 		}
 		return true;
 	}
@@ -327,7 +339,6 @@ public class XmTechnicianHoursServiceImpl extends BaseServiceImpl<XmTechnicianHo
 	@Override
 	public void export(OutputStream os, List<XmTechnicianHoursVO> list, String yearAndMonth) {
 		try {
-
 			AtomicInteger index = new AtomicInteger(1);
 			for (XmTechnicianHoursVO vo : list) {
 				vo.setXh(index.getAndIncrement() + "");
@@ -557,10 +568,17 @@ public class XmTechnicianHoursServiceImpl extends BaseServiceImpl<XmTechnicianHo
 	@Transactional
 	public boolean fetch(String yearAndMonth) {
 		List<XmTechnicianEntity> list = xmTechnicianMapper.selectList(Wrappers.<XmTechnicianEntity>lambdaQuery().eq(XmTechnicianEntity::getYearAndMonth, yearAndMonth));
-
 		if (Func.isEmpty(list)) {
 			throw new ServiceException("本月没有参研人员");
 		}
+		//过滤掉已结题项目
+		List<Long> jtXmIdList = new ArrayList<>();
+		for (XmTechnicianEntity entity : list) {
+			if (xmService.judgeXmIsOver(entity.getXmId(), false)) {
+				jtXmIdList.add(entity.getXmId());
+			}
+		}
+		list = list.stream().filter(xmTechnician -> !jtXmIdList.contains(xmTechnician.getXmId())).toList();
 
 		List<XmTechnicianHours> insertList = new ArrayList<>();
 		for (XmTechnicianEntity xmTechnician : list) {
@@ -579,13 +597,11 @@ public class XmTechnicianHoursServiceImpl extends BaseServiceImpl<XmTechnicianHo
 		if (collect.isEmpty()) {
 			return this.saveBatch(insertList);
 		} else {
-//			collect.get()
-			List<XmTechnicianHours> deduplicationList = insertList.stream().filter(item -> !(collect.containsKey(item.getXmId()) && collect.get(item.getXmId()).contains(item.getUnicode()))).toList();
+ 			List<XmTechnicianHours> deduplicationList = insertList.stream().filter(item -> !(collect.containsKey(item.getXmId()) && collect.get(item.getXmId()).contains(item.getUnicode()))).toList();
 			if (Func.isEmpty(deduplicationList)) {
 				throw new ServiceException("本月参研人员已全部引用");
 			}
 			return this.saveBatch(deduplicationList);
 		}
 	}
-
 }

+ 19 - 0
kd-service/kd-scientific/src/main/java/org/sky/scientific/service/impl/XmWwxmCostServiceImpl.java

@@ -25,8 +25,10 @@ import org.sky.scientific.pojo.dto.XmWwxmCostQuery;
 import org.sky.scientific.pojo.entity.XmWwxmCost;
 import org.sky.scientific.pojo.entity.XmWwxmEntity;
 import org.sky.scientific.pojo.vo.XmWwxmCostVO;
+import org.sky.scientific.service.IXmService;
 import org.sky.scientific.service.IXmWwxmCostService;
 import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
 import org.springframework.web.multipart.MultipartFile;
 
 import java.io.InputStream;
@@ -49,14 +51,20 @@ public class XmWwxmCostServiceImpl extends BaseServiceImpl<XmWwxmCostMapper, XmW
 
 	private final XmMapper xmMapper;
 	private final XmWwxmMapper wwxmMapper;
+	private final IXmService xmService;
 
 	@Override
+	@Transactional
 	public boolean submit(XmWwxmCost cost) {
 
 		String judged = DateUtil.judgeDate(cost.getPayDate(), cost.getYearAndMonth());
 		if (judged != null) {
 			throw new ServiceException(judged);
 		}
+		XmWwxmEntity wwxm = wwxmMapper.selectById(cost.getWwId());
+		if (Func.notNull(wwxm)) {
+			xmService.judgeXmIsOver(wwxm.getXmId(), true);
+		}
 		boolean result = false;
 		if (Func.isNull(cost.getId())) {
 			result = this.save(cost);
@@ -87,6 +95,7 @@ public class XmWwxmCostServiceImpl extends BaseServiceImpl<XmWwxmCostMapper, XmW
 			if (xmId == null) {
 				throw new ServiceException("序号为[" + data.getSerialNumber() + "]的项目不存在");
 			}
+			xmService.judgeXmIsOver(xmId, true);
 
 			LambdaQueryWrapper<XmWwxmEntity> eq = Wrappers.<XmWwxmEntity>lambdaQuery()
 				.eq(XmWwxmEntity::getXmId, xmId)
@@ -114,7 +123,17 @@ public class XmWwxmCostServiceImpl extends BaseServiceImpl<XmWwxmCostMapper, XmW
 	}
 
 	@Override
+	@Transactional
 	public boolean physicalDeleteByIds(List<Long> ids) {
+		for (Long id : ids) {
+			XmWwxmCost cost = baseMapper.selectById(id);
+			if (Func.notNull(cost)) {
+				XmWwxmEntity wwxm = wwxmMapper.selectById(cost.getWwId());
+				if (Func.notNull(wwxm)) {
+					xmService.judgeXmIsOver(wwxm.getXmId(), true);
+				}
+			}
+		}
 		return baseMapper.physicalDeleteByIds(ids);
 	}
 

+ 1 - 0
kd-service/kd-scientific/src/main/java/org/sky/scientific/service/impl/XmWwxmServiceImpl.java

@@ -35,6 +35,7 @@ public class XmWwxmServiceImpl extends BaseServiceImpl<XmWwxmMapper, XmWwxmEntit
 
 	@Override
 	public boolean physicalDeleteByIds(List<Long> ids) {
+
 		return baseMapper.physicalDeleteByIds(ids);
 	}