-- 项目勘察(现场勘察派单)功能扩展 -- 背景: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;