111
tjx
10 小时以前 8e3309ef57424194ce9683175b59d3c9e8cb0b27
111
已修改1个文件
已添加5个文件
421 ■■■■■ 文件已修改
src/main/java/com/gs/dingtalk/entity/QwCheckinDayData.java 170 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/gs/dingtalk/mapper/QwCheckinDayDataMapper.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/gs/dingtalk/service/QwCheckinDayDataService.java 46 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/gs/dingtalk/service/impl/QwCheckinDayDataServiceImpl.java 178 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/QwCheckinDayDataMapper.xml 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/test/java/com/gs/dingtalk/DeviceReceivingApplicationTests.java 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/gs/dingtalk/entity/QwCheckinDayData.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,170 @@
package com.gs.dingtalk.entity;
import com.baomidou.mybatisplus.annotation.*;
import lombok.Data;
import java.io.Serializable;
import java.util.Date;
/**
 * ä¼ä¸šå¾®ä¿¡æ‰“卡日报数据
 * @TableName QW_CHECKIN_DAY_DATA
 */
@TableName(value = "QW_CHECKIN_DAY_DATA")
@Data
@KeySequence(value = "SEQ_QW_CHECKIN_DAY_DATA", dbType = DbType.ORACLE)
public class QwCheckinDayData implements Serializable {
    @TableField(exist = false)
    private static final long serialVersionUID = 1L;
    /**
     * ä¸»é”®ID
     */
    @TableId
    private Long id;
    /**
     * æ—¥æŠ¥æ—¥æœŸï¼ˆUnix时间戳)
     */
    private Long reportDate;
    /**
     * æ—¥æŠ¥æ—¥æœŸï¼ˆè½¬æ¢åŽçš„æ—¥æœŸï¼‰
     */
    private Date reportDatetime;
    /**
     * ç”¨æˆ·è´¦å·(userid)
     */
    private String acctid;
    /**
     * å‘˜å·¥å§“名
     */
    private String name;
    /**
     * å‘˜å·¥åˆ«å
     */
    private String nameEx;
    /**
     * æ‰€å±žéƒ¨é—¨ï¼ˆå¤šä¸ªéƒ¨é—¨ä»¥åˆ†å·åˆ†éš”)
     */
    private String departsName;
    /**
     * è®°å½•类型:1-固定上下班;3-按班次上下班;4-自由签到;5-加班;7-无规则
     */
    private Integer recordType;
    /**
     * æ—¥æŠ¥ç±»åž‹ï¼š0-工作日日报;1-休息日日报
     */
    private Integer dayType;
    /**
     * è§„则ID
     */
    private Integer groupid;
    /**
     * è§„则名称
     */
    private String groupname;
    /**
     * ç­æ¬¡ID
     */
    private Integer scheduleid;
    /**
     * ç­æ¬¡åç§°
     */
    private String schedulename;
    /**
     * å½“日打卡次数
     */
    private Integer checkinCount;
    /**
     * å½“日实际工作时长(秒)
     */
    private Integer regularWorkSec;
    /**
     * å½“日标准工作时长(秒)
     */
    private Integer standardWorkSec;
    /**
     * å½“日最早打卡时间(距0点秒数)
     */
    private Integer earliestTime;
    /**
     * å½“日最晚打卡时间(距0点秒数)
     */
    private Integer lastestTime;
    /**
     * è¿Ÿåˆ°æ¬¡æ•°
     */
    private Integer lateCount;
    /**
     * è¿Ÿåˆ°æ—¶é•¿ï¼ˆç§’)
     */
    private Integer lateDuration;
    /**
     * æ—©é€€æ¬¡æ•°
     */
    private Integer earlyLeaveCount;
    /**
     * æ—©é€€æ—¶é•¿ï¼ˆç§’)
     */
    private Integer earlyLeaveDuration;
    /**
     * ç¼ºå¡æ¬¡æ•°
     */
    private Integer absentCount;
    /**
     * æ—·å·¥æ¬¡æ•°
     */
    private Integer absenteeismCount;
    /**
     * æ—·å·¥æ—¶é•¿ï¼ˆç§’)
     */
    private Integer absenteeismDuration;
    /**
     * åœ°ç‚¹å¼‚常次数
     */
    private Integer locationExCount;
    /**
     * è®¾å¤‡å¼‚常次数
     */
    private Integer deviceExCount;
    /**
     * åŠ ç­çŠ¶æ€ï¼š0-无加班;1-正常;2-缺时长
     */
    private Integer otStatus;
    /**
     * åŠ ç­æ—¶é•¿ï¼ˆç§’ï¼‰
     */
    private Integer otDuration;
    /**
     * åˆ›å»ºæ—¶é—´
     */
    private Date createTime;
}
src/main/java/com/gs/dingtalk/mapper/QwCheckinDayDataMapper.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,12 @@
package com.gs.dingtalk.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.gs.dingtalk.entity.QwCheckinDayData;
import org.apache.ibatis.annotations.Mapper;
/**
 * ä¼ä¸šå¾®ä¿¡æ‰“卡日报数据Mapper
 */
