挂号补单功能的完善

This commit is contained in:
2026-01-20 09:31:37 +08:00
parent 649f7bcf5b
commit d1223aec07
27 changed files with 4875 additions and 307 deletions

View File

@@ -0,0 +1,45 @@
-- 智能分诊排队:候选池排除记录表
-- 用途:记录已从智能候选池中移除的患者(加入队列后不再出现在候选池)
-- 注意:必须在后端实际连接的 schema 中执行dev环境是 hisdevtest环境是 histestprd环境是 hisprd
-- 执行前请先确认SET search_path TO hisdev; (或对应的 schema
CREATE TABLE IF NOT EXISTS hisdev.triage_candidate_exclusion (
id BIGSERIAL PRIMARY KEY,
tenant_id INTEGER NOT NULL,
exclusion_date DATE NOT NULL,
encounter_id BIGINT NOT NULL,
patient_id BIGINT,
patient_name VARCHAR(255),
organization_id BIGINT,
organization_name VARCHAR(255),
reason VARCHAR(100) DEFAULT 'ADDED_TO_QUEUE', -- 排除原因ADDED_TO_QUEUE加入队列、MANUAL_REMOVE手动移除
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
delete_flag CHAR(1) NOT NULL DEFAULT '0'
);
-- 常用查询索引:按租户/日期/就诊记录查询
CREATE INDEX IF NOT EXISTS idx_triage_candidate_exclusion_list
ON hisdev.triage_candidate_exclusion (tenant_id, exclusion_date, delete_flag, encounter_id);
-- 防重复:同一天同租户同就诊记录只能有一条排除记录(未删除)
CREATE UNIQUE INDEX IF NOT EXISTS uq_triage_candidate_exclusion_encounter
ON hisdev.triage_candidate_exclusion (tenant_id, exclusion_date, encounter_id, delete_flag)
WHERE delete_flag = '0';
-- 就诊记录ID索引用于关联查询
CREATE INDEX IF NOT EXISTS idx_triage_candidate_exclusion_encounter_id
ON hisdev.triage_candidate_exclusion (encounter_id);
-- 注释
COMMENT ON TABLE hisdev.triage_candidate_exclusion IS '智能分诊排队候选池排除记录表';
COMMENT ON COLUMN hisdev.triage_candidate_exclusion.tenant_id IS '租户ID';
COMMENT ON COLUMN hisdev.triage_candidate_exclusion.exclusion_date IS '排除日期(通常为当天)';
COMMENT ON COLUMN hisdev.triage_candidate_exclusion.encounter_id IS '就诊记录ID唯一标识';
COMMENT ON COLUMN hisdev.triage_candidate_exclusion.patient_id IS '患者ID';
COMMENT ON COLUMN hisdev.triage_candidate_exclusion.patient_name IS '患者姓名';
COMMENT ON COLUMN hisdev.triage_candidate_exclusion.organization_id IS '科室ID';
COMMENT ON COLUMN hisdev.triage_candidate_exclusion.organization_name IS '科室名称';
COMMENT ON COLUMN hisdev.triage_candidate_exclusion.reason IS '排除原因ADDED_TO_QUEUE加入队列、MANUAL_REMOVE手动移除';
COMMENT ON COLUMN hisdev.triage_candidate_exclusion.delete_flag IS '删除标志0-未删除1-已删除';

View File

@@ -0,0 +1,35 @@
-- 智能分诊排队:队列持久化表(与 TriageQueueItem.java 字段一致)
-- 注意:必须在后端实际连接的 schema 中执行dev环境是 hisdevtest环境是 histestprd环境是 hisprd
-- 执行前请先确认SET search_path TO hisdev; (或对应的 schema
CREATE TABLE IF NOT EXISTS triage_queue_item (
id BIGSERIAL PRIMARY KEY,
tenant_id INTEGER NOT NULL,
queue_date DATE NOT NULL,
organization_id BIGINT NOT NULL,
organization_name VARCHAR(255),
encounter_id BIGINT NOT NULL,
patient_id BIGINT,
patient_name VARCHAR(255),
healthcare_name VARCHAR(255),
practitioner_name VARCHAR(255),
status VARCHAR(50) NOT NULL, -- WAITING/CALLING/SKIPPED/COMPLETED
queue_order INTEGER NOT NULL,
create_time TIMESTAMP,
update_time TIMESTAMP,
delete_flag CHAR(1) NOT NULL DEFAULT '0'
);
-- 常用查询索引:按租户/科室/日期/状态/顺序取队列
CREATE INDEX IF NOT EXISTS idx_triage_queue_item_list
ON triage_queue_item (tenant_id, queue_date, organization_id, delete_flag, status, queue_order);
-- 防重复:同一天同租户同科室同就诊记录只能在队列里一条(未删除)
CREATE UNIQUE INDEX IF NOT EXISTS uq_triage_queue_item_encounter
ON triage_queue_item (tenant_id, queue_date, organization_id, encounter_id, delete_flag)
WHERE delete_flag = '0';
-- 就诊记录ID索引用于关联查询
CREATE INDEX IF NOT EXISTS idx_triage_queue_item_encounter_id
ON triage_queue_item (encounter_id);

View File

@@ -0,0 +1,108 @@
-- ============================================
-- 调试队列日期问题
-- 用途:检查数据库中的 queue_date 字段值,找出为什么查询不到数据
-- ============================================
-- 1. 查看所有队列记录的日期分布
SELECT
queue_date,
status,
COUNT(*) AS count,
STRING_AGG(patient_name, ', ') AS patients
FROM hisdev.triage_queue_item
WHERE tenant_id = 1
AND delete_flag = '0'
GROUP BY queue_date, status
ORDER BY queue_date DESC, status;
-- 2. 查看指定科室的所有记录(不限制日期)
SELECT
id,
queue_date,
status,
patient_name,
organization_id,
organization_name,
queue_order,
create_time
FROM hisdev.triage_queue_item
WHERE tenant_id = 1
AND delete_flag = '0'
AND organization_id = 1995302136614969300
ORDER BY queue_date DESC, queue_order ASC;
-- 3. 查看今天的记录(使用 CURRENT_DATE
SELECT
id,
queue_date,
status,
patient_name,
organization_id,
queue_order
FROM hisdev.triage_queue_item
WHERE tenant_id = 1
AND delete_flag = '0'
AND queue_date = CURRENT_DATE
AND organization_id = 1995302136614969300
ORDER BY queue_order ASC;
-- 4. 查看 2026-01-16 的记录
SELECT
id,
queue_date,
status,
patient_name,
organization_id,
queue_order
FROM hisdev.triage_queue_item
WHERE tenant_id = 1
AND delete_flag = '0'
AND queue_date = '2026-01-16'::DATE
AND organization_id = 1995302136614969300
ORDER BY queue_order ASC;
-- 5. 查看 2025-01-16 的记录(可能是昨天的数据)
SELECT
id,
queue_date,
status,
patient_name,
organization_id,
queue_order
FROM hisdev.triage_queue_item
WHERE tenant_id = 1
AND delete_flag = '0'
AND queue_date = '2025-01-16'::DATE
AND organization_id = 1995302136614969300
ORDER BY queue_order ASC;
-- 6. 查看最近的记录最近7天
SELECT
queue_date,
status,
COUNT(*) AS count
FROM hisdev.triage_queue_item
WHERE tenant_id = 1
AND delete_flag = '0'
AND queue_date >= CURRENT_DATE - INTERVAL '7 days'
GROUP BY queue_date, status
ORDER BY queue_date DESC, status;
-- 7. 检查系统当前日期PostgreSQL
SELECT CURRENT_DATE AS current_date_in_db;
-- 8. 查看所有状态为 WAITING 或 SKIPPED 的记录(不限制日期)
SELECT
id,
queue_date,
status,
patient_name,
organization_id,
queue_order
FROM hisdev.triage_queue_item
WHERE tenant_id = 1
AND delete_flag = '0'
AND status IN ('WAITING', 'SKIPPED')
AND organization_id = 1995302136614969300
ORDER BY queue_date DESC, queue_order ASC;

View File

@@ -0,0 +1,313 @@
-- ============================================
-- 智能候选池查询SQL当日已挂号患者
-- 对应接口GET /charge-manage/register/current-day-encounter
-- 用途:查询当日已挂号但未入队的患者,用于智能分诊排队管理
-- ============================================
-- 完整SQL查询包含所有关联表
SELECT T9.tenant_id AS tenantId,
T9.encounter_id AS encounterId,
T9.display_order AS displayOrder,
T9.organization_id AS organizationId,
T9.organization_name AS organizationName,
T9.healthcare_name AS healthcareName,
T9.practitioner_user_id AS practitionerUserId,
T9.practitioner_name AS practitionerName,
T9.contract_name AS contractName,
T9.patient_id AS patientId,
T9.patient_name AS patientName,
T9.phone,
T9.gender_enum AS genderEnum,
T9.id_card AS idCard,
T9.status_enum AS statusEnum,
T9.register_time AS registerTime,
T9.total_price AS totalPrice,
T9.account_name AS accountName,
T9.enterer_name AS entererName,
T9.charge_item_ids AS chargeItemIds,
T9.payment_id AS paymentId,
T9.picture_url AS pictureUrl,
T9.birth_date AS birthDate,
COALESCE(T9.identifier_no, T9.patient_bus_no, '') AS identifierNo
FROM (
SELECT T1.tenant_id AS tenant_id,
T1.id AS encounter_id,
T1.display_order AS display_order,
T1.organization_id AS organization_id,
T2.NAME AS organization_name,
T3.NAME AS healthcare_name,
T5.user_id AS practitioner_user_id,
T5.NAME AS practitioner_name,
T7.contract_name AS contract_name,
T8.id AS patient_id,
T8.NAME AS patient_name,
T8.phone AS phone,
T8.gender_enum AS gender_enum,
T8.id_card AS id_card,
T1.status_enum AS status_enum,
T1.create_time AS register_time,
T10.total_price,
T11."name" AS account_name,
T12."name" AS enterer_name,
T13.charge_item_ids,
T13.id AS payment_id,
ai.picture_url AS picture_url,
T8.birth_date AS birth_date,
T8.bus_no AS patient_bus_no,
T18.identifier_no AS identifier_no
FROM adm_encounter AS T1
-- 关联科室表
LEFT JOIN adm_organization AS T2
ON T1.organization_id = T2.ID
AND T2.delete_flag = '0'
-- 关联医疗服务类型表(号别)
LEFT JOIN adm_healthcare_service AS T3
ON T1.service_type_id = T3.ID
AND T3.delete_flag = '0'
-- 关联就诊参与者表(医生信息)
LEFT JOIN (
SELECT *
FROM (
SELECT *,
ROW_NUMBER() OVER (PARTITION BY encounter_id ORDER BY create_time ASC) AS rn
FROM adm_encounter_participant
WHERE delete_flag = '0'
AND (
-- 如果就诊状态为"进行中",查找"接诊医生"admitter
(type_code = 'admitter' AND EXISTS(SELECT 1
FROM adm_encounter AS T1
WHERE T1.status_enum = 2 -- IN_PROGRESS
AND T1.ID = encounter_id))
OR
-- 如果就诊状态不是"进行中",查找"挂号医生"registration_doctor
(type_code = 'registration_doctor' AND NOT EXISTS(SELECT 1
FROM adm_encounter AS T1
WHERE T1.status_enum = 2 -- IN_PROGRESS
AND T1.ID = encounter_id))
)
) t
WHERE rn = 1
) AS T4 ON T1.ID = T4.encounter_id
-- 关联医生表
LEFT JOIN adm_practitioner AS T5
ON T5.ID = T4.practitioner_id
AND T5.delete_flag = '0'
-- 关联账户表
LEFT JOIN adm_account AS T6
ON T1.ID = T6.encounter_id
AND T6.delete_flag = '0'
AND T6.encounter_flag = '1'
-- 关联合同表
LEFT JOIN fin_contract AS T7
ON T6.contract_no = T7.bus_no
AND T7.delete_flag = '0'
-- 关联患者表
LEFT JOIN adm_patient AS T8
ON T1.patient_id = T8.ID
AND T8.delete_flag = '0'
-- 关联患者标识表(身份证号等)
LEFT JOIN (
SELECT patient_id,
identifier_no
FROM (
SELECT patient_id,
identifier_no,
ROW_NUMBER() OVER (PARTITION BY patient_id ORDER BY create_time ASC) AS rn
FROM adm_patient_identifier
WHERE delete_flag = '0'
AND identifier_no IS NOT NULL
AND identifier_no != ''
) t
WHERE rn = 1
) AS T18 ON T8.id = T18.patient_id
-- 关联收费项目表(挂号费)
LEFT JOIN adm_charge_item AS T10
ON T1.id = T10.encounter_id
AND T10.delete_flag = '0'
AND T10.context_enum = 1 -- REGISTER挂号
-- 关联账户表(收费账户)
LEFT JOIN adm_account AS T11
ON T10.account_id = T11.id
AND T11.delete_flag = '0'
-- 关联医生表(收费医生)
LEFT JOIN adm_practitioner AS T12
ON T12.ID = T10.enterer_id
AND T12.delete_flag = '0'
-- 关联支付对账表(已支付)
LEFT JOIN fin_payment_reconciliation T13
ON T10.id::TEXT = ANY(string_to_array(T13.charge_item_ids,','))
AND T13.delete_flag = '0'
AND T13.status_enum = 1 -- SUCCESS支付成功
-- 关联退号记录当状态为退号时通过relation_id关联原支付记录
LEFT JOIN fin_payment_reconciliation T14
ON T13.id = T14.relation_id
AND T14.delete_flag = '0'
AND T14.status_enum = 3 -- REFUND退款
AND T14.payment_enum = 1
-- 关联退号医生
LEFT JOIN adm_practitioner AS T15
ON T15.ID = T14.enterer_id
AND T15.delete_flag = '0'
-- 关联系统用户表
LEFT JOIN sys_user AS T17
ON T17.user_id = T15.user_id
AND T17.delete_flag = '0'
-- 关联退号支付详情,获取退款方式(聚合多个支付方式)
LEFT JOIN (
SELECT reconciliation_id,
STRING_AGG(
CASE pay_enum
WHEN 220400 THEN '现金'
WHEN 220100 THEN '微信'
WHEN 220200 THEN '支付宝'
WHEN 220300 THEN '银联'
END,
','
ORDER BY pay_enum
) AS refund_method
FROM fin_payment_rec_detail
WHERE delete_flag = '0'
AND amount < 0
AND pay_enum IN (220400, 220100, 220200, 220300)
GROUP BY reconciliation_id
) AS T16 ON T14.id = T16.reconciliation_id
-- 关联发票表
LEFT JOIN adm_invoice AS ai
ON ai.reconciliation_id = T13.id
AND ai.delete_flag = '0'
WHERE T1.delete_flag = '0'
AND T1.class_enum = 1 -- 门诊AMB
AND T10.context_enum = 1 -- 挂号REGISTER
-- 动态条件(由前端传入,通过 ${ew.customSqlSegment} 注入)
-- 例如AND T1.create_time::DATE = CURRENT_DATE -- 当日挂号
-- 例如AND T1.status_enum != 6 -- 排除退号statusEnum = -1时
-- 例如AND (T8.name LIKE '%关键词%' OR T2.name LIKE '%关键词%' ...) -- 模糊搜索
) AS T9
-- 动态查询条件(由 MyBatis-Plus QueryWrapper 生成)
-- ${ew.customSqlSegment}
ORDER BY T9.register_time DESC;
-- ============================================
-- 简化版查询(仅查询核心字段,用于快速测试)
-- ============================================
SELECT
enc.id AS encounterId,
enc.patient_id AS patientId,
pt.name AS patientName,
pt.birth_date AS birthDate,
org.id AS organizationId,
org.name AS organizationName,
hcs.name AS healthcareName,
pr.name AS practitionerName,
enc.create_time AS registerTime,
enc.status_enum AS statusEnum
FROM adm_encounter enc
INNER JOIN adm_patient pt
ON enc.patient_id = pt.id
AND pt.delete_flag = '0'
LEFT JOIN adm_organization org
ON enc.organization_id = org.id
AND org.delete_flag = '0'
LEFT JOIN adm_healthcare_service hcs
ON enc.service_type_id = hcs.id
AND hcs.delete_flag = '0'
LEFT JOIN (
SELECT encounter_id, practitioner_id,
ROW_NUMBER() OVER (PARTITION BY encounter_id ORDER BY create_time ASC) AS rn
FROM adm_encounter_participant
WHERE delete_flag = '0'
AND type_code IN ('admitter', 'registration_doctor')
) ep ON enc.id = ep.encounter_id AND ep.rn = 1
LEFT JOIN adm_practitioner pr
ON ep.practitioner_id = pr.id
AND pr.delete_flag = '0'
INNER JOIN adm_charge_item ci
ON enc.id = ci.encounter_id
AND ci.delete_flag = '0'
AND ci.context_enum = 1 -- 挂号
INNER JOIN fin_payment_reconciliation prc
ON ci.id::TEXT = ANY(string_to_array(prc.charge_item_ids,','))
AND prc.delete_flag = '0'
AND prc.status_enum = 1 -- 支付成功
WHERE enc.delete_flag = '0'
AND enc.class_enum = 1 -- 门诊
AND enc.create_time::DATE = CURRENT_DATE -- 当日挂号
AND enc.status_enum != 6 -- 排除退号
ORDER BY enc.create_time DESC;
-- ============================================
-- 查询条件说明
-- ============================================
-- 1. 基础条件:
-- - enc.delete_flag = '0' -- 未删除
-- - enc.class_enum = 1 -- 门诊AMB
-- - ci.context_enum = 1 -- 挂号REGISTER
-- - prc.status_enum = 1 -- 支付成功SUCCESS
--
-- 2. 日期过滤:
-- - enc.create_time::DATE = CURRENT_DATE -- 当日挂号(由前端传入 date 参数)
--
-- 3. 状态过滤:
-- - enc.status_enum != 6 -- 排除退号(当 statusEnum = -1 时)
-- - enc.status_enum = 2 -- 进行中IN_PROGRESS用于判断医生类型
--
-- 4. 模糊搜索(由前端传入 searchKey 参数):
-- - patient_name患者姓名
-- - organization_name科室名称
-- - practitioner_name医生姓名
-- - healthcare_name号别名称
-- - identifier_no身份证号
--
-- 5. 租户过滤(由后端自动添加):
-- - tenant_id = ? -- 当前登录用户的租户ID
--
-- 6. 分页(由 MyBatis-Plus Page 对象处理):
-- - LIMIT ? OFFSET ?
-- ============================================
-- 常用查询示例
-- ============================================
-- 示例1查询今天所有已挂号患者排除退号
SELECT
enc.id AS encounterId,
pt.name AS patientName,
org.name AS organizationName,
hcs.name AS healthcareName,
pr.name AS practitionerName,
enc.create_time AS registerTime
FROM adm_encounter enc
INNER JOIN adm_patient pt ON enc.patient_id = pt.id AND pt.delete_flag = '0'
LEFT JOIN adm_organization org ON enc.organization_id = org.id AND org.delete_flag = '0'
LEFT JOIN adm_healthcare_service hcs ON enc.service_type_id = hcs.id AND hcs.delete_flag = '0'
LEFT JOIN (
SELECT encounter_id, practitioner_id,
ROW_NUMBER() OVER (PARTITION BY encounter_id ORDER BY create_time ASC) AS rn
FROM adm_encounter_participant
WHERE delete_flag = '0' AND type_code IN ('admitter', 'registration_doctor')
) ep ON enc.id = ep.encounter_id AND ep.rn = 1
LEFT JOIN adm_practitioner pr ON ep.practitioner_id = pr.id AND pr.delete_flag = '0'
INNER JOIN adm_charge_item ci ON enc.id = ci.encounter_id AND ci.delete_flag = '0' AND ci.context_enum = 1
INNER JOIN fin_payment_reconciliation prc ON ci.id::TEXT = ANY(string_to_array(prc.charge_item_ids,','))
AND prc.delete_flag = '0' AND prc.status_enum = 1
WHERE enc.delete_flag = '0'
AND enc.class_enum = 1
AND enc.create_time::DATE = CURRENT_DATE
AND enc.status_enum != 6
ORDER BY enc.create_time DESC;
-- 示例2查询指定科室的已挂号患者
-- 在示例1的基础上添加
-- AND enc.organization_id = ? -- 科室ID
-- 示例3按患者姓名模糊搜索
-- 在示例1的基础上添加
-- AND pt.name LIKE '%关键词%'
-- 示例4查询已加入队列的患者用于去重
SELECT DISTINCT encounter_id
FROM hisdev.triage_queue_item
WHERE delete_flag = '0'
AND queue_date = CURRENT_DATE
AND status != 'COMPLETED';

View File

@@ -0,0 +1,268 @@
-- ============================================
-- 智能候选池查询SQL智能分诊排队管理页面专用
-- 页面:智能分诊排队管理 - 心内科
-- 用途:查询"已签到未入队"的患者(当日已挂号,但未加入队列)
-- ============================================
-- ============================================
-- 方案一:完整查询(包含所有字段,排除已在队列中的患者)
-- ============================================
SELECT
enc.id AS encounterId,
enc.patient_id AS patientId,
pt.name AS patientName,
pt.birth_date AS birthDate,
-- 计算年龄(前端会调用 parseAge 函数)
CASE
WHEN pt.birth_date IS NOT NULL THEN
EXTRACT(YEAR FROM AGE(pt.birth_date))::TEXT || ''
ELSE ''
END AS age,
org.id AS organizationId,
org.name AS organizationName,
hcs.name AS healthcareName,
pr.name AS practitionerName,
enc.create_time AS registerTime,
enc.status_enum AS statusEnum,
-- 其他字段(如果需要)
pt.phone,
pt.gender_enum AS genderEnum,
pt.id_card AS idCard
FROM adm_encounter enc
-- 关联患者表
INNER JOIN adm_patient pt
ON enc.patient_id = pt.id
AND pt.delete_flag = '0'
-- 关联科室表
LEFT JOIN adm_organization org
ON enc.organization_id = org.id
AND org.delete_flag = '0'
-- 关联医疗服务类型表(号别)
LEFT JOIN adm_healthcare_service hcs
ON enc.service_type_id = hcs.id
AND hcs.delete_flag = '0'
-- 关联就诊参与者表(医生信息)
LEFT JOIN (
SELECT encounter_id, practitioner_id,
ROW_NUMBER() OVER (PARTITION BY encounter_id ORDER BY create_time ASC) AS rn
FROM adm_encounter_participant
WHERE delete_flag = '0'
AND (
-- 如果就诊状态为"进行中",查找"接诊医生"admitter
(type_code = 'admitter' AND EXISTS(SELECT 1
FROM adm_encounter AS e
WHERE e.status_enum = 2 -- IN_PROGRESS
AND e.id = encounter_id))
OR
-- 如果就诊状态不是"进行中",查找"挂号医生"registration_doctor
(type_code = 'registration_doctor' AND NOT EXISTS(SELECT 1
FROM adm_encounter AS e
WHERE e.status_enum = 2 -- IN_PROGRESS
AND e.id = encounter_id))
)
) ep ON enc.id = ep.encounter_id AND ep.rn = 1
-- 关联医生表
LEFT JOIN adm_practitioner pr
ON ep.practitioner_id = pr.id
AND pr.delete_flag = '0'
-- 关联收费项目表(挂号费)
INNER JOIN adm_charge_item ci
ON enc.id = ci.encounter_id
AND ci.delete_flag = '0'
AND ci.context_enum = 1 -- REGISTER挂号
-- 关联支付对账表(已支付)
INNER JOIN fin_payment_reconciliation prc
ON ci.id::TEXT = ANY(string_to_array(prc.charge_item_ids,','))
AND prc.delete_flag = '0'
AND prc.status_enum = 1 -- SUCCESS支付成功
-- 排除已在队列中的患者关键LEFT JOIN + WHERE IS NULL
LEFT JOIN hisdev.triage_queue_item tqi
ON enc.id = tqi.encounter_id
AND tqi.delete_flag = '0'
AND tqi.queue_date = CURRENT_DATE
AND tqi.status != 'COMPLETED' -- 排除已完成的状态
WHERE enc.delete_flag = '0'
AND enc.class_enum = 1 -- 门诊AMB
AND enc.create_time::DATE = CURRENT_DATE -- 当日挂号(前端会过滤 registerTime
AND enc.status_enum != 6 -- 排除退号statusEnum = -1 时)
AND tqi.id IS NULL -- 关键:只查询不在队列中的患者
ORDER BY enc.create_time DESC;
-- ============================================
-- 方案二:简化查询(仅核心字段,便于快速测试)
-- ============================================
SELECT
enc.id AS encounterId,
enc.patient_id AS patientId,
pt.name AS patientName,
org.id AS organizationId,
org.name AS organizationName,
hcs.name AS healthcareName,
pr.name AS practitionerName,
enc.create_time AS registerTime
FROM adm_encounter enc
INNER JOIN adm_patient pt ON enc.patient_id = pt.id AND pt.delete_flag = '0'
LEFT JOIN adm_organization org ON enc.organization_id = org.id AND org.delete_flag = '0'
LEFT JOIN adm_healthcare_service hcs ON enc.service_type_id = hcs.id AND hcs.delete_flag = '0'
LEFT JOIN (
SELECT encounter_id, practitioner_id,
ROW_NUMBER() OVER (PARTITION BY encounter_id ORDER BY create_time ASC) AS rn
FROM adm_encounter_participant
WHERE delete_flag = '0' AND type_code IN ('admitter', 'registration_doctor')
) ep ON enc.id = ep.encounter_id AND ep.rn = 1
LEFT JOIN adm_practitioner pr ON ep.practitioner_id = pr.id AND pr.delete_flag = '0'
INNER JOIN adm_charge_item ci ON enc.id = ci.encounter_id AND ci.delete_flag = '0' AND ci.context_enum = 1
INNER JOIN fin_payment_reconciliation prc ON ci.id::TEXT = ANY(string_to_array(prc.charge_item_ids,','))
AND prc.delete_flag = '0' AND prc.status_enum = 1
-- 排除已在队列中的患者
LEFT JOIN hisdev.triage_queue_item tqi
ON enc.id = tqi.encounter_id
AND tqi.delete_flag = '0'
AND tqi.queue_date = CURRENT_DATE
AND tqi.status != 'COMPLETED'
WHERE enc.delete_flag = '0'
AND enc.class_enum = 1
AND enc.create_time::DATE = CURRENT_DATE
AND enc.status_enum != 6
AND tqi.id IS NULL -- 不在队列中
ORDER BY enc.create_time DESC;
-- ============================================
-- 方案三:分步查询(便于调试和理解)
-- ============================================
-- 步骤1查询当日已挂号的患者不排除队列
SELECT
enc.id AS encounterId,
pt.name AS patientName,
org.name AS organizationName,
enc.create_time AS registerTime
FROM adm_encounter enc
INNER JOIN adm_patient pt ON enc.patient_id = pt.id AND pt.delete_flag = '0'
LEFT JOIN adm_organization org ON enc.organization_id = org.id AND org.delete_flag = '0'
INNER JOIN adm_charge_item ci ON enc.id = ci.encounter_id AND ci.delete_flag = '0' AND ci.context_enum = 1
INNER JOIN fin_payment_reconciliation prc ON ci.id::TEXT = ANY(string_to_array(prc.charge_item_ids,','))
AND prc.delete_flag = '0' AND prc.status_enum = 1
WHERE enc.delete_flag = '0'
AND enc.class_enum = 1
AND enc.create_time::DATE = CURRENT_DATE
AND enc.status_enum != 6;
-- 步骤2查询已在队列中的患者
SELECT DISTINCT encounter_id
FROM hisdev.triage_queue_item
WHERE delete_flag = '0'
AND queue_date = CURRENT_DATE
AND status != 'COMPLETED';
-- 步骤3合并查询使用 NOT EXISTS 或 NOT IN
SELECT
enc.id AS encounterId,
pt.name AS patientName,
org.name AS organizationName,
enc.create_time AS registerTime
FROM adm_encounter enc
INNER JOIN adm_patient pt ON enc.patient_id = pt.id AND pt.delete_flag = '0'
LEFT JOIN adm_organization org ON enc.organization_id = org.id AND org.delete_flag = '0'
INNER JOIN adm_charge_item ci ON enc.id = ci.encounter_id AND ci.delete_flag = '0' AND ci.context_enum = 1
INNER JOIN fin_payment_reconciliation prc ON ci.id::TEXT = ANY(string_to_array(prc.charge_item_ids,','))
AND prc.delete_flag = '0' AND prc.status_enum = 1
WHERE enc.delete_flag = '0'
AND enc.class_enum = 1
AND enc.create_time::DATE = CURRENT_DATE
AND enc.status_enum != 6
-- 排除已在队列中的患者
AND NOT EXISTS (
SELECT 1
FROM hisdev.triage_queue_item tqi
WHERE tqi.encounter_id = enc.id
AND tqi.delete_flag = '0'
AND tqi.queue_date = CURRENT_DATE
AND tqi.status != 'COMPLETED'
)
ORDER BY enc.create_time DESC;
-- ============================================
-- 查询条件说明
-- ============================================
-- 1. 基础条件:
-- - enc.delete_flag = '0' -- 未删除
-- - enc.class_enum = 1 -- 门诊AMB
-- - ci.context_enum = 1 -- 挂号REGISTER
-- - prc.status_enum = 1 -- 支付成功SUCCESS
--
-- 2. 日期过滤:
-- - enc.create_time::DATE = CURRENT_DATE -- 当日挂号
-- 注意:前端还会基于 registerTime 字段再次过滤今天的数据
--
-- 3. 状态过滤:
-- - enc.status_enum != 6 -- 排除退号(对应前端 statusEnum = -1
--
-- 4. 队列去重:
-- - LEFT JOIN hisdev.triage_queue_item ... WHERE tqi.id IS NULL
-- 或者
-- - NOT EXISTS (SELECT 1 FROM hisdev.triage_queue_item ...)
-- 排除已在队列中且状态不是 COMPLETED 的患者
--
-- 5. 租户过滤(如果需要):
-- - enc.tenant_id = ? -- 当前登录用户的租户ID
--
-- 6. 模糊搜索(如果需要):
-- - pt.name LIKE '%关键词%' -- 患者姓名
-- - org.name LIKE '%关键词%' -- 科室名称
-- - pr.name LIKE '%关键词%' -- 医生姓名
-- - hcs.name LIKE '%关键词%' -- 号别名称
-- ============================================
-- 调试查询(检查数据是否正确)
-- ============================================
-- 1. 检查当日已挂号患者总数
SELECT COUNT(*) AS total_registered
FROM adm_encounter enc
INNER JOIN adm_charge_item ci ON enc.id = ci.encounter_id AND ci.delete_flag = '0' AND ci.context_enum = 1
INNER JOIN fin_payment_reconciliation prc ON ci.id::TEXT = ANY(string_to_array(prc.charge_item_ids,','))
AND prc.delete_flag = '0' AND prc.status_enum = 1
WHERE enc.delete_flag = '0'
AND enc.class_enum = 1
AND enc.create_time::DATE = CURRENT_DATE
AND enc.status_enum != 6;
-- 2. 检查已在队列中的患者数量
SELECT COUNT(DISTINCT encounter_id) AS in_queue_count
FROM hisdev.triage_queue_item
WHERE delete_flag = '0'
AND queue_date = CURRENT_DATE
AND status != 'COMPLETED';
-- 3. 检查候选池应该显示的患者数量(已挂号 - 已在队列)
SELECT
(SELECT COUNT(*)
FROM adm_encounter enc
INNER JOIN adm_charge_item ci ON enc.id = ci.encounter_id AND ci.delete_flag = '0' AND ci.context_enum = 1
INNER JOIN fin_payment_reconciliation prc ON ci.id::TEXT = ANY(string_to_array(prc.charge_item_ids,','))
AND prc.delete_flag = '0' AND prc.status_enum = 1
WHERE enc.delete_flag = '0'
AND enc.class_enum = 1
AND enc.create_time::DATE = CURRENT_DATE
AND enc.status_enum != 6)
-
(SELECT COUNT(DISTINCT encounter_id)
FROM hisdev.triage_queue_item
WHERE delete_flag = '0'
AND queue_date = CURRENT_DATE
AND status != 'COMPLETED')
AS candidate_pool_count;
-- 4. 查看队列中的患者详情(用于对比)
SELECT
tqi.encounter_id,
tqi.patient_name,
tqi.status,
tqi.queue_order
FROM hisdev.triage_queue_item tqi
WHERE tqi.delete_flag = '0'
AND tqi.queue_date = CURRENT_DATE
AND tqi.status != 'COMPLETED'
ORDER BY tqi.queue_order;

View File

@@ -0,0 +1,366 @@
-- ============================================
-- 智能候选池查询SQL完整版 - 包含排除列表)
-- 页面:智能分诊排队管理 - 心内科
-- 用途:查询"已签到未入队"的患者(当日已挂号,但未加入队列,且未在排除列表中)
-- 更新日期2025-01-15
-- ============================================
-- ============================================
-- 方案一:完整查询(包含所有字段,排除已在队列和排除列表中的患者)
-- ============================================
SELECT
T9.tenant_id AS tenantId,
T9.encounter_id AS encounterId,
T9.display_order AS displayOrder,
T9.organization_id AS organizationId,
T9.organization_name AS organizationName,
T9.healthcare_name AS healthcareName,
T9.practitioner_user_id AS practitionerUserId,
T9.practitioner_name AS practitionerName,
T9.contract_name AS contractName,
T9.patient_id AS patientId,
T9.patient_name AS patientName,
T9.phone,
T9.gender_enum AS genderEnum,
T9.id_card AS idCard,
T9.status_enum AS statusEnum,
T9.register_time AS registerTime,
T9.total_price AS totalPrice,
T9.account_name AS accountName,
T9.enterer_name AS entererName,
T9.charge_item_ids AS chargeItemIds,
T9.payment_id AS paymentId,
T9.picture_url AS pictureUrl,
T9.birth_date AS birthDate,
COALESCE(T9.identifier_no, T9.patient_bus_no, '') AS identifierNo,
-- 计算年龄(前端会调用 parseAge 函数)
CASE
WHEN T9.birth_date IS NOT NULL THEN
EXTRACT(YEAR FROM AGE(T9.birth_date))::TEXT || ''
ELSE ''
END AS age
FROM (
SELECT T1.tenant_id AS tenant_id,
T1.id AS encounter_id,
T1.display_order AS display_order,
T1.organization_id AS organization_id,
T2.NAME AS organization_name,
T3.NAME AS healthcare_name,
T5.user_id AS practitioner_user_id,
T5.NAME AS practitioner_name,
T7.contract_name AS contract_name,
T8.id AS patient_id,
T8.NAME AS patient_name,
T8.phone AS phone,
T8.gender_enum AS gender_enum,
T8.id_card AS id_card,
T1.status_enum AS status_enum,
T1.create_time AS register_time,
T10.total_price,
T11."name" AS account_name,
T12."name" AS enterer_name,
T13.charge_item_ids,
T13.id AS payment_id,
ai.picture_url AS picture_url,
T8.birth_date AS birth_date,
T8.bus_no AS patient_bus_no,
T18.identifier_no AS identifier_no
FROM adm_encounter AS T1
LEFT JOIN adm_organization AS T2 ON T1.organization_id = T2.ID AND T2.delete_flag = '0'
LEFT JOIN adm_healthcare_service AS T3 ON T1.service_type_id = T3.ID AND T3.delete_flag = '0'
LEFT JOIN (
SELECT *
FROM (
SELECT *,
ROW_NUMBER() OVER (PARTITION BY encounter_id ORDER BY create_time ASC) AS rn
FROM adm_encounter_participant
WHERE delete_flag = '0'
AND (
(type_code = 'admitter' AND EXISTS(SELECT 1
FROM adm_encounter AS T1
WHERE T1.status_enum = 2 -- IN_PROGRESS
AND T1.ID = encounter_id))
OR
(type_code = 'registration_doctor' AND NOT EXISTS(SELECT 1
FROM adm_encounter AS T1
WHERE T1.status_enum = 2 -- IN_PROGRESS
AND T1.ID = encounter_id))
)
) t
WHERE rn = 1
) AS T4 ON T1.ID = T4.encounter_id
LEFT JOIN adm_practitioner AS T5 ON T5.ID = T4.practitioner_id AND T5.delete_flag = '0'
LEFT JOIN adm_account AS T6
ON T1.ID = T6.encounter_id AND T6.delete_flag = '0' AND T6.encounter_flag = '1'
LEFT JOIN fin_contract AS T7 ON T6.contract_no = T7.bus_no AND T7.delete_flag = '0'
LEFT JOIN adm_patient AS T8 ON T1.patient_id = T8.ID AND T8.delete_flag = '0'
LEFT JOIN (
SELECT patient_id,
identifier_no
FROM (
SELECT patient_id,
identifier_no,
ROW_NUMBER() OVER (PARTITION BY patient_id ORDER BY create_time ASC) AS rn
FROM adm_patient_identifier
WHERE delete_flag = '0'
AND identifier_no IS NOT NULL
AND identifier_no != ''
) t
WHERE rn = 1
) AS T18 ON T8.id = T18.patient_id
LEFT JOIN adm_charge_item AS T10 ON T1.id = T10.encounter_id AND T10.delete_flag = '0'
LEFT JOIN adm_account AS T11 ON T10.account_id = T11.id AND T11.delete_flag = '0'
LEFT JOIN adm_practitioner AS T12 ON T12.ID = T10.enterer_id AND T12.delete_flag = '0'
LEFT JOIN fin_payment_reconciliation T13
ON T10.id::TEXT = ANY(string_to_array(T13.charge_item_ids,','))
AND T13.delete_flag = '0'
AND T13.status_enum = 1 -- SUCCESS支付成功
LEFT JOIN adm_invoice AS ai
ON ai.reconciliation_id = T13.id AND ai.delete_flag = '0'
WHERE T1.delete_flag = '0'
AND T1.class_enum = 1 -- 门诊AMB
AND T1.create_time::DATE = CURRENT_DATE -- 当日挂号
AND T1.status_enum != 6 -- 排除退号
AND T10.context_enum = 1 -- REGISTER挂号
) AS T9
-- 排除已在队列中的患者关键LEFT JOIN + WHERE IS NULL
LEFT JOIN hisdev.triage_queue_item tqi
ON T9.encounter_id = tqi.encounter_id
AND tqi.delete_flag = '0'
AND tqi.queue_date = CURRENT_DATE
AND tqi.status != 'COMPLETED' -- 排除已完成的状态
-- 排除已在排除列表中的患者新增关键LEFT JOIN + WHERE IS NULL
LEFT JOIN hisdev.triage_candidate_exclusion tce
ON T9.encounter_id = tce.encounter_id
AND tce.delete_flag = '0'
AND tce.exclusion_date = CURRENT_DATE
AND tce.tenant_id = T9.tenant_id -- 按租户过滤
WHERE tqi.id IS NULL -- 关键:只查询不在队列中的患者
AND tce.id IS NULL -- 关键:只查询不在排除列表中的患者
ORDER BY T9.register_time DESC;
-- ============================================
-- 方案二:简化查询(仅核心字段,便于快速测试)
-- ============================================
SELECT
enc.id AS encounterId,
enc.patient_id AS patientId,
pt.name AS patientName,
org.id AS organizationId,
org.name AS organizationName,
hcs.name AS healthcareName,
pr.name AS practitionerName,
enc.create_time AS registerTime
FROM adm_encounter enc
INNER JOIN adm_patient pt ON enc.patient_id = pt.id AND pt.delete_flag = '0'
LEFT JOIN adm_organization org ON enc.organization_id = org.id AND org.delete_flag = '0'
LEFT JOIN adm_healthcare_service hcs ON enc.service_type_id = hcs.id AND hcs.delete_flag = '0'
LEFT JOIN (
SELECT encounter_id, practitioner_id,
ROW_NUMBER() OVER (PARTITION BY encounter_id ORDER BY create_time ASC) AS rn
FROM adm_encounter_participant
WHERE delete_flag = '0' AND type_code IN ('admitter', 'registration_doctor')
) ep ON enc.id = ep.encounter_id AND ep.rn = 1
LEFT JOIN adm_practitioner pr ON ep.practitioner_id = pr.id AND pr.delete_flag = '0'
INNER JOIN adm_charge_item ci ON enc.id = ci.encounter_id AND ci.delete_flag = '0' AND ci.context_enum = 1
INNER JOIN fin_payment_reconciliation prc ON ci.id::TEXT = ANY(string_to_array(prc.charge_item_ids,','))
AND prc.delete_flag = '0' AND prc.status_enum = 1
-- 排除已在队列中的患者
LEFT JOIN hisdev.triage_queue_item tqi
ON enc.id = tqi.encounter_id
AND tqi.delete_flag = '0'
AND tqi.queue_date = CURRENT_DATE
AND tqi.status != 'COMPLETED'
-- 排除已在排除列表中的患者(新增)
LEFT JOIN hisdev.triage_candidate_exclusion tce
ON enc.id = tce.encounter_id
AND tce.delete_flag = '0'
AND tce.exclusion_date = CURRENT_DATE
AND tce.tenant_id = enc.tenant_id
WHERE enc.delete_flag = '0'
AND enc.class_enum = 1
AND enc.create_time::DATE = CURRENT_DATE
AND enc.status_enum != 6
AND tqi.id IS NULL -- 不在队列中
AND tce.id IS NULL -- 不在排除列表中
ORDER BY enc.create_time DESC;
-- ============================================
-- 方案三:使用 NOT EXISTS 子查询(性能可能更好)
-- ============================================
SELECT
enc.id AS encounterId,
enc.patient_id AS patientId,
pt.name AS patientName,
org.id AS organizationId,
org.name AS organizationName,
hcs.name AS healthcareName,
pr.name AS practitionerName,
enc.create_time AS registerTime
FROM adm_encounter enc
INNER JOIN adm_patient pt ON enc.patient_id = pt.id AND pt.delete_flag = '0'
LEFT JOIN adm_organization org ON enc.organization_id = org.id AND org.delete_flag = '0'
LEFT JOIN adm_healthcare_service hcs ON enc.service_type_id = hcs.id AND hcs.delete_flag = '0'
LEFT JOIN (
SELECT encounter_id, practitioner_id,
ROW_NUMBER() OVER (PARTITION BY encounter_id ORDER BY create_time ASC) AS rn
FROM adm_encounter_participant
WHERE delete_flag = '0' AND type_code IN ('admitter', 'registration_doctor')
) ep ON enc.id = ep.encounter_id AND ep.rn = 1
LEFT JOIN adm_practitioner pr ON ep.practitioner_id = pr.id AND pr.delete_flag = '0'
INNER JOIN adm_charge_item ci ON enc.id = ci.encounter_id AND ci.delete_flag = '0' AND ci.context_enum = 1
INNER JOIN fin_payment_reconciliation prc ON ci.id::TEXT = ANY(string_to_array(prc.charge_item_ids,','))
AND prc.delete_flag = '0' AND prc.status_enum = 1
WHERE enc.delete_flag = '0'
AND enc.class_enum = 1
AND enc.create_time::DATE = CURRENT_DATE
AND enc.status_enum != 6
-- 排除已在队列中的患者
AND NOT EXISTS (
SELECT 1
FROM hisdev.triage_queue_item tqi
WHERE tqi.encounter_id = enc.id
AND tqi.delete_flag = '0'
AND tqi.queue_date = CURRENT_DATE
AND tqi.status != 'COMPLETED'
)
-- 排除已在排除列表中的患者(新增)
AND NOT EXISTS (
SELECT 1
FROM hisdev.triage_candidate_exclusion tce
WHERE tce.encounter_id = enc.id
AND tce.delete_flag = '0'
AND tce.exclusion_date = CURRENT_DATE
AND tce.tenant_id = enc.tenant_id
)
ORDER BY enc.create_time DESC;
-- ============================================
-- 查询条件说明
-- ============================================
-- 1. 基础条件:
-- - enc.delete_flag = '0' -- 未删除
-- - enc.class_enum = 1 -- 门诊AMB
-- - ci.context_enum = 1 -- 挂号REGISTER
-- - prc.status_enum = 1 -- 支付成功SUCCESS
--
-- 2. 日期过滤:
-- - enc.create_time::DATE = CURRENT_DATE -- 当日挂号
-- 注意:前端还会基于 registerTime 字段再次过滤今天的数据
--
-- 3. 状态过滤:
-- - enc.status_enum != 6 -- 排除退号(对应前端 statusEnum = -1
--
-- 4. 队列去重:
-- - LEFT JOIN hisdev.triage_queue_item ... WHERE tqi.id IS NULL
-- 或者
-- - NOT EXISTS (SELECT 1 FROM hisdev.triage_queue_item ...)
-- 排除已在队列中且状态不是 COMPLETED 的患者
--
-- 5. 排除列表去重(新增):
-- - LEFT JOIN hisdev.triage_candidate_exclusion ... WHERE tce.id IS NULL
-- 或者
-- - NOT EXISTS (SELECT 1 FROM hisdev.triage_candidate_exclusion ...)
-- 排除已在排除列表中的患者(已加入队列后被记录)
--
-- 6. 租户过滤(如果需要):
-- - enc.tenant_id = ? -- 当前登录用户的租户ID
--
-- 7. 模糊搜索(如果需要):
-- - pt.name LIKE '%关键词%' -- 患者姓名
-- - org.name LIKE '%关键词%' -- 科室名称
-- - pr.name LIKE '%关键词%' -- 医生姓名
-- - hcs.name LIKE '%关键词%' -- 号别名称
-- ============================================
-- 调试查询(检查数据是否正确)
-- ============================================
-- 1. 检查当日已挂号患者总数
SELECT COUNT(*) AS total_registered
FROM adm_encounter enc
INNER JOIN adm_charge_item ci ON enc.id = ci.encounter_id AND ci.delete_flag = '0' AND ci.context_enum = 1
INNER JOIN fin_payment_reconciliation prc ON ci.id::TEXT = ANY(string_to_array(prc.charge_item_ids,','))
AND prc.delete_flag = '0' AND prc.status_enum = 1
WHERE enc.delete_flag = '0'
AND enc.class_enum = 1
AND enc.create_time::DATE = CURRENT_DATE
AND enc.status_enum != 6;
-- 2. 检查已在队列中的患者数量
SELECT COUNT(DISTINCT encounter_id) AS in_queue_count
FROM hisdev.triage_queue_item
WHERE delete_flag = '0'
AND queue_date = CURRENT_DATE
AND status != 'COMPLETED';
-- 3. 检查已在排除列表中的患者数量(新增)
SELECT COUNT(DISTINCT encounter_id) AS in_exclusion_count
FROM hisdev.triage_candidate_exclusion
WHERE delete_flag = '0'
AND exclusion_date = CURRENT_DATE;
-- 4. 检查候选池应该显示的患者数量(已挂号 - 已在队列 - 已在排除列表)
SELECT
(SELECT COUNT(*)
FROM adm_encounter enc
INNER JOIN adm_charge_item ci ON enc.id = ci.encounter_id AND ci.delete_flag = '0' AND ci.context_enum = 1
INNER JOIN fin_payment_reconciliation prc ON ci.id::TEXT = ANY(string_to_array(prc.charge_item_ids,','))
AND prc.delete_flag = '0' AND prc.status_enum = 1
WHERE enc.delete_flag = '0'
AND enc.class_enum = 1
AND enc.create_time::DATE = CURRENT_DATE
AND enc.status_enum != 6)
-
(SELECT COUNT(DISTINCT encounter_id)
FROM hisdev.triage_queue_item
WHERE delete_flag = '0'
AND queue_date = CURRENT_DATE
AND status != 'COMPLETED')
-
(SELECT COUNT(DISTINCT encounter_id)
FROM hisdev.triage_candidate_exclusion
WHERE delete_flag = '0'
AND exclusion_date = CURRENT_DATE)
AS candidate_pool_count;
-- 5. 查看队列中的患者详情(用于对比)
SELECT
tqi.encounter_id,
tqi.patient_name,
tqi.status,
tqi.queue_order
FROM hisdev.triage_queue_item tqi
WHERE tqi.delete_flag = '0'
AND tqi.queue_date = CURRENT_DATE
AND tqi.status != 'COMPLETED'
ORDER BY tqi.queue_order;
-- 6. 查看排除列表中的患者详情(新增)
SELECT
tce.encounter_id,
tce.patient_name,
tce.reason,
tce.create_time
FROM hisdev.triage_candidate_exclusion tce
WHERE tce.delete_flag = '0'
AND tce.exclusion_date = CURRENT_DATE
ORDER BY tce.create_time DESC;
-- 7. 查看重叠的患者(既在队列中,又在排除列表中)
SELECT
tqi.encounter_id,
tqi.patient_name AS queue_patient_name,
tce.patient_name AS exclusion_patient_name,
tqi.status,
tce.reason
FROM hisdev.triage_queue_item tqi
INNER JOIN hisdev.triage_candidate_exclusion tce
ON tqi.encounter_id = tce.encounter_id
AND tqi.queue_date = tce.exclusion_date
AND tqi.tenant_id = tce.tenant_id
WHERE tqi.delete_flag = '0'
AND tce.delete_flag = '0'
AND tqi.queue_date = CURRENT_DATE
ORDER BY tqi.encounter_id;