zhouli 10 months ago
parent
commit
a68ad993b9

+ 0 - 1
kd-service-api/kd-scientific-api/src/main/java/org/sky/scientific/pojo/entity/AttendanceEntity.java

@@ -42,5 +42,4 @@ public class AttendanceEntity extends TenantEntity {
 	@Max(value = 24, message = "请填写正确的出勤时长(小时)")
 	private Double workHours;
 
-
 }

+ 48 - 0
kd-service-api/kd-scientific-api/src/main/java/org/sky/scientific/pojo/entity/XmAssetHoursEntity.java

@@ -0,0 +1,48 @@
+
+package org.sky.scientific.pojo.entity;
+
+import com.baomidou.mybatisplus.annotation.TableName;
+import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.validation.constraints.Max;
+import jakarta.validation.constraints.Min;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotNull;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import org.sky.core.tenant.mp.TenantEntity;
+
+import java.io.Serial;
+
+/**
+ * 科研仪器设备工时登记表 实体类
+ *
+ * @author Kd
+ * @since 2025-06-29
+ */
+@Data
+@TableName("kd_xm_asset_hours")
+@Schema(description = "科研仪器设备工时登记表")
+@EqualsAndHashCode(callSuper = true)
+public class XmAssetHoursEntity extends TenantEntity {
+
+	@Serial
+	private static final long serialVersionUID = 1L;
+
+	@Schema(description = "研发项目id")
+	@NotBlank(message = "请选择研发项目")
+	private Long xmId;
+
+	@Schema(description = "资产id")
+	@NotBlank(message = "请选择资产")
+	private Long assetId;
+
+	@Schema(description="考勤时间,yyyyMMdd")
+	@NotNull(message = "请选择出工日期")
+	private String workDate;
+
+	@Schema(description="出勤时长(小时)")
+	@NotNull(message = "请填写工时(小时)")
+	@Min(value = 0, message = "请填写正确的出勤时长(小时)")
+	@Max(value = 24, message = "请填写正确的出勤时长(小时)")
+	private Double workHours;
+}

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

@@ -0,0 +1,51 @@
+package org.sky.scientific.pojo.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.validation.constraints.NotBlank;
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+public class XmAssetHoursVO {
+
+	@Schema(description = "项目ID")
+	private Long xmId;
+
+	@Schema(description = "项目编号")
+	private String xmbh;
+
+	@NotBlank(message = "项目名称不能为空")
+	private String xmmc;
+
+	@Schema(description = "资产ID")
+	private Long assetId;
+
+	@Schema(description = "资产编码")
+	private String zcbm;
+
+	@Schema(description = "资产名称")
+	private String zcmc;
+
+	@Schema(description = "资产类别")
+	private String zclb;
+
+	@Schema(description = "用途")
+	private String yt;
+
+	@Schema(description = "出工明细")
+	private List<DailyAttendance> dailyAttendances;
+
+	@Schema(description="使用时长/小时")
+ 	private Double monthlyHours;
+
+	@Schema(description="使用时长-起始值")
+	private Double monthlyHoursStart;
+
+	@Schema(description="使用时长-结束值")
+	private Double monthlyHoursEnd;
+
+	@Schema(description = "所属年月")
+	private String yearAndMonth;
+
+}

+ 16 - 0
kd-service/kd-scientific/src/main/java/org/sky/scientific/controller/AssetController.java

@@ -23,6 +23,7 @@ import org.sky.scientific.pojo.dto.AssetDTO;
 import org.sky.scientific.pojo.entity.AssetEntity;
 import org.sky.scientific.pojo.entity.XmAssetEntity;
 import org.sky.scientific.pojo.vo.AssetVO;
+import org.sky.scientific.pojo.vo.XmAssetHoursVO;
 import org.sky.scientific.service.IAssetService;
 import org.sky.scientific.service.IXmAssetService;
 import org.sky.scientific.wrapper.ZcWrapper;
