这个死财务提的莫名其妙的需求

This commit is contained in:
2025-06-12 17:43:56 +08:00
parent cc6bba96f6
commit e8adc2b14d
13 changed files with 317 additions and 60 deletions

View File

@@ -2,23 +2,21 @@ package com.ruoyi.oa.controller;
import java.util.List;
import java.util.Arrays;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import com.ruoyi.oa.domain.vo.ProjectAttendanceVo;
import lombok.RequiredArgsConstructor;
import javax.servlet.http.HttpServletResponse;
import javax.validation.constraints.*;
import cn.dev33.satoken.annotation.SaCheckPermission;
import org.springframework.web.bind.annotation.*;
import org.springframework.validation.annotation.Validated;
import com.ruoyi.common.annotation.RepeatSubmit;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.PageQuery;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.validate.AddGroup;
import com.ruoyi.common.core.validate.EditGroup;
import com.ruoyi.common.core.validate.QueryGroup;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.oa.domain.vo.OaAttendanceRecordVo;
import com.ruoyi.oa.domain.bo.OaAttendanceRecordBo;
@@ -99,4 +97,18 @@ public class OaAttendanceRecordController extends BaseController {
@PathVariable Long[] recordIds) {
return toAjax(iOaAttendanceRecordService.deleteWithValidByIds(Arrays.asList(recordIds), true));
}
@GetMapping("/attendance")
public R<List<ProjectAttendanceVo>>getAttendance(
@RequestParam List<String> userIds,
@RequestParam(required = false) String calcTime,
@RequestParam String relationMonth) {
// 使用 Stream 将 List<String> 转换为 List<Long>
List<Long> longList = userIds.stream()
.map(Long::parseLong) // 将每个 String 转换为 Long
.collect(Collectors.toList());
return R.ok(iOaAttendanceRecordService.getAttendance(longList,calcTime, relationMonth));
}
}

View File

@@ -128,4 +128,13 @@ public class SysOaWarehouseMasterController extends BaseController {
@PathVariable Long[] masterIds) {
return toAjax(iSysOaWarehouseMasterService.deleteWithValidByIds(Arrays.asList(masterIds), true));
}
/**
* 撤回出库单
* 这个傻逼库房非得让写个撤回 勾八自己写错了信息化背锅
*/
@GetMapping("/redo/{masterId}")
public R<Void> redo(@PathVariable("masterId") Long masterId) {
return toAjax(iSysOaWarehouseMasterService.redoMaster(masterId));
}
}

View File

@@ -0,0 +1,13 @@
package com.ruoyi.oa.domain;
import lombok.Data;
@Data
public class ProjectAttendance {
private Long userId;
private String relationMonth;
private Long projectId;
private String projectName;
private Long workDays;
}

View File

@@ -0,0 +1,19 @@
package com.ruoyi.oa.domain.vo;
import com.ruoyi.oa.domain.ProjectAttendance;
import lombok.Data;
import java.util.List;
@Data
public class ProjectAttendanceVo {
private Long userId;
private String relationMonth;
private String nickName;
private List<ProjectAttendance> projects;
}

View File

@@ -1,8 +1,11 @@
package com.ruoyi.oa.mapper;
import com.ruoyi.oa.domain.ProjectAttendance;
import com.ruoyi.oa.domain.vo.ProjectAttendanceVo;
import com.ruoyi.oa.domain.OaAttendanceRecord;
import com.ruoyi.oa.domain.vo.OaAttendanceRecordVo;
import com.ruoyi.common.core.mapper.BaseMapperPlus;
import com.ruoyi.oa.domain.vo.SysOaProjectVo;
import org.apache.ibatis.annotations.Param;
import java.util.Date;
@@ -38,4 +41,12 @@ public interface OaAttendanceRecordMapper extends BaseMapperPlus<OaAttendanceRec
* @return
*/
OaAttendanceRecordVo selectVoByIdPlus(Long recordId);
List<ProjectAttendance> getAttendance(@Param("userIds") List<Long> userIds, @Param("calcTime") String calcTime, @Param("relationMonth") String relationMonth);
SysOaProjectVo getProjectById(Long projectId);
Long getWorkDays(@Param("userId") Long userId, @Param("projectIds") String[] projectIds, @Param("calcTime") String calcTime, @Param("relationMonth") String relationMonth);
List<String> selectProjectIds(@Param("userIds") List<Long> userIds, @Param("calcTime") String calcTime, @Param("relationMonth") String relationMonth);
}

