<?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="jnpf.attendance.mapper.AttendanceDailyRuleMapper" >

    <!-- 查询昨天和今天的出勤规则 -->
    <select id="getRuleClockTimeContainsToday" resultType="jnpf.entity.attendance.FtbAttendanceDailyRule">
        select adr.F_Id id, F_GroupId groupId, F_SelfGroup selfGroup, F_ShiftId periodId, F_PeriodInfo periodInfo, F_Day `day`, F_UserId userId, F_LateEnable lateEnable, F_EarlyEnable earlyEnable,
          F_BreakEnable breakEnable, F_NextDayEnable nextDayEnable, F_ClockStartPoint clockStartPoint, F_InPoint inPoint, F_LatePoint latePoint, F_InLackPoint inLackPoint,
          F_BreakStartPoint breakStartPoint, F_BreakEndPoint breakEndPoint, F_EarlyPoint earlyPoint, F_OutPoint outPoint, F_OutLackPoint outLackPoint, F_InStepOutType inStepOutType, F_OutStepOutType outStepOutType,
          F_AttendanceType attendanceType, F_ApplyStart applyStart, F_ApplyEnd applyEnd, F_ApplyViewEnable applyViewEnable, F_InUnbounded inUnbounded, F_OutUnbounded outUnbounded,
          F_IsLateOutLateIn isLateOutLateIn,
          <choose>
            <when test="null != userId and '' != userId">
              ROW_NUMBER() OVER (ORDER BY F_InPoint DESC) AS rn
            </when>
            <otherwise>
              ROW_NUMBER() OVER (PARTITION BY F_UserId ORDER BY F_InPoint DESC) AS rn
            </otherwise>
          </choose>
        from ftb_attendance_daily_rule adr
        left join ftb_attendance_group ag on F_GroupId = ag.F_Id
        where adr.F_DeleteMark = 0 and ag.F_DeleteMark = 0 and F_ApplyViewEnable in (1, 3, 9, 10)
        <if test="null != userId and '' != userId">
            and adr.F_UserId = #{userId}
        </if>
        and F_Day between DATE_FORMAT(DATE_SUB(#{currentDate}, interval 1 day), '%Y-%m-%d') AND DATE_FORMAT(#{currentDate}, '%Y-%m-%d')
        order by F_Day desc, F_InPoint desc
    </select>
    <!-- 查询指定日期的最后一个出勤规则 -->
    <select id="getLastDailyRule" resultType="jnpf.entity.attendance.FtbAttendanceDailyRule">
        select adr.F_Id id, F_GroupId groupId, F_SelfGroup selfGroup, F_ShiftId periodId, F_Day `day`, F_UserId userId, F_LateEnable lateEnable, F_EarlyEnable earlyEnable,
          F_BreakEnable breakEnable, F_NextDayEnable nextDayEnable, F_ClockStartPoint clockStartPoint, F_InPoint inPoint, F_LatePoint latePoint, F_InLackPoint inLackPoint,
          F_BreakStartPoint breakStartPoint, F_BreakEndPoint breakEndPoint, F_EarlyPoint earlyPoint, F_OutPoint outPoint, F_OutLackPoint outLackPoint,
          F_AttendanceType attendanceType, F_ApplyStart applyStart, F_ApplyEnd applyEnd, F_ApplyViewEnable applyViewEnable/*, F_WithSalary withSalary*/
        from ftb_attendance_daily_rule adr
        left join ftb_attendance_group ag on F_GroupId = ag.F_Id
        where DATE_FORMAT(F_Day, '%Y-%m-%d') = DATE_FORMAT(#{currentDate}, '%Y-%m-%d') and F_UserId = #{userId} and adr.F_DeleteMark = 0 and ag.F_DeleteMark = 0
          and F_ApplyViewEnable in (1, 3, 9, 10)
        order by F_InPoint desc limit 1
    </select>
    <!-- 查询ruleId的上/下一个(班/加班)出勤 -->
    <select id="getPreviousOrNextRule" resultType="jnpf.entity.attendance.FtbAttendanceDailyRule">
        select adr.F_Id id, F_GroupId groupId, F_SelfGroup selfGroup, F_ShiftId periodId, F_Day `day`, F_UserId userId, F_LateEnable lateEnable, F_EarlyEnable earlyEnable,
          F_BreakEnable breakEnable, F_NextDayEnable nextDayEnable, F_ClockStartPoint clockStartPoint, F_InPoint inPoint, F_LatePoint latePoint, F_InLackPoint inLackPoint,
          F_BreakStartPoint breakStartPoint, F_BreakEndPoint breakEndPoint, F_EarlyPoint earlyPoint, F_OutPoint outPoint, F_OutLackPoint outLackPoint,
          F_AttendanceType attendanceType, F_ApplyStart applyStart, F_ApplyEnd applyEnd, /*F_WithSalary withSalary, */F_Sort sort
        from ftb_attendance_daily_rule adr
        left join ftb_attendance_group ag on F_GroupId = ag.F_Id
        where adr.F_ApplyViewEnable in (1, 3, 9, 10) and adr.F_Id != #{ruleId} and adr.F_UserId = #{userId} and adr.F_DeleteMark = 0 and adr.F_AttendanceType in (1, 4) and ag.F_DeleteMark = 0
        <![CDATA[
          and DATE_FORMAT(adr.F_InPoint, '%Y-%m-%d %H:%i:%S') >= DATE_FORMAT(#{startTime}, '%Y-%m-%d %H:%i:%S')
          and DATE_FORMAT(adr.F_InPoint, '%Y-%m-%d %H:%i:%S') <= DATE_FORMAT(#{endTime}, '%Y-%m-%d %H:%i:%S')
        ]]>
        <if test="'previous' == queryType">
          order by adr.F_Day desc, adr.F_InPoint desc
        </if>
        <if test="'next' == queryType">
          order by adr.F_Day asc, adr.F_InPoint asc
        </if>
        limit 1
    </select>
<!--    获取指定日期的排班-->
    <select id="getShiftByDay" resultType="jnpf.model.attendance.vo.ClassesDetailVo">
        SELECT F_InPoint  inPointDate ,F_BreakStartPoint breakStartPointDate  ,F_BreakEndPoint breakEndPointDate  ,F_OutPoint outPointDate
        FROM ftb_attendance_daily_rule
        WHERE DATE_FORMAT(F_Day,'%Y-%m-%d') = DATE_FORMAT(#{startDay},'%Y-%m-%d') and F_UserId = #{userId} and F_AttendanceType in (1, 4)
    </select>
<!--    2024-1-12-->
<!--    <select id="getShiftByDay" resultType="jnpf.model.attendance.vo.ClassesDetailVo">-->
<!--        SELECT DATE_FORMAT(F_InPoint,'%H:%i')  inPoint ,DATE_FORMAT(F_BreakStartPoint,'%H:%i') breakStartPoint  ,DATE_FORMAT(F_BreakEndPoint,'%H:%i') breakEndPoint  ,DATE_FORMAT(F_OutPoint,'%H:%i') outPoint-->
<!--        FROM ftb_attendance_daily_rule-->
<!--        WHERE DATE_FORMAT(F_Day,'%Y-%m-%d') = DATE_FORMAT(#{startDay},'%Y-%m-%d') and F_UserId = #{userId} and F_AttendanceType in (1, 4)-->
<!--    </select>-->
    <!-- 查询所有下班缺卡时间是今天的出勤规则 -->
    <select id="getRuleListByDate" resultType="jnpf.entity.attendance.FtbAttendanceDailyRule">
        select F_Id id, F_GroupId groupId, F_SelfGroup selfGroup, F_ShiftId periodId, F_Day `day`, F_UserId userId, F_LateEnable lateEnable, F_EarlyEnable earlyEnable,
           F_BreakEnable breakEnable, F_NextDayEnable nextDayEnable, F_ClockStartPoint clockStartPoint, F_InPoint inPoint, F_LatePoint latePoint, F_InLackPoint inLackPoint,
           F_BreakStartPoint breakStartPoint, F_BreakEndPoint breakEndPoint, F_EarlyPoint earlyPoint, F_OutPoint outPoint, F_OutLackPoint outLackPoint,
           F_AttendanceType attendanceType, F_ApplyStart applyStart, F_ApplyEnd applyEnd, F_Sort sort
        from ftb_attendance_daily_rule
        where F_DeleteMark = 0 and F_AttendanceType = 1 and F_ApplyViewEnable in (1, 3, 9, 10)
        <![CDATA[
          and DATE_FORMAT(F_Day, '%Y-%m-%d') = DATE_FORMAT(#{yesterday}, '%Y-%m-%d')
          and DATE_FORMAT(F_OutLackPoint, '%Y-%m-%d') = DATE_FORMAT(#{today}, '%Y-%m-%d')
        ]]>
        <if test="null != userId and '' != userId">
            and F_UserId = #{userId}
        </if>
        order by F_OutLackPoint asc
    </select>
    <!-- 查询指定日期最后一个班次是加班的出勤记录 -->
    <select id="getOverTimeRuleListByDate" resultType="jnpf.entity.attendance.FtbAttendanceDailyRule">
        select F_Id id, F_GroupId groupId, F_SelfGroup selfGroup, F_ShiftId periodId, F_Day `day`, F_UserId userId, F_LateEnable lateEnable, F_EarlyEnable earlyEnable,
            F_BreakEnable breakEnable, F_NextDayEnable nextDayEnable, F_ClockStartPoint clockStartPoint, F_InPoint inPoint, F_LatePoint latePoint, F_InLackPoint inLackPoint,
            F_BreakStartPoint breakStartPoint, F_BreakEndPoint breakEndPoint, F_EarlyPoint earlyPoint, F_OutPoint outPoint, F_OutLackPoint outLackPoint,
            F_AttendanceType attendanceType, F_ApplyStart applyStart, F_ApplyEnd applyEnd, F_Sort sort
        from ftb_attendance_daily_rule adr
        inner join (
            select F_UserId userId, max(F_InPoint) inPoint
            from ftb_attendance_daily_rule
            where F_DeleteMark = 0 and F_AttendanceType in (4) and F_ApplyViewEnable in (1, 3, 9, 10)
            and DATE_FORMAT(F_InPoint, '%Y-%m-%d') = DATE_FORMAT(#{date}, '%Y-%m-%d')
            and DATE_FORMAT(F_Day, '%Y-%m-%d') = DATE_FORMAT(#{date}, '%Y-%m-%d')
            group by F_UserId
        ) t on adr.F_UserId = t.userId and adr.F_InPoint = t.inPoint
        where adr.F_DeleteMark = 0 and adr.F_ApplyViewEnable in (1, 3, 9, 10)
        and DATE_FORMAT(adr.F_Day, '%Y-%m-%d') = DATE_FORMAT(#{date}, '%Y-%m-%d')
        <if test="null != userId and '' != userId">
            and adr.F_UserId = #{userId}
        </if>
    </select>
<!--    获取用户时间段内排班信息-->
    <select id="getUserShift" resultType="java.lang.Integer">
        SELECT count(0)
        FROM ftb_attendance_daily_rule
        WHERE F_UserId = #{userId} AND F_AttendanceType in (1, 4)
        <![CDATA[
          AND DATE_FORMAT(F_InPoint,'%Y-%m-%d %H:%i') < DATE_FORMAT(#{endTime},'%Y-%m-%d %H:%i')
          AND DATE_FORMAT(F_OutPoint,'%Y-%m-%d %H:%i') > DATE_FORMAT(#{startTime},'%Y-%m-%d %H:%i')
        ]]>
    </select>
    <!-- 查询所有工作时间是queryDate的出勤规则 -->
    <select id="getListWorkTimeInToday" resultType="jnpf.entity.attendance.FtbAttendanceDailyRule">
        select F_Id id, F_GroupId groupId, F_SelfGroup selfGroup, F_ShiftId periodId, F_Day `day`, F_UserId userId, F_LateEnable lateEnable, F_EarlyEnable earlyEnable,
           F_BreakEnable breakEnable, F_NextDayEnable nextDayEnable, F_ClockStartPoint clockStartPoint, F_InPoint inPoint, F_LatePoint latePoint, F_InLackPoint inLackPoint,
           F_BreakStartPoint breakStartPoint, F_BreakEndPoint breakEndPoint, F_EarlyPoint earlyPoint, F_OutPoint outPoint, F_OutLackPoint outLackPoint,
           F_AttendanceType attendanceType, F_ApplyStart applyStart, F_ApplyEnd applyEnd, F_Sort sort
        from ftb_attendance_daily_rule
        where F_DeleteMark = 0 and F_AttendanceType = 1 and F_ApplyViewEnable in (1, 3, 9, 10)
        <![CDATA[
          and (
            DATE_FORMAT(F_InPoint, '%Y-%m-%d') = DATE_FORMAT(#{queryDate}, '%Y-%m-%d') or DATE_FORMAT(F_OutPoint, '%Y-%m-%d') = DATE_FORMAT(#{queryDate}, '%Y-%m-%d')
          )
        ]]>
        order by F_InPoint asc
    </select>
    <!-- 查询上班/下班时间在时间范围内的出勤规则 -->
    <select id="getListByWorkTime" resultType="jnpf.entity.attendance.FtbAttendanceDailyRule">
        select F_Id id, F_GroupId groupId, F_SelfGroup selfGroup, F_ShiftId periodId, F_Day `day`, F_UserId userId, F_LateEnable lateEnable, F_EarlyEnable earlyEnable,
           F_BreakEnable breakEnable, F_NextDayEnable nextDayEnable, F_ClockStartPoint clockStartPoint, F_InPoint inPoint, F_LatePoint latePoint, F_InLackPoint inLackPoint,
           F_BreakStartPoint breakStartPoint, F_BreakEndPoint breakEndPoint, F_EarlyPoint earlyPoint, F_OutPoint outPoint, F_OutLackPoint outLackPoint,
           F_AttendanceType attendanceType, F_ApplyStart applyStart, F_ApplyEnd applyEnd, F_Sort sort
        from ftb_attendance_daily_rule
        where F_DeleteMark = 0 and F_AttendanceType = 1 and F_ApplyViewEnable in (1, 3, 9, 10)
        <![CDATA[
          and (
            (DATE_FORMAT(F_InPoint, '%Y-%m-%d %H:%i:%S') >= DATE_FORMAT(#{beginDate}, '%Y-%m-%d %H:%i:%S') and DATE_FORMAT(F_InPoint, '%Y-%m-%d %H:%i:%S') < DATE_FORMAT(#{endDate}, '%Y-%m-%d %H:%i:%S'))
            or
            (DATE_FORMAT(F_OutPoint, '%Y-%m-%d %H:%i:%S') >= DATE_FORMAT(#{beginDate}, '%Y-%m-%d %H:%i:%S') and DATE_FORMAT(F_OutPoint, '%Y-%m-%d %H:%i:%S') < DATE_FORMAT(#{endDate}, '%Y-%m-%d %H:%i:%S'))
          )
        ]]>
        order by F_InPoint asc
    </select>
    <!-- 查询一个月的打卡记录(缺勤次数统计) -->
    <select id="selectMonthRecord" resultType="jnpf.model.attendance.vo.MonthRecordVo">
        select dr.F_GroupId groupId, date_format(dr.F_Day, '%Y-%m-%d') `day`, acir.F_UserId userId, acir.F_RuleId ruleId, sum(acir.F_Absence = 1) absenceCount,
               sn.F_ShortName rule, concat_ws('至', date_format(dr.F_InPoint, '%H:%i'), date_format(dr.F_OutPoint, '%H:%i')) ruleTime
        from ftb_attendance_clock_in_result acir
        left join ftb_attendance_daily_rule dr on dr.F_Id = acir.F_RuleId
        left join ftb_attendance_shift_name sn on dr.F_ShiftId = sn.F_Id
        join (
          select adr.F_Id
          from ftb_attendance_daily_rule adr
          where adr.F_DeleteMark = 0 and F_AttendanceType in (1, 4)
          and adr.F_Day in (
            select F_Day
            from (
              select F_Day
              from ftb_attendance_daily_rule
              where F_AttendanceType in (1, 4)
              and F_DeleteMark = 0 and date_format(F_Day, '%Y-%m-%d') <![CDATA[<]]> date_format(now(), '%Y-%m-%d')
              group by F_Day
              order by F_Day desc
              limit 30
            ) as recent_days
          )
        ) as filtered_rules on acir.F_RuleId = filtered_rules.F_Id
        where acir.F_DeleteMark = 0
        group by dr.F_GroupId, dr.F_Day, acir.F_UserId, acir.F_RuleId, acir.F_Absence
        order by dr.F_GroupId, acir.F_UserId, dr.F_Day desc
    </select>
    <!-- 查询存在的出勤规则 -->
    <select id="getExistRuleId" resultType="java.lang.String">
        select F_Id from ftb_attendance_daily_rule where F_DeleteMark = 0 and F_Id in
        <foreach collection="list" index="index" item="item" open="(" separator="," close=")">
            #{item}
        </foreach>
    </select>
<!--    获取排班用户数-->
    <select id="getGroupUserNum" resultType="java.lang.Integer">
        SELECT COUNT(DISTINCT(F_UserId))
        FROM ftb_attendance_daily_rule
        WHERE F_Day = DATE_FORMAT(NOW(), '%Y-%m-%d') AND F_DeleteMark = 0 AND F_AttendanceType IN (1,2)
          AND F_GroupId IN
        <foreach collection="groupIds" index="index" item="item" open="(" separator="," close=")">
            #{item}
        </foreach>
    </select>
    <select id="getYesterdayRule" resultType="jnpf.model.attendance.vo.attendance.YesterdayRuleVo">
        select *,count(1) clockCount from
        (SELECT
        r.F_Id id,
        r.F_Day `day`,
        r.F_InPoint inPoint,
        r.F_OutPoint outPoint,
        r.F_AttendanceType attendanceType
        FROM
        ftb_attendance_daily_rule r
        left JOIN ftb_attendance_clock_in_result c ON  r.F_Id = c.F_RuleId
        WHERE
        r.F_ApplyViewEnable IN ( 1, 3, 9, 10 )
        AND r.F_AttendanceType IN ( 1, 4 )
        AND r.F_UserId = #{userId}
        AND r.F_Day BETWEEN #{startDate} and #{endDate}) info
        GROUP BY id having clockCount <![CDATA[<]]> 2
        order by inPoint asc
    </select>

    <select id="getDayRule" resultType="java.lang.String">
        SELECT F_Id
        FROM ftb_attendance_daily_rule
        WHERE F_Day = DATE_FORMAT(NOW(), '%Y-%m-%d') AND F_DeleteMark = 0 AND F_AttendanceType = 1
          AND F_GroupId IN
        <foreach collection="groupIds" index="index" item="item" open="(" separator="," close=")">
            #{item}
        </foreach>
          AND F_UserId IN
        <foreach collection="groupUserIds" index="index" item="item1" open="(" separator="," close=")">
            #{item1}
        </foreach>
    </select>
    <!-- 批量查询出勤规则 -->
    <select id="getDailyRuleListBatch" resultType="jnpf.entity.attendance.FtbAttendanceDailyRule">
        SELECT
        adr.F_Id AS id,
        adr.F_GroupId AS groupId,
        adr.F_SelfGroup AS selfGroup,
        adr.F_ShiftId AS periodId,
        adr.F_PeriodInfo AS periodInfo,
        adr.F_Day AS `day`,
        adr.F_UserId AS userId,
        adr.F_LateEnable AS lateEnable,
        adr.F_EarlyEnable AS earlyEnable,
        adr.F_BreakEnable AS breakEnable,
        adr.F_NextDayEnable AS nextDayEnable,
        adr.F_ClockStartPoint AS clockStartPoint,
        adr.F_InPoint AS inPoint,
        adr.F_LatePoint AS latePoint,
        adr.F_InLackPoint AS inLackPoint,
        adr.F_BreakStartPoint AS breakStartPoint,
        adr.F_BreakEndPoint AS breakEndPoint,
        adr.F_EarlyPoint AS earlyPoint,
        adr.F_OutPoint AS outPoint,
        adr.F_OutLackPoint AS outLackPoint,
        adr.F_InStepOutType AS inStepOutType,
        adr.F_OutStepOutType AS outStepOutType,
        adr.F_AttendanceType AS attendanceType,
        adr.F_ApplyStart AS applyStart,
        adr.F_ApplyEnd AS applyEnd,
        adr.F_ApplyViewEnable AS applyViewEnable,
        adr.F_InUnbounded AS inUnbounded,
        adr.F_OutUnbounded AS outUnbounded,
        adr.F_IsLateOutLateIn AS isLateOutLateIn,
        ROW_NUMBER() OVER (
          PARTITION BY p.userId, p.targetDate ORDER BY adr.F_InPoint DESC
        ) AS rn,
        p.targetDate,
        p.queryDate
        FROM ftb_attendance_daily_rule adr
        LEFT JOIN ftb_attendance_group ag ON adr.F_GroupId = ag.F_Id
        JOIN (
            VALUES
            <foreach collection="list" item="it" separator=",">
                ROW(#{it.userId}, #{it.dayStr}, #{it.dayStr})
            </foreach>
        ) AS p(userId, targetDate, queryDate) ON adr.F_UserId = p.userId AND adr.F_Day = p.queryDate
        WHERE adr.F_DeleteMark = 0
        AND ag.F_DeleteMark = 0
        AND adr.F_ApplyViewEnable IN (1,3,9,10)
        ORDER BY p.userId, p.targetDate, p.queryDate, adr.F_InPoint DESC
    </select>
    <select id="getUserPublicHoliday" resultType="jnpf.model.attendance.vo.KeyValueVo">
        SELECT
            F_UserId as userId ,
            IFNULL(SUM(F_PeriodWorkDay),0) as value
        FROM ftb_attendance_daily_rule
        WHERE F_AttendanceType = 2  AND DATE_FORMAT(F_Day,'%Y-%m') = #{yearMonth} AND F_UserId IN
         <foreach collection="userIds" item="item" open="(" separator="," close=")">
            #{item}
        </foreach>
         AND F_ApplyViewEnable IN (1,3,9,10) AND F_DeleteMark = 0
        GROUP BY F_UserId
    </select>
    <!-- 查询每个出勤规则的下一个出勤规则 -->
    <select id="getNextRulePartInfo" resultType="jnpf.model.attendance.vo.NextRuleVo">
        SELECT * FROM (
            SELECT
                F_Id AS ruleId,
                LEAD(F_Id) OVER (PARTITION BY F_Day, F_UserId ORDER BY F_InPoint) AS nextRuleId,
                LEAD(F_AttendanceType) OVER (PARTITION BY F_Day, F_UserId ORDER BY F_InPoint) AS nextAttendanceType
            FROM ftb_attendance_daily_rule
            WHERE F_Day = #{dayStr} AND F_DeleteMark = 0
        ) t
        WHERE t.ruleId IN
        <foreach collection="list" index="index" item="item" open="(" separator="," close=")">
           #{item}
        </foreach>
    </select>
    <select id="getDayRuleByMonth" resultType="jnpf.model.attendance.vo.CreateDayStatistics">
        SELECT
            F_GroupId AS groupId,
            F_UserId AS userId,
            F_Day AS day
        FROM ftb_attendance_daily_rule
        WHERE F_Day BETWEEN #{startDate} AND #{endDate}
          AND F_DeleteMark = 0
        GROUP BY F_GroupId, F_UserId, F_Day;
    </select>
</mapper>