Files
smart_grid_iot/database/migrations/20261001_om_worker_registry.sql
T
andyesfly f4454ad014 feat: 新增电工APP端与定时任务管理功能
- 新增电工APP独立鉴权中间件与登录注册接口
- 新增定时任务管理模块,支持任务配置、执行日志与手动触发
- 新增运维费定价与电工派单成本价目管理
- 新增电工资质证照管理与到期提醒定时任务
- 完善数据库实体与DTO校验,优化权限控制
2026-10-02 16:08:00 +08:00

221 lines
13 KiB
PL/PgSQL
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.
-- 运维费定价 + 电工登记管理功能扩展
-- 背景:运营派单域由「派单执行」扩展为「客户运维服务价目 + 电工派单成本价 + 电工登记审核」,
-- 对应新增 service_price(客户运维服务价目)、worker_cert(电工资质证照)、
-- sys_notice(证照到期站内通知)三张表,并为 worker / dispatch_price 补齐
-- 登录、审核、计价方式等业务字段,同时挂载运营派单子菜单与按钮权限。
-- 幂等:新增列一律带 DEFAULT + IF NOT EXISTS;建表/索引用 IF NOT EXISTS;
-- 菜单/角色绑定用 ON CONFLICT;字典用「先 DELETE 再 INSERT」收敛。
-- 注意:本文件不 TRUNCATE sys_dict(避免清空其它字典及重置 id 影响 db_seed.sql)。
BEGIN;
-- ------------------------------------------------------------
-- 1) worker 表扩展:电工 APP 登录与入驻审核
-- ------------------------------------------------------------
ALTER TABLE worker ADD COLUMN IF NOT EXISTS password_hash VARCHAR(255); -- 电工APP登录密码bcrypt哈希
ALTER TABLE worker ADD COLUMN IF NOT EXISTS audit_status SMALLINT NOT NULL DEFAULT 0; -- 审核状态:0待审核 1已通过 2已驳回
ALTER TABLE worker ADD COLUMN IF NOT EXISTS audit_remark VARCHAR(255); -- 驳回理由/审核备注
ALTER TABLE worker ADD COLUMN IF NOT EXISTS audit_by BIGINT; -- 审核人(→ sys_user.id)
ALTER TABLE worker ADD COLUMN IF NOT EXISTS audit_at TIMESTAMPTZ; -- 审核时间
ALTER TABLE worker ADD COLUMN IF NOT EXISTS last_login_at TIMESTAMPTZ; -- 最后登录时间
COMMENT ON COLUMN worker.password_hash IS '电工APP登录密码bcrypt哈希';
COMMENT ON COLUMN worker.audit_status IS '审核状态:0待审核 1已通过 2已驳回';
COMMENT ON COLUMN worker.audit_remark IS '驳回理由/审核备注';
COMMENT ON COLUMN worker.audit_by IS '审核人(→ sys_user.id)';
COMMENT ON COLUMN worker.audit_at IS '审核时间';
COMMENT ON COLUMN worker.last_login_at IS '最后登录时间';
-- 电工登记台账按审核状态过滤/统计
CREATE INDEX IF NOT EXISTS idx_worker_audit_status ON worker (audit_status);
-- ------------------------------------------------------------
-- 2) 电工资质证照表(电工登记管理的资质附件与到期提醒依据)
-- ------------------------------------------------------------
CREATE TABLE IF NOT EXISTS worker_cert (
id BIGSERIAL PRIMARY KEY,
worker_id BIGINT NOT NULL REFERENCES worker(id) ON DELETE CASCADE,
cert_type VARCHAR(64), -- 证书类型(字典 worker_cert_type)
cert_no VARCHAR(64), -- 证书编号
issue_authority VARCHAR(128), -- 发证机关
issue_date DATE, -- 发证日期
expire_date DATE, -- 有效期至(到期提醒依据;NULL=长期有效)
cert_image_url VARCHAR(512), -- 证照图片对象key
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
COMMENT ON TABLE worker_cert IS '电工资质证照表';
COMMENT ON COLUMN worker_cert.id IS '自增主键';
COMMENT ON COLUMN worker_cert.worker_id IS '共享电工ID(→ worker)';
COMMENT ON COLUMN worker_cert.cert_type IS '证书类型(字典 worker_cert_type)';
COMMENT ON COLUMN worker_cert.cert_no IS '证书编号';
COMMENT ON COLUMN worker_cert.issue_authority IS '发证机关';
COMMENT ON COLUMN worker_cert.issue_date IS '发证日期';
COMMENT ON COLUMN worker_cert.expire_date IS '有效期至(到期提醒依据;NULL=长期有效)';
COMMENT ON COLUMN worker_cert.cert_image_url IS '证照图片对象key';
COMMENT ON COLUMN worker_cert.created_at IS '创建时间';
COMMENT ON COLUMN worker_cert.updated_at IS '更新时间';
CREATE INDEX IF NOT EXISTS idx_worker_cert_worker ON worker_cert (worker_id);
CREATE INDEX IF NOT EXISTS idx_worker_cert_expire ON worker_cert (expire_date);
CREATE UNIQUE INDEX IF NOT EXISTS uk_worker_cert_type_no ON worker_cert (worker_id, cert_type, cert_no);
-- ------------------------------------------------------------
-- 3) 客户运维服务价目表(运维费定价)
-- ------------------------------------------------------------
CREATE TABLE IF NOT EXISTS service_price (
id BIGSERIAL PRIMARY KEY,
price_code VARCHAR(64) NOT NULL UNIQUE,
price_name VARCHAR(64) NOT NULL,
service_type VARCHAR(32),
price_mode SMALLINT NOT NULL DEFAULT 1,
unit_price NUMERIC(10,2) NOT NULL DEFAULT 0,
unit VARCHAR(16),
status SMALLINT NOT NULL DEFAULT 1,
remark VARCHAR(255),
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
COMMENT ON TABLE service_price IS '客户运维服务价目表';
COMMENT ON COLUMN service_price.id IS '自增主键';
COMMENT ON COLUMN service_price.price_code IS '价目编码(唯一,FW+YYYYMMDD+3位)';
COMMENT ON COLUMN service_price.price_name IS '价目名称';
COMMENT ON COLUMN service_price.service_type IS '服务类型:维修/维保/报警处理/巡检/其他';
COMMENT ON COLUMN service_price.price_mode IS '计价方式:1按次 2按工时 3材料';
COMMENT ON COLUMN service_price.unit_price IS '单价';
COMMENT ON COLUMN service_price.unit IS '计价单位:次/小时/个/米/根';
COMMENT ON COLUMN service_price.status IS '状态:1启用 0停用';
COMMENT ON COLUMN service_price.remark IS '备注';
COMMENT ON COLUMN service_price.created_at IS '创建时间';
COMMENT ON COLUMN service_price.updated_at IS '更新时间';
CREATE UNIQUE INDEX IF NOT EXISTS uk_service_price_code ON service_price (price_code);
CREATE INDEX IF NOT EXISTS idx_service_price_mode_status ON service_price (price_mode, status);
-- ------------------------------------------------------------
-- 4) dispatch_price 表扩展:电工派单成本价
-- ------------------------------------------------------------
ALTER TABLE dispatch_price ADD COLUMN IF NOT EXISTS price_mode SMALLINT NOT NULL DEFAULT 1; -- 计价方式:1按次 2按工时
ALTER TABLE dispatch_price ADD COLUMN IF NOT EXISTS unit VARCHAR(16) DEFAULT '次'; -- 计价单位
ALTER TABLE dispatch_price ADD COLUMN IF NOT EXISTS status SMALLINT NOT NULL DEFAULT 1; -- 状态:1启用 0停用
ALTER TABLE dispatch_price ADD COLUMN IF NOT EXISTS remark VARCHAR(255); -- 备注
ALTER TABLE dispatch_price ADD COLUMN IF NOT EXISTS updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW();
COMMENT ON COLUMN dispatch_price.price_mode IS '计价方式:1按次 2按工时';
COMMENT ON COLUMN dispatch_price.unit IS '计价单位';
COMMENT ON COLUMN dispatch_price.status IS '状态:1启用 0停用';
COMMENT ON COLUMN dispatch_price.remark IS '备注';
COMMENT ON COLUMN dispatch_price.updated_at IS '更新时间';
CREATE INDEX IF NOT EXISTS idx_dispatch_price_status ON dispatch_price (status);
-- ------------------------------------------------------------
-- 5) 站内通知表(当前用途:电工资质证照到期提醒)
-- ------------------------------------------------------------
CREATE TABLE IF NOT EXISTS sys_notice (
id BIGSERIAL PRIMARY KEY,
notice_type VARCHAR(32) NOT NULL,
title VARCHAR(128) NOT NULL,
content VARCHAR(512),
biz_type VARCHAR(32),
biz_id BIGINT,
receiver_id BIGINT NOT NULL,
is_read SMALLINT NOT NULL DEFAULT 0,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
COMMENT ON TABLE sys_notice IS '站内通知表';
COMMENT ON COLUMN sys_notice.id IS '自增主键';
COMMENT ON COLUMN sys_notice.notice_type IS '通知类型:cert_expire证照到期';
COMMENT ON COLUMN sys_notice.title IS '通知标题';
COMMENT ON COLUMN sys_notice.content IS '通知内容';
COMMENT ON COLUMN sys_notice.biz_type IS '业务类型:worker_cert电工资质证照';
COMMENT ON COLUMN sys_notice.biz_id IS '业务主键(→ worker_cert.id)';
COMMENT ON COLUMN sys_notice.receiver_id IS '接收人(→ sys_user.id)';
COMMENT ON COLUMN sys_notice.is_read IS '是否已读:0未读 1已读';
COMMENT ON COLUMN sys_notice.created_at IS '创建时间';
CREATE INDEX IF NOT EXISTS idx_sys_notice_receiver ON sys_notice (receiver_id, is_read);
CREATE UNIQUE INDEX IF NOT EXISTS uk_sys_notice_biz ON sys_notice (notice_type, biz_id, receiver_id);
-- ------------------------------------------------------------
-- 6) 菜单与权限
-- 「运营派单」由顶级菜单项改为目录,运维费定价/成本价/电工登记作为其子菜单
-- ------------------------------------------------------------
UPDATE sys_menu SET menu_type = 1 WHERE id = 3;
INSERT INTO sys_menu (id, parent_id, menu_name, menu_path, component, icon, sort_order, menu_type, permission, visible) VALUES
(34, 3, '运维费定价', '/dispatch/price', 'dispatch/price/index', 'MoneyCollectOutlined', 1, 2, 'dispatch:price', 1),
(35, 3, '电工派单成本价', '/dispatch/cost', 'dispatch/cost/index', 'AccountBookOutlined', 2, 2, 'dispatch:cost', 1),
(36, 3, '电工登记管理', '/dispatch/worker', 'dispatch/worker/index', 'ToolOutlined', 3, 2, 'dispatch:worker', 1)
ON CONFLICT (id) DO UPDATE SET
parent_id = EXCLUDED.parent_id,
menu_name = EXCLUDED.menu_name,
menu_path = EXCLUDED.menu_path,
component = EXCLUDED.component,
icon = EXCLUDED.icon,
sort_order = EXCLUDED.sort_order,
menu_type = EXCLUDED.menu_type,
permission = EXCLUDED.permission,
visible = EXCLUDED.visible;
-- 按钮权限(menu_type=3,无路由/组件/图标)
INSERT INTO sys_menu (id, parent_id, menu_name, menu_path, component, icon, sort_order, menu_type, permission, visible) VALUES
(37, 3, '新增价目', NULL, NULL, NULL, 1, 3, 'price:create', 1),
(38, 3, '编辑价目', NULL, NULL, NULL, 2, 3, 'price:update', 1),
(39, 3, '删除价目', NULL, NULL, NULL, 3, 3, 'price:delete', 1),
(40, 3, '新增成本价', NULL, NULL, NULL, 4, 3, 'cost:create', 1),
(41, 3, '编辑成本价', NULL, NULL, NULL, 5, 3, 'cost:update', 1),
(42, 3, '删除成本价', NULL, NULL, NULL, 6, 3, 'cost:delete', 1),
(43, 3, '新增电工', NULL, NULL, NULL, 7, 3, 'worker:create', 1),
(44, 3, '编辑电工', NULL, NULL, NULL, 8, 3, 'worker:update', 1),
(45, 3, '删除电工', NULL, NULL, NULL, 9, 3, 'worker:delete', 1),
(46, 3, '审核电工', NULL, NULL, NULL, 10, 3, 'worker:audit', 1)
ON CONFLICT (id) DO UPDATE SET
parent_id = EXCLUDED.parent_id,
menu_name = EXCLUDED.menu_name,
menu_path = EXCLUDED.menu_path,
component = EXCLUDED.component,
icon = EXCLUDED.icon,
sort_order = EXCLUDED.sort_order,
menu_type = EXCLUDED.menu_type,
permission = EXCLUDED.permission,
visible = EXCLUDED.visible;
-- 角色绑定:ADMIN(role_id=1)拥有 34~46
INSERT INTO sys_role_menu (role_id, menu_id) VALUES
(1, 34), (1, 35), (1, 36), (1, 37), (1, 38), (1, 39), (1, 40), (1, 41), (1, 42), (1, 43), (1, 44), (1, 45), (1, 46)
ON CONFLICT (role_id, menu_id) DO NOTHING;
-- 重置 sys_menu 自增序列,避免后续插入 id 冲突
SELECT setval('sys_menu_id_seq', 46, true);
-- ------------------------------------------------------------
-- 7) 字典(sys_dict 无业务唯一键,先 DELETE 目标 dict_type 再 INSERT,保证幂等)
-- ------------------------------------------------------------
DELETE FROM sys_dict WHERE dict_type IN (
'om_service_type', 'om_price_mode', 'om_price_unit', 'worker_cert_type', 'worker_audit_status'
);
INSERT INTO sys_dict (dict_type, dict_label, dict_value, sort_order) VALUES
('om_service_type', '维修', '维修', 1),
('om_service_type', '维保', '维保', 2),
('om_service_type', '报警处理', '报警处理', 3),
('om_service_type', '巡检', '巡检', 4),
('om_service_type', '其他', '其他', 5),
('om_price_mode', '按次', '1', 1),
('om_price_mode', '按工时', '2', 2),
('om_price_mode', '材料', '3', 3),
('om_price_unit', '次', '次', 1),
('om_price_unit', '小时', '小时', 2),
('om_price_unit', '个', '个', 3),
('om_price_unit', '米', '米', 4),
('om_price_unit', '根', '根', 5),
('worker_cert_type', '低压电工证', '低压电工证', 1),
('worker_cert_type', '高压电工证', '高压电工证', 2),
('worker_cert_type', '特种作业证', '特种作业证', 3),
('worker_cert_type', '登高证', '登高证', 4),
('worker_cert_type', '其他', '其他', 5),
('worker_audit_status', '待审核', '0', 1),
('worker_audit_status', '已通过', '1', 2),
('worker_audit_status', '已驳回', '2', 3);
COMMIT;