Houjie
2025-06-13 4dd33cbe7be8c0e552962b64d9f323a9cc04db45
设备打卡率定时任务。设备打卡率列表接口
已添加8个文件
已修改6个文件
903 ■■■■ 文件已修改
lxzn-module-mdc/src/main/java/org/jeecg/modules/mdc/controller/MdcEquipmentPunchController.java 85 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
lxzn-module-mdc/src/main/java/org/jeecg/modules/mdc/controller/MdcEquipmentPunchRateController.java 81 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
lxzn-module-mdc/src/main/java/org/jeecg/modules/mdc/dto/MdcEquipmentPunchExportDTO.java 98 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
lxzn-module-mdc/src/main/java/org/jeecg/modules/mdc/entity/MdcEquipmentPunch.java 104 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
lxzn-module-mdc/src/main/java/org/jeecg/modules/mdc/entity/MdcEquipmentPunchRate.java 129 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
lxzn-module-mdc/src/main/java/org/jeecg/modules/mdc/job/DailyPunchRateJob.java 108 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
lxzn-module-mdc/src/main/java/org/jeecg/modules/mdc/mapper/MdcEquipmentPunchMapper.java 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
lxzn-module-mdc/src/main/java/org/jeecg/modules/mdc/mapper/MdcEquipmentPunchRateMapper.java 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
lxzn-module-mdc/src/main/java/org/jeecg/modules/mdc/mapper/xml/MdcEquipmentPunchMapper.xml 91 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
lxzn-module-mdc/src/main/java/org/jeecg/modules/mdc/mapper/xml/MdcEquipmentPunchRateMapper.xml 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
lxzn-module-mdc/src/main/java/org/jeecg/modules/mdc/service/IMdcEquipmentPunchRateService.java 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
lxzn-module-mdc/src/main/java/org/jeecg/modules/mdc/service/IMdcEquipmentPunchService.java 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
lxzn-module-mdc/src/main/java/org/jeecg/modules/mdc/service/impl/MdcEquipmentPunchRateServiceImpl.java 81 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
lxzn-module-mdc/src/main/java/org/jeecg/modules/mdc/service/impl/MdcEquipmentPunchServiceImpl.java 63 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
lxzn-module-mdc/src/main/java/org/jeecg/modules/mdc/controller/MdcEquipmentPunchController.java
@@ -16,55 +16,56 @@
/**
 * @Description: mdc_equipment_punch
 * @Author: jeecg-boot
 * @Date:   2025-06-09
 * @Date: 2025-06-09
 * @Version: V1.0
 */
@Api(tags="上下班打卡记录表")
@Api(tags = "上下班打卡记录表")
@RestController
@RequestMapping("/mdcEquipmentPunch")
@Slf4j
public class MdcEquipmentPunchController extends JeecgController<MdcEquipmentPunch, IMdcEquipmentPunchService> {
    @Autowired
    private IMdcEquipmentPunchService mdcEquipmentPunchService;
    @Autowired
    private IMdcEquipmentPunchService mdcEquipmentPunchService;
    private static final String msg = "打卡成功!";
    /**
     * æŸ¥è¯¢å½“前登录人所负责设备打卡情况
     *
     * @return
     */
    @ApiOperation(value="查询当前登录人所负责设备打卡情况", notes="查询当前登录人所负责设备打卡情况")
    @GetMapping(value = "/list")
    public Result<List<MdcEquipmentPunch>> queryList() {
        return Result.OK(mdcEquipmentPunchService.queryList());
    }
    private static final String msg = "打卡成功!";
    /**
     *   ä¸Šç­æ‰“卡
     *
     * @param mdcEquipmentPunch
     * @return
     */
    @AutoLog(value = "上班打卡")
    @ApiOperation(value="上班打卡", notes="上班打卡")
    @PostMapping(value = "/workUp")
    public Result<String> workUp(@RequestBody MdcEquipmentPunch mdcEquipmentPunch) {
        mdcEquipmentPunchService.workUp(mdcEquipmentPunch);
        return Result.OK(msg);
    }
    /**
     * æŸ¥è¯¢å½“前登录人所负责设备打卡情况
     *
     * @return
     */
    @ApiOperation(value = "查询当前登录人所负责设备打卡情况", notes = "查询当前登录人所负责设备打卡情况")
    @GetMapping(value = "/list")
    public Result<List<MdcEquipmentPunch>> queryList() {
        return Result.OK(mdcEquipmentPunchService.queryList());
    }
    /**
     *   ä¸‹ç­æ‰“卡
     *
     * @param mdcEquipmentPunch
     * @return
     */
    @AutoLog(value = "下班打卡")
    @ApiOperation(value="下班打卡", notes="下班打卡")
    @PostMapping(value = "/workDown")
    public Result<String> workDown(@RequestBody MdcEquipmentPunch mdcEquipmentPunch) {
        mdcEquipmentPunchService.workDown(mdcEquipmentPunch);
        return Result.OK(msg);
    }
    /**
     * ä¸Šç­æ‰“卡
     *
     * @param mdcEquipmentPunch
     * @return
     */
    @AutoLog(value = "上班打卡")
    @ApiOperation(value = "上班打卡", notes = "上班打卡")
    @PostMapping(value = "/workUp")
    public Result<String> workUp(@RequestBody MdcEquipmentPunch mdcEquipmentPunch) {
        mdcEquipmentPunchService.workUp(mdcEquipmentPunch);
        return Result.OK(msg);
    }
    /**
     * ä¸‹ç­æ‰“卡
     *
     * @param mdcEquipmentPunch
     * @return
     */
    @AutoLog(value = "下班打卡")
    @ApiOperation(value = "下班打卡", notes = "下班打卡")
    @PostMapping(value = "/workDown")
    public Result<String> workDown(@RequestBody MdcEquipmentPunch mdcEquipmentPunch) {
        mdcEquipmentPunchService.workDown(mdcEquipmentPunch);
        return Result.OK(msg);
    }
}
lxzn-module-mdc/src/main/java/org/jeecg/modules/mdc/controller/MdcEquipmentPunchRateController.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,81 @@
package org.jeecg.modules.mdc.controller;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.aspect.annotation.AutoLog;
import org.jeecg.common.system.base.controller.JeecgController;
import org.jeecg.common.system.query.QueryGenerator;
import org.jeecg.modules.mdc.entity.MdcEquipmentPunchRate;
import org.jeecg.modules.mdc.service.IMdcEquipmentPunchRateService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
/**
 * @Description: mdc_equipment_punch_rate
 * @Author: jeecg-boot
 * @Date: 2025-06-09
 * @Version: V1.0
 */
