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

119 lines
8.2 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 对外房间门禁服务接口 P2(结果回调)
--
-- 背景:P1 只做「同步受理」,门锁下发结果没有回传渠道。P2 在授权/清除命令
-- 进入终态时生成回调任务,按应用配置的地址上报,失败按退避重试,最终死信,
-- 支持人工重发。本文档对应设计:doc/对外开放房间门禁服务接口设计.md §8、§9
--
-- 只新增一张表 + 两个字典 + 一组菜单,不改动 P1 已建的表结构。
--
-- 执行前置:
-- 1) 先执行 upgrade_d20_openapi_stay.sql(P1),本脚本依赖入住单的
-- biz_no / biz_system 字段;
-- 2) 与 P2 代码同批次发布:代码会在入住/退房/续住时写本表,缺表会导致
-- 这些操作在事务内报错回滚(受影响的只是接口单,平台手工单不受影响);
-- 3) 每个接入应用需在 iot.openapi.apps[] 配置 callback-url 与 callback-secret:
-- callback-url 为空视为「未开通回调」,不产生任务;
-- callback-url 已配置但 callback-secret 为空时事件直接落死信(避免无签名报文),
-- 补齐密钥后在页面人工重发即可。
--
-- 可重复执行:建表用 if not exists、字典与菜单先 delete 再 insert。
-- =========================================================================
set names utf8mb4;
-- =========================================================================
-- 1、回调任务表
-- status:0 待结果(已登记事件,等设备回执)1 待发送 2 已成功 3 死信
-- revision:同一应用 + 同一单号 + 同一事件的结果版本,补偿成功后递增,
-- 对方按 revision 最大者为最终结果(见设计稿 §8.3)
-- callback_url 存事件产生时的配置快照,避免上线换地址后旧事件发错地方
-- =========================================================================
create table if not exists lock_callback_task (
task_id bigint(20) not null auto_increment comment '任务ID',
event_id varchar(64) not null comment '事件ID(回调头 X-Callback-Id,对方据此去重)',
app_code varchar(32) not null comment '接入应用编码(iot.openapi.apps[].app-code)',
event_type varchar(32) not null comment '事件类型(STAY_CHECKIN_RESULT / STAY_CHECKOUT_RESULT / STAY_EXTEND_RESULT)',
biz_no varchar(64) not null comment '业务系统单号',
revision int(11) not null default 1 comment '同单同事件的版本(结果变更时递增)',
auth_id bigint(20) default null comment '关联授权ID(lock_auth.auth_id),命令终态据此落库',
callback_url varchar(500) default null comment '回调地址(事件产生时的应用配置快照)',
payload text comment '回调报文原文(参与签名)',
status char(1) not null default '0' comment '状态(0待结果 1待发送 2已成功 3死信,字典 lock_callback_status)',
retry_count int(11) not null default 0 comment '已重试次数',
next_retry_time datetime default null comment '下次发送时间',
last_error varchar(500) default null comment '最后一次失败原因',
create_by varchar(64) default '' comment '创建者',
create_time datetime comment '创建时间',
update_time datetime comment '更新时间',
primary key (task_id),
unique key uk_lock_callback_event (event_id),
unique key uk_lock_callback_rev (app_code, biz_no, event_type, revision),
key idx_lock_callback_due (status, next_retry_time),
key idx_lock_callback_auth (auth_id, status),
key idx_lock_callback_list (app_code, create_time)
) engine=innodb comment = '开放接口结果回调任务表';
-- =========================================================================
-- 2、字典
-- =========================================================================
delete from sys_dict_data where dict_type in ('lock_callback_status', 'lock_callback_event');
delete from sys_dict_type where dict_type in ('lock_callback_status', 'lock_callback_event');
insert into sys_dict_type (dict_name, dict_type, status, create_by, create_time, remark) values
('回调任务状态', 'lock_callback_status', '0', 'admin', now(), '开放接口结果回调任务状态'),
('回调事件类型', 'lock_callback_event', '0', 'admin', now(), '开放接口结果回调事件');
insert into sys_dict_data (dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, status, create_by, create_time, remark) values
(1, '待结果', '0', 'lock_callback_status', '', 'info', 'Y', '0', 'admin', now(), '已登记事件,等待设备回执'),
(2, '待发送', '1', 'lock_callback_status', '', 'primary', 'N', '0', 'admin', now(), '报文就绪,等待投递'),
(3, '已成功', '2', 'lock_callback_status', '', 'success', 'N', '0', 'admin', now(), '对方已接收'),
(4, '死信', '3', 'lock_callback_status', '', 'danger', 'N', '0', 'admin', now(), '重试耗尽或配置缺失,需人工处理'),
(1, '入住结果', 'STAY_CHECKIN_RESULT', 'lock_callback_event', '', 'primary', 'Y', '0', 'admin', now(), ''),
(2, '退房结果', 'STAY_CHECKOUT_RESULT', 'lock_callback_event', '', 'warning', 'N', '0', 'admin', now(), ''),
(3, '续住结果', 'STAY_EXTEND_RESULT', 'lock_callback_event', '', 'success', 'N', '0', 'admin', now(), '');
-- =========================================================================
-- 3、菜单:回调任务(2140 号段,接在住宿 2130 之后)
-- =========================================================================
delete from sys_menu where perms like 'lock:callback:%';
insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, query, route_name, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, remark) values
(2140, '回调任务', 2000, 13, 'callback', 'iot/callback/index', '', '', 1, 0, 'C', '0', '0', 'lock:callback:list', 'message', 'admin', CURRENT_TIMESTAMP, '开放接口结果回调任务');
insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, query, route_name, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, remark) values
(2141, '回调查询', 2140, 1, '', null, '', '', 1, 0, 'F', '0', '0', 'lock:callback:query', '#', 'admin', CURRENT_TIMESTAMP, ''),
(2142, '人工重发', 2140, 2, '', null, '', '', 1, 0, 'F', '0', '0', 'lock:callback:resend', '#', 'admin', CURRENT_TIMESTAMP, '死信重新投递');
-- =========================================================================
-- 4、执行后核对(只读,按需执行)
-- =========================================================================
-- 4.1 表与索引是否到位(应返回 1 行,含 3 个索引)
-- show create table lock_callback_task;
-- 4.2 各状态任务数(上线初期除 0/1 外都应为 0)
-- select status, count(1) as total from lock_callback_task group by status;
-- 4.3 同一单号同一事件不应出现重复 revision(应为空)
-- select app_code, biz_no, event_type, revision, count(1) c
-- from lock_callback_task group by app_code, biz_no, event_type, revision having c > 1;
-- 4.4 长期卡在「待结果」的任务(超过 24 小时,通常是被补偿任务覆盖或命令丢失)
-- select task_id, app_code, biz_no, event_type, create_time
-- from lock_callback_task
-- where status = '0' and create_time < date_sub(now(), interval 1 day);
-- =========================================================================
-- 5、回滚(仅在确认不再需要回调记录后执行)
-- =========================================================================
-- drop table if exists lock_callback_task;
-- delete from sys_menu where perms like 'lock:callback:%';
-- delete from sys_dict_data where dict_type in ('lock_callback_status', 'lock_callback_event');
-- delete from sys_dict_type where dict_type in ('lock_callback_status', 'lock_callback_event');