Merge branch 'dev' into frx

This commit is contained in:
furongxin 2024-06-25 14:29:48 +08:00
commit 644fc15bc1
29 changed files with 334 additions and 30 deletions

View File

@ -62,7 +62,9 @@ public class DeptDataPermissionRule implements DataPermissionRule {
"work_log_use",
"work_log_statistics",
"work_log_instance_ext",
"bpm_oa_work_task"
"bpm_oa_work_task",
"zc_dept_assets",
"zc_dept_assets_in_out_stock"
);
/**

View File

@ -9,6 +9,8 @@ import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import javax.annotation.security.PermitAll;
@FeignClient(name = ApiConstants.NAME) // TODO 芋艿fallbackFactory =
@Tag(name = "RPC 服务 - 文件")
public interface ConfigApi {
@ -18,6 +20,7 @@ public interface ConfigApi {
@GetMapping(value = "/get-value-by-key")
@Operation(summary = "根据参数键名查询参数值", description = "不可见的配置,不允许返回给前端")
@Parameter(name = "key", description = "参数键", required = true, example = "yunai.biz.username")
@PermitAll
CommonResult<String> getConfigKey(@RequestParam("key") String key);
}

View File

@ -9,6 +9,8 @@ import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import java.util.List;
@FeignClient(name = ApiConstants.NAME) // TODO 芋艿fallbackFactory =
@Tag(name = "RPC 服务 - 微信小程序订阅消息发送")
public interface SubscribeMessageSendApi {
@ -30,4 +32,8 @@ public interface SubscribeMessageSendApi {
@PostMapping(PREFIX + "/send-worklog-comment")
@Operation(summary = "发送日志评论、回复通知")
CommonResult<Long> sendWorkLogComment(@RequestBody SubscribeMessageReqDTO reqDTO);
@PostMapping(PREFIX + "/send-punch-reminder")
@Operation(summary = "发送打卡提醒通知")
CommonResult<Long> sendPunchReminder(@RequestBody SubscribeMessageReqDTO reqDTO);
}

View File

@ -6,6 +6,7 @@ import cn.iocoder.yudao.module.system.api.subscribe.dto.MsgData;
import cn.iocoder.yudao.module.system.api.subscribe.dto.SubscribeMessageReqDTO;
import cn.iocoder.yudao.module.system.service.social.SocialClientService;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RestController;
@ -22,6 +23,7 @@ import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
*/
@RestController // 提供 RESTful API 接口 Feign 调用
@Validated
@Slf4j
public class SubscribeMessageSendApiImpl implements SubscribeMessageSendApi {
@Resource
@ -55,6 +57,16 @@ public class SubscribeMessageSendApiImpl implements SubscribeMessageSendApi {
return success(1L);
}
@Override
public CommonResult<Long> sendPunchReminder(SubscribeMessageReqDTO reqDTO) {
try {
socialClientService.getWxMaService().getMsgService().sendSubscribeMsg(initWxMaSubscribeMessage(reqDTO));
} catch (Exception e) {
log.error("当前用户没有订阅考勤消息:{}", reqDTO.getToUser());
}
return success(1L);
}
private WxMaSubscribeMessage initWxMaSubscribeMessage(SubscribeMessageReqDTO reqDTO) {
WxMaSubscribeMessage message = WxMaSubscribeMessage.builder()
.toUser(reqDTO.getToUser())

View File

@ -73,7 +73,6 @@ public class AssetsController {
@GetMapping("/page")
@Operation(summary = "获得资产分页")
@PreAuthorize("@ss.hasPermission('system:assets:query')")
public CommonResult<PageResult<AssetsRespVO>> getAssetsPage(@Valid AssetsPageReqVO pageReqVO) {
PageResult<AssetsDO> pageResult = assetsService.getAssetsPage(pageReqVO);
return success(BeanUtils.toBean(pageResult, AssetsRespVO.class));

View File

@ -81,7 +81,6 @@ public class AssetsSecondmentController {
@GetMapping("/page")
@Operation(summary = "获得资产借调分页")
@PreAuthorize("@ss.hasPermission('system:assets-secondment:query')")
public CommonResult<PageResult<AssetsSecondmentRespVO>> getAssetsSecondmentPage(@Valid AssetsSecondmentPageReqVO pageReqVO) {
PageResult<AssetsSecondmentRespVO> pageResult = assetsSecondmentService.getAssetsSecondmentPage(pageReqVO);
return success(BeanUtils.toBean(pageResult, AssetsSecondmentRespVO.class));

View File

@ -24,6 +24,10 @@ public class AssetsSecondmentRecordRespVO {
@ExcelProperty("资产名称")
private String assetsName;
@Schema(description = "资产编号", example = "13886")
@ExcelProperty("资产编号")
private String assetsNo;
@Schema(description = "使用人id", example = "12905")
@ExcelProperty("使用人id")
private Long useUserId;

View File

@ -0,0 +1,16 @@
package cn.iocoder.yudao.module.system.controller.admin.attendance.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.experimental.Accessors;
@Data
@Accessors(chain = true)
public class AttendanceWorkDTO {
@Schema(description = "上下班")
private String workTypeStr;
@Schema(description = "内容")
private String data;
}

View File

@ -0,0 +1,53 @@
package cn.iocoder.yudao.module.system.controller.admin.attendance.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.experimental.Accessors;
@Data
@Accessors(chain = true)
public class AttendanceExportExcelByCycleVO {
@Schema(description = "用户名称")
private String name;
@Schema(description = "考勤组名称")
private String groupName;
@Schema(description = "部门名称")
private String deptName;
@Schema(description = "职位名称")
private String postName;
@Schema(description = "出勤天数")
private String attendanceDays;
@Schema(description = "休息天数")
private String restDays;
@Schema(description = "工作时长")
private String lengthOfWork;
@Schema(description = "迟到次数")
private String lateNum;
@Schema(description = "迟到时长")
private String lateTime;
@Schema(description = "早退次数")
private String leaveEarlyNum;
@Schema(description = "早退时长")
private String leaveEarlyTime;
@Schema(description = "上班缺卡次数")
private String upMissingCardsNum;
@Schema(description = "下班缺卡次数")
private String downMissingCardsNum;
@Schema(description = "旷工天数")
private String absenteeismNum;
// @Schema(description = "出差时长")
// private String onBusinessTripTime;
// @Schema(description = "加班-审批单统计")
// private String overtimeApprovalOrderStatistics;
@Data
public class OvertimeVO {
@Schema(description = "工作日加班")
private String workingOvertimeOnWorkingDays;
@Schema(description = "休息日加班")
private String workOvertimeOnRestDays;
@Schema(description = "节假日加班")
private String workOvertimeOnHolidays;
}
}

View File

@ -13,6 +13,8 @@ import java.util.List;
@Data
@Accessors(chain = true)
public class AttendancePunchPageVO {
@Schema(description = "考勤组id")
private Long attendanceGroupId;
@Schema(description = "是否在考勤组 0否 1是")
private Integer inGroup = 1;
@Schema(description = "当天是否需要考勤 0否 1是")

View File

@ -13,4 +13,6 @@ public class RoleSimpleRespVO {
@Schema(description = "角色名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋道")
private String name;
@Schema(description = "角色编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "admin")
private String code;
}

View File

@ -78,6 +78,9 @@ public class AttendancePunchRecordSaveReqVO {
@Schema(description = "早退时长时间戳")
private Long leaveEarlyTime;
@Schema(description = "加班时长时间戳")
private Long workOvertimeTime;
/**
* 打卡类型(0上班卡 1下班卡 2迟到卡 3早退卡 4未到打卡时间) 打卡状态 0正常 1迟到 2早退 3缺卡 4未打卡(还没到打卡时间) 5补卡

View File

@ -3,7 +3,9 @@ package cn.iocoder.yudao.module.system.controller.admin.user;
import cn.hutool.core.collection.CollUtil;
import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.datapermission.core.annotation.DataPermission;
import cn.iocoder.yudao.module.system.controller.admin.permission.vo.role.RoleSimpleRespVO;
import cn.iocoder.yudao.module.system.controller.admin.user.vo.profile.UserProfileRespVO;
import cn.iocoder.yudao.module.system.controller.admin.user.vo.profile.UserProfileUpdatePasswordReqVO;
import cn.iocoder.yudao.module.system.controller.admin.user.vo.profile.UserProfileUpdateReqVO;
@ -73,6 +75,18 @@ public class UserProfileController {
return success(UserConvert.INSTANCE.convert(user, userRoles, dept, posts, socialUsers));
}
@GetMapping("/getRoles")
@Operation(summary = "获得登录用户角色信息")
@DataPermission(enable = false) // 关闭数据权限避免只查看自己时查询不到部门
public CommonResult<List<RoleSimpleRespVO>> getRoles() {
// 获得用户基本信息
AdminUserDO user = userService.getUser(getLoginUserId());
// 获得用户角色
List<RoleDO> userRoles = roleService.getRoleListFromCache(permissionService.getUserRoleIdListByUserId(user.getId()));
List<RoleSimpleRespVO> bean = BeanUtils.toBean(userRoles, RoleSimpleRespVO.class);
return success(bean);
}
@PutMapping("/update")
@Operation(summary = "修改用户个人信息")
public CommonResult<Boolean> updateUserProfile(@Valid @RequestBody UserProfileUpdateReqVO reqVO) {

View File

@ -124,4 +124,14 @@ public class AttendancePunchRecordDO extends BaseDO {
* 早退时长时间戳
*/
private Long leaveEarlyTime;
/**
* 加班时长时间戳
*/
private Long workOvertimeTime;
/**
* 是否已提醒 0否 1是
*/
private Integer remindFlag;
}

View File

@ -1,6 +1,7 @@
package cn.iocoder.yudao.module.system.framework.datapermission.config;
import cn.iocoder.yudao.framework.datapermission.core.rule.dept.DeptDataPermissionRuleCustomizer;
import cn.iocoder.yudao.module.system.dal.dataobject.assets.DeptAssetsDO;
import cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO;
import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO;
import cn.iocoder.yudao.module.system.dal.dataobject.worklog.LogInstanceDO;
@ -24,13 +25,13 @@ public class DataPermissionConfiguration {
rule.addDeptColumn(LogUseDO.class, "use_user_dept");
rule.addDeptColumn(LogStatisticsDO.class, "dept_id");
rule.addDeptColumn(LogInstanceDO.class, "dept_id");
rule.addDeptColumn(DeptAssetsDO.class, "dept_id");
// user
rule.addUserColumn(AdminUserDO.class, "id");
rule.addUserColumn(LogUseDO.class, "use_user_id");
rule.addUserColumn(LogStatisticsDO.class, "user_id");
rule.addUserColumn(LogInstanceDO.class, "start_user_id");
};
}

View File

@ -0,0 +1,131 @@
package cn.iocoder.yudao.module.system.job.attendance;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.BetweenFormatter;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.framework.common.Constants;
import cn.iocoder.yudao.framework.tenant.core.job.TenantJob;
import cn.iocoder.yudao.module.system.api.subscribe.SubscribeMessageSendApi;
import cn.iocoder.yudao.module.system.api.subscribe.dto.MsgData;
import cn.iocoder.yudao.module.system.api.subscribe.dto.SubscribeMessageReqDTO;
import cn.iocoder.yudao.module.system.controller.admin.attendance.dto.AttendanceWorkDTO;
import cn.iocoder.yudao.module.system.dal.dataobject.attendance.punchrecord.AttendancePunchRecordDO;
import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO;
import cn.iocoder.yudao.module.system.service.attendance.punchrecord.AttendancePunchRecordService;
import cn.iocoder.yudao.module.system.service.user.AdminUserService;
import com.xxl.job.core.biz.model.ReturnT;
import com.xxl.job.core.handler.annotation.XxlJob;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@Component
@Slf4j
public class RemindJob {
@Resource
private AttendancePunchRecordService attendancePunchRecordService;
@Resource
private SubscribeMessageSendApi subscribeMessageSendApi;
@Resource
private AdminUserService adminUserService;
// TODO: 2024/4/22 - 考勤提醒 每10分钟执行一次
@XxlJob("remindJob")
@TenantJob // --- 这个注解 会将租户列表拉出来 完了后逐个租户执行 定时任务需要注意
public ReturnT<String> execute() throws Exception {
// -- 获取当天以及明天的未打卡并且未提醒记录
//未提醒列表
LocalDateTime localDateTime = LocalDateTime.now();
LocalDateTime futureTime = localDateTime.plusMinutes(15);
List<AttendancePunchRecordDO> attendancePunchRecordDOS = attendancePunchRecordService.getNotReminded(localDateTime);
if (attendancePunchRecordDOS.isEmpty()) {
return ReturnT.SUCCESS;
}
//还有10分钟就要上班了别忘记打卡哦
//幸苦一天了研发部全体人员提醒您记得打卡哦
Map<Long, AttendanceWorkDTO> map = new HashMap<>();
//打卡时间 - 15分钟之后是否是 大于打卡时间 - 是的话 - 把用户id拿出来 组装好消息发送
List<AttendancePunchRecordDO> editList = new ArrayList<>();
for (AttendancePunchRecordDO attendancePunchRecordDO : attendancePunchRecordDOS) {
if (attendancePunchRecordDO.getWorkType().equals(Constants.ZERO) && futureTime.isAfter(attendancePunchRecordDO.getShouldPunchTime())) {
AttendanceWorkDTO dto = new AttendanceWorkDTO();
dto.setWorkTypeStr("上班打卡");
dto.setData(String.format("还有%s钟就要上班了别忘记打卡哦",
DateUtil.formatBetween(LocalDateTimeUtil.between(localDateTime, attendancePunchRecordDO.getShouldPunchTime()).toMillis(), BetweenFormatter.Level.MINUTE)));
map.put(attendancePunchRecordDO.getUserId(), dto);
attendancePunchRecordDO.setRemindFlag(Constants.TRUE);
editList.add(attendancePunchRecordDO);
} else if (attendancePunchRecordDO.getWorkType().equals(Constants.ONE) && localDateTime.isAfter(attendancePunchRecordDO.getShouldPunchTime())) {
AttendanceWorkDTO dto = new AttendanceWorkDTO();
dto.setWorkTypeStr("下班打卡");
dto.setData("工作幸苦了,记得打卡哦~");
map.put(attendancePunchRecordDO.getUserId(), dto);
attendancePunchRecordDO.setRemindFlag(Constants.TRUE);
editList.add(attendancePunchRecordDO);
}
}
//获取到所有的用户id
if (MapUtil.isEmpty(map)) {
return ReturnT.SUCCESS;
}
List<Long> userIds = new ArrayList<>(map.keySet());
List<AdminUserDO> userList = adminUserService.getUserList(userIds);
List<AdminUserDO> users = userList.stream().filter(a -> StrUtil.isNotEmpty(a.getOpenId())).collect(Collectors.toList());
String templateId = "5yHyXhrsyqXi8s4hYhvaeMtz9kT5OPvDCe3h6G1T-OE";
List<SubscribeMessageReqDTO> dtos = new ArrayList<>();
for (AdminUserDO user : users) {
AttendanceWorkDTO attendanceWorkDTO = map.get(user.getId());
SubscribeMessageReqDTO dto = new SubscribeMessageReqDTO();
dto.setToUser(user.getOpenId());
dto.setTemplateId(templateId);
MsgData data = new MsgData();
data.setName("thing9");
data.setValue(attendanceWorkDTO.getWorkTypeStr());
dto.addData(data);
data = new MsgData();
data.setName("thing6");
data.setValue(attendanceWorkDTO.getData());
dto.addData(data);
dto.setPage("subPages/attendance/index");
dtos.add(dto);
}
if (CollectionUtil.isNotEmpty(dtos)) {
for (SubscribeMessageReqDTO dto : dtos) {
subscribeMessageSendApi.sendPunchReminder(dto);
}
}
if (CollectionUtil.isNotEmpty(editList)) {
attendancePunchRecordService.batchUpdate(editList);
}
// 返回执行成功
return ReturnT.SUCCESS;
}
}

View File

@ -1,5 +1,6 @@
package cn.iocoder.yudao.module.system.job.equipment;
import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.framework.tenant.core.job.TenantJob;
import cn.iocoder.yudao.framework.websocket.core.session.WebSocketSessionManager;
import cn.iocoder.yudao.module.system.dal.dataobject.equipment.AttendanceMachineDO;
@ -32,18 +33,15 @@ public class AttendanceMachineJob {
// 获得所有在线的设备
List<AttendanceMachineDO> attendanceMachineDOS = attendanceMachineService.getListByStatus();
for (AttendanceMachineDO reqDO : attendanceMachineDOS) {
// redis数据不存在则为离线状态
if (stringRedisTemplate.opsForValue().get(reqDO.getDeviceNo()) == null) {
String data = stringRedisTemplate.opsForValue().get(reqDO.getDeviceNo());
if (StrUtil.isEmpty(data)) {
attendanceMachineService.updateAttendanceMachineStatus(reqDO.getDeviceNo(), 0, null);
//同步 删除对应sessionId
WebSocketSessionManager webSocketSessionManager = SpringContentUtils.getBean(WebSocketSessionManager.class);
webSocketSessionManager.removeSession(webSocketSessionManager.getSessionByDeviceNum(reqDO.getDeviceNo()));
}else {
attendanceMachineService.updateAttendanceMachineStatus(reqDO.getDeviceNo(), 1, stringRedisTemplate.opsForValue().get(reqDO.getDeviceNo()));
} else {
attendanceMachineService.updateAttendanceMachineStatus(reqDO.getDeviceNo(), 1, data);
}
}
}

View File

@ -112,11 +112,10 @@ public class DeptAssetsInOutStockServiceImpl implements DeptAssetsInOutStockServ
// - 如果是部门入库 则更新该部门的资产
List<DeptAssetsInOutStockSaveReqVO> stockSaveReqVOS = inOutStockByDeptMap.get(vo.getInDeptId());
if (!stockSaveReqVOS.isEmpty()) {
Integer num = 0;
for (DeptAssetsInOutStockSaveReqVO stockSaveReqVO : stockSaveReqVOS) {
num += stockSaveReqVO.getNum();
Map<Long, Integer> stockSaveMaps = stockSaveReqVOS.stream().collect(Collectors.groupingBy(DeptAssetsInOutStockSaveReqVO::getAssetsId, Collectors.summingInt(DeptAssetsInOutStockSaveReqVO::getNum)));
for (Map.Entry<Long, Integer> entry : stockSaveMaps.entrySet()) {
deptInStockMap.put(vo.getInDeptId() + "_" + entry.getKey(), entry.getValue());
}
deptInStockMap.put(vo.getInDeptId() + "_" + vo.getAssetsId(), num);
}
}
}

View File

@ -163,6 +163,7 @@ public class AttendanceServiceImpl implements AttendanceService {
//取绝对值 如果status是负数则变为正数
.setLateTime(Constants.ONE.equals(status) ? Math.abs(LocalDateTimeUtil.between(dto.getLocalDateTime(), pageVO.getShouldPunchTime(), ChronoUnit.MILLIS)) : 0L)
.setLeaveEarlyTime(Constants.TWO.equals(status) ? Math.abs(LocalDateTimeUtil.between(dto.getLocalDateTime(), pageVO.getShouldPunchTime(), ChronoUnit.MILLIS)) : 0L)
.setWorkOvertimeTime(Constants.ZERO.equals(status) && Constants.ONE.equals(pageVO.getPunchType()) ? Math.abs(LocalDateTimeUtil.between(dto.getLocalDateTime(), pageVO.getShouldPunchTime(), ChronoUnit.MILLIS)) : 0L)
.setRemark(dto.getRemark())
.setImage(dto.getImage())
.setPunchAddress(dto.getPunchAddress());
@ -214,10 +215,17 @@ public class AttendanceServiceImpl implements AttendanceService {
Boolean flag = stringRedisTemplate.hasKey(key);
// 缓存不存在
if (Boolean.FALSE.equals(flag)) {
String url = "https://cdn.jsdelivr.net/gh/NateScarlet/holiday-cn@master/" + year + ".json";
String json = HttpUtil.get(url, 0);
String url = "https://timor.tech/api/holiday/year/" + year;
String json = HttpUtil.get(url, 3000);
Map<String, String> map = new HashMap<>();
JSONObject jsonObject = JSONUtil.parseObj(json);
Map<String, String> map = jsonObject.getBeanList("days", HolidayVO.class).stream().collect(Collectors.toMap(HolidayVO::getDate, HolidayVO::getIsOffDay));
Object o = jsonObject.get("holiday");
//将o转为json对象并且循环获取对象中所有的属性
JSONObject data = JSONUtil.parseObj(o);
data.forEach((k, v) -> {
JSONObject item = JSONUtil.parseObj(v);
map.put(item.get("date").toString(), item.get("holiday").toString());
});
stringRedisTemplate.opsForHash().putAll(key, map);
// -- 删除去年的
String lastKey = "holiday_" + (Integer.parseInt(year) - 1);
@ -753,9 +761,6 @@ public class AttendanceServiceImpl implements AttendanceService {
@Override
public void exportAttendanceExcel(HttpServletResponse response, ExportAttendanceExcelDTO dto) {
// 导出 Excel
// ExcelUtils.write(response, "考勤组人员.xls", "数据", AttendanceGroupUserRespVO.class,
// BeanUtils.toBean(list, AttendanceGroupUserRespVO.class));
}
/**

View File

@ -234,6 +234,7 @@ public class AttendanceFixedServiceImpl implements AttendanceFixedService, Punch
}
vo.setAttendanceGroupShiftId(attendanceFixedDO.getAttendanceGroupShiftId());
attendanceService.calculatePunch(dto, vo);
vo.setAttendanceGroupId(activationGroup.getId());
return vo;
}

View File

@ -21,6 +21,7 @@ import cn.iocoder.yudao.module.system.dal.mysql.attendance.groupshiftitem.Attend
import cn.iocoder.yudao.module.system.dal.mysql.attendance.punchrecord.AttendancePunchRecordMapper;
import cn.iocoder.yudao.module.system.dal.mysql.attendance.scheduling.AttendanceSchedulingMapper;
import cn.iocoder.yudao.module.system.service.attendance.group.AttendanceGroupService;
import cn.iocoder.yudao.module.system.service.attendance.punch.dto.AttendanceOnTheDayDTO;
import cn.iocoder.yudao.module.system.service.attendance.punchrecord.AttendancePunchRecordService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import org.springframework.context.annotation.Lazy;
@ -248,7 +249,10 @@ public class AttendanceGroupShiftServiceImpl implements AttendanceGroupShiftServ
// -- 删除当前考勤组预留的考勤记录
attendancePunchRecordMapper.delete(new LambdaQueryWrapper<AttendancePunchRecordDO>()
.in(AttendancePunchRecordDO::getAttendanceGroupId, groupIds)
.eq(AttendancePunchRecordDO::getNextDayFlag, Constants.TRUE));
.and(a -> a.eq(AttendancePunchRecordDO::getNextDayFlag, Constants.TRUE)
.or()
.eq(AttendancePunchRecordDO::getStatus, AttendanceOnTheDayDTO.PUNCH_STATUS_UN_PUNCH))
);
// -- 重新计算 - 插入到redis 和数据中
attendancePunchRecordService.defaultPersistence(groupIds, LocalDateTime.now());
}

View File

@ -12,6 +12,7 @@ import cn.iocoder.yudao.module.system.dal.dataobject.attendance.groupuser.Attend
import cn.iocoder.yudao.module.system.dal.dataobject.attendance.punchrecord.AttendancePunchRecordDO;
import cn.iocoder.yudao.module.system.dal.mysql.attendance.groupuser.AttendanceGroupUserMapper;
import cn.iocoder.yudao.module.system.dal.mysql.attendance.punchrecord.AttendancePunchRecordMapper;
import cn.iocoder.yudao.module.system.service.attendance.punch.dto.AttendanceOnTheDayDTO;
import cn.iocoder.yudao.module.system.service.attendance.punchrecord.AttendancePunchRecordService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import org.springframework.data.redis.core.StringRedisTemplate;
@ -130,7 +131,10 @@ public class AttendanceGroupUserServiceImpl implements AttendanceGroupUserServic
attendancePunchRecordMapper.delete(new LambdaQueryWrapper<AttendancePunchRecordDO>()
.eq(AttendancePunchRecordDO::getAttendanceGroupId, vo.getAttendanceGroupId())
.in(AttendancePunchRecordDO::getUserId, vo.getDelUserIds())
.eq(AttendancePunchRecordDO::getNextDayFlag, Constants.TRUE));
.and(a -> a.eq(AttendancePunchRecordDO::getNextDayFlag, Constants.TRUE)
.or()
.eq(AttendancePunchRecordDO::getStatus, AttendanceOnTheDayDTO.PUNCH_STATUS_UN_PUNCH))
);
}
if (CollectionUtil.isNotEmpty(vo.getSaveUserIds())) {
attendancePunchRecordService.defaultPersistence(vo.getAttendanceGroupId(), vo.getSaveUserIds(), LocalDateTime.now());

View File

@ -68,6 +68,7 @@ public interface AttendancePunchRecordService {
/**
* 预设考勤
*
* @param groupId
* @param userIds
* @param localDateTime
@ -96,4 +97,18 @@ public interface AttendancePunchRecordService {
*/
void defaultPersistence(Map<Long, Long> map, Map<Long, AttendanceGroupDO> groupMap, Map<Long, List<Long>> groupUserMap,
Map<Long, List<AttendanceGroupShiftItemDO>> itemMaps, String time, LocalDateTime localDateTime);
/**
* 获取未提醒列表 获取当天的未打卡并且未提醒记录
*
* @return
*/
List<AttendancePunchRecordDO> getNotReminded(LocalDateTime localDateTime);
/**
* 批量更新
*
* @param editList
*/
void batchUpdate(List<AttendancePunchRecordDO> editList);
}

View File

@ -153,6 +153,7 @@ public class AttendancePunchRecordServiceImpl implements AttendancePunchRecordSe
}
this.defaultPersistence(attendanceGroupDOS, attendanceGroupUserDOS, localDateTime);
}
@Override
public void defaultPersistence(List<AttendanceGroupDO> attendanceGroupDOS, List<AttendanceGroupUserDO> attendanceGroupUserDOS, LocalDateTime localDateTime) {
// 获取所有考勤组
@ -231,6 +232,20 @@ public class AttendancePunchRecordServiceImpl implements AttendancePunchRecordSe
this.saveBatch(attendancePunchRecordDOList);
}
@Override
public List<AttendancePunchRecordDO> getNotReminded(LocalDateTime localDateTime) {
String targetDayStr = localDateTime.format(Constants.REPO_DATE_FORMAT);
return punchRecordMapper.selectList(new LambdaQueryWrapper<AttendancePunchRecordDO>()
.eq(AttendancePunchRecordDO::getDayTime, targetDayStr)
.eq(AttendancePunchRecordDO::getStatus, AttendanceOnTheDayDTO.PUNCH_STATUS_UN_PUNCH)
.eq(AttendancePunchRecordDO::getRemindFlag, Constants.FALSE));
}
@Override
public void batchUpdate(List<AttendancePunchRecordDO> editList) {
punchRecordMapper.updateBatch(editList);
}
private Map<Long, Long> getAttendanceGroupShiftIdGroupByGroup(List<AttendanceGroupDO> attendanceGroupDOS, LocalDateTime localDateTime) {
Map<Long, Long> map = new HashMap<>();
List<AttendanceGroupDO> fixedList = attendanceGroupDOS.stream().filter(a -> a.getType().equals(1)).collect(Collectors.toList());

View File

@ -229,6 +229,7 @@ public class AttendanceSchedulingServiceImpl implements AttendanceSchedulingServ
}
vo.setAttendanceGroupShiftId(attendanceSchedulingDO.getAttendanceGroupShiftId());
attendanceService.calculatePunch(dto, vo);
vo.setAttendanceGroupId(activationGroup.getId());
return vo;
}

View File

@ -111,10 +111,9 @@ public class AttendanceMachineServiceImpl implements AttendanceMachineService {
@Override
public void updateAttendanceMachineStatus(String deviceNo, Integer status, String dateTime) {
AttendanceMachineDO updateDO = new AttendanceMachineDO();
updateDO.setStatus(status);
updateDO.setUpdater(getLoginUserId().toString());
// updateDO.setUpdater(getLoginUserId().toString());
if (status == 1) {
updateDO.setRequestTime(LocalDateTime.parse(dateTime, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
}
@ -130,7 +129,7 @@ public class AttendanceMachineServiceImpl implements AttendanceMachineService {
if (attendanceMachineDO == null) {
throw exception(ATTENDANCE_MACHINE_NOT_EXISTS);
}else {
} else {
if (!passwordEncoder.matches(updateReqVO.getOldPassword(), attendanceMachineDO.getPassword())) {
@ -221,7 +220,7 @@ public class AttendanceMachineServiceImpl implements AttendanceMachineService {
deviceNo = new ArrayList<>();
deviceNo.add(addReqVO.getDeviceNo());
}else {
} else {
if (!deviceNo.contains(addReqVO.getDeviceNo())) {
@ -232,7 +231,7 @@ public class AttendanceMachineServiceImpl implements AttendanceMachineService {
//设备 用户绑定设备
data.setAttendanceMachineNos(deviceNo);
});
}else if (addReqVO.getMethod() == 1) {
} else if (addReqVO.getMethod() == 1) {
usersExtDO.forEach(data -> {

View File

@ -35,6 +35,7 @@
SELECT
a.id,
a.util,
a.assets_no,
a.item_json,
a.name,
a.amount,
@ -57,6 +58,9 @@
<if test="reqVO.assetsNo != null and reqVO.assetsNo != ''">
and a.assets_no like concat('%', #{reqVO.keyWord}, '%')
</if>
<if test="reqVO.typeId != null">
and a.type_id = #{reqVO.typeId}
</if>
<if test="reqVO.keyWord != null and reqVO.keyWord != ''">
and (
a.name like concat('%', #{reqVO.keyWord}, '%')

View File

@ -14,6 +14,7 @@
SELECT a.id,
a.assets_id,
b.name as assetsName,
b.assets_no as assetsNo,
a.use_user_id,
c.nickname as useUserName,
a.use_dept_id,
@ -36,6 +37,7 @@
left join system_users as d on a.principal_user_id = d.id
left join system_dept as e on a.use_dept_id = e.id
<where>
a.deleted = 0
<if test="vo.useUserId != null">
and a.use_user_id = #{vo.useUserId}
</if>
@ -65,7 +67,7 @@
and a.create_time &lt;= #{vo.createTime[1]}
</if>
</if>
order by a.create_time desc
</where>
order by a.create_time desc
</select>
</mapper>

View File

@ -63,7 +63,7 @@ public class FactoryInfoSaveReqVO {
private BigDecimal lat;
@Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@NotNull(message = "状态不能为空")
// @NotNull(message = "状态不能为空")
private Integer status;
@Schema(description = "负责人编号", example = "126")