@Api(tags = "设备打卡率报表")
@RestController
@RequestMapping("/mdcEquipmentPunchRate")
@Slf4j
public class MdcEquipmentPunchRateController extends JeecgController<MdcEquipmentPunchRate, IMdcEquipmentPunchRateService> {
    @Autowired
    private IMdcEquipmentPunchRateService mdcEquipmentPunchService;
    /**
     * åˆ†é¡µåˆ—表查询
     *
     * @param mdEquipmentPunch æŸ¥è¯¢å‚æ•°
     * @param pageNo           å½“前页码
     * @param pageSize         æ¯é¡µæ¡æ•°
     * @param req              è¯·æ±‚对象
     * @return
     */
    @ApiOperation(value = "设备打卡率-分页列表查询", notes = "设备打卡率-分页列表查询")
    @AutoLog(value = "设备打卡率-分页列表查询")
    @GetMapping(value = "/queryPageList")
    public Result<IPage<MdcEquipmentPunchRate>> queryPageList(MdcEquipmentPunchRate mdEquipmentPunch,
                                                          @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
                                                          @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize,
                                                          HttpServletRequest req) {
        QueryWrapper<MdcEquipmentPunchRate> queryWrapper = QueryGenerator.initQueryWrapper(mdEquipmentPunch, req.getParameterMap());
        Page<MdcEquipmentPunchRate> page = new Page<MdcEquipmentPunchRate>(pageNo, pageSize);
        IPage<MdcEquipmentPunchRate> pageList = mdcEquipmentPunchService.page(page, queryWrapper);
        return Result.OK(pageList);
    }
    /**
     * å¯¼å‡ºexcel
     *
     * @param request
     * @param mdcEquipmentPunchRate
     */
    @RequestMapping(value = "/exportXls")
    public ModelAndView exportXls(HttpServletRequest request, MdcEquipmentPunchRate mdcEquipmentPunchRate) {
        return super.exportXls(request, mdcEquipmentPunchRate, MdcEquipmentPunchRate.class, "设备打卡率报表");
    }
}
lxzn-module-mdc/src/main/java/org/jeecg/modules/mdc/dto/MdcEquipmentPunchExportDTO.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,98 @@
package org.jeecg.modules.mdc.dto;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.jeecg.common.aspect.annotation.Dict;
import java.math.BigDecimal;
import java.util.Date;
@Data
public class MdcEquipmentPunchExportDTO {
    @ApiModelProperty(value = "设备编号")
    private String equipmentId;
    @ApiModelProperty(value = "打卡用户")
    @Dict(dicCode = "id", dictTable = "sys_user", dicText = "realname")
    private String punchUser;
    @ApiModelProperty(value = "上班时间")
    private Date checkInTime;
    /**
     * ä¸‹ç­æ—¶é—´
     */
    @ApiModelProperty(value = "下班时间")
    private Date checkOutTime;
    /**
     * è®°å½•日期
     */
    @ApiModelProperty(value = "记录日期")
    private String recordDate;
    @ApiModelProperty(value = "班次")
    @Dict(dicCode = "shift_schedule")
    private Integer shiftSchedule;
    @ApiModelProperty(value = "是否缺卡")
    private Integer isAbsent;
    @ApiModelProperty(value = "是否迟到")
    private Integer isLate;
    @ApiModelProperty(value = "是否早退")
    private Integer isEarly;
    /**
     * æ—©ç­ä¸Šç­æ‰“卡率
     */
    @ApiModelProperty(value = "早班上班打卡率")
    private BigDecimal morningShiftInRate;
    /**
     * æ™šç­ä¸Šç­æ‰“卡率
     */
    @ApiModelProperty(value = "晚班上班打卡率")
    private BigDecimal eveningShiftInRate;
    @ApiModelProperty(value = "早班下班打卡率")
    private BigDecimal morningShiftOutRate;
    @ApiModelProperty(value = "晚班下班打卡率")
    private BigDecimal eveningShiftOutRate;
    @ApiModelProperty(value = "白班上班打卡设备数量")
    private Integer morningShiftInDeviceNum;
    @ApiModelProperty(value = "白班下班打卡设备数量")
    private Integer morningShiftOutDeviceNum;
    @ApiModelProperty(value = "夜班上班打卡设备数量")
    private Integer eveningShiftInDeviceNum;
    @ApiModelProperty(value = "夜班下班打卡设备数量")
    private Integer eveningShiftOutDeviceNum;
    @ApiModelProperty(value = "设备总数")
    private Integer deviceCountNum;
    private String punchUserRealName;
}
lxzn-module-mdc/src/main/java/org/jeecg/modules/mdc/entity/MdcEquipmentPunch.java
@@ -1,22 +1,24 @@
package org.jeecg.modules.mdc.entity;
import java.io.Serializable;
import java.util.Date;
import cn.hutool.core.date.DatePattern;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import com.fasterxml.jackson.annotation.JsonFormat;
import org.jeecg.common.aspect.annotation.Dict;
import org.springframework.format.annotation.DateTimeFormat;
import org.jeecgframework.poi.excel.annotation.Excel;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import org.jeecg.common.aspect.annotation.Dict;
import org.jeecg.common.system.base.entity.JeecgEntity;
import org.jeecgframework.poi.excel.annotation.Excel;
import org.springframework.format.annotation.DateTimeFormat;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Date;
/**
 * @Description: mdc_equipment_punch
@@ -29,7 +31,7 @@
@Accessors(chain = true)
@EqualsAndHashCode(callSuper = false)
@ApiModel(value = "mdc_equipment_punch对象", description = "mdc_equipment_punch")
public class MdcEquipmentPunch implements Serializable {
public class MdcEquipmentPunch extends JeecgEntity implements Serializable {
    private static final long serialVersionUID = 1L;
    /**
@@ -49,18 +51,18 @@
     */
    @Excel(name = "打卡用户", width = 15)
    @ApiModelProperty(value = "打卡用户")
    @Dict(dicCode = "id", dictTable = "sys_user", dicText = "realname")
    private String punchUser;
    /**
     * æ‰“卡用户账号
     */
    @Excel(name = "打卡用户账号", width = 15)
    @ApiModelProperty(value = "打卡用户账号")
    @TableField(exist = false)
    private String punchUserRealName;
    /**
     * æ‰“卡用户名称
     */
    @Excel(name = "打卡用户名称", width = 15)
    @ApiModelProperty(value = "打卡用户名称")
    @TableField(exist = false)
    private String punchUserUserName;