@@ -130,4 +131,19 @@ public class AssetController extends KdController {
 	public R<Boolean> fetchData(String yearAndMonth) {
 		return R.status(xmAssetService.keyanyiqishebeimingxibiao_zhijieyinyong(yearAndMonth));
 	}
+
+	@PostMapping("/hours/import")
+	@ApiOperationSupport(order = 4)
+	@Operation(summary = "科研仪器设备工时登记表-导入", description = "传入excel")
+	public R importXmAssetHours(MultipartFile file,String yearAndMonth) {
+		service.importXmAssetHours(file, yearAndMonth);
+		return R.success("操作成功");
+	}
+
+	@GetMapping("/hours/page")
+	@ApiOperationSupport(order = 1)
+	@Operation(summary = "科研仪器设备工时登记表-分页")
+	public R<IPage<XmAssetHoursVO>> selectXmAssetHourspage(XmAssetHoursVO vo, Query query) {
+		return R.data(service.selectXmAssetHoursPage(vo, Condition.getPage(query)));
+	}
 }

+ 122 - 0
kd-service/kd-scientific/src/main/java/org/sky/scientific/excel/XmAssetHoursMonthlyDataListener.java

@@ -0,0 +1,122 @@
+package org.sky.scientific.excel;
+
+import com.alibaba.excel.context.AnalysisContext;
+import com.alibaba.excel.metadata.data.ReadCellData;
+import com.alibaba.excel.read.listener.ReadListener;
+import lombok.Data;
+import org.sky.core.tool.utils.StringUtil;
+import org.sky.scientific.pojo.vo.DailyAttendance;
+
+import java.math.BigDecimal;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+@Data
+public class XmAssetHoursMonthlyDataListener implements ReadListener<Map<Integer, String>> {
+
+	private static final int HEADER_ROW_1 = 1; // 星期行(0-based)
+	private static final int HEADER_ROW_2 = 2; // 日期行
+	private static final int DATA_START_ROW = 3; // 数据开始行
+
+ 	private List<String> dateHeaders = new ArrayList<>();
+	private List<XmAssetHoursMonthlyExcel> records = new ArrayList<>();
+	private boolean headersProcessed = false;
+	private String yearAndMonth;
+
+	@Override
+	public void invokeHead(Map<Integer, ReadCellData<?>> headMap, AnalysisContext context) {
+		int rowIndex = context.readRowHolder().getRowIndex();
+
+		 if (rowIndex == HEADER_ROW_2) {
+			// 处理日期行
+			dateHeaders = extractHeaders(headMap, 8);
+			headersProcessed = true;
+		}
+	}
+
+	private List<String> extractHeaders(Map<Integer, ReadCellData<?>> headMap, int startCol) {
+		List<String> headers = new ArrayList<>();
+		headMap.entrySet().stream()
+			.filter(entry -> entry.getKey() >= startCol)
+			.sorted(Map.Entry.comparingByKey())
+			.forEach(entry -> {
+				String stringValue = entry.getValue().getStringValue();
+				if(StringUtil.isBlank(stringValue)){
+					BigDecimal numberValue = entry.getValue().getNumberValue();
+					if(numberValue != null){
+						headers.add(numberValue.intValue()<=9?"0"+numberValue.intValue() : numberValue.intValue()+"");
+					}
+				}else {
+					headers.add(stringValue);
+				}
+
+
+			});
+		return headers;
+	}
+
+	@Override
+	public void invoke(Map<Integer, String> data, AnalysisContext context) {
+		if (!headersProcessed || context.readRowHolder().getRowIndex() < DATA_START_ROW) {
+			return;
+		}
+
+		// 跳过空行
+		if (data == null || data.isEmpty() || data.values().stream().allMatch(v -> v == null || v.trim().isEmpty())) {
+			return;
+		}
+
+		XmAssetHoursMonthlyExcel record = new XmAssetHoursMonthlyExcel();
+
+		// 解析固定列
+		record.setSerialNumber(safeParseInt(data.get(0)));
+		record.setXmbh(data.get(1));
+		record.setXmmc(data.get(2));
+		record.setZcbm(data.get(3));
+		record.setZcmc(data.get(4));
+		record.setZclb(data.get(5));
+		record.setYt(data.get(6));
+
+		// 解析每日工时数据
+ 		for (int i = 0; i < dateHeaders.size(); i++) {
+			String hoursStr = data.get(i + 8); // 工时数据从第5列开始
+			//没有填报的日期,跳过
+			if (hoursStr != null && !hoursStr.trim().isEmpty()) {
+				try {
+					DailyAttendance daily = new DailyAttendance();
+					daily.setWorkDate(yearAndMonth + dateHeaders.get(i));
+					daily.setWorkHours(safeParseDouble(hoursStr));
+					record.getDailyAttendances().add(daily);
+				} catch (NumberFormatException e) {
+					System.err.printf("解析错误: 资产[%s] 日期[%s] 值[%s]%n",
+						record.getZcmc(), dateHeaders.get(i), hoursStr);
+				}
+			}
+		}
+
+		records.add(record);
+	}
+
+	@Override
+	public void doAfterAllAnalysed(AnalysisContext context) {
+		System.out.println("科研仪器设备工时数据解析完成,共解析 " + records.size() + " 条记录");
+	}
+
+
+	private Integer safeParseInt(String value) {
+		try {
+			return value == null || value.trim().isEmpty() ? null : Integer.parseInt(value.trim());
+		} catch (NumberFormatException e) {
+			return null;
+		}
+	}
+
+	private Double safeParseDouble(String value) {
+		try {
+			return value == null || value.trim().isEmpty() ? null : Double.parseDouble(value.trim());
+		} catch (NumberFormatException e) {
+			return null;
+		}
+	}
+}

