<?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.zcloud.personnel.positioning.persistence.mapper.PersonnelMatchMapper">
    <select id="countActive" resultType="long">
        SELECT COUNT(1) FROM personnel_match
        WHERE source_config_code = #{sourceConfigCode}
          AND (delete_enum IS NULL OR delete_enum = 'FALSE')
          AND match_status &lt;&gt; 'DISABLED'
    </select>
    <select id="countAll" resultType="long">
        SELECT COUNT(1) FROM personnel_match
        WHERE (delete_enum IS NULL OR delete_enum = 'FALSE')
    </select>
    <select id="countMatched" resultType="long">
        SELECT COUNT(1) FROM personnel_match
        WHERE match_status = 'MATCHED'
          AND (delete_enum IS NULL OR delete_enum = 'FALSE')
    </select>
    <select id="maxLastSyncTime" resultType="java.time.LocalDateTime">
        SELECT MAX(last_sync_time) FROM personnel_match
        WHERE source_config_code = #{sourceConfigCode}
          AND (delete_enum IS NULL OR delete_enum = 'FALSE')
          AND match_status &lt;&gt; 'DISABLED'
    </select>
    <insert id="upsert">
        INSERT INTO personnel_match (
            source_system, source_config_code, finds_staff_no, finds_staff_no_type, finds_track_id,
            finds_id_card_no, finds_staff_name, finds_corpinfo_id, finds_corpinfo_name,
            finds_department_name, finds_terminal_no, local_user_id, local_mobile_no, local_id_card_no,
            match_status, match_type, last_seen_time, last_sync_time, sync_status, sync_error, delete_enum
        ) VALUES ('FINDS', #{sourceConfigCode}, #{staffNo}, #{staffNoType}, #{findsTrackId}, #{idCardNo},
            #{staffName}, #{corpinfoId}, #{corpinfoName}, #{departmentName}, #{terminalNo}, #{localUserId},
            #{localMobileNo}, #{localIdCardNo}, #{matchStatus}, #{matchType}, #{syncTime}, #{syncTime},
            'SUCCESS', NULL, 'FALSE')
        ON DUPLICATE KEY UPDATE finds_staff_no_type = VALUES(finds_staff_no_type),
            finds_track_id = VALUES(finds_track_id), finds_id_card_no = VALUES(finds_id_card_no),
            finds_staff_name = VALUES(finds_staff_name), finds_corpinfo_id = VALUES(finds_corpinfo_id),
            finds_corpinfo_name = VALUES(finds_corpinfo_name), finds_department_name = VALUES(finds_department_name),
            finds_terminal_no = VALUES(finds_terminal_no), local_user_id = VALUES(local_user_id),
            local_mobile_no = VALUES(local_mobile_no), local_id_card_no = VALUES(local_id_card_no),
            match_status = VALUES(match_status), match_type = VALUES(match_type),
            last_seen_time = VALUES(last_seen_time), last_sync_time = VALUES(last_sync_time),
            sync_status = 'SUCCESS', sync_error = NULL, delete_enum = 'FALSE', version = version + 1
    </insert>
    <update id="disableMissing">
        UPDATE personnel_match SET match_status = 'DISABLED', sync_status = 'SUCCESS',
            last_sync_time = #{syncTime}, version = version + 1
        WHERE source_config_code = #{sourceConfigCode}
          AND (delete_enum IS NULL OR delete_enum = 'FALSE')
          AND (last_seen_time IS NULL OR last_seen_time &lt; #{syncTime})
    </update>
    <update id="updateOnline">
        UPDATE personnel_match SET location_status = 'ONLINE', finds_device_status = #{deviceStatus},
            location_status_time = #{syncTime}, version = version + 1
        WHERE source_config_code = #{sourceConfigCode}
          AND (delete_enum IS NULL OR delete_enum = 'FALSE')
          AND finds_terminal_no = #{terminalNo}
    </update>
    <update id="clearTerminalBinding">
        UPDATE personnel_match
        SET finds_terminal_no = NULL, location_status = 'OFFLINE', finds_device_status = 'OFFLINE',
            location_status_time = #{syncTime}, version = version + 1
        WHERE source_config_code = #{sourceConfigCode}
          AND (delete_enum IS NULL OR delete_enum = 'FALSE')
          AND finds_terminal_no = #{terminalNo}
          AND (#{currentStaffNo} IS NULL OR finds_staff_no &lt;&gt; #{currentStaffNo})
    </update>
    <update id="bindTerminal">
        UPDATE personnel_match
        SET finds_terminal_no = #{terminalNo}, version = version + 1
        WHERE source_config_code = #{sourceConfigCode}
          AND (delete_enum IS NULL OR delete_enum = 'FALSE')
          AND match_status &lt;&gt; 'DISABLED'
          AND finds_staff_no = #{staffNo}
          AND (finds_terminal_no IS NULL OR finds_terminal_no &lt;&gt; #{terminalNo})
    </update>
    <update id="markStaleOffline">
        UPDATE personnel_match SET location_status = 'OFFLINE', finds_device_status = 'OFFLINE',
            location_status_time = #{syncTime}, version = version + 1
        WHERE source_config_code = #{sourceConfigCode}
          AND (delete_enum IS NULL OR delete_enum = 'FALSE')
          AND location_status = 'ONLINE'
          AND (location_status_time IS NULL OR location_status_time &lt; #{syncTime})
    </update>

    <sql id="localPersonSelect">
        SELECT u.id AS user_id, u.username AS local_staff_no, u.name AS staff_name,
               TRIM(u.phone) AS mobile_no, u.user_id_card AS id_card_no, ci.corpinfo_id,
               ci.corp_name AS corpinfo_name, ci.code AS credit_code, ci.port_area,
               u.department_id, d.dept_name AS department_name
        FROM user_scope_v u
        LEFT JOIN corp_info ci ON ci.id = u.corpinfo_id
        LEFT JOIN department d ON d.id = u.department_id
            AND (d.delete_enum IS NULL OR d.delete_enum = 'FALSE')
        WHERE (u.delete_enum IS NULL OR u.delete_enum = 'FALSE')
    </sql>
    <select id="listPeopleByPhones" resultType="com.zcloud.personnel.positioning.persistence.dataobject.PersonnelLocalPersonDO">
        <include refid="localPersonSelect"/>
        AND TRIM(u.phone) IN
        <foreach collection="values" item="value" open="(" separator="," close=")">#{value}</foreach>
        ORDER BY u.id DESC
    </select>
    <select id="listAllPeople" resultType="com.zcloud.personnel.positioning.persistence.dataobject.PersonnelLocalPersonDO">
        <include refid="localPersonSelect"/>
        ORDER BY u.id DESC
    </select>
    <select id="listPeopleByTerminalNos" resultType="com.zcloud.personnel.positioning.persistence.dataobject.PersonnelLocalPersonDO">
        SELECT DISTINCT t.terminal_no, u.id AS user_id, u.username AS local_staff_no, u.name AS staff_name,
               TRIM(u.phone) AS mobile_no, u.user_id_card AS id_card_no, ci.corpinfo_id,
               ci.corp_name AS corpinfo_name, ci.code AS credit_code, ci.port_area,
               u.department_id, d.dept_name AS department_name
        FROM terminal t
        LEFT JOIN terminal_bind tb ON tb.terminal_id = t.id AND tb.bind_status = 'BOUND'
            AND (tb.delete_enum IS NULL OR tb.delete_enum = 'FALSE')
        JOIN user_scope_v u ON u.user_id_card = COALESCE(NULLIF(tb.id_card_no, ''), NULLIF(t.bind_id_card_no, ''))
        LEFT JOIN corp_info ci ON ci.id = u.corpinfo_id
        LEFT JOIN department d ON d.id = u.department_id
            AND (d.delete_enum IS NULL OR d.delete_enum = 'FALSE')
        WHERE (t.delete_enum IS NULL OR t.delete_enum = 'FALSE')
          AND (u.delete_enum IS NULL OR u.delete_enum = 'FALSE')
          AND t.terminal_no IN
          <foreach collection="values" item="value" open="(" separator="," close=")">#{value}</foreach>
        ORDER BY t.terminal_no, u.id DESC
    </select>
    <select id="listTerminalBindingsByIdCardNos" resultType="com.zcloud.personnel.positioning.persistence.dataobject.TerminalBindingSnapshotDO">
        SELECT COALESCE(NULLIF(TRIM(tb.id_card_no), ''), NULLIF(TRIM(t.bind_id_card_no), '')) AS id_card_no,
               t.terminal_no
        FROM terminal t
        LEFT JOIN terminal_bind tb ON tb.id = (
            SELECT tb2.id FROM terminal_bind tb2 WHERE tb2.terminal_no = t.terminal_no
              AND tb2.bind_status = 'BOUND'
              AND (tb2.delete_enum IS NULL OR tb2.delete_enum = 'FALSE')
            ORDER BY tb2.bind_time DESC, tb2.id DESC LIMIT 1)
        WHERE (t.delete_enum IS NULL OR t.delete_enum = 'FALSE')
          AND COALESCE(NULLIF(TRIM(tb.id_card_no), ''), NULLIF(TRIM(t.bind_id_card_no), '')) IN
          <foreach collection="values" item="value" open="(" separator="," close=")">#{value}</foreach>
        ORDER BY id_card_no, t.update_time DESC, t.id DESC
    </select>
    <select id="listTerminals" resultType="com.zcloud.personnel.positioning.persistence.dataobject.TerminalLocationSnapshotDO">
        SELECT terminal_no, device_type, device_status, last_location_time, last_location_name
        FROM terminal WHERE (delete_enum IS NULL OR delete_enum = 'FALSE')
          AND terminal_no IN
          <foreach collection="values" item="value" open="(" separator="," close=")">#{value}</foreach>
        ORDER BY update_time DESC, id DESC
    </select>
    <select id="listMatched" resultType="com.zcloud.personnel.positioning.persistence.dataobject.PersonnelMappingSnapshotDO">
        SELECT pm.finds_staff_no, pm.finds_staff_no_type, pm.finds_id_card_no,
               pm.finds_staff_name, pm.finds_corpinfo_id, pm.finds_corpinfo_name,
               pm.finds_department_name, pm.finds_terminal_no, pm.location_status,
               pm.finds_device_status, u.id AS user_id, u.username AS local_staff_no,
               u.name AS staff_name, TRIM(u.phone) AS mobile_no, u.user_id_card AS id_card_no,
               ci.corpinfo_id, ci.corp_name AS corpinfo_name, ci.code AS credit_code, ci.port_area,
               u.department_id, d.dept_name AS department_name
        FROM personnel_match pm JOIN user_scope_v u ON u.id = pm.local_user_id
        LEFT JOIN corp_info ci ON ci.id = u.corpinfo_id
        LEFT JOIN department d ON d.id = u.department_id
            AND (d.delete_enum IS NULL OR d.delete_enum = 'FALSE')
        WHERE pm.match_status = 'MATCHED'
          AND (pm.delete_enum IS NULL OR pm.delete_enum = 'FALSE')
          AND (u.delete_enum IS NULL OR u.delete_enum = 'FALSE')
        <if test="params.userId != null">AND u.id = #{params.userId}</if>
        <if test="params.staffName != null and params.staffName != ''">AND u.name LIKE CONCAT('%', #{params.staffName}, '%')</if>
        <if test="params.corpinfoId != null">AND CAST(ci.corpinfo_id AS CHAR) = #{params.corpinfoId}</if>
        <if test="params.corpinfoName != null and params.corpinfoName != ''">AND ci.corp_name LIKE CONCAT('%', #{params.corpinfoName}, '%')</if>
        <if test="params.departmentId != null">AND u.department_id = #{params.departmentId}</if>
        <if test="params.departmentName != null and params.departmentName != ''">AND d.dept_name LIKE CONCAT('%', #{params.departmentName}, '%')</if>
        ORDER BY u.id DESC, pm.finds_staff_no
    </select>

    <select id="listMatchedPersonCompanies"
            resultType="com.zcloud.personnel.positioning.persistence.dataobject.CorpInfoSnapshotDO">
        SELECT DISTINCT CAST(ci.corpinfo_id AS CHAR) AS corpinfo_id, ci.corp_name
        FROM personnel_match pm
        INNER JOIN user_scope_v u ON u.id = pm.local_user_id
        INNER JOIN corp_info ci ON ci.id = u.corpinfo_id
        WHERE pm.match_status = 'MATCHED'
          AND (pm.delete_enum IS NULL OR pm.delete_enum = 'FALSE')
          AND (u.delete_enum IS NULL OR u.delete_enum = 'FALSE')
        <choose>
            <when test="params.idCardNo != null and params.idCardNo != ''">
                AND pm.finds_id_card_no = #{params.idCardNo}
            </when>
            <when test="params.staffNo != null and params.staffNo != ''">
                AND pm.finds_staff_no = #{params.staffNo}
            </when>
            <otherwise>AND pm.finds_staff_name = #{params.staffName}</otherwise>
        </choose>
    </select>

    <select id="listLocalPersonCompanies"
            resultType="com.zcloud.personnel.positioning.persistence.dataobject.CorpInfoSnapshotDO">
        SELECT DISTINCT CAST(ci.corpinfo_id AS CHAR) AS corpinfo_id, ci.corp_name
        FROM user_scope_v u
        INNER JOIN corp_info ci ON ci.id = u.corpinfo_id
        WHERE (u.delete_enum IS NULL OR u.delete_enum = 'FALSE')
          AND (ci.delete_enum IS NULL OR ci.delete_enum = 'FALSE')
        <choose>
            <when test="params.idCardNo != null and params.idCardNo != ''">
                AND u.user_id_card = #{params.idCardNo}
            </when>
            <when test="params.staffNo != null and params.staffNo != ''">
                AND u.username = #{params.staffNo}
            </when>
            <otherwise>AND u.name = #{params.staffName}</otherwise>
        </choose>
    </select>

    <select id="listTerminalCompanies"
            resultType="com.zcloud.personnel.positioning.persistence.dataobject.CorpInfoSnapshotDO">
        SELECT DISTINCT CAST(corpinfo_id AS CHAR) AS corpinfo_id, corpinfo_name AS corp_name
        FROM terminal
        WHERE terminal_no = #{terminalNo}
          AND corpinfo_id IS NOT NULL AND corpinfo_id != '0'
          AND (delete_enum IS NULL OR delete_enum = 'FALSE')
    </select>
</mapper>