@@ -87,7 +89,7 @@
    @ApiModelProperty(value = "记录日期")
    private String recordDate;
    /**
     * ç­æ¬¡
     *  ç­æ¬¡
     */
    @Excel(name = "班次", width = 15)
    @ApiModelProperty(value = "班次")
@@ -107,7 +109,7 @@
    @ApiModelProperty(value = "是否缺卡")
    private Integer isAbsent;
    /**
     * æ˜¯å¦è¿Ÿåˆ°
     * æ˜¯å¦è¿Ÿåˆ°ï¼ˆ0未早退,1早退)
     */
    @Excel(name = "是否迟到", width = 15)
    @ApiModelProperty(value = "是否迟到")
@@ -118,28 +120,74 @@
    @Excel(name = "是否早退", width = 15)
    @ApiModelProperty(value = "是否早退")
    private Integer isEarly;
    /**
     * åˆ›å»ºäºº
     * æ—©ç­ä¸Šç­æ‰“卡率
     */
    @ApiModelProperty(value = "创建人")
    private String createBy;
    @TableField(exist = false)
    @Excel(name = "早班上班打卡率", width = 15)
    @ApiModelProperty(value = "早班上班打卡率")
    private BigDecimal morningShiftInRate;
    /**
     * åˆ›å»ºæ—¶é—´
     * æ™šç­ä¸Šç­æ‰“卡率
     */
    @JsonFormat(timezone = "GMT+8", pattern = DatePattern.NORM_DATETIME_PATTERN)
    @DateTimeFormat(pattern = DatePattern.NORM_DATETIME_PATTERN)
    @ApiModelProperty(value = "创建时间")
    private Date createTime;
    @TableField(exist = false)
    @Excel(name = "晚班上班打卡率", width = 15)
    @ApiModelProperty(value = "晚班上班打卡率")
    private BigDecimal eveningShiftInRate;
    /**
     * æ›´æ–°äºº
     * æ—©ç­ä¸‹ç­æ‰“卡率
     */
    @ApiModelProperty(value = "更新人")
    private String updateBy;
    @TableField(exist = false)
    @Excel(name = "早班下班打卡率", width = 15)
    @ApiModelProperty(value = "早班下班打卡率")
    private BigDecimal morningShiftOutRate;
    /**
     * æ›´æ–°æ—¶é—´
     * æ™šç­ä¸‹ç­æ‰“卡率
     */
    @JsonFormat(timezone = "GMT+8", pattern = DatePattern.NORM_DATETIME_PATTERN)
    @DateTimeFormat(pattern = DatePattern.NORM_DATETIME_PATTERN)
    @ApiModelProperty(value = "更新时间")
    private Date updateTime;
    @TableField(exist = false)
    @Excel(name = "晚班下班打卡率", width = 15)
    @ApiModelProperty(value = "晚班下班打卡率")
    private BigDecimal eveningShiftOutRate;
    /**
     * ç™½ç­ä¸Šç­æ‰“卡设备数量
     */
    @TableField(exist = false)
    @Excel(name = "白班上班打卡设备数量", width = 15)
    @ApiModelProperty(value = "白班上班打卡设备数量")
    private Integer morningShiftInDeviceNum;
    /**
     * ç™½ç­ä¸‹ç­æ‰“卡设备数量
     */
    @TableField(exist = false)
    @Excel(name = "白班下班打卡设备数量", width = 15)
    @ApiModelProperty(value = "白班下班打卡设备数量")
    private Integer morningShiftOutDeviceNum;
    /**
     * å¤œç­ä¸Šç­æ‰“卡设备数量
     */
    @TableField(exist = false)
    @Excel(name = "夜班上班打卡设备数量", width = 15)
    @ApiModelProperty(value = "夜班上班打卡设备数量")
    private Integer eveningShiftInDeviceNum;
    /**
     * å¤œç­ä¸‹ç­æ‰“卡设备数量
     */
    @TableField(exist = false)
    @Excel(name = "夜班下班打卡设备数量", width = 15)
    @ApiModelProperty(value = "夜班下班打卡设备数量")
    private Integer eveningShiftOutDeviceNum;
    /**
     * è®¾å¤‡æ€»æ•°
     */
    @TableField(exist = false)
    @Excel(name = "设备总数", width = 15)
    @ApiModelProperty(value = "设备总数")
    private Integer deviceCountNum;
}
lxzn-module-mdc/src/main/java/org/jeecg/modules/mdc/entity/MdcEquipmentPunchRate.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,129 @@
package org.jeecg.modules.mdc.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import org.jeecg.common.aspect.annotation.Dict;
import org.jeecg.common.system.base.entity.JeecgEntity;
import org.jeecgframework.poi.excel.annotation.Excel;
import java.io.Serializable;
import java.math.BigDecimal;
/**
 * @Description: mdc_equipment_punch_rate
 * @Author: jeecg-boot
 * @Date: 2025-06-09
 * @Version: V1.0
 */
