|
@@ -25,6 +25,8 @@ import java.time.LocalDate;
|
|
|
import java.time.format.DateTimeFormatter;
|
|
|
import java.util.*;
|
|
|
import java.util.stream.Collectors;
|
|
|
+import java.math.BigDecimal;
|
|
|
+import java.math.RoundingMode;
|
|
|
|
|
|
/**
|
|
|
* <p>
|
|
@@ -55,6 +57,8 @@ public class FinanceMonthlyWorktimeServiceImpl extends ServiceImpl<FinanceMonthl
|
|
|
private ProjectMapper projectMapper;
|
|
|
@Autowired
|
|
|
private FmwDetailService fmwDetailService;
|
|
|
+ @Resource
|
|
|
+ private ErpOrderInfoMapper erpOrderInfoMapper;
|
|
|
|
|
|
@Override
|
|
|
public HttpRespMsg send(String fmwId, String timesheetDate, HttpServletRequest request) {
|
|
@@ -118,22 +122,37 @@ public class FinanceMonthlyWorktimeServiceImpl extends ServiceImpl<FinanceMonthl
|
|
|
|
|
|
@Transactional(rollbackFor = Exception.class)
|
|
|
@Override
|
|
|
- public HttpRespMsg getByMonth(Integer companyId, String ymonth, HttpServletRequest request) {
|
|
|
+ public HttpRespMsg getByMonth(Integer companyId, String ymonth, Integer reGenerate, HttpServletRequest request) throws Exception {
|
|
|
//获取该月份的数据,如果没有自动生成
|
|
|
String token = request.getHeader("token");
|
|
|
User user = userMapper.selectById(token);
|
|
|
FinanceMonthlyWorktime financeMonthlyWorktime = financeMonthlyWorktimeMapper.selectOne(new LambdaQueryWrapper<FinanceMonthlyWorktime>().eq(FinanceMonthlyWorktime::getCompanyId, companyId).eq(FinanceMonthlyWorktime::getYmonth, ymonth));
|
|
|
- if(null != financeMonthlyWorktime){
|
|
|
- //生成数据
|
|
|
- financeMonthlyWorktime = new FinanceMonthlyWorktime();
|
|
|
- financeMonthlyWorktime.setCompanyId(companyId);
|
|
|
- financeMonthlyWorktime.setYmonth(ymonth);
|
|
|
- financeMonthlyWorktime.setStatus(0);
|
|
|
- //数据日期就是当前日期
|
|
|
- financeMonthlyWorktime.setTimesheetDate(LocalDate.now());
|
|
|
- financeMonthlyWorktime.setUserId(user.getId());
|
|
|
- financeMonthlyWorktimeMapper.insert(financeMonthlyWorktime);
|
|
|
-
|
|
|
+ Integer detailCount = 0;
|
|
|
+ if (financeMonthlyWorktime != null) {
|
|
|
+ if (reGenerate== 1) {
|
|
|
+ //删除明细数据
|
|
|
+ fmwDetailMapper.delete(new LambdaQueryWrapper<FmwDetail>().eq(FmwDetail::getFmwId, financeMonthlyWorktime.getId()));
|
|
|
+ } else {
|
|
|
+ detailCount = fmwDetailMapper.selectCount(new QueryWrapper<FmwDetail>().eq("fmw_id", financeMonthlyWorktime.getId()));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if(null == financeMonthlyWorktime || detailCount == 0){
|
|
|
+ if (null == financeMonthlyWorktime) {
|
|
|
+ //生成数据
|
|
|
+ financeMonthlyWorktime = new FinanceMonthlyWorktime();
|
|
|
+ financeMonthlyWorktime.setCompanyId(companyId);
|
|
|
+ financeMonthlyWorktime.setYmonth(ymonth);
|
|
|
+ financeMonthlyWorktime.setStatus(0);
|
|
|
+ //数据日期就是当前日期
|
|
|
+ financeMonthlyWorktime.setTimesheetDate(LocalDate.now());
|
|
|
+ financeMonthlyWorktime.setUserId(user.getId());
|
|
|
+ financeMonthlyWorktimeMapper.insert(financeMonthlyWorktime);
|
|
|
+ } else {
|
|
|
+ //更新数据日期为当前日期
|
|
|
+ financeMonthlyWorktime.setTimesheetDate(LocalDate.now());
|
|
|
+ financeMonthlyWorktime.setUserId(user.getId());
|
|
|
+ financeMonthlyWorktimeMapper.updateById(financeMonthlyWorktime);
|
|
|
+ }
|
|
|
//生成明细数据
|
|
|
//获取当月的第一天和最后一天
|
|
|
LocalDate firstDayOfMonth = LocalDate.parse(ymonth + "-01", DateTimeFormatter.ofPattern("yyyy-MM-dd"));
|
|
@@ -141,6 +160,8 @@ public class FinanceMonthlyWorktimeServiceImpl extends ServiceImpl<FinanceMonthl
|
|
|
//查询日报数据
|
|
|
List<Department> departmentList = departmentMapper.selectList(new LambdaQueryWrapper<Department>().eq(Department::getCompanyId, user.getCompanyId()));
|
|
|
List<Project> projectList = projectMapper.selectList(new LambdaQueryWrapper<Project>().eq(Project::getCompanyId, user.getCompanyId()));
|
|
|
+ List<Project> publicProjectList = projectList.stream().filter(p -> p.getIsPublic() == 1).collect(Collectors.toList());
|
|
|
+ List<ErpOrderInfo> erpOrderInfoList = erpOrderInfoMapper.selectList(new LambdaQueryWrapper<ErpOrderInfo>());
|
|
|
List<User> userList = userMapper.selectList(new LambdaQueryWrapper<User>().select(User::getId, User::getName, User::getDepartmentId).eq(User::getCompanyId, user.getCompanyId()));
|
|
|
List<String> groupNameList = new ArrayList<>();
|
|
|
groupNameList.add("组装/维修工时");
|
|
@@ -159,6 +180,11 @@ public class FinanceMonthlyWorktimeServiceImpl extends ServiceImpl<FinanceMonthl
|
|
|
setFmwTime(fmwDetail, report);
|
|
|
} else {
|
|
|
FmwDetail fmwDetail = new FmwDetail();
|
|
|
+ fmwDetail.setMaintanceTime(0.0);
|
|
|
+ fmwDetail.setDebugTime(0.0);
|
|
|
+ fmwDetail.setWaitingTime(0.0);
|
|
|
+ fmwDetail.setAssistTime(0.0);
|
|
|
+
|
|
|
fmwDetail.setFmwId(financeMonthlyWorktime.getId());
|
|
|
fmwDetail.setProjectId(report.getProjectId());
|
|
|
projectList.stream().filter(p->p.getId().equals(report.getProjectId())).findFirst().ifPresent(project -> {
|
|
@@ -170,6 +196,10 @@ public class FinanceMonthlyWorktimeServiceImpl extends ServiceImpl<FinanceMonthl
|
|
|
departmentList.stream().filter(d->d.getDepartmentId().equals(report.getDeptId())).findFirst().ifPresent(d->{
|
|
|
fmwDetail.setDeptCode(d.getDeptCode());
|
|
|
fmwDetail.setDeptName(d.getDepartmentName());
|
|
|
+ //为提高可读性,从erpOrderInfo表中获取部门名称
|
|
|
+ erpOrderInfoList.stream().filter(e->e.getDeptId().equals(d.getDeptCode())).findFirst().ifPresent(e->{
|
|
|
+ fmwDetail.setDeptName(e.getDeptName());
|
|
|
+ });
|
|
|
});
|
|
|
setFmwTime(fmwDetail, report);
|
|
|
//从assistList中获取协作工时
|
|
@@ -181,6 +211,111 @@ public class FinanceMonthlyWorktimeServiceImpl extends ServiceImpl<FinanceMonthl
|
|
|
}
|
|
|
}
|
|
|
System.out.println("插入数据大小=="+insertDataList.size());
|
|
|
+
|
|
|
+ // 处理公共项目工时分摊
|
|
|
+ List<Integer> publicProjectIds = publicProjectList.stream()
|
|
|
+ .map(Project::getId)
|
|
|
+ .collect(Collectors.toList());
|
|
|
+
|
|
|
+ if (!publicProjectIds.isEmpty()) {
|
|
|
+ // 查询公共项目工时
|
|
|
+ //TODO: 需确认,员工填报公共项目工时的时候,会选择到工单吗?
|
|
|
+ List<Report> publicReportList = reportMapper.selectList(
|
|
|
+ new LambdaQueryWrapper<Report>().select(Report::getCreatorId, Report::getDeptId, Report::getWorkingTime).eq(Report::getState, 1)
|
|
|
+ .in(Report::getProjectId, publicProjectIds).between(Report::getCreateDate, firstDayOfMonth, lastDayOfMonth));
|
|
|
+ //按照人员所在的部门进行分组,汇总,如果公共项目没有工单,此步骤可以省略
|
|
|
+ publicReportList.forEach(report -> {
|
|
|
+ User reportOwner = userList.stream().filter(u -> u.getId().equals(report.getCreatorId())).findFirst().orElse(null);
|
|
|
+ if (reportOwner != null) {
|
|
|
+ report.setDeptId(reportOwner.getDepartmentId());
|
|
|
+ }
|
|
|
+ });
|
|
|
+ //分组,合计部门公共工时
|
|
|
+ Map<Integer, Double> map = publicReportList.stream().collect(Collectors.groupingBy(Report::getDeptId, Collectors.summingDouble(Report::getWorkingTime)));
|
|
|
+ //将map按照List形式重新组合
|
|
|
+ publicReportList = map.entrySet().stream()
|
|
|
+ .map(e -> {
|
|
|
+ Report report = new Report();
|
|
|
+ report.setDeptId(e.getKey());
|
|
|
+ report.setWorkingTime(e.getValue());
|
|
|
+ return report;
|
|
|
+ })
|
|
|
+ .collect(Collectors.toList());
|
|
|
+ if (!publicReportList.isEmpty()) {
|
|
|
+ //处理每个部门的公共项目工时分摊
|
|
|
+ for (Report publicReportDeptItem : publicReportList) {
|
|
|
+ Integer deptId = publicReportDeptItem.getDeptId();
|
|
|
+ List<FmwDetail> deptAllReportList = insertDataList.stream().filter(r -> r.getDeptId().equals(deptId)).collect(Collectors.toList());
|
|
|
+ double totalDeptTime = deptAllReportList.stream().reduce(0.0, (a, b) -> a + b.getMaintanceTime() + b.getDebugTime() + b.getWaitingTime(), Double::sum);
|
|
|
+ System.out.println("处理公共工时分摊,总工时=="+totalDeptTime);
|
|
|
+ if (totalDeptTime > 0) {
|
|
|
+ //计算总工时: 用维修组装工时,调试工时和等料工时相加
|
|
|
+ insertDataList.forEach(fmwDetail -> {
|
|
|
+ //计算每一个项目的部门内部工时占比,按比例分摊公共工时
|
|
|
+ if (fmwDetail.getDeptId().equals(deptId)) {
|
|
|
+ double curProjectTime = fmwDetail.getMaintanceTime() + fmwDetail.getDebugTime() + fmwDetail.getWaitingTime();
|
|
|
+ double assignTime = curProjectTime / totalDeptTime * publicReportDeptItem.getWorkingTime();
|
|
|
+ //理论上不会出现fmwDetail.getPublicTime()有值的情况,但是为了保险起见做个叠加计算吧
|
|
|
+ fmwDetail.setPublicTime(fmwDetail.getPublicTime() == null ? assignTime : fmwDetail.getPublicTime() + assignTime);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ } else {
|
|
|
+ //该部门没有部门内部工时,按照填报部门找协作工时
|
|
|
+ // 查找该部门的员工都协作了哪些部门
|
|
|
+ List<User> deptUserList = userList.stream().filter(u -> u.getDepartmentId().equals(deptId)).collect(Collectors.toList());
|
|
|
+ List<String> deptUserIds = deptUserList.stream().map(User::getId).collect(Collectors.toList());
|
|
|
+ List<Report> assistDeptListByUser = reportMapper.selectList(new QueryWrapper<Report>().select("dept_id, sum(working_time) working_time").eq("is_assist", 1)
|
|
|
+ .in("creator_id", deptUserIds).between("create_date", firstDayOfMonth, lastDayOfMonth).groupBy("dept_id"));
|
|
|
+ //按协作的工时占比来分配
|
|
|
+ if (!assistDeptListByUser.isEmpty()) {
|
|
|
+ double totalAssistTime = assistDeptListByUser.stream().mapToDouble(Report::getWorkingTime).sum();
|
|
|
+ if (totalAssistTime > 0) {
|
|
|
+ for (Report assistDeptItem : assistDeptListByUser) {
|
|
|
+ //处理部门公共工时的分摊,先按协作的其他部门的占比,分到其他部门
|
|
|
+ double curAssistTime = assistDeptItem.getWorkingTime();
|
|
|
+ double assignToDeptTime = curAssistTime / totalAssistTime * publicReportDeptItem.getWorkingTime();
|
|
|
+ //按目标部门的部门内部工时占比进行二次分配
|
|
|
+ Integer assignToDeptId = assistDeptItem.getDeptId();
|
|
|
+ List<FmwDetail> targetDeptReportList = insertDataList.stream().filter(r -> r.getDeptId().equals(assignToDeptId)).collect(Collectors.toList());
|
|
|
+ double totalTargetDeptTime = targetDeptReportList.stream().reduce(0.0, (a, b) -> a + b.getMaintanceTime() + b.getDebugTime() + b.getWaitingTime(), Double::sum);
|
|
|
+ if (totalTargetDeptTime > 0) {
|
|
|
+ //计算总工时: 用维修组装工时,调试工时和等料工时相加
|
|
|
+ insertDataList.forEach(fmwDetail -> {
|
|
|
+ //计算每一个项目的部门内部工时占比,按比例分摊公共工时
|
|
|
+ if (fmwDetail.getDeptId().equals(assignToDeptId)) {
|
|
|
+ double curProjectTime = fmwDetail.getMaintanceTime() + fmwDetail.getDebugTime() + fmwDetail.getWaitingTime();
|
|
|
+ double assignTime = curProjectTime / totalTargetDeptTime * assignToDeptTime;
|
|
|
+ //可能之前已经有其他部门的分摊过来了,需要叠加
|
|
|
+ fmwDetail.setPublicTime(fmwDetail.getPublicTime() == null ? assignTime : fmwDetail.getPublicTime() +assignTime);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ } else {
|
|
|
+ throw new Exception("存在目标部门没有内部工时,导致公共工时无法分摊:targetDeptId=="+assignToDeptId);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ List<FmwDetail> fmwDetails = insertDataList.stream().filter(fmwDetail -> fmwDetail.getDeptId().equals(deptId)).collect(Collectors.toList());
|
|
|
+ double assistDeptTotalTime = fmwDetails.stream().reduce(0.0, (a, b) -> a + b.getMaintanceTime() + b.getDebugTime() + b.getWaitingTime(), Double::sum);
|
|
|
+ if (assistDeptTotalTime > 0) {
|
|
|
+ //计算总工时: 用维修组装工时,调试工时和等料工时相加
|
|
|
+ insertDataList.forEach(fmwDetail -> {
|
|
|
+ //计算每一个项目的部门内部工时占比,按比例分摊公共工时
|
|
|
+ if (fmwDetail.getProjectId().equals(publicReportDeptItem.getProjectId())) {
|
|
|
+ double curProjectTime = fmwDetail.getMaintanceTime() + fmwDetail.getDebugTime() + fmwDetail.getWaitingTime();
|
|
|
+ double assignTime = curProjectTime / assistDeptTotalTime * publicReportDeptItem.getWorkingTime();
|
|
|
+ fmwDetail.setPublicTime(assignTime);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ } else {
|
|
|
+ throw new Exception("存在部门公共工时无法分配,来源deptId=="+deptId);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
if (insertDataList.size() > 0) {
|
|
|
fmwDetailService.saveBatch(insertDataList);
|
|
|
}
|