Files
doorcontrol/base/RuoYi-Vue-master/sql/upgrade_d20_openapi_stay.sql
T
zfjia 271e4ca77c chore: 导入门锁迭代开发工程基线
包含 RuoYi-Vue 后端(ruoyi-iot 门禁模块)、RuoYi-Vue2 前端、设计文档与升级脚本。
忽略构建产物(target/node_modules/dist)、IDE 配置、运行日志与数据库转储。
2026-11-01 19:44:40 +08:00

163 lines
8.9 KiB
SQL
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
-- =========================================================================
-- 存量升级:D20 对外房间门禁服务接口 P1(v1 库)
--
-- 背景:向外部业务系统(PMS/访客/园区平台)开放入住、退房、续住能力。
-- 对外接口复用住宿模块(lock_room / lock_stay)与授权下发(lock_auth),
-- 本期只补三处数据结构:
-- 1) lock_stay 增加业务系统归属字段,用于幂等与数据隔离;
-- 2) lock_person_ref 把外部人员标识映射到平台 person_no(按应用隔离);
-- 3) lock_room_device_history 记录房间-门锁绑定历史,支撑后续
-- 「开锁记录查询包含历史门锁」(P3)。
--
-- 本文档对应设计:doc/对外开放房间门禁服务接口设计.md §9
--
-- 执行前置:
-- 1) 备份 lock_stay / lock_room / lock_device;
-- 2) 与 D20 代码同批次发布:新代码写 biz_no/biz_system/source 三列,
-- 缺列会导致接口入住直接失败(平台页面入住不受影响);
-- 3) 低峰期执行;alter 段锁表时间取决于 lock_stay 行数。
--
-- 可重复执行说明:建表用 if not exists、回填用 not exists 保护;
-- MySQL 不支持 add column / add index if not exists,第 1 节重复执行会报
-- "Duplicate column name 'biz_no'" 或 "Duplicate key name",忽略即可继续。
--
-- 未包含:lock_callback_task(结果回调与重试,P2 交付时再建)。
-- =========================================================================
set names utf8mb4;
-- =========================================================================
-- 1、lock_stay 增加业务系统字段
-- biz_system + biz_no 为对外幂等键:业务号只在应用内唯一,平台手工单
-- 两者均为 NULL(MySQL 唯一索引允许多行 NULL,不会互相冲突)。
-- source 区分单据来源,便于页面与对账区分「平台办理」和「接口办理」。
-- =========================================================================
alter table lock_stay
add column biz_no varchar(64) default null comment '业务系统单号(应用内唯一,平台手工单为空)' after stay_no,
add column biz_system varchar(32) default null comment '业务系统编码(iot.openapi.apps[].app-code,平台手工单为空)' after biz_no,
add column source char(1) default '1' comment '单据来源(1平台 2接口)' after biz_system;
alter table lock_stay
add unique key uk_lock_stay_biz (biz_system, biz_no);
-- =========================================================================
-- 2、外部人员标识映射表
-- 业务系统的人员标识格式不受 person_no(2 字母 + 6 数字)约束,因此单独
-- 建映射;(app_code, external_id) 唯一,同一自然人在不同应用各自建档。
-- =========================================================================
create table if not exists lock_person_ref (
ref_id bigint(20) not null auto_increment comment '映射ID',
person_id bigint(20) not null comment '人员ID(lock_person.person_id)',
person_no varchar(32) not null comment '人员编号(冗余协议键)',
app_code varchar(32) not null comment '接入应用编码(iot.openapi.apps[].app-code)',
external_id varchar(64) not null comment '业务系统人员标识(假定稳定不变)',
create_by varchar(64) default '' comment '创建者',
create_time datetime comment '创建时间',
remark varchar(500) default null comment '备注',
primary key (ref_id),
unique key uk_lock_person_ref (app_code, external_id),
key idx_lock_person_ref_person (person_no)
) engine=innodb comment = '外部人员标识映射表';
-- =========================================================================
-- 3、房间-门锁绑定历史表
-- 只增不改(解绑时回填 unbind_time):房间换锁后,历史时段内的开锁记录
-- 仍要能按房间查出来,因此需要保留「哪段时间绑的是哪把锁」。
-- =========================================================================
create table if not exists lock_room_device_history (
history_id bigint(20) not null auto_increment comment '历史ID',
room_id bigint(20) not null comment '房间ID(lock_room.room_id)',
device_id bigint(20) not null comment '门锁ID(lock_device.device_id)',
device_sn varchar(32) default null comment '门锁SN(冗余快照)',
bind_time datetime not null comment '绑定生效时间',
unbind_time datetime default null comment '解绑时间(为空表示当前仍在绑)',
create_by varchar(64) default '' comment '创建者',
create_time datetime comment '创建时间',
remark varchar(500) default null comment '备注',
primary key (history_id),
key idx_lock_room_device_history (room_id, bind_time, unbind_time),
key idx_lock_room_device_history_device (device_id)
) engine=innodb comment = '房间门锁绑定历史表';
-- =========================================================================
-- 4、存量回填:把房间当前绑定登记为一条未解绑的历史
-- bind_time 取房间的 update_time(最近一次绑定/换锁),缺失时退到
-- create_time,再缺失取当前时间。
-- =========================================================================
insert into lock_room_device_history (room_id, device_id, device_sn, bind_time, create_by, create_time, remark)
select r.room_id, r.device_id, d.device_sn,
ifnull(r.update_time, ifnull(r.create_time, now())), 'migrate', now(),
'D20 存量回填:当前绑定视为历史起点'
from lock_room r
join lock_device d on d.device_id = r.device_id
where r.del_flag = '0'
and r.device_id is not null
and not exists (
select 1 from lock_room_device_history h
where h.room_id = r.room_id and h.device_id = r.device_id and h.unbind_time is null
);
-- =========================================================================
-- 5、执行后核对(只读,按需执行)
-- =========================================================================
-- 5.1 新增列与唯一键是否到位
-- select column_name, column_type, column_default, column_comment
-- from information_schema.columns
-- where table_schema = database() and table_name = 'lock_stay'
-- and column_name in ('biz_no', 'biz_system', 'source');
--
-- select index_name, column_name from information_schema.statistics
-- where table_schema = database() and table_name = 'lock_stay'
-- and index_name = 'uk_lock_stay_biz';
--
-- 5.2 回填的历史行数应等于当前已绑锁的房间数
-- select (select count(1) from lock_room_device_history where unbind_time is null) as open_history_cnt,
-- (select count(1) from lock_room where del_flag = '0' and device_id is not null) as bound_room_cnt;
--
-- 5.3 存量入住单的 source 应全部为 1(平台),biz_no/biz_system 应为空
-- select source, count(1) from lock_stay group by source;
--
-- 5.4 业务号重复检查(应为空)
-- select biz_system, biz_no, count(1) from lock_stay
-- where biz_no is not null group by biz_system, biz_no having count(1) > 1;
-- =========================================================================
-- 5.5 修复:平台手工单被写成空串的 biz_no / biz_system(2026-11-01)
-- 现象:入住管理第二次办理入住报
-- Duplicate entry '' for key 'lock_stay.uk_lock_stay_biz'
-- 原因:唯一键只允许多行 NULL,平台单落的却是空串。
-- 代码已修正为空 → NULL;存量空串按下面语句归一,可重复执行。
-- 接口单的业务号必非空,这里的空串只可能来自平台手工单,不会误伤接口单据。
-- =========================================================================
update lock_stay
set biz_no = null
where biz_no = ''
and (biz_system is null or biz_system = '');
update lock_stay
set biz_system = null
where biz_system = ''
and biz_no is null;
-- 核对:结果应为 0
-- select count(1) from lock_stay where biz_no = '' or biz_system = '';
-- =========================================================================
-- 6、回滚(仅在确认没有接口单据后执行)
-- =========================================================================
-- 6.1 删除新增表
-- drop table if exists lock_room_device_history;
-- drop table if exists lock_person_ref;
--
-- 6.2 回退 lock_stay 字段(会丢失接口单据的业务号归属,执行前先确认)
-- select count(1) from lock_stay where biz_no is not null;
-- alter table lock_stay drop index uk_lock_stay_biz;
-- alter table lock_stay drop column source, drop column biz_system, drop column biz_no;