|
|
@@ -17,6 +17,7 @@ import org.sky.core.tool.utils.Func;
|
|
|
import org.sky.core.tool.utils.StringUtil;
|
|
|
import org.sky.scientific.excel.XmTechnicianHoursExcel;
|
|
|
import org.sky.scientific.excel.XmTechnicianHoursListener;
|
|
|
+import org.sky.scientific.mapper.AttendanceMapper;
|
|
|
import org.sky.scientific.mapper.XmMapper;
|
|
|
import org.sky.scientific.mapper.XmTechnicianHoursMapper;
|
|
|
import org.sky.scientific.mapper.XmTechnicianMapper;
|
|
|
@@ -30,6 +31,7 @@ import org.springframework.web.multipart.MultipartFile;
|
|
|
|
|
|
import java.io.BufferedInputStream;
|
|
|
import java.util.*;
|
|
|
+import java.util.stream.Collectors;
|
|
|
|
|
|
/**
|
|
|
* 研发人员研发工时记录表 服务实现类
|
|
|
@@ -44,6 +46,7 @@ public class XmTechnicianHoursServiceImpl extends BaseServiceImpl<XmTechnicianHo
|
|
|
|
|
|
private final XmMapper xmMapper;
|
|
|
private final XmTechnicianMapper xmTechnicianMapper;
|
|
|
+ private final AttendanceMapper attendanceMapper;
|
|
|
|
|
|
@SneakyThrows
|
|
|
@Transactional(rollbackFor = Exception.class)
|
|
|
@@ -54,7 +57,7 @@ public class XmTechnicianHoursServiceImpl extends BaseServiceImpl<XmTechnicianHo
|
|
|
EasyExcel.read(new BufferedInputStream(file.getInputStream()))
|
|
|
.registerReadListener(listener)
|
|
|
.sheet(0)
|
|
|
- .headRowNumber(3) // 重要:设置表头行数(0-based)
|
|
|
+ .headRowNumber(4) // 重要:设置表头行数(0-based)
|
|
|
.doRead();
|
|
|
List<XmTechnicianHoursExcel> records = listener.getRecords();
|
|
|
if (CollectionUtil.isEmpty(records)) {
|
|
|
@@ -67,26 +70,67 @@ public class XmTechnicianHoursServiceImpl extends BaseServiceImpl<XmTechnicianHo
|
|
|
List<XmTechnicianHours> updateList = new ArrayList<>();
|
|
|
|
|
|
int batchCount = 20;
|
|
|
+ //月度工时列表
|
|
|
+ List<XmTechnicianHours> dbList = baseMapper.selectByYearAndMonth(yearAndMonth, null, null);
|
|
|
+
|
|
|
+ //将研发项目信息缓存起来
|
|
|
+ Map<String, Long> xmMap = new HashMap<>();
|
|
|
+ //将研发人员信息缓存起来
|
|
|
+ Map<String, String> technicianMap = new HashMap<>();
|
|
|
|
|
|
- List<XmTechnicianHours> dbList = baseMapper.selectByYearAndMonth(yearAndMonth);
|
|
|
for (XmTechnicianHoursExcel 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() + "]的研发项目编号和研发项目名称都不存在");
|
|
|
+ String xmKey = record.getXmmc() + ":" + record.getXmbh();
|
|
|
+ Long xmId = null;
|
|
|
+ if (xmMap.containsKey(xmKey)) {
|
|
|
+ xmId = xmMap.get(xmKey);
|
|
|
+ } else {
|
|
|
+ xmId = xmMapper.getXmIdByXmmcOrXmbh(yearAndMonth, record.getXmmc(), record.getXmbh());
|
|
|
+ if (xmId == null) {
|
|
|
+ throw new ServiceException("序号为[" + record.getSerialNumber() + "]的研发项目编号和研发项目名称都不存在");
|
|
|
+ }
|
|
|
+ xmMap.put(xmKey, xmId);
|
|
|
}
|
|
|
|
|
|
- String unicode = xmTechnicianMapper.countByXmIdAndNumberAndIdCardAndYearMonth(xmId, record.getNumber(), record.getIdCard(), yearAndMonth);
|
|
|
- if (unicode == null) {
|
|
|
- throw new ServiceException("序号为[" + record.getSerialNumber() + "]的研发人员不存在");
|
|
|
+ String unicode = null;
|
|
|
+ String techniciankey = record.getNumber() + ":" + record.getIdCard();
|
|
|
+ if (technicianMap.containsKey(techniciankey)) {
|
|
|
+ unicode = technicianMap.get(techniciankey);
|
|
|
+ } else {
|
|
|
+ unicode = xmTechnicianMapper.countByXmIdAndNumberAndIdCardAndYearMonth(xmId, record.getNumber(), record.getIdCard(), yearAndMonth);
|
|
|
+ if (unicode == null) {
|
|
|
+ throw new ServiceException("序号为[" + record.getSerialNumber() + "]的研发人员不存在");
|
|
|
+ }
|
|
|
+ technicianMap.put(techniciankey, unicode);
|
|
|
}
|
|
|
- List<XmTechnicianHours> byXmAndUnicodeList = dbList.stream().filter(e -> e.getXmId().equals(xmId) && e.getUnicode().equals(unicode)).toList();
|
|
|
+
|
|
|
+ //根据人员和项目获取工时列表,用于后续决定是新增还是修改
|
|
|
+ Long finalXmId = xmId;
|
|
|
+ String finalUnicode = unicode;
|
|
|
+ List<XmTechnicianHours> byXmAndUnicodeList = dbList.stream().filter(e -> e.getXmId().equals(finalXmId) && e.getUnicode().equals(finalUnicode)).toList();
|
|
|
+
|
|
|
+ //根据unicode、yearAndMonth获取考勤明细
|
|
|
+ List<DailyAttendance> dailyAttendanceList = attendanceMapper.selectDailyAttendanceByUnicodeAndMonth(unicode, yearAndMonth);
|
|
|
+ if (CollectionUtil.isEmpty(dailyAttendanceList)) {
|
|
|
+ throw new ServiceException("未设置考勤数据");
|
|
|
+ }
|
|
|
+ //每天的考勤总时长
|
|
|
+ Map<String, Double> hoursByDateMap = dailyAttendanceList.stream().collect(Collectors.groupingBy(DailyAttendance::getWorkDate, Collectors.summingDouble(DailyAttendance::getWorkHours)));
|
|
|
+
|
|
|
+ //按人员筛选、根据日期分组,再对工时求和
|
|
|
+ Map<String, Double> usedByUnicodeAndDateMap = dbList.stream().filter(e -> e.getUnicode().equals(finalUnicode)).collect(Collectors.groupingBy(XmTechnicianHours::getWorkDate, Collectors.summingDouble(XmTechnicianHours::getWorkHours)));
|
|
|
+
|
|
|
for (DailyAttendance dailyAttendance : record.getDailyAttendances()) {
|
|
|
|
|
|
- List<Long> primaryKeyList = byXmAndUnicodeList.stream().filter(e -> Objects.equals(e.getWorkDate(), dailyAttendance.getWorkDate())).map(XmTechnicianHours::getId).toList();
|
|
|
+ Double usedHours = usedByUnicodeAndDateMap.get(dailyAttendance.getWorkDate());
|
|
|
+ if (hoursByDateMap.get(dailyAttendance.getWorkDate()) - usedHours < dailyAttendance.getWorkHours()) {
|
|
|
+ //当 考勤时长 - 当天以用工时 < 新的工时 ,则提示“考勤时长不足”
|
|
|
+ throw new ServiceException("考勤总时长为" + hoursByDateMap.get(dailyAttendance.getWorkDate()) + "小时,工时已用" + usedHours + "小时,请核对数据");
|
|
|
+ }
|
|
|
+ List<Long> primaryKeyList = byXmAndUnicodeList.stream().filter(e -> Objects.equals(e.getWorkDate(), dailyAttendance.getWorkDate()) && Objects.equals(e.getXmId(), finalXmId) && Objects.equals(e.getUnicode(), finalUnicode)).map(XmTechnicianHours::getId).toList();
|
|
|
Long primaryKey = CollectionUtil.isEmpty(primaryKeyList) ? null : primaryKeyList.get(0);
|
|
|
XmTechnicianHours entity = new XmTechnicianHours();
|
|
|
if (primaryKey == null) {
|
|
|
@@ -98,10 +142,17 @@ public class XmTechnicianHoursServiceImpl extends BaseServiceImpl<XmTechnicianHo
|
|
|
entity.setCreateUser(SecureUtil.getUserId());
|
|
|
entity.setCreateDept(Func.toLong(SecureUtil.getDeptId()));
|
|
|
insertList.add(entity);
|
|
|
+
|
|
|
+ //已用工时 加上新增的工时
|
|
|
+ usedByUnicodeAndDateMap.put(dailyAttendance.getWorkDate(), usedHours + dailyAttendance.getWorkHours());
|
|
|
} else {
|
|
|
entity.setId(primaryKey);
|
|
|
entity.setWorkHours(dailyAttendance.getWorkHours());
|
|
|
updateList.add(entity);
|
|
|
+
|
|
|
+ //查询数据库中的原有的工时,需要加上旧值,在减去新值
|
|
|
+ double oldHours = byXmAndUnicodeList.stream().filter(e -> Objects.equals(e.getWorkDate(), dailyAttendance.getWorkDate())).mapToDouble(XmTechnicianHours::getWorkHours).sum();
|
|
|
+ usedByUnicodeAndDateMap.put(dailyAttendance.getWorkDate(), usedHours - oldHours + dailyAttendance.getWorkHours());
|
|
|
}
|
|
|
if (!insertList.isEmpty() && insertList.size() % batchCount == 0) {
|
|
|
if (this.saveBatch(insertList)) {
|
|
|
@@ -150,7 +201,15 @@ public class XmTechnicianHoursServiceImpl extends BaseServiceImpl<XmTechnicianHo
|
|
|
if (dto.getUnicode() == null) {
|
|
|
throw new ServiceException("参数unicode不能为空");
|
|
|
}
|
|
|
- List<XmTechnicianHours> dbList = baseMapper.selectByYearAndMonth(dto.getYearAndMonth());
|
|
|
+
|
|
|
+ //获取考勤数据,具体人员在某个月的考勤明细
|
|
|
+ List<DailyAttendance> dailyAttendanceList = attendanceMapper.selectDailyAttendanceByUnicodeAndMonth(dto.getUnicode(), dto.getYearAndMonth());
|
|
|
+ if (CollectionUtil.isEmpty(dailyAttendanceList)) {
|
|
|
+ throw new ServiceException("未设置考勤数据");
|
|
|
+ }
|
|
|
+
|
|
|
+ //获取工时数据,具体项目、具体人员在某月的工时数据
|
|
|
+ List<XmTechnicianHours> dbList = baseMapper.selectByYearAndMonth(dto.getYearAndMonth(), null, dto.getUnicode());
|
|
|
|
|
|
//需要新增的,以便后续批量新增
|
|
|
List<XmTechnicianHours> insertList = new ArrayList<>();
|
|
|
@@ -158,11 +217,22 @@ public class XmTechnicianHoursServiceImpl extends BaseServiceImpl<XmTechnicianHo
|
|
|
List<XmTechnicianHours> updateList = new ArrayList<>();
|
|
|
|
|
|
for (DailyAttendance dailyAttendance : dto.getDailyAttendances()) {
|
|
|
+ //查询一天的考勤时长
|
|
|
+ double attendanceHours = dailyAttendanceList.stream().filter(e -> Objects.equals(e.getWorkDate(), dailyAttendance.getWorkDate())).mapToDouble(DailyAttendance::getWorkHours).sum();
|
|
|
+ //查询一天所有项目的工时总和
|
|
|
+ double hoursTotal = dbList.stream().filter(e -> Objects.equals(e.getWorkDate(), dailyAttendance.getWorkDate())).mapToDouble(XmTechnicianHours::getWorkHours).sum();
|
|
|
+
|
|
|
+ List<XmTechnicianHours> tempList = dbList.stream().filter(e -> Objects.equals(e.getWorkDate(), dailyAttendance.getWorkDate()) && Objects.equals(e.getXmId(), dto.getXmId())).toList();
|
|
|
+ Long primaryKey = CollectionUtil.isEmpty(tempList) ? null : tempList.get(0).getId();
|
|
|
|
|
|
- List<Long> primaryKeyList = dbList.stream().filter(e -> Objects.equals(e.getWorkDate(), dailyAttendance.getWorkDate())).map(XmTechnicianHours::getId).toList();
|
|
|
- Long primaryKey = CollectionUtil.isEmpty(primaryKeyList) ? null : primaryKeyList.get(0);
|
|
|
XmTechnicianHours entity = new XmTechnicianHours();
|
|
|
if (primaryKey == null) {
|
|
|
+
|
|
|
+ //当 考勤时长 - 项目工时总和 - 新的工时 < 0,则提示“考勤时长不足”
|
|
|
+ if (attendanceHours - hoursTotal - dailyAttendance.getWorkHours() < 0) {
|
|
|
+ throw new ServiceException(dailyAttendance.getWorkDate() + "的考勤时长为" + attendanceHours + "小时,可填写的工时不能超过" + (attendanceHours - hoursTotal) + "小时,请核对数据");
|
|
|
+ }
|
|
|
+
|
|
|
entity.setXmId(dto.getXmId());
|
|
|
entity.setUnicode(dto.getUnicode());
|
|
|
entity.setWorkDate(dailyAttendance.getWorkDate());
|
|
|
@@ -172,6 +242,10 @@ public class XmTechnicianHoursServiceImpl extends BaseServiceImpl<XmTechnicianHo
|
|
|
entity.setCreateDept(Func.toLong(SecureUtil.getDeptId()));
|
|
|
insertList.add(entity);
|
|
|
} else {
|
|
|
+//当 考勤时长 - 项目工时总和 + 旧工时 - 新的工时 < 0,则提示“考勤时长不足”
|
|
|
+ if (attendanceHours + tempList.get(0).getWorkHours() - hoursTotal - dailyAttendance.getWorkHours() < 0) {
|
|
|
+ throw new ServiceException(dailyAttendance.getWorkDate() + "的考勤时长为" + attendanceHours + "小时,可填写的工时不能超过" + (attendanceHours + tempList.get(0).getWorkHours() - hoursTotal) + "小时,请核对数据");
|
|
|
+ }
|
|
|
entity.setId(primaryKey);
|
|
|
entity.setWorkHours(dailyAttendance.getWorkHours());
|
|
|
updateList.add(entity);
|
|
|
@@ -202,8 +276,14 @@ public class XmTechnicianHoursServiceImpl extends BaseServiceImpl<XmTechnicianHo
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
+ //
|
|
|
@Override
|
|
|
public void export(HttpServletResponse response, XmTechnicianHoursVO param) {
|
|
|
|
|
|
}
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public List<JSONObject> selectListForPrint(XmTechnicianHoursVO dto) {
|
|
|
+ return baseMapper.selectListForPrint(dto);
|
|
|
+ }
|
|
|
}
|