View File

@@ -44,4 +44,6 @@ public interface SysOaAttendanceMapper extends BaseMapperPlus<SysOaAttendanceMap
AttendanceMonthlyCount selectAttendanceMonthlyCountByMonth(String refDate);
List<AttendanceMonthlyCount> selectMonthlyCounts(String refDate);
Long getWorkDaysByUserIdAndProjectId(@Param("userId") Long userId, @Param("projectId") Long projectId, @Param("calcTime") String calcTime, @Param("relationMonth") String relationMonth);
}

View File

@@ -1,5 +1,6 @@
package com.ruoyi.oa.service;
import com.ruoyi.oa.domain.vo.ProjectAttendanceVo;
import com.ruoyi.oa.domain.vo.OaAttendanceRecordVo;
import com.ruoyi.oa.domain.bo.OaAttendanceRecordBo;
import com.ruoyi.common.core.page.TableDataInfo;
@@ -53,4 +54,6 @@ public interface IOaAttendanceRecordService {
*/
List<String> listGenDate(String date);
List<ProjectAttendanceVo> getAttendance(List<Long> userIds,String calcTime, String relationMonth);
}

View File

@@ -63,4 +63,12 @@ public interface ISysOaWarehouseMasterService {
*/
int updateMasterAndInsertBatchWare(SysOaWarehouseMasterBo bo);
/**
* 撤回出库
* @param masterId
* @return
*/
int redoMaster(Long masterId);
}

View File