+ 43 - 0
kd-service/kd-scientific/src/main/java/org/sky/scientific/excel/XmAssetHoursMonthlyExcel.java

@@ -0,0 +1,43 @@
+
+package org.sky.scientific.excel;
+
+
+import com.alibaba.excel.annotation.write.style.ColumnWidth;
+import com.alibaba.excel.annotation.write.style.ContentRowHeight;
+import com.alibaba.excel.annotation.write.style.HeadRowHeight;
+import lombok.Data;
+import org.sky.scientific.pojo.vo.DailyAttendance;
+
+import java.io.Serial;
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+
+
+/**
+ * 科研仪器设备工时
+ *
+ * @author Kd
+ * @since 2025-06-29
+ */
+@Data
+@ColumnWidth(25)
+@HeadRowHeight(20)
+@ContentRowHeight(18)
+public class XmAssetHoursMonthlyExcel implements Serializable {
+
+	@Serial
+	private static final long serialVersionUID = 1L;
+
+	private Integer serialNumber;  // 序号
+	private String xmbh;
+	private String xmmc;
+
+	private String zcbm;
+	private String zcmc;
+	private String zclb;
+	private String yt;
+
+	private List<DailyAttendance> dailyAttendances = new ArrayList<>(); // 每日考勤数据
+	private Double monthlyHours;   // 使用工时/小时
+}

+ 30 - 0
kd-service/kd-scientific/src/main/java/org/sky/scientific/mapper/XmAssetHoursMapper.java

@@ -0,0 +1,30 @@
+
+package org.sky.scientific.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import org.apache.ibatis.annotations.Param;
+import org.sky.scientific.pojo.entity.XmAssetHoursEntity;
+import org.sky.scientific.pojo.vo.DailyAttendance;
+import org.sky.scientific.pojo.vo.XmAssetHoursVO;
+
+import java.util.List;
+
+/**
+ * 科研仪器设备工时 Mapper 接口
+ *
+ * @author Kd
+ * @since 2025-06-29
+ */
+public interface XmAssetHoursMapper extends BaseMapper<XmAssetHoursEntity> {
+
+	List<XmAssetHoursEntity> selectByYearAndMonth(@Param("yearAndMonth") String yearAndMonth);
+//
+	int batchUpdate(List<XmAssetHoursEntity> list);
+
+	int batchInsert(List<XmAssetHoursEntity> list);
+//
+	List<DailyAttendance> selectHoursByXmIdAndAssetId(@Param("xmId") Long xmId, @Param("assetId") Long assetId, @Param("yearAndMonth") String yearAndMonth);
+//
+	List<XmAssetHoursVO> selectXmAssetHoursPage(IPage<XmAssetHoursVO> page, @Param("ew") XmAssetHoursVO attendance);
+}