@Mapper
public interface QwCheckinDayDataMapper extends BaseMapper<QwCheckinDayData> {
}
src/main/java/com/gs/dingtalk/service/QwCheckinDayDataService.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,46 @@
package com.gs.dingtalk.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.gs.dingtalk.entity.QwCheckinDayData;
import java.io.IOException;
import java.util.List;
/**
 * ä¼ä¸šå¾®ä¿¡æ‰“卡日报数据Service
 */
public interface QwCheckinDayDataService extends IService<QwCheckinDayData> {
    /**
     * å°†CheckinDayData转换为QwCheckinDayData实体
     *
     * @param dayData ä¼ä¸šå¾®ä¿¡æ‰“卡日报数据
     * @return QwCheckinDayData实体
     */
    QwCheckinDayData convertToEntity(WorkWXService.CheckinDayData dayData);
    /**
     * æ‰¹é‡ä¿å­˜æ‰“卡日报数据(自动去重,按acctid+report_date)
     *
     * @param dayDataList æ‰“卡日报数据列表
     * @return æ–°å¢žè®°å½•æ•°
     */
    int saveDayDataBatch(List<WorkWXService.CheckinDayData> dayDataList);
    /**
     * åŒæ­¥æŒ‡å®šæ—¥æœŸçš„æ‰“卡日报数据到数据库
     *
     * @param date æ—¥æœŸï¼ˆUnix时间戳,需为当天0点)
     * @return æ–°å¢žè®°å½•æ•°
     * @throws IOException èŽ·å–æ‰“å¡æ—¥æŠ¥æ•°æ®å¼‚å¸¸
     */
    int syncDayData(long date) throws IOException;
    /**
     * åŒæ­¥æ˜¨å¤©çš„æ‰“卡日报数据到数据库
     *
     * @return æ–°å¢žè®°å½•æ•°
     * @throws IOException èŽ·å–æ‰“å¡æ—¥æŠ¥æ•°æ®å¼‚å¸¸
     */
    int syncYesterdayDayData() throws IOException;
}
src/main/java/com/gs/dingtalk/service/impl/QwCheckinDayDataServiceImpl.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,178 @@
package com.gs.dingtalk.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.gs.dingtalk.entity.QwCheckinDayData;
import com.gs.dingtalk.mapper.QwCheckinDayDataMapper;
import com.gs.dingtalk.service.QwCheckinDayDataService;
import com.gs.dingtalk.service.WorkWXService;
import lombok.RequiredArgsConstructor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import java.io.IOException;
import java.util.Date;
import java.util.List;
/**
 * ä¼ä¸šå¾®ä¿¡æ‰“卡日报数据Service实现
 */
