diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysUser.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysUser.java index 82aa639..1cffffb 100644 --- a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysUser.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysUser.java @@ -148,6 +148,7 @@ public class SysUser extends BaseEntity { private Long laborCost; + @TableField(exist = false) private Double workTime; diff --git a/ruoyi-oa/src/main/java/com/ruoyi/oa/controller/SysOaCostController.java b/ruoyi-oa/src/main/java/com/ruoyi/oa/controller/SysOaCostController.java index 92dd0be..51a04ea 100644 --- a/ruoyi-oa/src/main/java/com/ruoyi/oa/controller/SysOaCostController.java +++ b/ruoyi-oa/src/main/java/com/ruoyi/oa/controller/SysOaCostController.java @@ -110,7 +110,7 @@ public class SysOaCostController extends BaseController { /** * 查询详情 */ - @SaCheckPermission("oa:oaCost:list") + @SaCheckPermission("oa:oaCost:query") @GetMapping("/{projectId}") public TableDataInfo getDetail(@NotNull(message = "项目id不能为空") @PathVariable Long projectId) { diff --git a/ruoyi-oa/src/main/java/com/ruoyi/oa/domain/vo/SysOaCostAllVo.java b/ruoyi-oa/src/main/java/com/ruoyi/oa/domain/vo/SysOaCostAllVo.java index 0993f33..b227702 100644 --- a/ruoyi-oa/src/main/java/com/ruoyi/oa/domain/vo/SysOaCostAllVo.java +++ b/ruoyi-oa/src/main/java/com/ruoyi/oa/domain/vo/SysOaCostAllVo.java @@ -4,6 +4,7 @@ import com.baomidou.mybatisplus.annotation.TableField; import com.fasterxml.jackson.annotation.JsonFormat; import lombok.AllArgsConstructor; import lombok.Data; +import lombok.NoArgsConstructor; import java.util.Date; @@ -12,6 +13,7 @@ import java.util.Date; */ @Data @AllArgsConstructor +@NoArgsConstructor public class SysOaCostAllVo { private Long projectId; diff --git a/ruoyi-oa/src/main/java/com/ruoyi/oa/domain/vo/SysOaCostList.java b/ruoyi-oa/src/main/java/com/ruoyi/oa/domain/vo/SysOaCostList.java index 610d0b2..5a02fc7 100644 --- a/ruoyi-oa/src/main/java/com/ruoyi/oa/domain/vo/SysOaCostList.java +++ b/ruoyi-oa/src/main/java/com/ruoyi/oa/domain/vo/SysOaCostList.java @@ -8,13 +8,27 @@ import lombok.NoArgsConstructor; @NoArgsConstructor @AllArgsConstructor public class SysOaCostList { - private Long costId; - private Double cost; + /** + * userCostList + */ private Long userId; - private Object userVo; + private String nickName; + private Double laborCost; + private Double attendenceNum; + + /** + * materialList + */ private Long materialId; - private Object materialVo; + private String name; + private Double price; + private Long amount; + + /** + * claimList + */ private Long claimId; - private Object claimVo; - private Integer costType; + // private String nickName; 申请人姓名 + private Double cost; + private String remark; } diff --git a/ruoyi-oa/src/main/java/com/ruoyi/oa/mapper/SysOaClaimMapper.java b/ruoyi-oa/src/main/java/com/ruoyi/oa/mapper/SysOaClaimMapper.java index 3ccdad4..fccd0be 100644 --- a/ruoyi-oa/src/main/java/com/ruoyi/oa/mapper/SysOaClaimMapper.java +++ b/ruoyi-oa/src/main/java/com/ruoyi/oa/mapper/SysOaClaimMapper.java @@ -7,8 +7,10 @@ import com.ruoyi.oa.domain.SysOaClaim; import com.ruoyi.oa.domain.vo.SysOaClaimVo; import com.ruoyi.common.core.mapper.BaseMapperPlus; import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.Select; import javax.validation.constraints.NotNull; +import java.util.List; /** * 差旅费报销Mapper接口 @@ -25,4 +27,7 @@ public interface SysOaClaimMapper extends BaseMapperPlus List(@Param("projectId") Long projectId); } diff --git a/ruoyi-oa/src/main/java/com/ruoyi/oa/mapper/SysOaOutWarehouseMapper.java b/ruoyi-oa/src/main/java/com/ruoyi/oa/mapper/SysOaOutWarehouseMapper.java index a0cf2f9..8f7858d 100644 --- a/ruoyi-oa/src/main/java/com/ruoyi/oa/mapper/SysOaOutWarehouseMapper.java +++ b/ruoyi-oa/src/main/java/com/ruoyi/oa/mapper/SysOaOutWarehouseMapper.java @@ -29,4 +29,8 @@ public interface SysOaOutWarehouseMapper extends BaseMapperPlus List(@Param("projectId") Long projectId); } diff --git a/ruoyi-oa/src/main/java/com/ruoyi/oa/service/impl/SysOaCostServiceImpl.java b/ruoyi-oa/src/main/java/com/ruoyi/oa/service/impl/SysOaCostServiceImpl.java index 09d9168..9989cf6 100644 --- a/ruoyi-oa/src/main/java/com/ruoyi/oa/service/impl/SysOaCostServiceImpl.java +++ b/ruoyi-oa/src/main/java/com/ruoyi/oa/service/impl/SysOaCostServiceImpl.java @@ -1,6 +1,7 @@ package com.ruoyi.oa.service.impl; import cn.hutool.core.bean.BeanUtil; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.ruoyi.common.core.domain.entity.SysUser; import com.ruoyi.common.exception.ServiceException; import com.ruoyi.common.utils.StringUtils; @@ -9,21 +10,21 @@ import com.ruoyi.common.core.domain.PageQuery; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.toolkit.Wrappers; -import com.ruoyi.oa.domain.SysOaAttendance; -import com.ruoyi.oa.domain.SysOaProject; +import com.ruoyi.oa.domain.*; import com.ruoyi.oa.domain.vo.*; import com.ruoyi.oa.mapper.*; import com.ruoyi.system.mapper.SysUserMapper; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.BeanUtils; import org.springframework.stereotype.Service; import com.ruoyi.oa.domain.bo.SysOaCostBo; -import com.ruoyi.oa.domain.SysOaCost; import com.ruoyi.oa.service.ISysOaCostService; +import java.math.BigDecimal; import java.util.*; +import java.util.function.Function; import java.util.stream.Collectors; +import java.util.stream.Stream; /** * 项目成本分析Service业务层处理 @@ -44,8 +45,11 @@ public class SysOaCostServiceImpl implements ISysOaCostService { private final SysOaWarehouseMapper warehouseMapper; + private final SysOaOutWarehouseMapper outWarehouseMapper; + private final SysOaAttendanceMapper attendanceMapper; + private final SysOaProjectMapper projectMapper; /** * 查询项目成本分析 @@ -138,118 +142,208 @@ public class SysOaCostServiceImpl implements ISysOaCostService { */ @Override - public TableDataInfo AllList(String projectName, String createTime) { // 包括每个项目的成本分析,每个都有这几种类型,即每个项目返回几列数据 - - - List alls = baseMapper.AllList(projectName,createTime); - log.info("alls:{}",alls); - List allVos = new java.util.ArrayList<>(Collections.emptyList()); - if (alls.isEmpty()) return TableDataInfo.build(allVos); - for (SysOaCostAll all : alls) { - SysOaCostAllVo allVo = BeanUtil.toBean(all, SysOaCostAllVo.class); - log.info("allVo:{}", allVo); - - if (allVo.getCostType() == null) allVo.setCost(0.0); - // 车间用工 - else {if (allVo.getCostType() == 1) { //根据出勤,计算人天数 - Double days = attendanceMapper.getAttendanceDay(allVo.getUserId(), allVo.getProjectId()); - Long laborCost = userMapper.selectUserById(allVo.getUserId()).getLaborCost(); - if (days == null || laborCost == null) allVo.setUserCost(0.0); - else allVo.setUserCost(days * laborCost); - } else if (allVo.getCostType() == 2) { // 差旅花费 差旅花费 = 该项目下的所有差旅费用 - allVo.setClaimCost(claimMapper.getClaimCost(allVo.getClaimId())); - - } else if (allVo.getCostType() == 3) { // 库房物料 物料花费 =物料价格*数量 - SysOaWarehouseVo warehouseVo = warehouseMapper.selectVoById(allVo.getMaterialId()); - if (warehouseVo == null) allVo.setMaterialCost(0.0); - else allVo.setMaterialCost(warehouseVo.getInventory() * warehouseVo.getPrice()); - - } else if (allVo.getCostType() == 4) { // 其他 - - - } else if (allVo.getCostType() == 5) { // 接待 - - }} - allVos.add(allVo); - + public TableDataInfo AllList(String projectName, String createTime) { + log.info("查询所有项目对应的/物料费用/工资费用/差旅费用//其他费用"); + LambdaQueryWrapper lqw = Wrappers.lambdaQuery(SysOaProject.class); + if (StringUtils.isNotBlank(projectName)) { + lqw.like(SysOaProject::getProjectName, projectName); } + List projects = projectMapper.selectList(lqw); + log.info(" 查询projects: {}", projects); + if (projects.isEmpty()) { + return TableDataInfo.build(); + } + List sysOaCostAllVos = new ArrayList<>(); -// 假设原始数据列表为 allVos - List resVos = allVos.stream() - .collect(Collectors.groupingBy(SysOaCostAllVo::getProjectId)) - .values().stream() - .map(group -> { - Double userCostSum = group.stream().mapToDouble(x -> Optional.ofNullable((Double)x.getUserCost()).orElse(0.0)).sum(); + for (SysOaProject project : projects) { + SysOaCostAllVo sysOaCostAllVo = new SysOaCostAllVo(); + Long projectId = project.getProjectId(); + sysOaCostAllVo.setProjectId(projectId); + sysOaCostAllVo.setProjectName(project.getProjectName()); - Double claimCostSum = group.stream().mapToDouble(x -> Optional.ofNullable((Double)x.getUserCost()).orElse(0.0)).sum(); - Double materialCostSum = group.stream().mapToDouble(x -> Optional.ofNullable((Double)x.getUserCost()).orElse(0.0)).sum(); - Double totalCost = userCostSum + claimCostSum + materialCostSum; + // 2、 查询所有项目对应的物料 - return new SysOaCostAllVo( - group.get(0).getProjectId(), - group.get(0).getProjectName(), - totalCost, - null, - "汇总数据", // 备注 - null, - null, // materialId - materialCostSum, - null, // userId - userCostSum, - null, // claimId - claimCostSum, - null// financeId - ); - }) - .collect(Collectors.toList()); + List outWarehouses = outWarehouseMapper.List(projectId); + Double materialCost = 0.0; + if (!outWarehouses.isEmpty()) { + Map warehouseMap = warehouseMapper.selectList(Wrappers.lambdaQuery(SysOaWarehouse.class)).stream().collect(Collectors.toMap(SysOaWarehouse::getId, Function.identity())); + log.info("查询所有项目对应的物料:{}",warehouseMap); + materialCost = outWarehouses.stream().map(v -> { + Long warehouseId = v.getWarehouseId(); + BigDecimal amount = BigDecimal.valueOf(v.getAmount()); + SysOaWarehouse warehouse = warehouseMap.get(warehouseId); + if (warehouse == null) { + log.error("仓库信息不存在,仓库ID: " + warehouseId); + return BigDecimal.ZERO; + } + BigDecimal price = BigDecimal.valueOf(warehouse.getPrice()); + return amount.multiply(price); + }).reduce(BigDecimal.ZERO, BigDecimal::add).doubleValue(); + } + sysOaCostAllVo.setMaterialCost(materialCost); - return TableDataInfo.build(resVos); + // 3、 查询所有项目对应的工资费用 + LambdaQueryWrapper lqw2 = Wrappers.lambdaQuery(SysOaAttendance.class); + lqw2.eq(SysOaAttendance::getProjectId, projectId); + List attendances = attendanceMapper.selectList(lqw2); + Double userCost = 0.0; + if (!attendances.isEmpty()) { + // 分组出每个用户的天数 + Map daynumMap = attendances.stream().collect(Collectors.groupingBy( + SysOaAttendance::getUserId, + Collectors.summingDouble(attendance -> { + double attendanceDay = Optional.ofNullable(attendance.getAttendanceDay()).orElse(0L); + double dayLength = Optional.ofNullable(attendance.getDayLength()).orElse(0.0); + double hour = Optional.ofNullable(attendance.getHour()).orElse(0.0); + return attendanceDay * dayLength * 9 + hour; + }) + )); + // 获取user表中的劳务费用 + List users = userMapper.selectList(Wrappers.lambdaQuery(SysUser.class)); + Map userMap = users.stream().collect(Collectors.toMap(SysUser::getUserId, Function.identity())); + // 计算用工总价 + userCost = attendances.stream().map(v -> { + Long userId = v.getUserId(); + SysUser user = userMap.get(userId); + if (user == null) { + log.warn("用户ID信息不存在,用户ID: {}", userId); + return BigDecimal.ZERO; + } + Long laborCost = Optional.ofNullable(user.getLaborCost()).orElse(0L); + Double daynum = daynumMap.getOrDefault(userId, 0.0); + BigDecimal laborCostBigDecimal = BigDecimal.valueOf(laborCost); + BigDecimal daynumBigDecimal = BigDecimal.valueOf(daynum); + return laborCostBigDecimal.multiply(daynumBigDecimal); + }).reduce(BigDecimal.ZERO, BigDecimal::add).doubleValue(); + } + sysOaCostAllVo.setUserCost(userCost); + + // 4、 查询所有项目对应的差旅费用 + + List claims = claimMapper.List(projectId); + Double claimCost = 0.0; + if (!claims.isEmpty()) { + claimCost = claims.stream().map(v -> BigDecimal.valueOf(v.getCost())).reduce(BigDecimal.ZERO, BigDecimal::add).doubleValue(); + } + sysOaCostAllVo.setClaimCost(claimCost); + + // 5、 设置总费用 + sysOaCostAllVo.setCost(materialCost + userCost + claimCost); + // 6、 将 sysOaCostAllVo 添加到 sysOaCostAllVos 中 + sysOaCostAllVos.add(sysOaCostAllVo); + log.info("查询项目对应的费用信息:{}", sysOaCostAllVo); + if (sysOaCostAllVo.getProjectId() == 1862663507129614338L) { + log.info("查询项目对应的费用信息:{}", sysOaCostAllVo); + } + } + log.info("查询所有项目对应的费用信息:{}", sysOaCostAllVos); + return TableDataInfo.build(sysOaCostAllVos); } + /** * 查询详情 */ @Override public TableDataInfo getDetail(Long projectId) { -// log.info("查询projectId = {}", projectId); -// LambdaQueryWrapper lqw = Wrappers.lambdaQuery(SysOaCost.class); -// lqw.eq(SysOaCost::getProjectId,projectId); -// List costs = baseMapper.selectList(lqw); - List costs = baseMapper.getListByProjectId(projectId); -// log.info("查询costs = {}", costs); - - if (costs.isEmpty()) { - return TableDataInfo.build(); - } SysOaCostRow sysOaCostRow = new SysOaCostRow(); - sysOaCostRow.setUserCostList(new ArrayList<>()); - sysOaCostRow.setMaterialList(new ArrayList<>()); - sysOaCostRow.setClaimList(new ArrayList<>()); - sysOaCostRow.setOtherList(new ArrayList<>()); - for(SysOaCost cost : costs) { - SysOaCostList sysOaCostList = BeanUtil.toBean(cost,SysOaCostList.class); - log.info("查询cost = {}", cost); - log.info("sysOaCostList = {}", sysOaCostList); - if(cost.getCostType() == 1) { -// log.info("查询useVo = {}", userMapper.selectUserById(cost.getUserId())); - sysOaCostList.setUserVo(userMapper.selectUserById(cost.getUserId())); - sysOaCostRow.getUserCostList().add(sysOaCostList); - } else if(cost.getCostType() == 2) { -// log.info("查询claimMapperVo = {}", claimMapper.selectSysOaClaimVoById(cost.getClaimId())); - sysOaCostList.setClaimVo(claimMapper.selectSysOaClaimVoById(cost.getClaimId())); - sysOaCostRow.getClaimList().add(sysOaCostList); - } else if(cost.getCostType() == 3) { -// log.info("查询warehouseMapperVo = {}",warehouseMapper.selectVoById(cost.getMaterialId())); - sysOaCostList.setMaterialVo(warehouseMapper.selectVoById(cost.getMaterialId())); - sysOaCostRow.getMaterialList().add(sysOaCostList); - } else{ - sysOaCostRow.getOtherList().add(sysOaCostList); + List UserCostList = new ArrayList<>(); + List MaterialList = new ArrayList<>(); + List ClaimList = new ArrayList<>(); + List OtherList = new ArrayList<>(); + // 1、 查询项目信息 + SysOaProject project = projectMapper.selectById(projectId); + if (project == null) { + throw new ServiceException("项目信息不存在,项目ID: " + projectId); + } + // 2、 查询项目对应的每个人的工资详情 + LambdaQueryWrapper lqw = Wrappers.lambdaQuery(SysOaAttendance.class); + lqw.eq(SysOaAttendance::getProjectId, projectId); + // 查询出该项目下每个用户的工作情况 + List attendances = attendanceMapper.selectList(lqw); + if (!attendances.isEmpty()) { + // 查询出该项目下每个用户的工作天数 + // 分组出每个用户的天数 + // 按用户 ID 分组,并计算每个用户的 attendance_day * day_length * 9 + hour 的总和 + Map daynumMap = attendances.stream() + .collect(Collectors.groupingBy( + SysOaAttendance::getUserId, // 按用户 ID 分组 + Collectors.summingDouble(attendance -> + (attendance.getAttendanceDay() * attendance.getDayLength() * 9 + attendance.getHour())/9 + ) + )); + + + List users = userMapper.selectList(Wrappers.lambdaQuery(SysUser.class)); + Map userMap = users.stream().collect(Collectors.toMap(SysUser::getUserId, Function.identity())); + // 获取user表中的人力成本 + + // attendances 遍历,去重获取每个用户的userid + Set userIds = daynumMap.keySet(); + for (Long userId : userIds) { + SysUser user = userMap.get(userId); + if (user == null) { + continue; + } + SysOaCostList sysOaCostList = new SysOaCostList(); + Double dayNum = daynumMap.get(userId) == null ? 0.0 : daynumMap.get(userId); + Long laborCost = user.getLaborCost() == null ? 0L : user.getLaborCost(); + sysOaCostList.setUserId(userId); + sysOaCostList.setNickName(user.getNickName()); + sysOaCostList.setLaborCost(laborCost * dayNum); + sysOaCostList.setAttendenceNum(dayNum); + UserCostList.add(sysOaCostList); } } -// log.info("sysOaCostRow = {}", sysOaCostRow); + // 3、 查询项目对应的物料详情 + LambdaQueryWrapper lqw1 = Wrappers.lambdaQuery(SysOaOutWarehouse.class); + lqw1.eq(SysOaOutWarehouse::getProjectId, projectId); + List outWarehouses = outWarehouseMapper.selectList(lqw1); + //log.info("查询项目对应的物料详情:{}", outWarehouses); + if (!outWarehouses.isEmpty()) { + Map warehouseMap = warehouseMapper.selectList(Wrappers.lambdaQuery(SysOaWarehouse.class)).stream().collect(Collectors.toMap(SysOaWarehouse::getId, Function.identity())); + + //log.info("查询项目对应的物料详情:{}", warehouseMap); + for (SysOaOutWarehouse outWarehouse : outWarehouses) { + SysOaWarehouse warehouse = warehouseMap.get(outWarehouse.getWarehouseId()); + SysOaCostList sysOaCostList = new SysOaCostList(); + sysOaCostList.setMaterialId(outWarehouse.getWarehouseId()); + sysOaCostList.setName(warehouse.getName()); + sysOaCostList.setPrice(warehouse.getPrice()); + sysOaCostList.setAmount(outWarehouse.getAmount()); + MaterialList.add(sysOaCostList); + } + } + + + // 4、 查询项目对应的差旅详情 + LambdaQueryWrapper lqw2 = Wrappers.lambdaQuery(SysOaClaim.class); + lqw2.eq(SysOaClaim::getProjectId, projectId); + List claims = claimMapper.selectVoList(lqw2); + Map claimMap = claims.stream().collect(Collectors.toMap(SysOaClaimVo::getClaimId, Function.identity())); + log.info("查询项目对应的差旅详情:{}", claims); + Set claimIds = claimMap.keySet(); + if (!claims.isEmpty()) { + for (Long claimId : claimIds) { + SysOaCostList sysOaCostList = new SysOaCostList(); + SysOaClaimVo claim = claimMap.get(claimId); + sysOaCostList.setClaimId(claim.getClaimId()); + sysOaCostList.setNickName(userMapper.selectUserById(claim.getUserId()).getNickName()); + sysOaCostList.setCost(claim.getCost()); + sysOaCostList.setRemark(claim.getRemark()); + ClaimList.add(sysOaCostList); + } + } + + + + sysOaCostRow.setUserCostList(UserCostList); + sysOaCostRow.setMaterialList(MaterialList); + sysOaCostRow.setClaimList(ClaimList); + sysOaCostRow.setOtherList(OtherList); List rows = new java.util.ArrayList<>(Collections.singletonList(sysOaCostRow)); return TableDataInfo.build(rows);