@@ -1,13 +1,20 @@
package com.ruoyi.oa.service.impl;
import cn.hutool.core.bean.BeanUtil;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.core.page.TableDataInfo;
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.ProjectAttendance;
import com.ruoyi.oa.domain.vo.ProjectAttendanceVo;
import com.ruoyi.oa.domain.vo.SysOaProjectVo;
import com.ruoyi.oa.mapper.SysOaAttendanceMapper;
import com.ruoyi.oa.mapper.SysOaProjectMapper;
import com.ruoyi.system.mapper.SysUserMapper;
import liquibase.pro.packaged.A;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ruoyi.oa.domain.bo.OaAttendanceRecordBo;
import com.ruoyi.oa.domain.vo.OaAttendanceRecordVo;
@@ -29,6 +36,15 @@ public class OaAttendanceRecordServiceImpl implements IOaAttendanceRecordService
private final OaAttendanceRecordMapper baseMapper;
@Autowired
private SysOaProjectMapper projectMapper;
@Autowired
private SysOaAttendanceMapper attendanceMapper;
@Autowired
private SysUserMapper userMapper;
/**
* 查询计算记录
*/
@@ -130,4 +146,75 @@ public class OaAttendanceRecordServiceImpl implements IOaAttendanceRecordService
return baseMapper.listGenDate(date);
}
/**
*
* @param userIds
* @param calcTime “yyyy-MM-dd”
* @param relationMonth “yyyy-MM-dd”
* @return
*/
@Override
public List<ProjectAttendanceVo> getAttendance(List<Long> userIds, String calcTime,String relationMonth) {
// 首先查询合并好的projectIds 然后在查到的这个Long类型的列表后加入 0 1, 分别代表0出差1请假
List<String> projectIdsString = baseMapper.selectProjectIds(userIds,calcTime,relationMonth);
List<Long> projectIds = parseProjectIds(projectIdsString);
projectIds.add(0L);
projectIds.add(1L);
// 然后拿着每一个userId和projectId去签到表查询出勤 在传入的计算时间之前
List<ProjectAttendanceVo> attendanceVoList = new ArrayList<>();
for (Long userId : userIds) {
List<ProjectAttendance> projects = new ArrayList<>();
for (Long projectId : projectIds) {
// 老规矩如果calcTime和relationMonth不在一个月则查询relationMonth全月的 如果在一个月则查询从一号到calcTime的出勤次数 及day_length>0或hour>0或project_id=0
Long workDays = attendanceMapper.getWorkDaysByUserIdAndProjectId(userId,projectId,calcTime,relationMonth);
ProjectAttendance projectAttendance = new ProjectAttendance();
projectAttendance.setProjectId(projectId);
projectAttendance.setWorkDays(workDays);
if (projectId.equals(0L)) {
projectAttendance.setProjectName("出差");
}else if (projectId.equals(1L)) {
projectAttendance.setProjectName("请假");
}else{
SysOaProjectVo sysOaProjectVo = projectMapper.selectVoById(projectId);
projectAttendance.setProjectName(sysOaProjectVo.getProjectName());
}
projects.add(projectAttendance);
}
ProjectAttendanceVo projectAttendanceVo = new ProjectAttendanceVo();
projectAttendanceVo.setProjects(projects);
projectAttendanceVo.setRelationMonth(relationMonth);
projectAttendanceVo.setNickName(userMapper.selectVoById(userId).getNickName());
attendanceVoList.add(projectAttendanceVo);
}
//
return attendanceVoList;
}
public static List<Long> parseProjectIds(List<String> projectIdsString) {
// 使用 HashSet 来确保去重
Set<Long> projectIdSet = new HashSet<>();
// 遍历输入的每个字符串
for (String ids : projectIdsString) {
// 按照逗号分割每个字符串
String[] idsArray = ids.split(",");
// 将每个分割出来的 ID 转换为 Long 类型并添加到 Set 中
for (String id : idsArray) {
// 去除空格并检查是否为空字符串
id = id.trim(); // 去除两端的空格
if (!id.isEmpty()) { // 如果不为空
projectIdSet.add(Long.parseLong(id)); // 转换并添加到 Set 中
}
}
}
// 返回 ListSet 会自动去重
return new ArrayList<>(projectIdSet);
}
}

View File