@Service
@RequiredArgsConstructor
public class QwCheckinDayDataServiceImpl extends ServiceImpl<QwCheckinDayDataMapper, QwCheckinDayData>
        implements QwCheckinDayDataService {
    private static final Logger log = LoggerFactory.getLogger(QwCheckinDayDataServiceImpl.class);
    private final WorkWXService workWXService;
    @Override
    public QwCheckinDayData convertToEntity(WorkWXService.CheckinDayData dayData) {
        if (dayData == null) {
            return null;
        }
        QwCheckinDayData entity = new QwCheckinDayData();
        // åŸºç¡€ä¿¡æ¯
        WorkWXService.BaseInfo baseInfo = dayData.getBaseInfo();
        if (baseInfo != null) {
            entity.setReportDate(baseInfo.getDate());
            if (baseInfo.getDate() != null) {
                entity.setReportDatetime(new Date(baseInfo.getDate() * 1000));
            }
            entity.setAcctid(baseInfo.getAcctid());
            entity.setName(baseInfo.getName());
            entity.setNameEx(baseInfo.getNameEx());
            entity.setDepartsName(baseInfo.getDepartsName());
            entity.setRecordType(baseInfo.getRecordType());
            entity.setDayType(baseInfo.getDayType());
            // è§„则信息
            WorkWXService.RuleInfo ruleInfo = baseInfo.getRuleInfo();
            if (ruleInfo != null) {
                entity.setGroupid(ruleInfo.getGroupid());
                entity.setGroupname(ruleInfo.getGroupname());
                entity.setScheduleid(ruleInfo.getScheduleid());
                entity.setSchedulename(ruleInfo.getSchedulename());
            }
        }
        // æ±‡æ€»ä¿¡æ¯
        WorkWXService.SummaryInfo summaryInfo = dayData.getSummaryInfo();
        if (summaryInfo != null) {
            entity.setCheckinCount(summaryInfo.getCheckinCount());
            entity.setRegularWorkSec(summaryInfo.getRegularWorkSec());
            entity.setStandardWorkSec(summaryInfo.getStandardWorkSec());
            entity.setEarliestTime(summaryInfo.getEarliestTime());
            entity.setLastestTime(summaryInfo.getLastestTime());
        }
        // å¼‚常信息 - åˆå§‹åŒ–默认值
        entity.setLateCount(0);
        entity.setLateDuration(0);
        entity.setEarlyLeaveCount(0);
        entity.setEarlyLeaveDuration(0);
        entity.setAbsentCount(0);
        entity.setAbsenteeismCount(0);
        entity.setAbsenteeismDuration(0);
        entity.setLocationExCount(0);
        entity.setDeviceExCount(0);
        // è§£æžå¼‚常信息
        List<WorkWXService.ExceptionInfo> exceptionInfos = dayData.getExceptionInfos();
        if (exceptionInfos != null && !exceptionInfos.isEmpty()) {
            for (WorkWXService.ExceptionInfo ex : exceptionInfos) {
                if (ex.getException() == null) continue;
                switch (ex.getException()) {
                    case 1: // è¿Ÿåˆ°
                        entity.setLateCount(ex.getCount() != null ? ex.getCount() : 0);
                        entity.setLateDuration(ex.getDuration() != null ? ex.getDuration() : 0);
                        break;
                    case 2: // æ—©é€€
                        entity.setEarlyLeaveCount(ex.getCount() != null ? ex.getCount() : 0);
                        entity.setEarlyLeaveDuration(ex.getDuration() != null ? ex.getDuration() : 0);
                        break;
                    case 3: // ç¼ºå¡
                        entity.setAbsentCount(ex.getCount() != null ? ex.getCount() : 0);
                        break;
                    case 4: // æ—·å·¥
                        entity.setAbsenteeismCount(ex.getCount() != null ? ex.getCount() : 0);
                        entity.setAbsenteeismDuration(ex.getDuration() != null ? ex.getDuration() : 0);
                        break;
                    case 5: // åœ°ç‚¹å¼‚常
                        entity.setLocationExCount(ex.getCount() != null ? ex.getCount() : 0);
                        break;
                    case 6: // è®¾å¤‡å¼‚常
                        entity.setDeviceExCount(ex.getCount() != null ? ex.getCount() : 0);
                        break;
                }
            }
        }
        // åŠ ç­ä¿¡æ¯
        entity.setOtStatus(0);
        entity.setOtDuration(0);
        WorkWXService.OtInfo otInfo = dayData.getOtInfo();
        if (otInfo != null) {
            entity.setOtStatus(otInfo.getOtStatus() != null ? otInfo.getOtStatus() : 0);
            entity.setOtDuration(otInfo.getOtDuration() != null ? otInfo.getOtDuration() : 0);
        }
        entity.setCreateTime(new Date());
        return entity;
    }
    @Override
    public int saveDayDataBatch(List<WorkWXService.CheckinDayData> dayDataList) {
        if (dayDataList == null || dayDataList.isEmpty()) {
            return 0;
        }
        int insertCount = 0;
        for (WorkWXService.CheckinDayData dayData : dayDataList) {
            QwCheckinDayData entity = convertToEntity(dayData);
            if (entity == null || entity.getAcctid() == null || entity.getReportDate() == null) {
                continue;
            }
            // æ£€æŸ¥æ˜¯å¦å·²å­˜åœ¨ï¼ˆæŒ‰acctid + report_date去重)
            LambdaQueryWrapper<QwCheckinDayData> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(QwCheckinDayData::getAcctid, entity.getAcctid())
                    .eq(QwCheckinDayData::getReportDate, entity.getReportDate());
            QwCheckinDayData existing = this.getOne(wrapper);
            if (existing != null) {
                // å·²å­˜åœ¨åˆ™æ›´æ–°
                entity.setId(existing.getId());
                this.updateById(entity);
                log.debug("更新打卡日报数据: acctid={}, date={}", entity.getAcctid(), entity.getReportDatetime());
            } else {
                // ä¸å­˜åœ¨åˆ™æ’å…¥
                this.save(entity);
                insertCount++;
                log.debug("新增打卡日报数据: acctid={}, date={}", entity.getAcctid(), entity.getReportDatetime());
            }
        }
        log.info("打卡日报数据保存完成,新增: {}, æ€»å¤„理: {}", insertCount, dayDataList.size());
        return insertCount;
    }
    @Override
    public int syncDayData(long date) throws IOException {
        List<WorkWXService.CheckinDayData> dayDataList = workWXService.getCheckinDayDataByQwStaff(date, date);
        return saveDayDataBatch(dayDataList);
    }
    @Override
    public int syncYesterdayDayData() throws IOException {
        long currentTime = System.currentTimeMillis() / 1000;
        long oneDaySeconds = 86400;
        long yesterdayStart = ((currentTime / oneDaySeconds) - 1) * oneDaySeconds;
        log.info("开始同步昨天({})的打卡日报数据", new Date(yesterdayStart * 1000));
        return syncDayData(yesterdayStart);
    }
}
src/main/resources/mapper/QwCheckinDayDataMapper.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="com.gs.dingtalk.mapper.QwCheckinDayDataMapper">
</mapper>
src/test/java/com/gs/dingtalk/DeviceReceivingApplicationTests.java
@@ -9,6 +9,7 @@
import com.gs.dingtalk.service.SimpleExample;
import com.gs.dingtalk.service.VwCjScSjTsBbService;
import com.gs.dingtalk.service.WorkWXService;
import com.gs.dingtalk.service.QwCheckinDayDataService;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
@@ -33,6 +34,9 @@
    @Autowired
    private QwCheckinDataService qwCheckinDataService;
    @Autowired
    private QwCheckinDayDataService qwCheckinDayDataService;
    /**
     * æµ‹è¯•导出生产数据并发送钉钉消息
@@ -285,6 +289,11 @@
                        });
                    }
                });
                // ä¿å­˜åˆ°æ•°æ®åº“
                System.out.println("  - å¼€å§‹ä¿å­˜æ‰“卡日报数据到数据库...");
                int insertCount = qwCheckinDayDataService.saveDayDataBatch(dayDataList);
                System.out.println("✓ ä¿å­˜å®Œæˆï¼Œæ–°å¢žè®°å½•æ•°: " + insertCount + ", æ›´æ–°(已存在): " + (dayDataList.size() - insertCount));
            } else {
                System.out.println("✗ èŽ·å–çš„æ‰“å¡æ—¥æŠ¥æ•°æ®ä¸ºç©º");
            }