@Data
@TableName("mdc_equipment_punch_rate")
@Accessors(chain = true)
@EqualsAndHashCode(callSuper = false)
@ApiModel(value = "mdc_equipment_punch_rate对象", description = "mdc_equipment_punch_rate")
public class MdcEquipmentPunchRate extends JeecgEntity implements Serializable {
    private static final long serialVersionUID = 1L;
    /**
     * id
     */
    @TableId(type = IdType.ASSIGN_ID)
    @ApiModelProperty(value = "id")
    private String id;
    /**
     * è®¾å¤‡ç¼–号
     */
    @Excel(name = "设备编号", width = 15)
    @ApiModelProperty(value = "设备编号")
    private String equipmentId;
    /**
     * è®°å½•日期
     */
    @Excel(name = "记录日期", width = 15)
    @ApiModelProperty(value = "记录日期")
    private String theDate;
    /**
     * ç­æ¬¡
     */
    @Excel(name = "班次", width = 15)
    @ApiModelProperty(value = "班次")
    @Dict(dicCode = "shift_schedule")
    private Integer shiftSchedule;
    /**
     * æ—©ç­ä¸Šç­æ‰“卡率
     */
    @Excel(name = "早班上班打卡率(%)", width = 15)
    @ApiModelProperty(value = "早班上班打卡率")
    private BigDecimal mornShiftInRate;
    /**
     * æ™šç­ä¸Šç­æ‰“卡率
     */
    @Excel(name = "晚班上班打卡率(%)", width = 15)
    @ApiModelProperty(value = "晚班上班打卡率")
    private BigDecimal evenShiftInRate;
    /**
     * æ—©ç­ä¸‹ç­æ‰“卡率
     */
    @Excel(name = "早班下班打卡率(%)", width = 15)
    @ApiModelProperty(value = "早班下班打卡率")
    private BigDecimal mornShiftOutRate;
    /**
     * æ™šç­ä¸‹ç­æ‰“卡率
     */
    @Excel(name = "晚班下班打卡率(%)", width = 15)
    @ApiModelProperty(value = "晚班下班打卡率")
    private BigDecimal evenShiftOutRate;
    /**
     * ç™½ç­ä¸Šç­æ‰“卡设备数量
     */
    @Excel(name = "白班上班打卡设备数量", width = 15)
    @ApiModelProperty(value = "白班上班打卡设备数量")
    private Integer mornShiftInNum;
    /**
     * ç™½ç­ä¸‹ç­æ‰“卡设备数量
     */
    @Excel(name = "白班下班打卡设备数量", width = 15)
    @ApiModelProperty(value = "白班下班打卡设备数量")
    private Integer mornShiftOutNum;
    /**
     * å¤œç­ä¸Šç­æ‰“卡设备数量
     */
    @Excel(name = "夜班上班打卡设备数量", width = 15)
    @ApiModelProperty(value = "夜班上班打卡设备数量")
    private Integer evenShiftInNum;
    /**
     * å¤œç­ä¸‹ç­æ‰“卡设备数量
     */
    @Excel(name = "夜班下班打卡设备数量", width = 15)
    @ApiModelProperty(value = "夜班下班打卡设备数量")
    private Integer evenShiftOutNum;
    /**
     * è®¾å¤‡æ€»æ•°
     */
    @Excel(name = "设备总数", width = 15)
    @ApiModelProperty(value = "设备总数")
    private Integer deviceCountNum;
}
lxzn-module-mdc/src/main/java/org/jeecg/modules/mdc/job/DailyPunchRateJob.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,108 @@
package org.jeecg.modules.mdc.job;
import cn.hutool.core.date.DatePattern;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.modules.mdc.entity.MdcEquipmentPunch;
import org.jeecg.modules.mdc.service.IMdcEquipmentPunchRateService;
import org.jeecg.modules.mdc.service.IMdcEquipmentPunchService;
import org.jeecg.modules.quartz.entity.QuartzJob;
import org.jeecg.modules.quartz.entity.SysQuartzLog;
import org.jeecg.modules.quartz.service.IQuartzJobService;
import org.jeecg.modules.quartz.service.ISysQuartzLogService;
import org.jeecg.modules.system.service.ISysAnnouncementService;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import javax.annotation.Resource;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.Date;
import java.util.List;
/**
 * @Description: æ¯æ—¥å‡Œæ™¨å®šæ—¶è®¡ç®—前一天的设备打卡率,并入库
 * @Author: Lius
 * @CreateTime: 2025-06-12
 */
