feat: 新增现场勘察派单全流程业务能力

1.  新增共享电工管理模块:包含实体、DTO、控制器、服务以及前后端API
2.  重构勘察工单实体与查询逻辑,完善工单全状态流程与字段
3.  新增勘察SOP模板与工单回执业务体系
4.  更新数据库字典与初始化脚本,补充业务数据
5.  新增勘察派单增删改查、指派、复核、催办等全流程接口
6.  修复用户服务角色关联SQL生成问题
7.  新增勘察派单前后端完整交互链路
This commit is contained in:
andyesfly committed 2026-09-15 08:50:55 +08:00
1 parent 1c83e09fa1
commit 6b00f61550
21 files changed
+4739 -388

No files matched your search

+148 -29
View File
@@ -3,7 +3,7 @@
-- 基于《鑫潼智电系统需求分析报告 V1.0》+ 数据库设计文档
-- 数据库: PostgreSQL 15+
-- 字符集: UTF8
-- 表数量: 37 张(含 1 张按月分区表)
-- 表数量: 39 张(含 1 张按月分区表)
--
-- 用法:
-- 1. 先安装 pg_cron 扩展并配置 postgresql.conf(见文件末尾说明)
@@ -620,34 +620,143 @@ CREATE INDEX idx_lr_room ON line_room (room_id);
CREATE INDEX idx_lr_customer ON line_room (customer_id);
-- ============================================================
-- 六、派单域(4 张表)
-- 六、派单域(6 张表)
-- ============================================================
-- 21. 勘察派单表
DROP TABLE IF EXISTS survey_order CASCADE;
CREATE TABLE survey_order (
id BIGSERIAL PRIMARY KEY,
survey_no VARCHAR(64) NOT NULL UNIQUE,
customer_id BIGINT NOT NULL REFERENCES customer(id),
surveyor VARCHAR(64),
worker_id BIGINT,
survey_time TIMESTAMPTZ,
remark TEXT,
status SMALLINT NOT NULL DEFAULT 0,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
id BIGSERIAL PRIMARY KEY,
survey_no VARCHAR(64) NOT NULL UNIQUE,
customer_id BIGINT NOT NULL REFERENCES customer(id),
surveyor VARCHAR(64),
worker_id BIGINT,
survey_time TIMESTAMPTZ,
priority SMALLINT DEFAULT 3,
task_title VARCHAR(128),
site_location VARCHAR(255),
source VARCHAR(32) DEFAULT 'ledger',
loop_spec VARCHAR(128),
loop_count INTEGER,
progress_done INTEGER DEFAULT 0,
progress_total INTEGER,
drawing_count INTEGER DEFAULT 0,
salesman_id BIGINT,
tech_contact VARCHAR(128),
plan_start TIMESTAMPTZ,
plan_end TIMESTAMPTZ,
expect_minutes INTEGER,
expect_arrival_at TIMESTAMPTZ,
sla_level VARCHAR(32),
urge_count INTEGER DEFAULT 0,
last_urged_at TIMESTAMPTZ,
is_draft SMALLINT NOT NULL DEFAULT 0,
estimated_fee NUMERIC(10,2),
actual_fee NUMERIC(10,2),
photos VARCHAR(1024),
review_remark TEXT,
reviewed_at TIMESTAMPTZ,
cancel_reason VARCHAR(255),
remark TEXT,
status SMALLINT NOT NULL DEFAULT 0,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
COMMENT ON TABLE survey_order IS '客户勘察派单信息表';
COMMENT ON COLUMN survey_order.id IS '自增主键';
COMMENT ON COLUMN survey_order.survey_no IS '勘察单号(唯一)';
COMMENT ON COLUMN survey_order.customer_id IS '客户 ID(→ customer)';
COMMENT ON COLUMN survey_order.surveyor IS '勘察人(共享电工)';
COMMENT ON COLUMN survey_order.worker_id IS '共享电工 ID';
COMMENT ON COLUMN survey_order.survey_time IS '勘察时间';
COMMENT ON COLUMN survey_order.remark IS '备注';
COMMENT ON COLUMN survey_order.status IS '状态:0已派发 1已接单 2已完成';
COMMENT ON COLUMN survey_order.created_at IS '创建时间';
CREATE INDEX idx_survey_customer ON survey_order (customer_id);
CREATE INDEX idx_survey_worker ON survey_order (worker_id);
COMMENT ON COLUMN survey_order.id IS '自增主键';
COMMENT ON COLUMN survey_order.survey_no IS '勘察单号(唯一)';
COMMENT ON COLUMN survey_order.customer_id IS '客户 ID(→ customer)';
COMMENT ON COLUMN survey_order.surveyor IS '勘察人(共享电工)';
COMMENT ON COLUMN survey_order.worker_id IS '共享电工 ID';
COMMENT ON COLUMN survey_order.survey_time IS '勘察时间';
COMMENT ON COLUMN survey_order.priority IS '优先级:1特急P1 2加急P2 3常规P3';
COMMENT ON COLUMN survey_order.task_title IS '勘察任务标题';
COMMENT ON COLUMN survey_order.site_location IS '具体勘察物理区域';
COMMENT ON COLUMN survey_order.source IS '工单来源:ledger台账派工 visit拜访转勘察 customer客户发起';
COMMENT ON COLUMN survey_order.loop_spec IS '主进线规约与断路器容量';
COMMENT ON COLUMN survey_order.loop_count IS '预估分支测绘回路数';
COMMENT ON COLUMN survey_order.progress_done IS '已完成测绘回路数';
COMMENT ON COLUMN survey_order.progress_total IS '应测绘回路总数';
COMMENT ON COLUMN survey_order.drawing_count IS '待技术复核图纸数';
COMMENT ON COLUMN survey_order.salesman_id IS '责任业务员ID(→ sys_user)';
COMMENT ON COLUMN survey_order.tech_contact IS '现场技术联系人';
COMMENT ON COLUMN survey_order.plan_start IS '计划到场窗口开始';
COMMENT ON COLUMN survey_order.plan_end IS '计划到场窗口结束';
COMMENT ON COLUMN survey_order.expect_minutes IS '要求接单后到场时限(分钟)';
COMMENT ON COLUMN survey_order.expect_arrival_at IS '期望到场时限(指派时按 expect_minutes 推算)';
COMMENT ON COLUMN survey_order.sla_level IS '履约质保要求';
COMMENT ON COLUMN survey_order.urge_count IS '催办次数';
COMMENT ON COLUMN survey_order.last_urged_at IS '最近催办时间';
COMMENT ON COLUMN survey_order.is_draft IS '是否草稿:0正式工单 1草稿';
COMMENT ON COLUMN survey_order.estimated_fee IS '预估劳务费(基础出场费+回路补贴)';
COMMENT ON COLUMN survey_order.actual_fee IS '实际结算劳务费';
COMMENT ON COLUMN survey_order.photos IS '现场取证照片对象key(JSON数组字符串)';
COMMENT ON COLUMN survey_order.review_remark IS '技术复核意见';
COMMENT ON COLUMN survey_order.reviewed_at IS '技术复核时间';
COMMENT ON COLUMN survey_order.cancel_reason IS '取消原因';
COMMENT ON COLUMN survey_order.remark IS '备注';
COMMENT ON COLUMN survey_order.status IS '状态:0待指派 1现场勘察中 2待技术复核 3已归档 4预留 5已取消';
COMMENT ON COLUMN survey_order.created_at IS '创建时间';
COMMENT ON COLUMN survey_order.updated_at IS '更新时间';
CREATE INDEX idx_survey_customer ON survey_order (customer_id);
CREATE INDEX idx_survey_worker ON survey_order (worker_id);
CREATE INDEX idx_survey_status ON survey_order (status);
CREATE INDEX idx_survey_priority ON survey_order (priority);
CREATE INDEX idx_survey_salesman ON survey_order (salesman_id);
CREATE INDEX idx_survey_plan_start ON survey_order (plan_start);
CREATE TRIGGER trg_survey_order_updated_at BEFORE UPDATE ON survey_order
FOR EACH ROW EXECUTE FUNCTION trigger_set_updated_at();
-- 21.1 勘察 SOP 模板检查项表
DROP TABLE IF EXISTS survey_sop_item CASCADE;
CREATE TABLE survey_sop_item (
id BIGSERIAL PRIMARY KEY,
template_code VARCHAR(64) NOT NULL DEFAULT 'standard_dist',
sort_order INTEGER NOT NULL DEFAULT 0,
item_name VARCHAR(128) NOT NULL,
item_desc VARCHAR(255),
receipt_type VARCHAR(16) NOT NULL DEFAULT 'photo',
receipt_require VARCHAR(64),
required BOOLEAN NOT NULL DEFAULT TRUE,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
COMMENT ON TABLE survey_sop_item IS '勘察 SOP 模板检查项表';
COMMENT ON COLUMN survey_sop_item.id IS '自增主键';
COMMENT ON COLUMN survey_sop_item.template_code IS 'SOP模板编码:standard_dist标准配电改造模板';
COMMENT ON COLUMN survey_sop_item.sort_order IS '检查项序号';
COMMENT ON COLUMN survey_sop_item.item_name IS '检查项名称';
COMMENT ON COLUMN survey_sop_item.item_desc IS '检查项说明';
COMMENT ON COLUMN survey_sop_item.receipt_type IS '回执形式:photo现场照片 form清单表单 meter测仪截图';
COMMENT ON COLUMN survey_sop_item.receipt_require IS '回执指标要求,如「照片 ≥ 2 张」';
COMMENT ON COLUMN survey_sop_item.required IS '是否必填';
COMMENT ON COLUMN survey_sop_item.created_at IS '创建时间';
CREATE UNIQUE INDEX uk_sop_template_order ON survey_sop_item (template_code, sort_order);
-- 21.2 勘察 SOP 工单回执表
DROP TABLE IF EXISTS survey_sop_result CASCADE;
CREATE TABLE survey_sop_result (
id BIGSERIAL PRIMARY KEY,
survey_order_id BIGINT NOT NULL REFERENCES survey_order(id) ON DELETE CASCADE,
sop_item_id BIGINT NOT NULL REFERENCES survey_sop_item(id),
checked BOOLEAN NOT NULL DEFAULT FALSE,
receipt_value VARCHAR(1024),
remark VARCHAR(255),
checked_at TIMESTAMPTZ,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
COMMENT ON TABLE survey_sop_result IS '勘察 SOP 工单回执表';
COMMENT ON COLUMN survey_sop_result.id IS '自增主键';
COMMENT ON COLUMN survey_sop_result.survey_order_id IS '勘察工单ID(→ survey_order)';
COMMENT ON COLUMN survey_sop_result.sop_item_id IS 'SOP检查项ID(→ survey_sop_item)';
COMMENT ON COLUMN survey_sop_result.checked IS '是否已完成回执';
COMMENT ON COLUMN survey_sop_result.receipt_value IS '回执内容(照片对象key数组/表单值/截图key)';
COMMENT ON COLUMN survey_sop_result.remark IS '回执备注';
COMMENT ON COLUMN survey_sop_result.checked_at IS '回执时间';
COMMENT ON COLUMN survey_sop_result.created_at IS '创建时间';
COMMENT ON COLUMN survey_sop_result.updated_at IS '更新时间';
CREATE UNIQUE INDEX uk_sop_result_order_item ON survey_sop_result (survey_order_id, sop_item_id);
CREATE INDEX idx_sop_result_order ON survey_sop_result (survey_order_id);
-- 22. 安装派单表
DROP TABLE IF EXISTS install_order CASCADE;
@@ -1033,18 +1142,28 @@ CREATE TABLE worker (
worker_name VARCHAR(64) NOT NULL,
phone VARCHAR(20) NOT NULL,
id_card VARCHAR(18),
worker_title VARCHAR(32),
rating NUMERIC(3,2) DEFAULT 5.00,
cert_info VARCHAR(128),
cert_verified BOOLEAN DEFAULT TRUE,
completed_count INTEGER DEFAULT 0,
status SMALLINT NOT NULL DEFAULT 1,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
COMMENT ON TABLE worker IS '共享电工信息表';
COMMENT ON COLUMN worker.id IS '自增主键';
COMMENT ON COLUMN worker.worker_name IS '电工姓名';
COMMENT ON COLUMN worker.phone IS '手机号';
COMMENT ON COLUMN worker.id_card IS '身份证号';
COMMENT ON COLUMN worker.status IS '状态:1在岗 0离职';
COMMENT ON COLUMN worker.created_at IS '创建时间';
COMMENT ON COLUMN worker.updated_at IS '更新时间';
COMMENT ON COLUMN worker.id IS '自增主键';
COMMENT ON COLUMN worker.worker_name IS '电工姓名';
COMMENT ON COLUMN worker.phone IS '手机号';
COMMENT ON COLUMN worker.id_card IS '身份证号';
COMMENT ON COLUMN worker.worker_title IS '职衔:电工/资深班组长/特种高压电工';
COMMENT ON COLUMN worker.rating IS '服务评分(0-5)';
COMMENT ON COLUMN worker.cert_info IS '持证资质';
COMMENT ON COLUMN worker.cert_verified IS '资质是否已核验';
COMMENT ON COLUMN worker.completed_count IS '历史累计勘察场次';
COMMENT ON COLUMN worker.status IS '状态:1在岗 0离职';
COMMENT ON COLUMN worker.created_at IS '创建时间';
COMMENT ON COLUMN worker.updated_at IS '更新时间';
CREATE INDEX idx_worker_phone ON worker (phone);
CREATE TRIGGER trg_worker_updated_at BEFORE UPDATE ON worker
FOR EACH ROW EXECUTE FUNCTION trigger_set_updated_at();
+6 -4
View File
@@ -149,9 +149,11 @@ INSERT INTO sys_dict (dict_type, dict_label, dict_value, sort_order) VALUES
('device_type', '网关', '网关', 1),
('device_type', '探测器', '探测器', 2),
('device_type', '采集器', '采集器', 3),
('dispatch_status', '已派发', '0', 1),
('dispatch_status', '已接单', '1', 2),
('dispatch_status', '已完成', '2', 3),
('dispatch_status', '待指派', '0', 1),
('dispatch_status', '现场勘察中', '1', 2),
('dispatch_status', '待技术复核', '2', 3),
('dispatch_status', '已归档', '3', 4),
('dispatch_status', '已取消', '5', 5),
('pay_cycle', '按月支付', '按月', 1),
('pay_cycle', '按年支付', '按年', 2),
('dispatch_type', '勘察派单', 'survey', 1),
@@ -203,5 +205,5 @@ DELETE FROM sys_menu WHERE id IN (25, 26);
COMMIT;
-- ============================================================
-- 完 · 7 张系统表种子数据(4 角色 + 32 菜单 + 20 字典 + 1 管理员 + 绑定关系)
-- 完 · 7 张系统表种子数据(4 角色 + 32 菜单 + 22 字典 + 1 管理员 + 绑定关系)
-- ============================================================
@@ -0,0 +1,226 @@
-- 项目勘察(现场勘察派单)功能扩展
-- 背景:db_init.sql 中 survey_order 原为 8 字段的极简结构(0已派发/1已接单/2已完成),
-- 现按「现场勘察派单台账」「现场勘察派单向导」两份 UI 稿完整落地,并引入
-- SOP 模板检查项 + 工单回执两张表,同时补齐共享电工的评分/资质/履约数据。
-- 幂等:全部使用 IF NOT EXISTS / ON CONFLICT,可重复执行。
BEGIN;
-- ------------------------------------------------------------
-- 1) 状态机迁移(必须先于 updated_at 建列执行,用于判定是否已迁移过)
-- 旧:0已派发 1已接单 2已完成
-- 新:0待指派 1现场勘察中 2待技术复核 3已归档 4预留 5已取消
-- 映射:0→0、1→1、2→3
-- ------------------------------------------------------------
DO $$
BEGIN
IF NOT EXISTS (
SELECT 1 FROM information_schema.columns
WHERE table_name = 'survey_order' AND column_name = 'updated_at'
) THEN
UPDATE survey_order SET status = 3 WHERE status = 2;
END IF;
END $$;
-- ------------------------------------------------------------
-- 2) survey_order 业务字段扩展
-- ------------------------------------------------------------
-- 派工属性
ALTER TABLE survey_order ADD COLUMN IF NOT EXISTS priority SMALLINT DEFAULT 3; -- 优先级:1特急P1 2加急P2 3常规P3
ALTER TABLE survey_order ADD COLUMN IF NOT EXISTS task_title VARCHAR(128); -- 勘察任务标题
ALTER TABLE survey_order ADD COLUMN IF NOT EXISTS site_location VARCHAR(255); -- 具体勘察物理区域
ALTER TABLE survey_order ADD COLUMN IF NOT EXISTS source VARCHAR(32) DEFAULT 'ledger'; -- 工单来源:ledger台账派工 visit拜访转勘察 customer客户发起
-- 现场测绘规格
ALTER TABLE survey_order ADD COLUMN IF NOT EXISTS loop_spec VARCHAR(128); -- 主进线规约与断路器容量
ALTER TABLE survey_order ADD COLUMN IF NOT EXISTS loop_count INTEGER; -- 预估分支测绘回路数
ALTER TABLE survey_order ADD COLUMN IF NOT EXISTS progress_done INTEGER DEFAULT 0; -- 已完成测绘回路数
ALTER TABLE survey_order ADD COLUMN IF NOT EXISTS progress_total INTEGER; -- 应测绘回路总数
ALTER TABLE survey_order ADD COLUMN IF NOT EXISTS drawing_count INTEGER DEFAULT 0; -- 待技术复核图纸数
-- 责任人与时效
ALTER TABLE survey_order ADD COLUMN IF NOT EXISTS salesman_id BIGINT; -- 责任业务员ID(→ sys_user)
ALTER TABLE survey_order ADD COLUMN IF NOT EXISTS tech_contact VARCHAR(128); -- 现场技术联系人
ALTER TABLE survey_order ADD COLUMN IF NOT EXISTS plan_start TIMESTAMPTZ; -- 计划到场窗口开始
ALTER TABLE survey_order ADD COLUMN IF NOT EXISTS plan_end TIMESTAMPTZ; -- 计划到场窗口结束
ALTER TABLE survey_order ADD COLUMN IF NOT EXISTS expect_minutes INTEGER; -- 要求接单后到场时限(分钟)
ALTER TABLE survey_order ADD COLUMN IF NOT EXISTS expect_arrival_at TIMESTAMPTZ; -- 期望到场时限(指派时按 expect_minutes 推算)
ALTER TABLE survey_order ADD COLUMN IF NOT EXISTS sla_level VARCHAR(32); -- 履约质保要求
ALTER TABLE survey_order ADD COLUMN IF NOT EXISTS urge_count INTEGER DEFAULT 0; -- 催办次数
ALTER TABLE survey_order ADD COLUMN IF NOT EXISTS last_urged_at TIMESTAMPTZ; -- 最近催办时间
-- 派单草稿(向导「保存为草稿」,台账与统计默认排除草稿)
ALTER TABLE survey_order ADD COLUMN IF NOT EXISTS is_draft SMALLINT NOT NULL DEFAULT 0;
-- 报酬
ALTER TABLE survey_order ADD COLUMN IF NOT EXISTS estimated_fee NUMERIC(10,2); -- 预估劳务费(基础出场费+回路补贴)
ALTER TABLE survey_order ADD COLUMN IF NOT EXISTS actual_fee NUMERIC(10,2); -- 实际结算劳务费
-- 成果与复核
ALTER TABLE survey_order ADD COLUMN IF NOT EXISTS photos VARCHAR(1024); -- 现场取证照片对象key(JSON数组字符串)
ALTER TABLE survey_order ADD COLUMN IF NOT EXISTS review_remark TEXT; -- 技术复核意见
ALTER TABLE survey_order ADD COLUMN IF NOT EXISTS reviewed_at TIMESTAMPTZ; -- 技术复核时间
ALTER TABLE survey_order ADD COLUMN IF NOT EXISTS cancel_reason VARCHAR(255); -- 取消原因
-- 更新时间(Sequelize 实体已开启 updated_at,缺列会导致写入失败)
ALTER TABLE survey_order ADD COLUMN IF NOT EXISTS updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW();
-- 3) 字段注释
COMMENT ON COLUMN survey_order.priority IS '优先级:1特急P1 2加急P2 3常规P3';
COMMENT ON COLUMN survey_order.task_title IS '勘察任务标题';
COMMENT ON COLUMN survey_order.site_location IS '具体勘察物理区域';
COMMENT ON COLUMN survey_order.source IS '工单来源:ledger台账派工 visit拜访转勘察 customer客户发起';
COMMENT ON COLUMN survey_order.loop_spec IS '主进线规约与断路器容量';
COMMENT ON COLUMN survey_order.loop_count IS '预估分支测绘回路数';
COMMENT ON COLUMN survey_order.progress_done IS '已完成测绘回路数';
COMMENT ON COLUMN survey_order.progress_total IS '应测绘回路总数';
COMMENT ON COLUMN survey_order.drawing_count IS '待技术复核图纸数';
COMMENT ON COLUMN survey_order.salesman_id IS '责任业务员ID(→ sys_user)';
COMMENT ON COLUMN survey_order.tech_contact IS '现场技术联系人';
COMMENT ON COLUMN survey_order.plan_start IS '计划到场窗口开始';
COMMENT ON COLUMN survey_order.plan_end IS '计划到场窗口结束';
COMMENT ON COLUMN survey_order.expect_minutes IS '要求接单后到场时限(分钟)';
COMMENT ON COLUMN survey_order.expect_arrival_at IS '期望到场时限(指派时按 expect_minutes 推算)';
COMMENT ON COLUMN survey_order.sla_level IS '履约质保要求';
COMMENT ON COLUMN survey_order.urge_count IS '催办次数';
COMMENT ON COLUMN survey_order.last_urged_at IS '最近催办时间';
COMMENT ON COLUMN survey_order.is_draft IS '是否草稿:0正式工单 1草稿';
COMMENT ON COLUMN survey_order.estimated_fee IS '预估劳务费(基础出场费+回路补贴)';
COMMENT ON COLUMN survey_order.actual_fee IS '实际结算劳务费';
COMMENT ON COLUMN survey_order.photos IS '现场取证照片对象key(JSON数组字符串)';
COMMENT ON COLUMN survey_order.review_remark IS '技术复核意见';
COMMENT ON COLUMN survey_order.reviewed_at IS '技术复核时间';
COMMENT ON COLUMN survey_order.cancel_reason IS '取消原因';
COMMENT ON COLUMN survey_order.updated_at IS '更新时间';
COMMENT ON COLUMN survey_order.status IS '状态:0待指派 1现场勘察中 2待技术复核 3已归档 4预留 5已取消';
-- 4) 查询索引(台账按状态/优先级/计划窗口/业务员过滤与排序)
CREATE INDEX IF NOT EXISTS idx_survey_status ON survey_order (status);
CREATE INDEX IF NOT EXISTS idx_survey_priority ON survey_order (priority);
CREATE INDEX IF NOT EXISTS idx_survey_salesman ON survey_order (salesman_id);
CREATE INDEX IF NOT EXISTS idx_survey_plan_start ON survey_order (plan_start);
-- 5) survey_order 更新时间触发器(与 customer 等表保持一致的库级约定)
DO $$
BEGIN
IF NOT EXISTS (SELECT 1 FROM pg_trigger WHERE tgname = 'trg_survey_order_updated_at') THEN
CREATE TRIGGER trg_survey_order_updated_at BEFORE UPDATE ON survey_order
FOR EACH ROW EXECUTE FUNCTION trigger_set_updated_at();
END IF;
END $$;
-- ------------------------------------------------------------
-- 6) 共享电工域:补齐评分/资质/履约数据(不做真实距离,无经纬度字段)
-- ------------------------------------------------------------
ALTER TABLE worker ADD COLUMN IF NOT EXISTS worker_title VARCHAR(32); -- 职衔:电工/资深班组长/特种高压电工
ALTER TABLE worker ADD COLUMN IF NOT EXISTS rating NUMERIC(3,2) DEFAULT 5.00; -- 服务评分(0-5)
ALTER TABLE worker ADD COLUMN IF NOT EXISTS cert_info VARCHAR(128); -- 持证资质
ALTER TABLE worker ADD COLUMN IF NOT EXISTS cert_verified BOOLEAN DEFAULT TRUE; -- 资质是否已核验
ALTER TABLE worker ADD COLUMN IF NOT EXISTS completed_count INTEGER DEFAULT 0; -- 历史累计勘察场次
COMMENT ON COLUMN worker.worker_title IS '职衔:电工/资深班组长/特种高压电工';
COMMENT ON COLUMN worker.rating IS '服务评分(0-5)';
COMMENT ON COLUMN worker.cert_info IS '持证资质';
COMMENT ON COLUMN worker.cert_verified IS '资质是否已核验';
COMMENT ON COLUMN worker.completed_count IS '历史累计勘察场次';
-- ------------------------------------------------------------
-- 7) 勘察 SOP 模板检查项表(向导第 2 步「标准配电改造模板」)
-- ------------------------------------------------------------
CREATE TABLE IF NOT EXISTS survey_sop_item (
id BIGSERIAL PRIMARY KEY,
template_code VARCHAR(64) NOT NULL DEFAULT 'standard_dist',
sort_order INTEGER NOT NULL DEFAULT 0,
item_name VARCHAR(128) NOT NULL,
item_desc VARCHAR(255),
receipt_type VARCHAR(16) NOT NULL DEFAULT 'photo',
receipt_require VARCHAR(64),
required BOOLEAN NOT NULL DEFAULT TRUE,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
COMMENT ON TABLE survey_sop_item IS '勘察 SOP 模板检查项表';
COMMENT ON COLUMN survey_sop_item.id IS '自增主键';
COMMENT ON COLUMN survey_sop_item.template_code IS 'SOP模板编码:standard_dist标准配电改造模板';
COMMENT ON COLUMN survey_sop_item.sort_order IS '检查项序号';
COMMENT ON COLUMN survey_sop_item.item_name IS '检查项名称';
COMMENT ON COLUMN survey_sop_item.item_desc IS '检查项说明';
COMMENT ON COLUMN survey_sop_item.receipt_type IS '回执形式:photo现场照片 form清单表单 meter测仪截图';
COMMENT ON COLUMN survey_sop_item.receipt_require IS '回执指标要求,如「照片 ≥ 2 张」';
COMMENT ON COLUMN survey_sop_item.required IS '是否必填';
COMMENT ON COLUMN survey_sop_item.created_at IS '创建时间';
CREATE UNIQUE INDEX IF NOT EXISTS uk_sop_template_order ON survey_sop_item (template_code, sort_order);
-- ------------------------------------------------------------
-- 8) 勘察 SOP 工单回执表(每张勘察工单的执行回执)
-- ------------------------------------------------------------
CREATE TABLE IF NOT EXISTS survey_sop_result (
id BIGSERIAL PRIMARY KEY,
survey_order_id BIGINT NOT NULL REFERENCES survey_order(id) ON DELETE CASCADE,
sop_item_id BIGINT NOT NULL REFERENCES survey_sop_item(id),
checked BOOLEAN NOT NULL DEFAULT FALSE,
receipt_value VARCHAR(1024),
remark VARCHAR(255),
checked_at TIMESTAMPTZ,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
COMMENT ON TABLE survey_sop_result IS '勘察 SOP 工单回执表';
COMMENT ON COLUMN survey_sop_result.id IS '自增主键';
COMMENT ON COLUMN survey_sop_result.survey_order_id IS '勘察工单ID(→ survey_order)';
COMMENT ON COLUMN survey_sop_result.sop_item_id IS 'SOP检查项ID(→ survey_sop_item)';
COMMENT ON COLUMN survey_sop_result.checked IS '是否已完成回执';
COMMENT ON COLUMN survey_sop_result.receipt_value IS '回执内容(照片对象key数组/表单值/截图key)';
COMMENT ON COLUMN survey_sop_result.remark IS '回执备注';
COMMENT ON COLUMN survey_sop_result.checked_at IS '回执时间';
COMMENT ON COLUMN survey_sop_result.created_at IS '创建时间';
COMMENT ON COLUMN survey_sop_result.updated_at IS '更新时间';
CREATE UNIQUE INDEX IF NOT EXISTS uk_sop_result_order_item ON survey_sop_result (survey_order_id, sop_item_id);
CREATE INDEX IF NOT EXISTS idx_sop_result_order ON survey_sop_result (survey_order_id);
-- ------------------------------------------------------------
-- 9) SOP 模板检查项种子数据(标准配电改造模板 5 项)
-- ------------------------------------------------------------
INSERT INTO survey_sop_item (template_code, sort_order, item_name, item_desc, receipt_type, receipt_require, required) VALUES
('standard_dist', 1, '变压器铭牌与备用容量', '拍摄变压器铭牌并核对备用容量', 'photo', '现场照片 ≥ 2 张', TRUE),
('standard_dist', 2, '母排厚度与电缆线径测绘', '测绘母排厚度与电缆线径', 'photo', '现场照片 ≥ 3 张', TRUE),
('standard_dist', 3, '老旧断路器脱扣特性清查', '清查老旧断路器脱扣特性', 'form', '清单格式·表单直填', TRUE),
('standard_dist', 4, 'DIN导轨剩余安装空间实测','实测配电箱内 DIN 导轨剩余空间','photo', '照片回传·含卷尺 1 张', TRUE),
('standard_dist', 5, '竖井4G/LoRa物联网场强测试','测试竖井物联网信号场强', 'meter', '手持测仪·信号截图', TRUE)
ON CONFLICT (template_code, sort_order) DO UPDATE SET
item_name = EXCLUDED.item_name,
item_desc = EXCLUDED.item_desc,
receipt_type = EXCLUDED.receipt_type,
receipt_require = EXCLUDED.receipt_require,
required = EXCLUDED.required;
-- ------------------------------------------------------------
-- 10) 共享电工种子数据(评分/资质/履约,供向导候选推荐使用)
-- ------------------------------------------------------------
INSERT INTO worker (worker_name, phone, status, worker_title, rating, cert_info, cert_verified, completed_count)
SELECT '赵志强', '13900000001', 1, '特种高压电工', 4.98, '特种低压电工证', TRUE, 24
WHERE NOT EXISTS (SELECT 1 FROM worker WHERE phone = '13900000001');
INSERT INTO worker (worker_name, phone, status, worker_title, rating, cert_info, cert_verified, completed_count)
SELECT '孙明远', '13900000002', 1, '继电保护技师', 4.92, '继电保护作业证', TRUE, 31
WHERE NOT EXISTS (SELECT 1 FROM worker WHERE phone = '13900000002');
INSERT INTO worker (worker_name, phone, status, worker_title, rating, cert_info, cert_verified, completed_count)
SELECT '王建国', '13900000003', 1, '资深班组长', 4.92, '高低压带电作业资质', TRUE, 68
WHERE NOT EXISTS (SELECT 1 FROM worker WHERE phone = '13900000003');
INSERT INTO worker (worker_name, phone, status, worker_title, rating, cert_info, cert_verified, completed_count)
SELECT '周正海', '13900000004', 1, '电气试验工程师', 4.88, '电气试验资质', TRUE, 12
WHERE NOT EXISTS (SELECT 1 FROM worker WHERE phone = '13900000004');
-- ------------------------------------------------------------
-- 11) 勘察派单价格种子数据(向导第 3 步报酬拆分规则)
-- 应付勘察劳务总报酬 = 基础出场工时费 350.00 + 回路数 × 5.00
-- ------------------------------------------------------------
INSERT INTO dispatch_price (price_code, dispatch_type, price_type, unit_price) VALUES
('SURVEY_BASE_FEE', 'survey', '基础出场工时费', 350.00),
('SURVEY_LOOP_FEE', 'survey', '回路测点补贴(元/路)', 5.00)
ON CONFLICT (price_code) DO UPDATE SET
dispatch_type = EXCLUDED.dispatch_type,
price_type = EXCLUDED.price_type,
unit_price = EXCLUDED.unit_price;
COMMIT;