+ 98 - 0
kd-service/kd-scientific/src/main/java/org/sky/scientific/mapper/XmAssetHoursMapper.xml

@@ -0,0 +1,98 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="org.sky.scientific.mapper.XmAssetHoursMapper">
+
+    <resultMap id="ResultMap" type="org.sky.scientific.pojo.entity.XmAssetHoursEntity">
+        <result column="id" property="id"/>
+        <result column="tenant_id" property="tenantId"/>
+        <result column="xm_id" property="xmId"/>
+        <result column="asset_id" property="assetId"/>
+        <result column="work_date" property="workDate"/>
+        <result column="work_hours" property="workHours"/>
+
+        <result column="create_user" property="createUser"/>
+        <result column="create_dept" property="createDept"/>
+        <result column="create_time" property="createTime"/>
+        <result column="update_user" property="updateUser"/>
+        <result column="update_time" property="updateTime"/>
+        <result column="status" property="status"/>
+        <result column="is_deleted" property="isDeleted"/>
+    </resultMap>
+
+    <resultMap id="ResultVoMap" type="org.sky.scientific.pojo.vo.XmAssetHoursVO">
+        <result column="xm_id" property="xmId"/>
+        <result column="xmbh" property="xmbh"/>
+        <result column="xmmc" property="xmmc"/>
+        <result column="asset_id" property="assetId"/>
+        <result column="zcbm" property="zcbm"/>
+        <result column="zcmc" property="zcmc"/>
+        <result column="zclb" property="zclb"/>
+        <result column="yt" property="yt"/>
+        <result column="monthly_hours" property="monthlyHours"/>
+        <collection property="dailyAttendances" ofType="org.sky.scientific.pojo.vo.DailyAttendance">
+            <result column="work_date" property="workDate"/>
+            <result column="work_hours" property="workHours"/>
+        </collection>
+    </resultMap>
+
+<!--    <select id="selectDailyAttendanceByTechnicianAndMonth" resultType="org.sky.scientific.pojo.vo.DailyAttendance">-->
+<!--        select work_date,work_hours-->
+<!--        from kd_attendance_records-->
+<!--        where technician_id = #{technicianId} and left(work_date,6) = #{yearAndMonth}-->
+<!--        order by work_date asc-->
+<!--    </select>-->
+
+    <select id="selectXmAssetHoursPage" resultMap="ResultVoMap">
+        SELECT xa.id,xa.xm_id,xm.xmbh,xm.xmmc,xa.asset_id,asset.zcbm,asset.zcmc,asset.zclb,asset.yt
+        FROM kd_xm_asset xa
+        LEFT JOIN kd_asset asset ON xa.asset_id = asset.id
+        INNER JOIN
+        (
+        SELECT
+        xm.id,xm.xmbh,
+        COALESCE( (SELECT bgrz.BGHDZ FROM kd_xm_bgrz bgrz WHERE bgrz.XM_ID = xm.id AND bgrz.ZDMC = 'XMMC' AND DATE_FORMAT(bgrz.BGSXSJ,'%Y%m') <![CDATA[<=]]> #{ew.yearAndMonth} ORDER BY bgrz.BGSXSJ DESC LIMIT 1),XMMC) AS XMMC,
+        COALESCE( (SELECT bgrz.BGHDZ FROM kd_xm_bgrz bgrz WHERE bgrz.XM_ID = xm.id AND bgrz.ZDMC = 'XMKSSJ' AND DATE_FORMAT(bgrz.BGSXSJ,'%Y%m') <![CDATA[<=]]> #{ew.yearAndMonth} ORDER BY bgrz.BGSXSJ DESC LIMIT 1),XMKSSJ) AS XMKSSJ,
+        COALESCE( (SELECT bgrz.BGHDZ FROM kd_xm_bgrz bgrz WHERE bgrz.XM_ID = xm.id AND bgrz.ZDMC = 'XMJSSJ' AND DATE_FORMAT(bgrz.BGSXSJ,'%Y%m') <![CDATA[<=]]> #{ew.yearAndMonth} ORDER BY bgrz.BGSXSJ DESC LIMIT 1),XMJSSJ) AS XMJSSJ
+        FROM kd_xm xm
+        WHERE xm.is_deleted = 0 and DATE_FORMAT(XMKSSJ, '%Y%m') <![CDATA[<=]]> #{ew.yearAndMonth}
+        ) xm on xm.id = xa.xm_id
+        WHERE xa.year_and_month = #{ew.yearAndMonth}
+        <if test="ew.zcmc != null">
+            and asset.name like concat('%',#{ew.zcmc},'%')
+        </if>
+        <if test="ew.xmmc != null">
+            and xm.xmmc like concat('%',#{ew.xmmc},'%')
+        </if>
+    </select>
+
+    <update id="batchUpdate" parameterType="java.util.List">
+        <foreach collection="list" item="record" separator=";">
+            update kd_xm_asset_hours
+            set work_hours = #{record.workHours}
+            where id = #{record.id}
+        </foreach>
+    </update>
+
+    <select id="selectHoursByXmIdAndAssetId" resultType="org.sky.scientific.pojo.vo.DailyAttendance">
+        select work_date,work_hours
+        from kd_xm_asset_hours
+        where xm_id = #{xmId} and asset_id = #{assetId} and left(work_date,6) = #{yearAndMonth}
+        order by work_date asc
+    </select>
+
+    <insert id="batchInsert" parameterType="java.util.List">
+        insert into kd_xm_asset_hours(tenant_id,xm_id,asset_id,work_date,work_hours,create_user,create_dept)
+        VALUES
+        <foreach collection="list" item="a" separator=",">
+            (#{a.tenantId},#{a.xmId}, #{a.assetId},#{a.workDate},#{a.workHours},#{a.createUser},#{a.createDept})
+        </foreach>
+    </insert>
+
+    <select id="selectByYearAndMonth" resultMap="ResultMap" parameterType="java.lang.String">
+        select id, xm_id, asset_id, work_date, work_hours
+        from kd_xm_asset_hours
+        where left(work_date,6) = #{yearAndMonth}
+    </select>
+
+
+</mapper>

+ 15 - 0
kd-service/kd-scientific/src/main/java/org/sky/scientific/service/IAssetService.java

@@ -8,6 +8,7 @@ import org.sky.scientific.excel.AssetExcel;
 import org.sky.scientific.pojo.dto.AssetDTO;
 import org.sky.scientific.pojo.entity.AssetEntity;
 import org.sky.scientific.pojo.vo.AssetVO;
+import org.sky.scientific.pojo.vo.XmAssetHoursVO;
 import org.springframework.web.multipart.MultipartFile;
 
 import java.util.List;
@@ -66,4 +67,18 @@ public interface IAssetService extends BaseService<AssetEntity> {
 	 */
 	List<AssetExcel> exportAsset(Wrapper<AssetEntity> queryWrapper);
 
+	/**
+	 * 科研仪器设备工时登记表-导入
+	 * @param file
+	 * @param yearAndMonth
+	 */
+    void importXmAssetHours(MultipartFile file, String yearAndMonth);
+
+	/**
+	 * 科研仪器设备工时登记表-分页
+	 * @param vo
+	 * @param page
+	 * @return
+	 */
+	IPage<XmAssetHoursVO> selectXmAssetHoursPage(XmAssetHoursVO vo, IPage<XmAssetHoursVO> page);
 }

+ 120 - 4
kd-service/kd-scientific/src/main/java/org/sky/scientific/service/impl/AssetServiceImpl.java

@@ -1,28 +1,38 @@
 
 package org.sky.scientific.service.impl;
 
+import com.alibaba.excel.EasyExcel;
 import com.baomidou.mybatisplus.core.conditions.Wrapper;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import jakarta.annotation.Resource;
+import lombok.SneakyThrows;
 import lombok.extern.slf4j.Slf4j;
 import org.sky.core.excel.util.ExcelUtil;
 import org.sky.core.log.exception.ServiceException;
 import org.sky.core.mp.base.BaseServiceImpl;
-import org.sky.core.tool.utils.BeanUtil;
-import org.sky.core.tool.utils.CollectionUtil;
-import org.sky.core.tool.utils.DateUtil;
-import org.sky.core.tool.utils.StringUtil;
+import org.sky.core.secure.utils.SecureUtil;
+import org.sky.core.tool.utils.*;
 import org.sky.scientific.excel.AssetExcel;
+import org.sky.scientific.excel.XmAssetHoursMonthlyDataListener;
+import org.sky.scientific.excel.XmAssetHoursMonthlyExcel;
 import org.sky.scientific.mapper.AssetMapper;
+import org.sky.scientific.mapper.XmAssetHoursMapper;
+import org.sky.scientific.mapper.XmMapper;
 import org.sky.scientific.pojo.dto.AssetDTO;
 import org.sky.scientific.pojo.entity.AssetEntity;
+import org.sky.scientific.pojo.entity.XmAssetHoursEntity;
 import org.sky.scientific.pojo.vo.AssetVO;
+import org.sky.scientific.pojo.vo.DailyAttendance;
+import org.sky.scientific.pojo.vo.XmAssetHoursVO;
 import org.sky.scientific.service.IAssetService;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.web.multipart.MultipartFile;
 
+import java.io.BufferedInputStream;
+import java.util.ArrayList;
 import java.util.List;
 import java.util.Objects;
 
@@ -36,6 +46,11 @@ import java.util.Objects;
 @Service
 public class AssetServiceImpl extends BaseServiceImpl<AssetMapper, AssetEntity> implements IAssetService {
 
+	@Resource
+	private XmMapper xmMapper;
+	@Resource
+	private XmAssetHoursMapper xmAssetHoursMapper;
+
 	@Override
 	public IPage<AssetVO> selectAssetPage(IPage<AssetVO> page, AssetVO asset) {
 		return page.setRecords(baseMapper.selectAssetPage(page, asset));
@@ -119,4 +134,105 @@ public class AssetServiceImpl extends BaseServiceImpl<AssetMapper, AssetEntity>
 		//});
 		return assetList;
 	}
+
+	@SneakyThrows
+	@Transactional(rollbackFor = Exception.class)
+    @Override
+    public void importXmAssetHours(MultipartFile file, String yearAndMonth) {
+		XmAssetHoursMonthlyDataListener listener = new XmAssetHoursMonthlyDataListener();
+		listener.setYearAndMonth(yearAndMonth);
+		EasyExcel.read(new BufferedInputStream(file.getInputStream()))
+			.registerReadListener(listener)
+			.sheet(0)
+			.headRowNumber(3) // 重要:设置表头行数(0-based)
+			.doRead();
+		List<XmAssetHoursMonthlyExcel> records = listener.getRecords();
+		if (CollectionUtil.isEmpty(records)) {
+			throw new ServiceException("未能从模板中读取数据,请检查模板格式是否正确");
+		}
+
+		//需要新增的,以便后续批量新增
+		List<XmAssetHoursEntity> insertList = new ArrayList<>();
+		//需要更新的,以便后续批量修改
+		List<XmAssetHoursEntity> updateList = new ArrayList<>();
+
+		int batchCount = 20;
+
+		List<XmAssetHoursEntity> dbList = xmAssetHoursMapper.selectByYearAndMonth(yearAndMonth);
+		for (XmAssetHoursMonthlyExcel record : records) {
+			//保存
+			if(StringUtil.isAllBlank(record.getXmmc(), record.getXmbh())){
+				throw new ServiceException("研发项目编号、研发项目名称都为空,请检查数据");
+			}
+			Long xmId = xmMapper.getXmIdByXmmcOrXmbh(yearAndMonth, record.getXmmc(), record.getXmbh());
+ 			if (xmId == null) {
+				throw new ServiceException("序号为[" + record.getSerialNumber() + "]的研发项目编号和研发项目名称都不存在");
+			}
+
+			if(StringUtil.isBlank(record.getZcbm())){
+				throw new ServiceException("序号为[" + record.getSerialNumber() + "]的资产编码为空");
+			}
+			AssetEntity dbAsset = baseMapper.selectOne(Wrappers.<AssetEntity>lambdaQuery().eq(AssetEntity::getZcbm, record.getZcbm()).eq(AssetEntity::getYearAndMonth, yearAndMonth));
+			if (dbAsset == null) {
+				throw new ServiceException("序号为[" + record.getSerialNumber() + "]的资产不存在");
+			}
+			List<XmAssetHoursEntity> byXmAndAssetList = dbList.stream().filter(e -> e.getXmId().equals(xmId) && e.getAssetId().equals(dbAsset.getId())).toList();
+			for (DailyAttendance dailyAttendance : record.getDailyAttendances()) {
+
+				List<Long> primaryKeyList = byXmAndAssetList.stream().filter(e -> Objects.equals(e.getWorkDate(), dailyAttendance.getWorkDate())).map(XmAssetHoursEntity::getId).toList();
+				Long primaryKey = CollectionUtil.isEmpty(primaryKeyList) ? null : primaryKeyList.get(0);
+				XmAssetHoursEntity entity = new XmAssetHoursEntity();
+				if (primaryKey == null) {
+					entity.setXmId(xmId);
+					entity.setAssetId(dbAsset.getId());
+					entity.setWorkDate(dailyAttendance.getWorkDate());
+					entity.setWorkHours(dailyAttendance.getWorkHours());
+					entity.setTenantId(SecureUtil.getTenantId());
+					entity.setCreateUser(SecureUtil.getUserId());
+					entity.setCreateDept(Func.toLong(SecureUtil.getDeptId()));
+					insertList.add(entity);
+				} else {
+					entity.setId(primaryKey);
+					entity.setWorkHours(dailyAttendance.getWorkHours());
+					updateList.add(entity);
+				}
+				if (!insertList.isEmpty() && insertList.size() % batchCount == 0) {
+					int insertCount = xmAssetHoursMapper.batchInsert(insertList);
+					if (insertCount == batchCount) {
+						insertList.clear();
+					}
+
+				}
+				if (!updateList.isEmpty() && updateList.size() % batchCount == 0) {
+					int updateCount = xmAssetHoursMapper.batchUpdate(updateList);
+					if (updateCount == batchCount) {
+						updateList.clear();
+					}
+				}
+			}
+		}
+		if (!insertList.isEmpty()) {
+			xmAssetHoursMapper.batchInsert(insertList);
+		}
+		if (!updateList.isEmpty()) {
+			xmAssetHoursMapper.batchUpdate(updateList);
+		}
+    }
+
+	@Override
+	public IPage<XmAssetHoursVO> selectXmAssetHoursPage(XmAssetHoursVO vo, IPage<XmAssetHoursVO> page) {
+		if (StringUtil.isBlank(vo.getYearAndMonth())) {
+			throw new ServiceException("参数yearAndMonth不能为空");
+		}
+		List<XmAssetHoursVO> list = xmAssetHoursMapper.selectXmAssetHoursPage(page, vo);
+//		for (XmAssetHoursVO temp : list) {
+//			List<DailyAttendance> dailyAttendanceList = xmAssetHoursMapper.selectHoursByXmIdAndAssetId(temp.getXmId(), temp.getAssetId(), vo.getYearAndMonth());
+//			if(CollectionUtil.isEmpty(dailyAttendanceList)){
+//				continue;
+//			}
+//			temp.setMonthlyHours(dailyAttendanceList.stream().mapToDouble(DailyAttendance::getWorkHours).sum());
+//			temp.setDailyAttendances(dailyAttendanceList);
+//		}
+		return page.setRecords(list);
+	}
 }

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

@@ -137,7 +137,7 @@ public class AttendanceServiceImpl extends BaseServiceImpl<AttendanceMapper, Att
 					}
 
 				}
-				if (!insertList.isEmpty() && updateList.size() % batchCount == 0) {
+				if (!updateList.isEmpty() && updateList.size() % batchCount == 0) {
 					int updateCount = baseMapper.batchUpdate(updateList);
 					if (updateCount == batchCount) {
 						updateList.clear();