@Slf4j
public class DailyPunchRateJob implements Job {
    private String parameter; // å¯é€‰å‚数:指定日期(如 "2025-06-11")
    public void setParameter(String parameter) {
        this.parameter = parameter;
    }
    @Resource
    private IQuartzJobService quartzJobService;
    @Resource
    private ISysQuartzLogService sysQuartzLogService;
    @Resource
    private ISysAnnouncementService sysAnnouncementService;
    @Resource
    private IMdcEquipmentPunchService mdcEquipmentPunchService;
    @Resource
    private IMdcEquipmentPunchRateService mdcEquipmentPunchRateService;
    @Override
    public void execute(JobExecutionContext context) throws JobExecutionException {
        SysQuartzLog quartzLog = new SysQuartzLog();
        quartzLog.setCreateTime(new Date());
        List<QuartzJob> jobList = this.quartzJobService.findByJobClassName(this.getClass().getName());
        if (jobList != null && !jobList.isEmpty()) {
            quartzLog.setJobId(jobList.get(0).getId());
        }
        log.info("【开始执行每日设备打卡率统计任务】");
        long startTime = System.currentTimeMillis();
        try {
            String yesterdayStr;
            if (parameter != null && !parameter.isEmpty()) {
                yesterdayStr = parameter; // æ”¯æŒæ‰‹åŠ¨ä¼ å‚
            } else {
                LocalDate yesterday = LocalDate.now().minusDays(1);
                 yesterdayStr = yesterday.format(DateTimeFormatter.ofPattern(DatePattern.PURE_DATE_PATTERN)); // æ ¼å¼åŒ–为 "yyyy-MM-dd"
            }
            log.info("✅ æˆåŠŸå®Œæˆæ¯æ—¥è®¾å¤‡æ‰“å¡çŽ‡ç»Ÿè®¡æ•°æ®", yesterdayStr);
            // Step 1:获取昨日打卡数据
            List<MdcEquipmentPunch> punchRecords = mdcEquipmentPunchService.getYesterdayRecords(yesterdayStr);
            log.info("✅ æˆåŠŸå®Œæˆæ¯æ—¥è®¾å¤‡æ‰“å¡çŽ‡ç»Ÿè®¡æ•°æ®", punchRecords);
            if (punchRecords == null || punchRecords.isEmpty()) {
                log.warn("⚠️ æ²¡æœ‰æ‰¾åˆ°æ˜¨æ—¥è®¾å¤‡æ‰“卡数据");
                quartzLog.setIsSuccess(0);
                return;
            }
            // Step 2:保存到打卡率表
            mdcEquipmentPunchRateService.savePunchRates(yesterdayStr, punchRecords);
            quartzLog.setIsSuccess(0);
            log.info("✅ æˆåŠŸå®Œæˆæ¯æ—¥è®¾å¤‡æ‰“å¡çŽ‡ç»Ÿè®¡ï¼Œå…±å¤„ç† {} æ¡è®°å½•,日期:{}", punchRecords.size(), yesterdayStr);
        } catch (Exception e) {
            quartzLog.setIsSuccess(-1);
            quartzLog.setExceptionDetail(e.getMessage());
            log.error("❌ è®¾å¤‡æ‰“卡率统计任务执行失败", e);
            sysAnnouncementService.jobSendMessage("设备打卡率统计任务", e.getMessage());
        }
        // è®°å½•执行时间
        long endTime = System.currentTimeMillis();
        quartzLog.setExecutionTime((int)(endTime - startTime));
        sysQuartzLogService.save(quartzLog);
    }
}
lxzn-module-mdc/src/main/java/org/jeecg/modules/mdc/mapper/MdcEquipmentPunchMapper.java
@@ -15,4 +15,22 @@
public interface MdcEquipmentPunchMapper extends BaseMapper<MdcEquipmentPunch> {
    List<MdcEquipmentPunch> list(@Param("equipmentIds") List<String> equipmentIds, @Param("date") String date);
    // æŸ¥è¯¢æ—©ç­ä¸Šç­æ‰“卡设备数
    int countMorningShiftIn(@Param("date") String date);
    // æŸ¥è¯¢æ™šç­ä¸Šç­æ‰“卡设备数
    int countEveningShiftIn(@Param("date") String date);
    // æŸ¥è¯¢æ—©ç­ä¸‹ç­æ‰“卡设备数
    int countMorningShiftOut(@Param("date") String date);
    // æŸ¥è¯¢æ™šç­ä¸‹ç­æ‰“卡设备数
    int countEveningShiftOut(@Param("date") String date);
    /**
     * èŽ·å–æ‰€æœ‰è®¾å¤‡æ•°
     */
    int getTotalDeviceCount();
}
lxzn-module-mdc/src/main/java/org/jeecg/modules/mdc/mapper/MdcEquipmentPunchRateMapper.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,14 @@
package org.jeecg.modules.mdc.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.jeecg.modules.mdc.entity.MdcEquipmentPunchRate;
/**
 * @Description: mdc_equipment_punch_rate
 * @Author: jeecg-boot
 * @Date:   2025-06-09
 * @Version: V1.0
 */