@@ -78,7 +78,7 @@ public class SysOaProjectServiceImpl implements ISysOaProjectService {
Map<String, Object> params = bo.getParams();
LambdaQueryWrapper<SysOaProject> lqw = Wrappers.lambdaQuery();
lqw.like(StringUtils.isNotBlank(bo.getProjectName()), SysOaProject::getProjectName, bo.getProjectName());
lqw.eq(StringUtils.isNotBlank(bo.getProjectNum()), SysOaProject::getProjectNum, bo.getProjectNum());
lqw.like(StringUtils.isNotBlank(bo.getProjectNum()), SysOaProject::getProjectNum, bo.getProjectNum());
lqw.like(StringUtils.isNotBlank(bo.getProjectCode()), SysOaProject::getProjectCode, bo.getProjectCode());
lqw.eq(bo.getTradeType() != null, SysOaProject::getTradeType, bo.getTradeType());

View File

@@ -3,23 +3,31 @@ package com.ruoyi.oa.service.impl;
import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.ruoyi.common.helper.LoginHelper;
import com.ruoyi.common.utils.BeanCopyUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.core.domain.PageQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.ruoyi.oa.domain.SysOaWarehouse;
import com.ruoyi.oa.domain.SysOaWarehouseDetail;
import com.ruoyi.oa.domain.bo.SysOaWarehouseBo;
import com.ruoyi.oa.domain.bo.SysOaWarehouseDetailBo;
import com.ruoyi.oa.domain.vo.SysOaWarehouseDetailVo;
import com.ruoyi.oa.domain.vo.SysOaWarehouseVo;
import com.ruoyi.oa.mapper.SysOaWarehouseDetailMapper;
import com.ruoyi.oa.mapper.SysOaWarehouseMapper;
import com.ruoyi.oa.service.ISysOaWarehouseDetailService;
import com.ruoyi.oa.service.ISysOaWarehouseService;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ruoyi.oa.domain.bo.SysOaWarehouseMasterBo;
import com.ruoyi.oa.domain.vo.SysOaWarehouseMasterVo;
import com.ruoyi.oa.domain.SysOaWarehouseMaster;
import com.ruoyi.oa.mapper.SysOaWarehouseMasterMapper;
import com.ruoyi.oa.service.ISysOaWarehouseMasterService;
import org.springframework.transaction.annotation.Transactional;
import java.util.*;
@@ -39,6 +47,9 @@ public class SysOaWarehouseMasterServiceImpl implements ISysOaWarehouseMasterSer
private final ISysOaWarehouseDetailService warehouseDetailService;
@Autowired
private SysOaWarehouseMapper warehouseMapper;
/**
* 查询出库单管理
@@ -161,7 +172,6 @@ public class SysOaWarehouseMasterServiceImpl implements ISysOaWarehouseMasterSer
*/
@Override
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
System.out.println(ids);
if (isValid) {
//TODO 做一些业务上的校验,判断是否需要校验
}
@@ -210,36 +220,6 @@ public class SysOaWarehouseMasterServiceImpl implements ISysOaWarehouseMasterSer
return flag;
// // 获取是否存在此采购单的入库单
// if (bo.getType() == 2L) {
// for (SysOaWarehouseDetailBo sysOaWarehouseDetailBo : bo.getWarehouseList()) {
// Long taskStatus = item.getTaskStatus();
// if (taskStatus == 1|| taskStatus == 0) {
// item.setInventory(item.getTaskInventory());
// SysOaWarehouseDetailBo bo = new SysOaWarehouseDetailBo();
// bo.setAmount(item.getInventory());
// bo.setSignPrice(item.getPrice());
// Long warehouseId = insertByBo2(item);
// bo.setWarehouseId(warehouseId);
// list.add(bo);
// }
// }
// SysOaWarehouseMasterBo sysOaWarehouseMaster = new SysOaWarehouseMasterBo();
// sysOaWarehouseMaster.setType(1L);
// List<SysOaWarehouseDetailBo> list = new ArrayList<>();
// boList.forEach(item -> {
//
// });
// sysOaWarehouseMaster.setWarehouseList(list);
// sysOaWarehouseMaster.setMasterNum(UUID.randomUUID().toString());
// return masterService.insertByBo(sysOaWarehouseMaster);
// }
//
//
// // 如果不是2应该进不来 后面看一下是否删除掉
}
@@ -247,4 +227,27 @@ public class SysOaWarehouseMasterServiceImpl implements ISysOaWarehouseMasterSer
return 0;
}
@Override
@Transactional(rollbackFor = Exception.class)
public int redoMaster(Long masterId) {
SysOaWarehouseDetailBo sysOaWarehouseDetailBo = new SysOaWarehouseDetailBo();
sysOaWarehouseDetailBo.setMasterId(masterId);
List<SysOaWarehouseDetailVo> sysOaWarehouseDetailVos = warehouseDetailService.queryList(sysOaWarehouseDetailBo);
for (SysOaWarehouseDetailVo sysOaWarehouseDetailVo : sysOaWarehouseDetailVos) {
SysOaWarehouseVo sysOaWarehouseVo = warehouseMapper.selectVoById(sysOaWarehouseDetailVo.getWarehouseId());
// 拿到原有的物料
if (sysOaWarehouseVo != null) {
// 如果还存在此物料就把库存恢复 然后把价格加权计算
Long newInventory = sysOaWarehouseDetailVo.getAmount()+sysOaWarehouseVo.getInventory();
Double newPrice = (sysOaWarehouseDetailVo.getSignPrice()*sysOaWarehouseDetailVo.getAmount()+sysOaWarehouseVo.getPrice()*sysOaWarehouseVo.getInventory())/(newInventory);
sysOaWarehouseVo.setPrice(newPrice);
sysOaWarehouseVo.setInventory(newInventory);
warehouseMapper.updateById(sysOaWarehouseVo);
}
}
// 全部做完之后删除此出库单
return baseMapper.deleteById(masterId);
}
}

