This commit is contained in:
zt
2025-12-23 20:09:21 +08:00
parent c713058dd3
commit 74c71a5612
10 changed files with 209 additions and 36 deletions

View File

@ -17,12 +17,14 @@ import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.web.core.BaseController;
import org.dromara.company.domain.bo.CompanyAttendanceRecordBo;
import org.dromara.company.domain.vo.CompanyAttendanceRecordVo;
import org.dromara.company.domain.vo.CompanyMonthAttendanceVo;
import org.dromara.company.service.ICompanyAttendanceRecordService;
import org.dromara.project.domain.dto.attendance.BusAttendancePunchCardByFaceReq;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import java.time.LocalDate;
import java.util.List;
import java.util.concurrent.TimeUnit;
@ -66,4 +68,20 @@ public class CompanyAttendanceRecordAppController extends BaseController {
return companyAttendanceRecordService.queryAbnormalListPageList(userId, pageQuery);
}
/**
* 当天打卡信息
*/
@GetMapping("/todayInfo")
public R<List<CompanyAttendanceRecordVo>> todayInfo(Long userId) {
return R.ok(companyAttendanceRecordService.todayInfo(userId));
}
/**
* 月份打卡信息
*/
@GetMapping("/monthInfo")
public R<List<CompanyMonthAttendanceVo>> monthInfo(Long userId, LocalDate month) {
return R.ok(companyAttendanceRecordService.monthInfo(userId,month));
}
}

View File

@ -95,5 +95,10 @@ public class CompanyLeaveVo implements Serializable {
@ExcelProperty(value = "备注")
private String remark;
/**
* 创建时间
*/
private Date createTime;
}

View File

@ -0,0 +1,39 @@
package org.dromara.company.domain.vo;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import io.github.linpeilie.annotations.AutoMapper;
import lombok.Data;
import org.dromara.project.domain.BusAttendance;
import org.dromara.project.domain.vo.BusAttendanceVo;
import java.io.Serial;
import java.io.Serializable;
import java.time.LocalDate;
import java.util.List;
/**
* 考勤视图对象 bus_attendance
*
* @author Lion Li
* @date 2025-08-05
*/
@Data
@ExcelIgnoreUnannotated
@AutoMapper(target = BusAttendance.class)
public class CompanyMonthAttendanceVo implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 打卡日期
*/
private LocalDate clockDate;
/**
* 考勤记录
*/
private List<CompanyAttendanceRecordVo> list;
}

View File

@ -10,6 +10,7 @@ import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.mybatis.core.page.PageQuery;
import com.baomidou.mybatisplus.extension.service.IService;
import org.dromara.company.domain.vo.CompanyMonthAttendanceVo;
import org.dromara.company.domain.vo.DayRecordCountVo;
import org.dromara.company.domain.vo.DayRecordVo;
import org.dromara.project.domain.dto.attendance.BusAttendancePunchCardByFaceReq;
@ -137,4 +138,15 @@ public interface ICompanyAttendanceRecordService extends IService<CompanyAttenda
* 未处理异常列表
*/
TableDataInfo<CompanyAttendanceRecordVo> queryAbnormalListPageList(Long userId, PageQuery pageQuery);
/**
* 当天打卡信息
*/
List<CompanyAttendanceRecordVo> todayInfo(Long userId);
/**
* 月份打卡信息
*/
List<CompanyMonthAttendanceVo> monthInfo(Long userId, LocalDate month);
}

View File