public interface MdcEquipmentPunchRateMapper extends BaseMapper<MdcEquipmentPunchRate> {
}
lxzn-module-mdc/src/main/java/org/jeecg/modules/mdc/mapper/xml/MdcEquipmentPunchMapper.xml
@@ -4,31 +4,31 @@
    <select id="list" resultType="org.jeecg.modules.mdc.entity.MdcEquipmentPunch">
        SELECT
          p.id,
          p.equipment_id,
          p.punch_user,
          p.check_in_time,
          p.check_out_time,
          p.record_date,
          p.is_absent,
          p.is_late,
          p.is_early,
          p.create_by,
          p.create_time,
          p.update_by,
          p.update_time,
          p.shift_schedule,
          u.realname punchUserRealName,
          u.username punchUserUserName,
          d1.item_text shiftScheduleName
        p.id,
        p.equipment_id,
        p.punch_user,
        p.check_in_time,
        p.check_out_time,
        p.record_date,
        p.is_absent,
        p.is_late,
        p.is_early,
        p.create_by,
        p.create_time,
        p.update_by,
        p.update_time,
        p.shift_schedule,
        u.realname punchUserRealName,
        u.username punchUserUserName,
        d1.item_text shiftScheduleName
        FROM
          mdc_equipment_punch p
          INNER JOIN sys_user u ON u.id = p.punch_user
          INNER JOIN (SELECT i1.item_text, i1.item_value
                      FROM sys_dict_item i1
                          LEFT JOIN sys_dict i2 ON i2.id = i1.dict_id
                      WHERE i2.dict_code = 'shift_schedule') d1
              ON d1.item_value = CAST (p.shift_schedule AS nvarchar)
        mdc_equipment_punch p
        INNER JOIN sys_user u ON u.id = p.punch_user
        INNER JOIN (SELECT i1.item_text, i1.item_value
        FROM sys_dict_item i1
        LEFT JOIN sys_dict i2 ON i2.id = i1.dict_id
        WHERE i2.dict_code = 'shift_schedule') d1
        ON d1.item_value = CAST (p.shift_schedule AS nvarchar)
        where 1=1
        AND p.equipment_id IN
        <foreach collection="equipmentIds" item="equipmentId" open="(" close=")" separator=",">
