cuilei
2025-06-13 21cbdad6f59a045910b22bb3bf771e47d56c096f
Merge remote-tracking branch 'origin/master'
已重命名2个文件
已添加8个文件
已修改15个文件
960 ■■■■ 文件已修改
lxzn-module-dnc/src/main/java/org/jeecg/modules/dnc/entity/DocInfo.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
lxzn-module-dnc/src/main/java/org/jeecg/modules/dnc/listener/FileListener.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
lxzn-module-dnc/src/main/java/org/jeecg/modules/dnc/service/impl/ProductInfoServiceImpl.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
lxzn-module-eam-common/src/main/java/org/jeecg/modules/eam/aspect/EquipmentHistoryLogAspect.java 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
lxzn-module-eam-common/src/main/java/org/jeecg/modules/eam/entity/EamSecondMaintenanceOrder.java 补丁 | 查看 | 原始文档 | blame | 历史
lxzn-module-eam-common/src/main/java/org/jeecg/modules/eam/entity/EamThirdMaintenanceOrder.java 补丁 | 查看 | 原始文档 | blame | 历史
lxzn-module-mdc-common/src/main/java/org/jeecg/modules/mdc/service/impl/MdcEquipmentServiceImpl.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
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/AndonOrder.java 5 ●●●● 补丁 | 查看 | 原始文档 | 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/MdcDowntimeOperatorMapper.xml 2 ●●● 补丁 | 查看 | 原始文档 | 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/AndonOrderServiceImpl.java 1 ●●●● 补丁 | 查看 | 原始文档 | 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 69 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
lxzn-module-system/lxzn-system-start/src/main/resources/application-prod.yml 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
lxzn-module-dnc/src/main/java/org/jeecg/modules/dnc/entity/DocInfo.java
@@ -82,6 +82,9 @@
    //所属节点代号
    @TableField(exist = false)
    private String nodeCode;
    //所属节点id
    @TableField(exist = false)
    private String nodeId;
    //设备类名称
    @TableField(exist = false)
    private String deviceName;
lxzn-module-dnc/src/main/java/org/jeecg/modules/dnc/listener/FileListener.java
@@ -26,7 +26,7 @@
    @Override
    public void onStart(FileAlterationObserver observer) {
        log.info("开始监听目录: {}", observer.getDirectory().getAbsolutePath());
//        log.info("开始监听目录: {}", observer.getDirectory().getAbsolutePath());
    }
    @Override
@@ -72,7 +72,7 @@
    @Override
    public void onStop(FileAlterationObserver observer) {
        log.info("结束监听目录: {}", observer.getDirectory().getAbsolutePath());
//        log.info("结束监听目录: {}", observer.getDirectory().getAbsolutePath());
    }
    /**
lxzn-module-dnc/src/main/java/org/jeecg/modules/dnc/service/impl/ProductInfoServiceImpl.java
@@ -422,6 +422,7 @@
     * @param paramId      äº§å“æ ‘节点id
     * @param relativeFlag 1 æ˜¯ 2 å¦
     * @param userIds      æ·»åŠ ç”¨æˆ·ids
     * todo优化结构,采用mix表进行父子递归查询,分类进行权限分配(单表查询)
     * @return
     */
    @Override
@@ -457,6 +458,7 @@
     * @param paramId       äº§å“æ ‘节点id
     * @param relativeFlag  1 æ˜¯ 2 å¦
     * @param departmentIds æ·»åŠ éƒ¨é—¨ids
     * todo优化结构,采用mix表进行父子递归查询,分类进行权限分配(单表查询)
     * @return
     */
    @Override
@@ -492,6 +494,7 @@
     * @param paramId      äº§å“æ ‘节点id
     * @param relativeFlag 1 æ˜¯ 2 å¦
     * @param userIds      ç§»é™¤ç”¨æˆ·ids
     * todo优化结构,采用mix表进行父子递归查询,分类进行权限分配(单表查询)
     * @return
     */
    @Override
@@ -526,6 +529,7 @@
     * @param paramId       äº§å“æ ‘节点id
     * @param relativeFlag  1 æ˜¯ 2 å¦
     * @param departmentIds ç§»é™¤éƒ¨é—¨ids
     * todo优化结构,采用mix表进行父子递归查询,分类进行权限分配(单表查询)
     * @return
     */
    @Override