@ -19,6 +19,7 @@ import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.common.utils.JtsUtil;
import org.dromara.company.domain.*;
import org.dromara.company.domain.dto.RecordCountDto;
import org.dromara.company.domain.vo.CompanyMonthAttendanceVo;
import org.dromara.company.domain.vo.DayRecordCountVo;
import org.dromara.company.domain.vo.DayRecordVo;
import org.dromara.company.service.*;
@ -28,6 +29,7 @@ import org.dromara.contractor.service.ISubConstructionUserService;
import org.dromara.project.domain.dto.attendance.BusAttendancePunchCardByFaceReq;
import org.dromara.project.domain.enums.BusAttendanceClockStatusEnum;
import org.dromara.project.domain.enums.BusAttendanceCommuterEnum;
import org.dromara.project.domain.vo.BusMonthAttendanceVo;
import org.dromara.system.domain.bo.SysUserBo;
import org.dromara.system.domain.vo.SysDeptVo;
import org.dromara.system.domain.vo.SysOssVo;
@ -278,6 +280,7 @@ public class CompanyAttendanceRecordServiceImpl extends ServiceImpl<CompanyAtten
uploadFacePic(file, newInRecord);
return this.save(newInRecord);
} else {
if(CollectionUtil.isEmpty(outPunchRecords)){
CompanyAttendanceRecord newOutRecord = buildPunchRecord(userId, companyId, deptId, nickname, source, req,
attendanceDate, punchTime, rule, BusAttendanceCommuterEnum.CLOCKOUT);
// 处理早退逻辑
@ -285,6 +288,12 @@ public class CompanyAttendanceRecordServiceImpl extends ServiceImpl<CompanyAtten
// 上传人脸照片
uploadFacePic(file, newOutRecord);
return this.save(newOutRecord);
}else {
CompanyAttendanceRecord existOutRecord = outPunchRecords.getFirst();
existOutRecord.setClockTime(punchTime);
fillEarlyLeaveStatus(existOutRecord, attendanceDate, punchTime, rule);
return this.updateById(existOutRecord);
}
}
}
// 下班打卡逻辑
@ -415,7 +424,7 @@ public class CompanyAttendanceRecordServiceImpl extends ServiceImpl<CompanyAtten
String verifyType = rule.getVerifyType();
//人脸校验
if (CompanyConstant.VERIFY_TYPE_FACE.equals(verifyType)) {
if (constructionUserService.faceComparison(file, userId)) {
if (!constructionUserService.faceComparison(file, userId)) {
throw new ServiceException("人脸校验失败");
}
}
@ -469,7 +478,7 @@ public class CompanyAttendanceRecordServiceImpl extends ServiceImpl<CompanyAtten
return res;
} else if (CompanyConstant.CLOCK_TYPE_RANGE.equals(clockType)) { //电子围栏校验
//获取范围
List<CompanyAttendanceRange> list = rangeService.lambdaQuery().eq(CompanyAttendanceRange::getId, ruleId).list();
List<CompanyAttendanceRange> list = rangeService.lambdaQuery().eq(CompanyAttendanceRange::getRuleId, ruleId).list();
List<String> punchRangeList = list.stream().map(CompanyAttendanceRange::getPunchRange).toList();
List<GeoPoint> matchingRange = JtsUtil.findMatchingRange(req.getLat(), req.getLng(), punchRangeList);
return matchingRange != null;
@ -654,7 +663,7 @@ public class CompanyAttendanceRecordServiceImpl extends ServiceImpl<CompanyAtten
List<Long> list1 = list.stream().map(CompanyAttendanceRule::getId).toList();
if (!list1.isEmpty()) {
List<CompanyAttendanceRuleDept> list2 = ruleDeptService.lambdaQuery()
.eq(CompanyAttendanceRuleDept::getRuleId, list1).list();
.in(CompanyAttendanceRuleDept::getRuleId, list1).list();
List<Long> list3 = list2.stream().map(CompanyAttendanceRuleDept::getDeptId).toList();
if (!list3.isEmpty()) {
List<SysUserVo> sysUserVos = userService.selectUserListByDeptList(list3);
@ -878,8 +887,6 @@ public class CompanyAttendanceRecordServiceImpl extends ServiceImpl<CompanyAtten
@Override
public List<CompanyAttendanceRecordVo> abnormalList(Long userId) {
return List.of();
}
@ -894,4 +901,36 @@ public class CompanyAttendanceRecordServiceImpl extends ServiceImpl<CompanyAtten
Page<CompanyAttendanceRecordVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
return TableDataInfo.build(result);
}
@Override
public List<CompanyAttendanceRecordVo> todayInfo(Long userId) {
LambdaQueryWrapper<CompanyAttendanceRecord> lqw = Wrappers.lambdaQuery();
lqw.eq(CompanyAttendanceRecord::getUserId, userId);
lqw.eq(CompanyAttendanceRecord::getClockDate, LocalDate.now());
return baseMapper.selectVoList(lqw);
}
@Override
public List<CompanyMonthAttendanceVo> monthInfo(Long userId, LocalDate month) {
LocalDate start = month.with(TemporalAdjusters.firstDayOfMonth());
LocalDate end = month.with(TemporalAdjusters.lastDayOfMonth());
LambdaQueryWrapper<CompanyAttendanceRecord> lqw = Wrappers.lambdaQuery();
lqw.eq(CompanyAttendanceRecord::getUserId, userId);
lqw.between(CompanyAttendanceRecord::getClockDate, start,end);
List<CompanyAttendanceRecordVo> list = baseMapper.selectVoList(lqw);
Map<LocalDate, List<CompanyAttendanceRecordVo>> map = list.stream().collect(Collectors.groupingBy(CompanyAttendanceRecordVo::getClockDate));
List<CompanyMonthAttendanceVo> result = new ArrayList<>();
LocalDate currentDate = start;
while (!currentDate.isAfter(end)) {
CompanyMonthAttendanceVo vo = new CompanyMonthAttendanceVo();
vo.setClockDate(currentDate);
vo.setList(map.getOrDefault(currentDate, Collections.emptyList()));
result.add(vo);
currentDate = currentDate.plusDays(1);
}
return result;
}
}

View File

@ -535,6 +535,25 @@ public class SysUserServiceImpl implements ISysUserService, UserService {
@CacheEvict(cacheNames = CacheNames.SYS_NICKNAME, key = "#user.userId")
@Transactional(rollbackFor = Exception.class)
public int updateUser(SysUserBo user) {
SysUser sysUser1 = baseMapper.selectById(user.getUserId());
String appUserType = sysUser1.getAppUserType();
if("0".equals(appUserType) || "2".equals(appUserType)){
int size = user.getProjectRoles().size();
if(size > 1){
throw new ServiceException("分包和施工只能关联一个项目");
}
SubConstructionUser bySysUserId = constructionUserService.getBySysUserId(user.getUserId());
if(bySysUserId == null){
throw new ServiceException("请先实名");
}
if(bySysUserId.getProjectId() == null){
throw new ServiceException("请先关联项目");
}
Long projectId = user.getProjectRoles().getFirst().getProjectId();
if(!Objects.equals(bySysUserId.getProjectId(), projectId)){
throw new ServiceException("与现有项目不匹配");
}
}
// 新增用户与角色管理
insertUserRole(user, true);
// 新增用户与岗位管理

View File

@ -55,4 +55,9 @@ public class FlowInstanceBo implements Serializable {
*/
private List<Long> createByIds;
/**
* 筛选 1-考勤
*/
private String type;
}

View File

@ -60,4 +60,8 @@ public class FlowTaskBo implements Serializable {
*/
private String isRead;
/**
* 筛选 1-考勤
*/
private String type;
}

View File

@ -2,6 +2,7 @@ package org.dromara.workflow.service.impl;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
@ -267,11 +268,11 @@ public class FlwInstanceServiceImpl implements IFlwInstanceService {
@Override
public TableDataInfo<FlowInstanceVo> selectCurrentInstanceList(FlowInstanceBo instanceBo, PageQuery pageQuery) {
QueryWrapper<FlowInstanceBo> queryWrapper = buildQueryWrapper(instanceBo);
if (!"0".equals(instanceBo.getProjectId())){
List<Long> definitionIds = new ArrayList<>();
if (!"0".equals(instanceBo.getProjectId()) && instanceBo.getProjectId() != null ){
List<FlowDefinition> flowDefinitions = flowDefinitionMapper.selectList(new LambdaQueryWrapper<FlowDefinition>()
.select(FlowDefinition::getId)
.like(StringUtils.isNotBlank(instanceBo.getProjectId()),FlowDefinition::getFlowCode, instanceBo.getProjectId()));
List<Long> definitionIds = new ArrayList<>();
if (flowDefinitions != null && !flowDefinitions.isEmpty()) {
flowDefinitions.forEach(flowDefinition -> {
definitionIds.add(flowDefinition.getId());
@ -280,8 +281,18 @@ public class FlwInstanceServiceImpl implements IFlwInstanceService {
if (definitionIds.isEmpty()) {
return null;
}
queryWrapper.in("fi.definition_id",definitionIds);
}
if("1".equals(instanceBo.getType())){
List<FlowDefinition> flowDefinitions = flowDefinitionMapper.selectList(new LambdaQueryWrapper<FlowDefinition>()
.select(FlowDefinition::getId)
.like(FlowDefinition::getFlowCode, "company"));
if (flowDefinitions != null && !flowDefinitions.isEmpty()) {
flowDefinitions.forEach(flowDefinition -> {
definitionIds.add(flowDefinition.getId());
});
}
}
queryWrapper.in(CollectionUtil.isNotEmpty(definitionIds),"fi.definition_id",definitionIds);
queryWrapper.eq("fi.create_by", LoginHelper.getUserIdStr());
Page<FlowInstanceVo> page = flwInstanceMapper.selectInstanceList(pageQuery.build(), queryWrapper);
return TableDataInfo.build(page);

View File

@ -276,7 +276,7 @@ public class FlwTaskServiceImpl implements IFlwTaskService {
public TableDataInfo<FlowTaskVo> pageByTaskWait(FlowTaskBo flowTaskBo, PageQuery pageQuery) {
QueryWrapper<FlowTaskBo> queryWrapper = buildQueryWrapper(flowTaskBo);
List<Long> definitionIds = new ArrayList<>();
if (!"0".equals(flowTaskBo.getProjectId())) {
if (!"0".equals(flowTaskBo.getProjectId()) && flowTaskBo.getProjectId() != null ) {
List<FlowDefinition> flowDefinitions = flowDefinitionMapper.selectList(new LambdaQueryWrapper<FlowDefinition>()
.select(FlowDefinition::getId)
.like(StringUtils.isNotBlank(flowTaskBo.getProjectId()), FlowDefinition::getFlowCode, flowTaskBo.getProjectId()));
@ -289,6 +289,17 @@ public class FlwTaskServiceImpl implements IFlwTaskService {
return null;
}
}
if("1".equals(flowTaskBo.getType())){
List<FlowDefinition> flowDefinitions = flowDefinitionMapper.selectList(new LambdaQueryWrapper<FlowDefinition>()
.select(FlowDefinition::getId)
.like(FlowDefinition::getFlowCode, "company"));
if (flowDefinitions != null && !flowDefinitions.isEmpty()) {
flowDefinitions.forEach(flowDefinition -> {
definitionIds.add(flowDefinition.getId());
});
}
}
queryWrapper.eq("t.node_type", NodeType.BETWEEN.getKey());
queryWrapper.in("t.processed_by", LoginHelper.getUserIdStr());
queryWrapper.in("t.flow_status", BusinessStatusEnum.WAITING.getStatus());
@ -306,7 +317,7 @@ public class FlwTaskServiceImpl implements IFlwTaskService {
public TableDataInfo<FlowHisTaskVo> pageByTaskFinish(FlowTaskBo flowTaskBo, PageQuery pageQuery) {
QueryWrapper<FlowTaskBo> queryWrapper = buildQueryWrapper(flowTaskBo);
List<Long> definitionIds = new ArrayList<>();
if (!"0".equals(flowTaskBo.getProjectId())) {
if (!"0".equals(flowTaskBo.getProjectId()) && flowTaskBo.getProjectId() != null ) {
List<FlowDefinition> flowDefinitions = flowDefinitionMapper.selectList(new LambdaQueryWrapper<FlowDefinition>()
.select(FlowDefinition::getId)
.like(StringUtils.isNotBlank(flowTaskBo.getProjectId()),FlowDefinition::getFlowCode, flowTaskBo.getProjectId()));
@ -319,6 +330,16 @@ public class FlwTaskServiceImpl implements IFlwTaskService {
return null;
}
}
if("1".equals(flowTaskBo.getType())){
List<FlowDefinition> flowDefinitions = flowDefinitionMapper.selectList(new LambdaQueryWrapper<FlowDefinition>()
.select(FlowDefinition::getId)
.like(FlowDefinition::getFlowCode, "company"));
if (flowDefinitions != null && !flowDefinitions.isEmpty()) {
flowDefinitions.forEach(flowDefinition -> {
definitionIds.add(flowDefinition.getId());
});
}
}
queryWrapper.eq("t.node_type", NodeType.BETWEEN.getKey());
queryWrapper.in("t.approver", LoginHelper.getUserIdStr());
queryWrapper.orderByDesc("t.create_time").orderByDesc("t.update_time");