@@ -39,4 +39,47 @@
        </if>
        order by p.equipment_id desc, p.shift_schedule asc
    </select>
    <!--查询所有设备数量-->
    <select id="getTotalDeviceCount" resultType="int">
        SELECT COUNT(*)
        FROM mdc_equipment
    </select>
    <!-- æ—©ç­ ä¸Šç­æ‰“卡 -->
    <select id="countMorningShiftIn" resultType="int">
        SELECT COUNT(DISTINCT equipment_id)
        FROM mdc_equipment_punch
        WHERE record_date = #{date, jdbcType=VARCHAR}
          AND shift_schedule = '1'
          AND check_in_time IS NOT NULL
    </select>
    <!-- æ™šç­ ä¸Šç­æ‰“卡 -->
    <select id="countEveningShiftIn" resultType="int">
        SELECT COUNT(DISTINCT equipment_id)
        FROM mdc_equipment_punch
        WHERE record_date = #{date, jdbcType=VARCHAR}
          AND shift_schedule = '2'
          AND check_in_time IS NOT NULL
    </select>
    <!-- æ—©ç­ ä¸‹ç­æ‰“卡 -->
    <select id="countMorningShiftOut" resultType="int">
        SELECT COUNT(DISTINCT equipment_id)
        FROM mdc_equipment_punch
        WHERE record_date = #{date, jdbcType=VARCHAR}
          AND shift_schedule = '1'
          AND check_out_time IS NOT NULL
    </select>
    <!-- æ™šç­ ä¸‹ç­æ‰“卡 -->
    <select id="countEveningShiftOut" resultType="int">
        SELECT COUNT(DISTINCT equipment_id)
        FROM mdc_equipment_punch
        WHERE record_date = #{date, jdbcType=VARCHAR}
          AND shift_schedule = '2'
          AND check_out_time IS NOT NULL
    </select>
</mapper>
lxzn-module-mdc/src/main/java/org/jeecg/modules/mdc/mapper/xml/MdcEquipmentPunchRateMapper.xml
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.jeecg.modules.mdc.mapper.MdcEquipmentPunchRateMapper">
</mapper>
lxzn-module-mdc/src/main/java/org/jeecg/modules/mdc/service/IMdcEquipmentPunchRateService.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,19 @@
package org.jeecg.modules.mdc.service;
import com.baomidou.mybatisplus.extension.service.IService;
import org.jeecg.modules.mdc.entity.MdcEquipmentPunch;
import org.jeecg.modules.mdc.entity.MdcEquipmentPunchRate;
import java.util.List;
/**
 * @Description: mdc_equipment_punch
 * @Author: jeecg-boot
 * @Date:   2025-06-09
 * @Version: V1.0
 */
public interface IMdcEquipmentPunchRateService extends IService<MdcEquipmentPunchRate> {
    void savePunchRates(String targetDate, List<MdcEquipmentPunch> punchRecords);
}
lxzn-module-mdc/src/main/java/org/jeecg/modules/mdc/service/IMdcEquipmentPunchService.java
@@ -18,4 +18,10 @@
    void workUp(MdcEquipmentPunch mdcEquipmentPunch);
    void workDown(MdcEquipmentPunch mdcEquipmentPunch);
    void fillPunchRates(List<MdcEquipmentPunch> punchList);
    /**
     * æŸ¥è¯¢æŒ‡å®šæ—¥æœŸçš„设备打卡数据(通常是昨天)
     */
    List<MdcEquipmentPunch> getYesterdayRecords(String targetDate);
}
lxzn-module-mdc/src/main/java/org/jeecg/modules/mdc/service/impl/MdcEquipmentPunchRateServiceImpl.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,81 @@
package org.jeecg.modules.mdc.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.jeecg.modules.mdc.entity.MdcEquipmentPunch;
import org.jeecg.modules.mdc.entity.MdcEquipmentPunchRate;
import org.jeecg.modules.mdc.mapper.MdcEquipmentPunchMapper;
import org.jeecg.modules.mdc.mapper.MdcEquipmentPunchRateMapper;
import org.jeecg.modules.mdc.service.IMdcEquipmentPunchRateService;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.List;
import java.util.UUID;
/**
 * @Description: mdc_equipment_punch
 * @Author: jeecg-boot
 * @Date:   2025-06-09
 * @Version: V1.0
 */