View File

@@ -7,31 +7,31 @@
<resultMap id="OaAttendanceRecordResult"
type="com.ruoyi.oa.domain.vo.OaAttendanceRecordVo">
<!-- ① 主键 -->
<id property="recordId" column="record_id"/>
<id property="recordId" column="record_id"/>
<!-- ② 其他主字段 -->
<result property="userId" column="user_id"/>
<result property="userId" column="user_id"/>
<result property="relationMonth" column="relation_month"/>
<result property="calcTime" column="calc_time"/>
<result property="nickName" column="nick_name"/>
<result property="trips" column="trips"/>
<result property="notNum" column="not_num"/>
<result property="works" column="works"/>
<result property="projectIds" column="project_ids"/>
<result property="overNum" column="over_num"/>
<result property="laborCost" column="labor_cost"/>
<result property="remark" column="remark"/>
<result property="calcTime" column="calc_time"/>
<result property="nickName" column="nick_name"/>
<result property="trips" column="trips"/>
<result property="notNum" column="not_num"/>
<result property="works" column="works"/>
<result property="projectIds" column="project_ids"/>
<result property="overNum" column="over_num"/>
<result property="laborCost" column="labor_cost"/>
<result property="remark" column="remark"/>
<!-- ③ ▶︎ 项目维度汇总列表 -->
<collection property="projectList"
ofType="com.ruoyi.oa.domain.vo.ProjectAttendanceSummaryVo"
javaType="list">
<result property="projectId" column="project_id"/>
<result property="projectName" column="project_name"/>
<result property="color" column="color"/>
<result property="workTimes" column="work_times"/>
<result property="hourWorkTimes" column="hour_work_times"/>
<result property="overTime" column="over_time"/>
<result property="tripDays" column="trip_days"/>
<result property="projectId" column="project_id"/>
<result property="projectName" column="project_name"/>
<result property="color" column="color"/>
<result property="workTimes" column="work_times"/>
<result property="hourWorkTimes" column="hour_work_times"/>
<result property="overTime" column="over_time"/>
<result property="tripDays" column="trip_days"/>
</collection>
</resultMap>
@@ -45,7 +45,7 @@
r.relation_month,
r.calc_time,
r.nick_name,
u.labor_cost,
u.labor_cost,
r.trips,
r.not_num,
r.works,
@@ -72,7 +72,7 @@
LEFT JOIN (SELECT user_id,
project_id,
DATE_FORMAT(create_time, '%Y-%m') AS relation_month,
DATE_FORMAT(create_time, '%Y-%m') AS relation_month,
COUNT(CASE WHEN project_id != 0 and project_id != 1 THEN 1 END) AS work_times,
@@ -95,7 +95,7 @@
GROUP BY user_id, project_id, relation_month) m
ON m.user_id = r.user_id
AND m.project_id = p.project_id
AND m.relation_month =DATE_FORMAT( r.relation_month , '%Y-%m')
AND m.relation_month = DATE_FORMAT(r.relation_month, '%Y-%m')
WHERE r.del_flag = 0
AND r.record_id = #{recordId}
@@ -117,9 +117,78 @@
and DAY(calc_time) = DAY(#{date})
and YEAR(relation_month) = YEAR(#{firstDay})
and MONTH(relation_month) = month(#{firstDay})
and del_flag = 0
and del_flag = 0
</select>
<!-- 查询每个用户的出勤记录,包括合并好的 project_ids -->
<select id="getAttendance" resultType="com.ruoyi.oa.domain.ProjectAttendance">
SELECT
oar.user_id,
oar.nick_name,
oar.relation_month,
oar.project_ids
FROM
oa_attendance_record oar
WHERE
oar.user_id IN
<foreach item="userId" collection="userIds" open="(" separator="," close=")">
#{userId}
</foreach>
AND oar.del_flag = '0'
AND YEAR(oar.relation_month) = YEAR(#{relationMonth})
AND MONTH(oar.relation_month) = MONTH(#{relationMonth})
</select>
<!-- 根据 project_id 获取项目名称 -->
<select id="getProjectById" resultType="com.ruoyi.oa.domain.vo.SysOaProjectVo">
SELECT project_name
FROM sys_oa_project
WHERE project_id = #{projectId}
</select>
<!-- 根据 userId 和 project_id 获取出勤天数 -->
<select id="getWorkDays" resultType="java.lang.Long">
SELECT COALESCE(SUM(CASE
WHEN (oas.day_length > 0 OR oas.hour > 0)
AND (oas.project_id != 1 OR oas.project_id = 0)
THEN 1
ELSE 0 END), 0) AS work_days
FROM sys_oa_attendance oas
WHERE oas.user_id = #{userId}
AND FIND_IN_SET(oas.project_id, #{projectIds}) > 0
AND oas.del_flag = '0'
AND oas.create_time BETWEEN
DATE_FORMAT(#{relationMonth}, '%Y-%m-01')
AND IF(#{calcTime} IS NOT NULL, #{calcTime}, NOW())
</select>
<select id="selectProjectIds" resultType="java.lang.String">
SELECT
oar.project_ids
FROM
oa_attendance_record oar
WHERE
oar.user_id IN
<foreach item="userId" collection="userIds" open="(" separator="," close=")">
#{userId}
</foreach>
AND oar.del_flag = '0'
AND YEAR(oar.relation_month) = YEAR(#{relationMonth})
AND MONTH(oar.relation_month) = MONTH(#{relationMonth})
AND (
-- 如果 calcTime 不为空,查询 calcTime 对应的记录
(#{calcTime} IS NOT NULL AND oar.calc_time = #{calcTime})
OR
-- 如果 calcTime 为空,查询该用户在该月的最新 calc_time
(#{calcTime} IS NULL AND oar.calc_time =
(SELECT MAX(oar2.calc_time)
FROM oa_attendance_record oar2
WHERE oar2.user_id = oar.user_id
AND YEAR(oar2.calc_time) = YEAR(#{relationMonth})
AND MONTH(oar2.calc_time) = MONTH(#{relationMonth}))
)
)
</select>
</mapper>

View File

@@ -305,6 +305,27 @@
GROUP BY m.month
ORDER BY m.month DESC; -- 本月在前,上月在后
</select>
<select id="getWorkDaysByUserIdAndProjectId" resultType="java.lang.Long">
SELECT
COALESCE(SUM(CASE
WHEN (day_length > 0 OR hour > 0)
OR project_id = 0
THEN 1 ELSE 0 END), 0) AS work_days
FROM sys_oa_attendance oas
WHERE oas.user_id = #{userId}
AND oas.project_id = #{projectId}
AND oas.del_flag = 0
AND (
<!-- 如果 calcTime 不为空,查询 calcTime 对应的出勤记录 -->
(#{calcTime} IS NOT NULL AND #{calcTime} >= oas.create_time)
<!-- 如果 calcTime 为空,查询整个 relationMonth -->
OR (#{calcTime} IS NULL AND oas.create_time BETWEEN
-- 提取relationMonth的年月部分并构造第一天
DATE_FORMAT(#{relationMonth}, '%Y-%m-01')
AND LAST_DAY(STR_TO_DATE(#{relationMonth}, '%Y-%m-%d'))
)
)
</select>
</mapper>