@@ -1179,31 +1183,37 @@
                        ProductInfo productInfo=this.getById(docInfo.getAttributionId());
                        docInfo.setNodeName(productInfo.getProductName());
                        docInfo.setNodeCode(productInfo.getProductNo());
                        docInfo.setNodeId(productInfo.getProductId());
                        break;
                    case 2:
                        ComponentInfo componentInfo=componentInfoService.getById(docInfo.getAttributionId());
                        docInfo.setNodeName(componentInfo.getComponentName());
                        docInfo.setNodeCode(componentInfo.getComponentCode());
                        docInfo.setNodeId(componentInfo.getComponentId());
                        break;
                    case 3:
                        PartsInfo partsInfo=partsInfoService.getById(docInfo.getAttributionId());
                        docInfo.setNodeCode(partsInfo.getPartsCode());
                        docInfo.setNodeName(partsInfo.getPartsName());
                        docInfo.setNodeId(partsInfo.getPartsId());
                        break;
                    case 4:
                        ProcessSpecVersion processSpecVersion=processSpecVersionService.getById(docInfo.getAttributionId());
                        docInfo.setNodeName(processSpecVersion.getProcessSpecVersionName());
                        docInfo.setNodeCode(processSpecVersion.getProcessSpecVersionCode());
                        docInfo.setNodeId(processSpecVersion.getId());
                        break;
                    case 5:
                        ProcessStream processStream=processStreamService.getById(docInfo.getAttributionId());
                        docInfo.setNodeName(processStream.getProcessName());
                        docInfo.setNodeCode(processStream.getProcessCode());
                        docInfo.setNodeId(processStream.getProcessId());
                        break;
                    case 6:
                        WorkStep workStep=workStepService.getById(docInfo.getAttributionId());
                        docInfo.setNodeName(workStep.getStepName());
                        docInfo.setNodeCode(workStep.getStepName());
                        docInfo.setNodeId(workStep.getId());
                        break;
                }
            });
@@ -1225,11 +1235,13 @@
                    ProcessStream processStream=processStreamService.getById(deviceType.getAttributionId());
                    docInfo.setNodeName(processStream.getProcessName());
                    docInfo.setNodeCode(processStream.getProcessCode());
                    docInfo.setNodeId(processStream.getProcessId());
                }else {
                    //工步下的设备类
                    WorkStep workStep=workStepService.getById(deviceType.getAttributionId());
                    docInfo.setNodeName(workStep.getStepName());
                    docInfo.setNodeCode(workStep.getStepName());
                    docInfo.setNodeId(workStep.getId());
                }
            });
        }