@Service
public class MdcEquipmentPunchRateServiceImpl extends ServiceImpl<MdcEquipmentPunchRateMapper, MdcEquipmentPunchRate> implements IMdcEquipmentPunchRateService {
    @Resource
    private MdcEquipmentPunchRateMapper mdcEquipmentPunchRateMapper;
    @Resource
    private MdcEquipmentPunchMapper mdcEquipmentPunchMapper;
    @Override
    public void savePunchRates(String targetDate, List<MdcEquipmentPunch> punchRecords) {
        int morningIn = mdcEquipmentPunchMapper.countMorningShiftIn(targetDate);
        int eveningIn = mdcEquipmentPunchMapper.countEveningShiftIn(targetDate);
        int morningOut = mdcEquipmentPunchMapper.countMorningShiftOut(targetDate);
        int eveningOut = mdcEquipmentPunchMapper.countEveningShiftOut(targetDate);
        for (MdcEquipmentPunch punch : punchRecords) {
            MdcEquipmentPunchRate rate = new MdcEquipmentPunchRate();
            rate.setId(UUID.randomUUID().toString()); // ç”Ÿæˆå”¯ä¸€ID
            rate.setEquipmentId(punch.getEquipmentId());
            rate.setTheDate(targetDate);
            rate.setShiftSchedule(punch.getShiftSchedule());
            // è®¾ç½®è®¾å¤‡æ•°é‡
            rate.setMornShiftInNum(morningIn);
            rate.setMornShiftOutNum(eveningIn);
            rate.setEvenShiftInNum(morningOut);
            rate.setEvenShiftOutNum(eveningOut);
            // èŽ·å–æ€»è®¾å¤‡æ•°
            int totalDevices = mdcEquipmentPunchMapper.getTotalDeviceCount();
            if (totalDevices == 0) return;
            rate.setDeviceCountNum(totalDevices);
            // è®¡ç®—打卡率(保留两位小数)
            rate.setMornShiftInRate(calculateRate(morningIn, totalDevices));
            rate.setMornShiftOutRate(calculateRate(eveningIn, totalDevices));
            rate.setEvenShiftInRate(calculateRate(morningOut, totalDevices));
            rate.setEvenShiftOutRate(calculateRate(eveningOut, totalDevices));
            this.save(rate);
        }
    }
    private BigDecimal calculateRate(int actual, int total) {
        if (total == 0) return BigDecimal.ZERO;
        return new BigDecimal(actual)
                .divide(new BigDecimal(total), 4, RoundingMode.DOWN)
                .multiply(BigDecimal.valueOf(100))
                .setScale(2, RoundingMode.DOWN); // ä¿ç•™ä¸¤ä½å°æ•°ï¼Œä¸è¿›è¡Œå››èˆäº”å…¥
    }
}
lxzn-module-mdc/src/main/java/org/jeecg/modules/mdc/service/impl/MdcEquipmentPunchServiceImpl.java
@@ -3,6 +3,7 @@
import cn.hutool.core.date.DatePattern;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
@@ -19,6 +20,10 @@
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;
@@ -30,7 +35,8 @@
 */
@Service
public class MdcEquipmentPunchServiceImpl extends ServiceImpl<MdcEquipmentPunchMapper, MdcEquipmentPunch> implements IMdcEquipmentPunchService {
    @Resource
    private MdcEquipmentPunchMapper mdcEquipmentPunchMapper;
    @Resource
    private IMdcEquipmentService mdcEquipmentService;
@@ -235,4 +241,59 @@
        this.saveOrUpdateBatch(list);
    }
    @Override
    public void fillPunchRates(List<MdcEquipmentPunch> punchList) {
        // èŽ·å–æ˜¨å¤©æ—¥æœŸ
        LocalDate yesterday = LocalDate.now().minusDays(1);
        String yesterdayStr = yesterday.format(DateTimeFormatter.ofPattern(DatePattern.PURE_DATE_PATTERN)); // æ ¼å¼åŒ–为 "yyyy-MM-dd"
        // èŽ·å–æ€»è®¾å¤‡æ•°
        int totalDevices = mdcEquipmentPunchMapper.getTotalDeviceCount();
        if (totalDevices == 0) return;
        // ç»Ÿè®¡å„类型打卡人数
        int morningIn = mdcEquipmentPunchMapper.countMorningShiftIn(yesterdayStr);
        int eveningIn = mdcEquipmentPunchMapper.countEveningShiftIn(yesterdayStr);
        int morningOut = mdcEquipmentPunchMapper.countMorningShiftOut(yesterdayStr);
        int eveningOut = mdcEquipmentPunchMapper.countEveningShiftOut(yesterdayStr);
        // è®¾ç½®æ‰“卡率到每个 DTO
        for (MdcEquipmentPunch dto : punchList) {
            dto.setMorningShiftInRate(calculateRate(morningIn, totalDevices));
            dto.setEveningShiftInRate(calculateRate(eveningIn, totalDevices));
            dto.setMorningShiftOutRate(calculateRate(morningOut, totalDevices));
            dto.setEveningShiftOutRate(calculateRate(eveningOut, totalDevices));
            // è®¾ç½®æ‰“卡设备数量字段
            dto.setMorningShiftInDeviceNum(morningIn);
            dto.setMorningShiftOutDeviceNum(morningOut);
            dto.setEveningShiftInDeviceNum(eveningIn);
            dto.setEveningShiftOutDeviceNum(eveningOut);
            dto.setDeviceCountNum(totalDevices);
        }
    }
    // è®¡ç®—百分比并保留两位小数
    private BigDecimal calculateRate(int actual, int total) {
        if (total == 0) return BigDecimal.ZERO;
        return new BigDecimal(actual)
                .divide(new BigDecimal(total), 4, RoundingMode.HALF_UP)
                .multiply(BigDecimal.valueOf(100))
                .setScale(2, RoundingMode.HALF_UP); // ä¿ç•™ä¸¤ä½å°æ•°
    }
    @Override
    public List<MdcEquipmentPunch> getYesterdayRecords(String  targetDate) {
        // æž„造查询条件:record_date = targetDate.toString()
        QueryWrapper<MdcEquipmentPunch> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("record_date", targetDate);
        // æ‰§è¡ŒæŸ¥è¯¢å¹¶è¿”回结果
        return baseMapper.selectList(queryWrapper);
    }
}