436 lines
17 KiB
XML
436 lines
17 KiB
XML
<?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.openhis.appointmentmanage.mapper.ScheduleSlotMapper">
|
||
|
||
<!-- 统一状态值(兼容数字/英文字符串存储),输出 Integer,避免 resultType 映射 NumberFormatException -->
|
||
<sql id="slotStatusNormExpr">
|
||
CASE
|
||
WHEN LOWER(CONCAT('', s.status)) IN ('0', 'unbooked', 'available') THEN 0
|
||
WHEN LOWER(CONCAT('', s.status)) IN ('1', 'booked') THEN 1
|
||
WHEN LOWER(CONCAT('', s.status)) IN ('2', 'cancelled', 'canceled', 'stopped') THEN 2
|
||
WHEN LOWER(CONCAT('', s.status)) IN ('3', 'checked', 'checked_in', 'checkin') THEN 3
|
||
WHEN LOWER(CONCAT('', s.status)) IN ('4', 'locked') THEN 4
|
||
WHEN LOWER(CONCAT('', s.status)) IN ('5', 'returned') THEN 5
|
||
ELSE NULL
|
||
END
|
||
</sql>
|
||
|
||
<sql id="orderStatusNormExpr">
|
||
CASE
|
||
WHEN LOWER(CONCAT('', o.status)) IN ('1', 'booked') THEN 1
|
||
WHEN LOWER(CONCAT('', o.status)) IN ('2', 'checked', 'checked_in', 'checkin') THEN 2
|
||
WHEN LOWER(CONCAT('', o.status)) IN ('3', 'cancelled', 'canceled') THEN 3
|
||
WHEN LOWER(CONCAT('', o.status)) IN ('4', 'returned') THEN 4
|
||
ELSE NULL
|
||
END
|
||
</sql>
|
||
|
||
<sql id="poolStatusNormExpr">
|
||
CASE
|
||
WHEN LOWER(CONCAT('', p.status)) IN ('0', 'unbooked', 'available') THEN 0
|
||
WHEN LOWER(CONCAT('', p.status)) IN ('1', 'booked') THEN 1
|
||
WHEN LOWER(CONCAT('', p.status)) IN ('2', 'cancelled', 'canceled', 'stopped') THEN 2
|
||
WHEN LOWER(CONCAT('', p.status)) IN ('3', 'checked', 'checked_in', 'checkin') THEN 3
|
||
WHEN LOWER(CONCAT('', p.status)) IN ('4', 'locked') THEN 4
|
||
WHEN LOWER(CONCAT('', p.status)) IN ('5', 'returned') THEN 5
|
||
ELSE NULL
|
||
END
|
||
</sql>
|
||
|
||
<!-- 注意这里的 resultType 指向了您刚建好的 DTO 实体类 -->
|
||
<select id="selectAllTicketSlots" resultType="com.openhis.appointmentmanage.domain.TicketSlotDTO">
|
||
SELECT
|
||
s.id AS slotId,
|
||
s.seq_no AS seqNo,
|
||
p.schedule_id AS scheduleId,
|
||
p.doctor_name AS doctor,
|
||
p.dept_id AS departmentId,
|
||
p.fee AS fee,
|
||
o.patient_id AS patientId,
|
||
o.patient_name AS patientName,
|
||
o.medical_card AS medicalCard,
|
||
o.phone AS phone,
|
||
<include refid="orderStatusNormExpr" /> AS orderStatus,
|
||
<include refid="slotStatusNormExpr" /> AS slotStatus,
|
||
s.expect_time AS expectTime,
|
||
p.schedule_date AS scheduleDate,
|
||
d.reg_type AS regType,
|
||
<include refid="poolStatusNormExpr" /> AS poolStatus,
|
||
p.stop_reason AS stopReason,
|
||
d.is_stopped AS isStopped
|
||
FROM
|
||
adm_schedule_slot s
|
||
INNER JOIN adm_schedule_pool p ON s.pool_id = p.id
|
||
LEFT JOIN adm_doctor_schedule d ON p.schedule_id = d.id
|
||
LEFT JOIN (
|
||
SELECT DISTINCT
|
||
ON (slot_id) slot_id,
|
||
patient_id,
|
||
patient_name,
|
||
medical_card,
|
||
phone,
|
||
status
|
||
FROM
|
||
order_main
|
||
WHERE
|
||
LOWER(CONCAT('', status)) IN ('1', '2', '4', 'booked', 'checked', 'checked_in', 'checkin', 'returned')
|
||
ORDER BY
|
||
slot_id,
|
||
create_time DESC
|
||
) o ON o.slot_id = s.id
|
||
WHERE
|
||
p.delete_flag = '0'
|
||
AND s.delete_flag = '0'
|
||
ORDER BY
|
||
p.schedule_date,
|
||
p.doctor_id,
|
||
s.expect_time,
|
||
s.seq_no ASC
|
||
</select>
|
||
|
||
<select id="selectTicketSlotById" resultType="com.openhis.appointmentmanage.domain.TicketSlotDTO">
|
||
SELECT
|
||
s.id AS slotId,
|
||
s.seq_no AS seqNo,
|
||
p.schedule_id AS scheduleId,
|
||
p.doctor_name AS doctor,
|
||
p.doctor_id AS doctorId,
|
||
p.dept_id AS departmentId,
|
||
org.name AS departmentName,
|
||
p.fee AS fee,
|
||
o.patient_id AS patientId,
|
||
o.patient_name AS patientName,
|
||
o.medical_card AS medicalCard,
|
||
o.phone AS phone,
|
||
o.id AS orderId,
|
||
o.order_no AS orderNo,
|
||
COALESCE(CAST(o.gender AS VARCHAR), CAST(pinfo.gender_enum AS VARCHAR)) AS patientGender,
|
||
pinfo.gender_enum AS genderEnum,
|
||
pinfo.id_card AS idCard,
|
||
o.appointment_time AS appointmentTime,
|
||
<include refid="orderStatusNormExpr" /> AS orderStatus,
|
||
<include refid="slotStatusNormExpr" /> AS slotStatus,
|
||
s.expect_time AS expectTime,
|
||
p.schedule_date AS scheduleDate,
|
||
d.reg_type AS regType,
|
||
<include refid="poolStatusNormExpr" /> AS poolStatus,
|
||
p.stop_reason AS stopReason,
|
||
d.is_stopped AS isStopped
|
||
FROM
|
||
adm_schedule_slot s
|
||
INNER JOIN adm_schedule_pool p ON s.pool_id = p.id
|
||
LEFT JOIN adm_doctor_schedule d ON p.schedule_id = d.id
|
||
LEFT JOIN adm_organization org ON p.dept_id = org.id
|
||
AND org.delete_flag = '0'
|
||
LEFT JOIN (
|
||
SELECT DISTINCT
|
||
ON (slot_id) slot_id,
|
||
patient_id,
|
||
patient_name,
|
||
medical_card,
|
||
phone,
|
||
id,
|
||
order_no,
|
||
gender,
|
||
appointment_time,
|
||
status
|
||
FROM
|
||
order_main
|
||
WHERE
|
||
LOWER(CONCAT('', status)) IN ('1', '2', '4', 'booked', 'checked', 'checked_in', 'checkin', 'returned')
|
||
ORDER BY
|
||
slot_id,
|
||
create_time DESC
|
||
) o ON o.slot_id = s.id
|
||
LEFT JOIN adm_patient pinfo ON o.patient_id = pinfo.id
|
||
WHERE
|
||
s.id = #{id}
|
||
</select>
|
||
|
||
<update id="lockSlotForBooking">
|
||
UPDATE adm_schedule_slot
|
||
SET
|
||
status = 1,
|
||
update_time = now()
|
||
WHERE
|
||
id = #{slotId}
|
||
AND status = 0
|
||
AND delete_flag = '0'
|
||
</update>
|
||
|
||
<update id="updateSlotStatus">
|
||
UPDATE adm_schedule_slot
|
||
SET
|
||
status = #{status},
|
||
<if test="status != null and '0'.equals(status.toString())">
|
||
order_id = NULL,
|
||
</if>
|
||
update_time = now()
|
||
WHERE
|
||
id = #{slotId}
|
||
AND delete_flag = '0'
|
||
</update>
|
||
|
||
<update id="updateSlotStatusAndCheckInTime">
|
||
UPDATE adm_schedule_slot
|
||
SET
|
||
status = #{status},
|
||
check_in_time = #{checkInTime},
|
||
update_time = NOW()
|
||
WHERE
|
||
id = #{slotId}
|
||
AND delete_flag = '0'
|
||
</update>
|
||
|
||
<select id="selectPoolIdBySlotId" resultType="java.lang.Long">
|
||
SELECT
|
||
pool_id
|
||
FROM
|
||
adm_schedule_slot
|
||
WHERE
|
||
id = #{slotId}
|
||
AND delete_flag = '0'
|
||
</select>
|
||
|
||
<update id="bindOrderToSlot">
|
||
UPDATE adm_schedule_slot
|
||
SET
|
||
order_id = #{orderId},
|
||
update_time = now()
|
||
WHERE
|
||
id = #{slotId}
|
||
AND status = 1
|
||
AND delete_flag = '0'
|
||
</update>
|
||
|
||
<select id="selectTicketSlotsPage" resultType="com.openhis.appointmentmanage.domain.TicketSlotDTO">
|
||
SELECT
|
||
s.id AS slotId,
|
||
s.seq_no AS seqNo,
|
||
p.schedule_id AS scheduleId,
|
||
p.doctor_name AS doctor,
|
||
p.doctor_id AS doctorId,
|
||
p.dept_id AS departmentId,
|
||
org.name AS departmentName,
|
||
p.fee AS fee,
|
||
o.patient_id AS patientId,
|
||
o.patient_name AS patientName,
|
||
o.medical_card AS medicalCard,
|
||
o.phone AS phone,
|
||
o.id AS orderId,
|
||
o.order_no AS orderNo,
|
||
COALESCE(CAST(o.gender AS VARCHAR), CAST(pinfo.gender_enum AS VARCHAR)) AS patientGender,
|
||
pinfo.gender_enum AS genderEnum,
|
||
pinfo.id_card AS idCard,
|
||
o.appointment_time AS appointmentTime,
|
||
<include refid="orderStatusNormExpr" /> AS orderStatus,
|
||
<include refid="slotStatusNormExpr" /> AS slotStatus,
|
||
s.expect_time AS expectTime,
|
||
p.schedule_date AS scheduleDate,
|
||
d.reg_type AS regType,
|
||
<include refid="poolStatusNormExpr" /> AS poolStatus,
|
||
p.stop_reason AS stopReason,
|
||
d.is_stopped AS isStopped
|
||
FROM
|
||
adm_schedule_slot s
|
||
INNER JOIN adm_schedule_pool p ON s.pool_id = p.id
|
||
LEFT JOIN adm_doctor_schedule d ON p.schedule_id = d.id
|
||
LEFT JOIN adm_organization org ON p.dept_id = org.id
|
||
AND org.delete_flag = '0'
|
||
LEFT JOIN (
|
||
SELECT DISTINCT
|
||
ON (slot_id) slot_id,
|
||
patient_id,
|
||
patient_name,
|
||
medical_card,
|
||
phone,
|
||
id,
|
||
order_no,
|
||
gender,
|
||
appointment_time,
|
||
status
|
||
FROM
|
||
order_main
|
||
WHERE
|
||
LOWER(CONCAT('', status)) IN ('1', '2', '4', 'booked', 'checked', 'checked_in', 'checkin', 'returned')
|
||
ORDER BY
|
||
slot_id,
|
||
create_time DESC
|
||
) o ON o.slot_id = s.id
|
||
LEFT JOIN adm_patient pinfo ON o.patient_id = pinfo.id
|
||
<where>
|
||
p.delete_flag = '0'
|
||
AND s.delete_flag = '0'
|
||
<!-- 1. 按日期查 -->
|
||
<if test="query.date != null and query.date != ''">
|
||
AND p.schedule_date = CAST(#{query.date} AS DATE)
|
||
</if>
|
||
<!-- 2. 按科室查 -->
|
||
<if test="query.department != null and query.department != '' and query.department != 'all'">
|
||
AND org.name = #{query.department}
|
||
</if>
|
||
<if test="query.doctorId != null">
|
||
AND p.doctor_id = #{query.doctorId}
|
||
</if>
|
||
<!-- 3. 按号源类型查 (专家/普通) -->
|
||
<if test="query.type != null and query.type != ''">
|
||
<choose>
|
||
<when test="query.type == 'expert'">
|
||
AND d.reg_type = 1
|
||
</when>
|
||
<when test="query.type == 'general'">
|
||
AND (
|
||
d.reg_type != 1
|
||
OR d.reg_type IS NULL
|
||
)
|
||
</when>
|
||
</choose>
|
||
</if>
|
||
<!-- 4. 模糊搜索患者信息 -->
|
||
<if test="query.name != null and query.name != ''">
|
||
AND o.patient_name LIKE CONCAT('%', #{query.name}, '%')
|
||
</if>
|
||
<if test="query.card != null and query.card != ''">
|
||
AND o.medical_card LIKE CONCAT('%', #{query.card}, '%')
|
||
</if>
|
||
<if test="query.phone != null and query.phone != ''">
|
||
AND o.phone LIKE CONCAT('%', #{query.phone}, '%')
|
||
</if>
|
||
<!-- 5. 核心:按系统时间过滤,只返回未过期的号源 -->
|
||
AND (p.schedule_date > CURRENT_DATE OR (p.schedule_date = CURRENT_DATE AND s.expect_time >= CURRENT_TIME::TIME))
|
||
<!-- 6. 状态过滤 -->
|
||
<if test="query.status != null and query.status != '' and query.status != 'all'">
|
||
<choose>
|
||
<when test="'unbooked'.equals(query.status) or '未预约'.equals(query.status)">
|
||
AND <include refid="slotStatusNormExpr" /> = 0
|
||
AND (
|
||
d.is_stopped IS NULL
|
||
OR d.is_stopped = FALSE
|
||
)
|
||
</when>
|
||
<when test="'booked'.equals(query.status) or '已预约'.equals(query.status)">
|
||
AND <include refid="slotStatusNormExpr" /> = 1
|
||
AND <include refid="orderStatusNormExpr" /> = 1
|
||
AND (
|
||
d.is_stopped IS NULL
|
||
OR d.is_stopped = FALSE
|
||
)
|
||
</when>
|
||
<when test="'checked'.equals(query.status) or '已取号'.equals(query.status)">
|
||
AND (
|
||
<include refid="slotStatusNormExpr" /> = 3
|
||
OR (
|
||
<include refid="slotStatusNormExpr" /> = 1
|
||
AND <include refid="orderStatusNormExpr" /> = 2
|
||
)
|
||
)
|
||
AND (
|
||
d.is_stopped IS NULL
|
||
OR d.is_stopped = FALSE
|
||
)
|
||
</when>
|
||
<when test="'cancelled'.equals(query.status) or '已停诊'.equals(query.status) or '已取消'.equals(query.status)">
|
||
AND (
|
||
<include refid="slotStatusNormExpr" /> = 2
|
||
OR d.is_stopped = TRUE
|
||
)
|
||
</when>
|
||
<when test="'returned'.equals(query.status) or '已退号'.equals(query.status)">
|
||
AND (
|
||
<include refid="slotStatusNormExpr" /> = 5
|
||
OR <include refid="orderStatusNormExpr" /> = 4
|
||
)
|
||
</when>
|
||
<otherwise>
|
||
AND 1 = 2
|
||
</otherwise>
|
||
</choose>
|
||
</if>
|
||
</where>
|
||
ORDER BY
|
||
p.schedule_date DESC,
|
||
s.expect_time ASC,
|
||
s.seq_no ASC
|
||
</select>
|
||
|
||
<select id="selectDoctorAvailabilitySummary" resultType="com.openhis.appointmentmanage.domain.DoctorAvailabilityDTO">
|
||
SELECT
|
||
p.doctor_id AS doctorId,
|
||
p.doctor_name AS doctorName,
|
||
p.schedule_date AS scheduleDate,
|
||
<!-- 直接 COUNT 未预约的号源,前端已经做了时间过滤,这里只按日期统计 -->
|
||
COUNT(
|
||
CASE
|
||
WHEN s.delete_flag = '0'
|
||
AND <include refid="slotStatusNormExpr" /> = 0
|
||
<!-- 使用前端传来的当前时间戳过滤过期号源,保证和前端完全一致 -->
|
||
AND (
|
||
p.schedule_date > CURRENT_DATE
|
||
OR (
|
||
p.schedule_date = CURRENT_DATE
|
||
AND CAST(p.schedule_date AS TIMESTAMP) + CAST(s.expect_time AS TIME) > TO_TIMESTAMP(#{query.currentTime}/1000)
|
||
)
|
||
)
|
||
THEN s.id
|
||
ELSE NULL
|
||
END
|
||
) AS available,
|
||
COUNT(DISTINCT p.id) AS poolCount,
|
||
CASE
|
||
WHEN MAX(
|
||
CASE
|
||
WHEN d.reg_type = 1 THEN 1
|
||
ELSE 0
|
||
END
|
||
) = 1 THEN 'expert'
|
||
ELSE 'general'
|
||
END AS ticketType
|
||
FROM
|
||
adm_schedule_pool p
|
||
LEFT JOIN adm_doctor_schedule d ON p.schedule_id = d.id
|
||
LEFT JOIN adm_organization org ON p.dept_id = org.id AND org.delete_flag = '0'
|
||
LEFT JOIN adm_schedule_slot s ON s.pool_id = p.id AND s.delete_flag = '0'
|
||
<where>
|
||
p.delete_flag = '0'
|
||
<!-- 排除医生已停诊的号源 -->
|
||
AND (d.is_stopped IS NULL OR d.is_stopped = FALSE)
|
||
<!-- 过滤未来号源:只统计当前日期及未来日期的号源 -->
|
||
<if test="query.date != null and query.date != ''">
|
||
AND p.schedule_date = CAST(#{query.date} AS DATE)
|
||
</if>
|
||
<!-- 增加时间过滤:排除已过去的就诊日期 -->
|
||
AND p.schedule_date >= CURRENT_DATE
|
||
<if test="query.department != null and query.department != '' and query.department != 'all'">
|
||
AND org.name = #{query.department}
|
||
</if>
|
||
<if test="query.type != null and query.type != '' and query.type != 'all'">
|
||
<choose>
|
||
<when test="query.type == 'expert'">
|
||
AND d.reg_type = 1
|
||
</when>
|
||
<when test="query.type == 'general'">
|
||
AND (
|
||
d.reg_type != 1
|
||
OR d.reg_type IS NULL
|
||
)
|
||
</when>
|
||
</choose>
|
||
</if>
|
||
<if test="query.doctorId != null">
|
||
AND p.doctor_id = #{query.doctorId}
|
||
</if>
|
||
</where>
|
||
GROUP BY
|
||
p.doctor_id,
|
||
p.doctor_name,
|
||
p.schedule_date
|
||
ORDER BY
|
||
p.schedule_date ASC,
|
||
p.doctor_name ASC
|
||
</select>
|
||
|
||
|
||
</mapper>
|