lxzn-module-eam-common/src/main/java/org/jeecg/modules/eam/aspect/EquipmentHistoryLogAspect.java
@@ -100,8 +100,28 @@
                }
                break;
            case SECOND_MAINTENANCE:
                if (result instanceof EamSecondMaintenanceOrder) {
                    EamSecondMaintenanceOrder order = (EamSecondMaintenanceOrder) result;
                    if (SecondMaintenanceStatusEnum.COMPLETE.name().equals(order.getMaintenanceStatus())) {
                        log.setEquipmentId(order.getEquipmentId());
                        log.setBusinessId(order.getId());
                        log.setOperator(order.getOperator());
                        log.setDescription(order.getConfirmComment());
                        log.setCreateTime(order.getActualEndTime());
                    }
                }
                break;
            case THIRD_MAINTENANCE:
                if (result instanceof EamThirdMaintenanceOrder) {
                    EamThirdMaintenanceOrder order = (EamThirdMaintenanceOrder) result;
                    if (ThirdMaintenanceStatusEnum.COMPLETE.name().equals(order.getMaintenanceStatus())) {
                        log.setEquipmentId(order.getEquipmentId());
                        log.setBusinessId(order.getId());
                        log.setOperator(order.getOperator());
                        log.setDescription(order.getLeaderConfirmComment());
                        log.setCreateTime(order.getActualEndTime());
                    }
                }
                break;
            case REPORT_REPAIR:
                if (result instanceof EamReportRepair) {
lxzn-module-eam-common/src/main/java/org/jeecg/modules/eam/entity/EamSecondMaintenanceOrder.java
lxzn-module-eam-common/src/main/java/org/jeecg/modules/eam/entity/EamThirdMaintenanceOrder.java
lxzn-module-mdc-common/src/main/java/org/jeecg/modules/mdc/service/impl/MdcEquipmentServiceImpl.java
@@ -1049,7 +1049,7 @@
        LoginUser user = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        String userId = user.getId();
        if (StringUtils.isNotEmpty(user.getEquipmentIds())) {
            return this.baseMapper.selectList(new LambdaQueryWrapper<MdcEquipment>().eq(MdcEquipment::getEquipmentId, Arrays.asList(user.getEquipmentIds().split(StringPool.COMMA))));
            return this.baseMapper.selectList(new LambdaQueryWrapper<MdcEquipment>().in(MdcEquipment::getEquipmentId, Arrays.asList(user.getEquipmentIds().split(StringPool.COMMA))));
        }
        //获取所有产线数据
        List<MdcProduction> productionList = mdcProductionService.list(new LambdaQueryWrapper<MdcProduction>().eq(MdcProduction::getDelFlag, CommonConstant.DEL_FLAG_0.toString()).orderByAsc(MdcProduction::getProductionOrder));
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/AndonOrder.java
@@ -12,6 +12,7 @@
import com.baomidou.mybatisplus.annotation.TableLogic;
import lombok.Data;
import com.fasterxml.jackson.annotation.JsonFormat;
import org.jeecg.common.constant.CommonConstant;
import org.springframework.format.annotation.DateTimeFormat;
import org.jeecgframework.poi.excel.annotation.Excel;
import org.jeecg.common.aspect.annotation.Dict;
@@ -57,6 +58,7 @@
     */
    @Excel(name = "安灯类型", width = 15)
    @ApiModelProperty(value = "安灯类型")
    @Dict(dicCode = "andon_type")
    private String andonType;
    /**
     * å®‰ç¯äºº(呼叫人)
@@ -111,6 +113,7 @@
     */
    @Excel(name = "安灯状态;待响应、待处理、已完成", width = 15)
    @ApiModelProperty(value = "安灯状态;待响应、待处理、已完成")
    @Dict(dicCode = "order_status")
    private String orderStatus;
    /**
     * é—®é¢˜æè¿°
@@ -136,7 +139,7 @@
    @Excel(name = "删除标记", width = 15)
    @ApiModelProperty(value = "删除标记")
    @TableLogic
    private Integer delFlag;
    private Integer delFlag = CommonConstant.DEL_FLAG_0;
    /**
     * åˆ›å»ºäºº
     */
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/MdcDowntimeOperatorMapper.xml
@@ -9,6 +9,6 @@
            t2.downtime_description downtimeDescription
        FROM mdc_downtime t1 LEFT JOIN mdc_downtime_reason t2 ON t1.reason_id = t2.id
        ${ew.customSqlSegment}
        ORDER BY t1.create_time DESC
        ORDER BY t1.equipment_id DESC, t1.start_date ASC
    </select>
</mapper>
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/AndonOrderServiceImpl.java
@@ -57,6 +57,7 @@
            andonOrderInfo.setEquipmentId(equipmentId);
            andonOrderInfo.setPlantName(equipmentIdToProductionIdMap != null && equipmentIdToProductionIdMap.containsKey(equipmentId) ? equipmentIdToProductionIdMap.get(equipmentId).getId() : null);
            andonOrderInfo.setAndonType(StringPool.ONE);
            andonOrderInfo.setOrderStatus(StringPool.ONE);
            andonOrderInfo.setOperator(andonOrder.getOperator());
            andonOrderInfo.setOperateTime(new Date());
            andonOrderInfo.setResponder(userId);
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;
@@ -136,13 +142,16 @@
            MdcEquipmentPunch equipmentPunch = new MdcEquipmentPunch();
            if (first.isPresent()) {
                equipmentPunch = first.get();
                //已存在记录说明已打下班卡,故将是否缺卡置为否
                equipmentPunch.setIsAbsent(0);
            }else {
                equipmentPunch.setEquipmentId(equipment);
                equipmentPunch.setPunchUser(userId);
                equipmentPunch.setRecordDate(currentDate);
                equipmentPunch.setShiftSchedule(mdcEquipmentPunch.getShiftSchedule());
                equipmentPunch.setIsAbsent(0);
                equipmentPunch.setIsEarly(0);
                //正常打卡时先将是否缺卡置为“是”,防止未打下班卡时无法调整状态
                equipmentPunch.setIsAbsent(1);
            }
            equipmentPunch.setCheckInTime(mdcEquipmentPunch.getCheckInTime());
            //打卡时间大于8:30/17:00时为迟到打卡
@@ -214,6 +223,7 @@
            MdcEquipmentPunch equipmentPunch = new MdcEquipmentPunch();
            if (mdcEquipmentPunchOptional.isPresent()) {
                equipmentPunch = mdcEquipmentPunchOptional.get();
                equipmentPunch.setIsAbsent(0);
            }else {
                equipmentPunch.setIsAbsent(1);
                equipmentPunch.setIsLate(0);
@@ -231,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);
    }
}
lxzn-module-system/lxzn-system-start/src/main/resources/application-prod.yml
@@ -291,4 +291,4 @@
      client-id: ??
      # appSecret
      client-secret: ??
      agent-id: ??
      agent-id: ??